空变量/参数/临时表/临时过程名称的好处或用例?

Sol*_*zky 6 sql-server t-sql parameter temporary-tables table-variable

我才发现, 通过纯粹的光彩意外的是,SQL Server 允许您创建没有任何名称的变量、参数、表变量、临时表(本地和全局)和临时存储过程(本地和全局)!好吧,至少不是我认为的名字。意思是,您可以指定DECLARE @ INT = 5;并且是有效的 T-SQL:它执行时没有错误甚至没有在 SSMS 中用红色波浪线下划线标记(本问题末尾显示了完整示例列表的代码)。

鉴于数据库标识符的 MSDN 页面指出(强调我的):

有两类标识符:
常规标识符
...
分隔标识符
... 常规标识符和分隔标识符都必须包含1 到128 个字符。对于本地临时表,标识符最多可以有 116 个字符。

这当然看起来不像预期的行为,我最初认为这是一个缺陷(不会导致任何错误,但似乎不是“正确”的行为)并提交了一个连接错误:参数、变量和临时表和过程名称/标识符可以为空

然而,同一个 MSDN 页面还指出:

常规标识符规则

变量、函数和存储过程的名称必须符合以下 Transact-SQL 标识符规则。

  1. 第一个字符必须是以下字符之一:

    • Unicode 标准 3.2 定义的字母。字母的 Unicode 定义包括从 a 到 z、从 A 到 Z 的拉丁字符,以及来自其他语言的字母字符。
    • 下划线 (_)、at 符号 (@) 或数字符号 (#)。

      标识符开头的某些符号在 SQL Server 中具有特殊含义。以 at 符号开头的常规标识符始终表示局部变量或参数,不能用作任何其他类型对象的名称。以数字符号开头的标识符表示临时表或过程。以双数字符号 (##) 开头的标识符表示全局临时对象。尽管可以使用数字符号或双数字符号字符作为其他类型对象的名称的开头,但我们不推荐这种做法。

因此,可以解释为,名称的 1 个字符的最低要求(从显示“1 到 128 个字符”的最上面引用的部分)将通过简单地具有以下任一@#因为:

  1. 它指出那些将是“第一个”字符,而不是它是事物类型的某种类型的外部指示,并且
  2. 没有说明当@#是第一个字符时,需要2 到128 个字符。

所以,如果这种行为既不是错误也不是缺陷,那么利用这种能力有什么好处吗?是否有一个合法的用例可以通过这样做而受益(即对项目的一些功能好处,而不仅仅是减少源代码的字符数)?

除了不专业并且在你搬到新雇主时为每个人留下可怕的难以管理的代码之外,我想不出一个。

但我也可以看到一个相关的功能问题,因为在许多解析 T-SQL 对象的项目中有大量代码块。如果有人使用 RegEx 模式寻找@后跟类似的东西(\w+),那么它会跳过这些条目。

-- Local variables:
DECLARE @ INT = 99;
DECLARE @@ VARCHAR(10);
SELECT CONVERT(VARCHAR(20), @), STR(@);
SET @@ = STR(@);
SELECT @@;
GO

-- Table Variable:
DECLARE @ TABLE (Col1 INT);
INSERT INTO @ (Col1) VALUES (86);
SELECT * FROM @;
GO

-- Local Temporary Table:
CREATE TABLE # (Col2 DATETIME);
INSERT INTO # (Col2) VALUES (GETDATE());
SELECT * FROM #;
SELECT OBJECT_ID(N'tempdb..#');
GO

-- Global Temporary Stored Procedure
CREATE PROCEDURE ##  ( @ INT = 999 )
AS
SELECT @ AS [Huh?];
GO

EXEC ##;

EXEC ## 204;

DECLARE @ INT = 12345;
EXEC ## @ = @;
-- The above also work in another session on the same instance, in a different Database

SELECT * FROM tempdb.sys.parameters tsp WHERE tsp.[object_id] = OBJECT_ID(N'tempdb..##');
-- returns 1 row showing a name of just "@"
Run Code Online (Sandbox Code Playgroud)

PS 我在这里、Google 和 Microsoft Connect 上搜索过,但找不到任何对“缺失”或“空”变量名称或“标识符”的引用。但是,@MartinSmith 确实指出了在以下 StackOverflow 答案中使用的这种“能力”来减少代码的字符数:Build an ASCII chart of the most common used words in a given text

Sol*_*zky 1

似乎这种行为/能力是已知的并且已被弃用。前几天我正在查看sys.dm_os_performance_counters DMV,并注意到以下两个条目:

object_name                      counter_name    instance_name
-----------------------------    ------------    -------------------------------
SQLServer:Deprecated Features    Usage           '@' and names that start with '@@' as
                                                 Transact-SQL identifiers

SQLServer:Deprecated Features    Usage           '#' and '##' as the name of temporary
                                                 tables and stored procedures
Run Code Online (Sandbox Code Playgroud)

然后,我检查了 MSDN 文档,并在“SQL Server 2016 中已弃用的数据库引擎功能”页面、“ SQL Server 未来版本中不支持的功能”部分的“Transact-SQL”类别下找到了这两个注释:

object_name                      counter_name    instance_name
-----------------------------    ------------    -------------------------------
SQLServer:Deprecated Features    Usage           '@' and names that start with '@@' as
                                                 Transact-SQL identifiers

SQLServer:Deprecated Features    Usage           '#' and '##' as the name of temporary
                                                 tables and stored procedures
Run Code Online (Sandbox Code Playgroud)

我可以在SQL Server 2008 文档中找到有关此弃用通知的最早参考资料。虽然“已弃用的数据库引擎功能”页面上的版本下拉列表中没有 SQL Server 2005 的条目,但您仍然可以通过https://msdn.microsoft.com/en-us/library访问该文档/ms143729(v=sql.90).aspx,并看到这些项目均未列出。

这些信息使我得出以下结论:

  • 问题第 1 部分(这是错误还是预期行为):

    这是有意的行为,尽管是不可取的。

  • 问题第 2 部分(这种行为有好处吗):

    这里不仅似乎没有任何有益的用例,即使有,也不会太重要,因为这种行为/能力已被弃用,因此不应该继续使用,特别是在新代码中/ 项目。