有时我将对象名称(标识符)存储在我们的某些数据库中,例如某些参数表中。因为我使用 '=' 或 'LIKE' 比较运算符从这些表中选择记录,所以我必须注意始终使用或不使用括号来存储这些名称。
IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = '[TABLE_NAME]';
或者
IF EXISTS (SELECT 1 FROM MYTABLE WHERE OBJ_NAME = 'TABLE_NAME';
但是,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
现在我可以使用 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. |
我是否通过带有或不带有括号的标识符 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
然后以这种方式使用它:
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
但我的问题是:
- 是否有任何隐藏的内置函数可以使用 T-SQL 删除括号?
dbfiddle在这里
“对象名称”在技术上称为标识符。在某些情况下,标识符将出现在 TSQL 代码中,由 [ 和 ] 或“和”包围。这些字符不是标识符的一部分,您永远不应该存储它们。
而是将标识符存储为 nvarchar(128)(或 sysname),并在运行时使用QUOTENAME函数添加分隔符。
QUOTENAME 的倒数是PARSENAME,它具有导航多部分名称的额外能力。
请注意,QUOTENAME 有一个可选的第二个参数,如果您为该参数指定单引号字符,QUOTENAME 不会创建有效的分隔标识符表达式。它发出一个 varchar 文字表达式。
不,不使用 T-SQL。
OBJECT_ID
是一个内在函数。它直接在 SQL Server 可执行代码中实现,而不是在 T-SQL 中;并且它在调用时不调用任何 T-SQL。在运行时,通过表达式服务调用获取对象 id
sqlmin!I4ObjIdWstr
。然后,实现会执行所有必要的步骤,将提供的字符串参数解析为引用数据库中对象的 id。
第一步包括通过处理字符串中的任何分隔标识符
sqlmin!CbParseQuotesW
。狭义上就是你说的代码函数,但是不能直接从T-SQL访问。它包含以下代码:...这是处理字符的测试:
"
.
[
]
将参数解析为 id 的其余过程包括:
在旁注中,问题中的代码:
...不只是寻找表格。为此,需要使用第二个函数参数。此外,它只查找名为 TEST 的任何模式范围的对象 - 例如,名为 BananaSchema.TEST 的视图将匹配。更好的表达方式是:
相关问答:
SQL Server 显然有一些内部的东西可以去掉
[square brackets]
(或其他标识符,如"double quotes"
)。当您创建一个类似的表时
[dbo].[foo]
,您是对的,它只foo
存储在sys.tables
and中sys.objects
,并且没有抱怨找不到架构[dbo]
(带有方括号)。但这发生在
CREATE TABLE
.PARSENAME()
正如大卫指出的那样,他们可能正在使用. 连接调试器可以确定,但这有关系吗?您可以查看其他地方以查看他们在做什么,
sys.sp_rename
实际上确实PARSENAME()
使用了 yield:但同样,我不确定我是否理解您为什么只想有时删除方括号。
就我个人而言,我的代码中有足够大比例是为更广泛的受众编写的,他们将在我不知道或无法控制他们是否使用不安全标识符的环境中使用代码。所以我一直并且总是会编写(并且更喜欢)
QUOTENAME()
用于生成包含任何类型标识符的脚本的代码。我宁愿一直把方括号放在那里,也不愿在需要的时候把它们拿走并被咬。
当需要方括号时——这是因为您的标识符已经是保留关键字。任意使用它们不仅没有必要,而且如您所见,它会导致很多混乱。
在我看来,最好的方法是首先避免使用保留标识符。