有时我将对象名称(标识符)存储在我们的一些数据库中,例如在一些参数表中。因为我使用 '=' 或 'LIKE' 比较运算符从这些表中选择记录,所以我必须注意存储这些名称时总是带括号或不带括号。
IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = '[TABLE_NAME]';
Run Code Online (Sandbox Code Playgroud)
或者
IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = 'TABLE_NAME';
Run Code Online (Sandbox Code Playgroud)
但是,MS-SQL 有一些函数,您可以在其中使用带或不带括号的对象名称,例如 OBJECT_ID() 函数。我在dbfiddle.uk上设置了一个最小的例子。
CREATE TABLE TEST
(
ID INT IDENTITY(1,1) PRIMARY KEY,
OBJECT sysname NOT NULL
);
GO
INSERT INTO TEST VALUES ('[obj1]'),('obj2'),('obj3'),('[obj4]');
GO
Run Code Online (Sandbox Code Playgroud)
现在我可以使用 OBJECT_ID() 以这种方式检查表 TEST 是否存在:
IF OBJECT_ID('TEST') IS NOT NULL
BEGIN
SELECT 'TEST EXISTS.' OBJECT_ID;
END
GO
| OBJECT_ID |
| :----------- |
| TEST EXISTS. |
IF OBJECT_ID('[TEST]') IS NOT NULL
BEGIN
SELECT '[TEST] EXISTS.' OBJECT_ID;
END
GO
| OBJECT_ID |
| :------------- |
| [TEST] EXISTS. |
Run Code Online (Sandbox Code Playgroud)
我是否通过带或不带括号的标识符 TEST 都没有关系,解析器足够聪明,可以删除括号。
好吧,我可以通过添加一个从一个字符串中删除括号的标量函数来模拟这一点:
CREATE FUNCTION UNQUOTENAME(@TXT NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
RETURN IIF(LEFT(@TXT, 1) = N'[' AND RIGHT(@TXT, 1) = N']',
SUBSTRING(@TXT, 2, LEN(@TXT) - 2),
@TXT);
END;
GO
Run Code Online (Sandbox Code Playgroud)
然后以这种方式使用它:
SELECT dbo.UNQUOTENAME (N'[FIELD]') NAME1, N'FIELD' NAME2;
GO
NAME1 | NAME2
:---- | :----
FIELD | FIELD
SELECT ID, OBJECT
FROM TEST
WHERE OBJECT LIKE 'obj%';
GO
ID | OBJECT
-: | :-----
2 | obj2
3 | obj3
SELECT ID, dbo.UNQUOTENAME(OBJECT)
FROM TEST
WHERE dbo.UNQUOTENAME(OBJECT) LIKE 'obj%';
GO
ID | (No column name)
-: | :---------------
1 | obj1
2 | obj2
3 | obj3
4 | obj4
Run Code Online (Sandbox Code Playgroud)
但我的问题是:
dbfiddle在这里
Dav*_*oft 18
有时我将对象名称存储在我们的一些数据库中
我必须小心地存储这些名称,无论有没有括号。
“对象名称”在技术上称为标识符。在某些情况下,标识符会出现在 TSQL 代码中,被 [ 和 ] 或“和”包围。这些字符不是标识符的一部分,您不应该存储它们。
而是将标识符存储为 nvarchar(128)(或 sysname),并在运行时使用QUOTENAME函数添加分隔符。
QUOTENAME 的反面是PARSENAME,它具有导航多部分名称的附加功能。
请注意,QUOTENAME 有一个可选的第二个参数,如果您为该参数指定单引号字符,QUOTENAME 不会创建有效的分隔标识符表达式。它发出一个 varchar 文字表达式。
Pau*_*ite 12
是否有任何隐藏的内置函数可以使用 T-SQL 删除括号?
不,不使用 T-SQL。
OBJECT_ID
是一个内在函数。它直接在 SQL Server 可执行代码中实现,而不是在 T-SQL 中;并且在调用时不调用任何 T-SQL。
在运行时,对象 id 是通过表达式服务调用获得的sqlmin!I4ObjIdWstr
。
然后,实现会执行所有必要的步骤,将提供的字符串参数解析为引用数据库中对象的 id。
第一步包括通过 处理字符串中的任何分隔标识符sqlmin!CbParseQuotesW
。从狭义上讲,这就是您所指的代码函数,但它不能直接从 T-SQL 访问。它包含以下代码:
cmp r9d,22h
je sqlmin!CbParseQuotesW+0x185
cmp r9d,2Eh
je sqlmin!CbParseQuotesW+0x139
cmp r9d,5Bh
je sqlmin!CbParseQuotesW+0xfe
cmp r9d,5Dh
je sqlmin!CbParseQuotesW+0xda
Run Code Online (Sandbox Code Playgroud)
...这是处理字符的测试:
"
.
[
]
将参数解析为 id 的其余过程包括:
附带说明一下,问题中的代码:
IF OBJECT_ID('TEST') IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
...不只寻找表格。为此需要使用第二个函数参数。此外,它只查找任何名为 TEST 的模式范围对象 - 例如,名为 BananaSchema.TEST 的视图将匹配。更好的表达方式是:
IF OBJECT_ID(N'dbo.TEST', N'U') IS NOT NULL
Run Code Online (Sandbox Code Playgroud)
相关问答:
SQL Server 显然有一些内部的东西可以去掉[square brackets]
(或其他标识符,比如"double quotes"
)。
当您创建一个类似于 的表时[dbo].[foo]
,您是对的,只会foo
存储在sys.tables
and 中sys.objects
,并且没有人抱怨找不到架构[dbo]
(带方括号)。
但这发生在CREATE TABLE
. PARSENAME()
正如大卫指出的那样,他们可能正在使用。连接调试器可以肯定地表明,但这有关系吗?
你可以在别处看看他们在做什么,sys.sp_rename
实际上确实产生了PARSENAME()
使用:
select @UnqualOldName = parsename(@objname, 1),
@QualName1 = parsename(@objname, 2),
@QualName2 = parsename(@objname, 3),
@QualName3 = parsename(@objname, 4)
Run Code Online (Sandbox Code Playgroud)
但同样,我不确定我是否理解为什么您只想有时删除方括号。
就我个人而言,我的代码中有足够大的百分比是为更广泛的受众编写的,他们将在我不知道或无法控制他们是否使用不安全标识符的环境中使用代码。所以我总是并且总是会编写(并且更喜欢)QUOTENAME()
用于生成包含任何类型标识符的脚本的代码。
我宁愿一直把方括号放在那里,也不愿把它们拿走,并在需要它们的时候被咬伤。
归档时间: |
|
查看次数: |
2351 次 |
最近记录: |