空變數/參數/臨時表/臨時過程名稱的好處或案例?
我才發現,
通過純粹的光彩意外的是,SQL Server 允許您創建沒有任何名稱的變數、參數、表變數、臨時表(本地和全域)和臨時儲存過程(本地和全域)!好吧,至少不是我認為的名字。DECLARE @ INT = 5;
意思是,您可以指定這是有效的 T-SQL:它執行時沒有錯誤*,*甚至沒有在 SSMS 中用波浪形的紅色下劃線標記(本問題末尾顯示的帶有完整範例列表的程式碼)。鑑於數據庫標識符的 MSDN 頁面狀態(強調我的):
有兩類標識符:
正常標識符
…定界
標識符
…正常標識符和定界標識符都必須包含1 到128 個字元。對於本地臨時表,標識符最多可以有 116 個字元。
這當然不像是預期的行為,我最初認為這是一個缺陷(不會導致任何錯誤,但似乎不是“正確”的行為)並送出了一個連接錯誤:參數、變數和臨時表和過程名稱/標識符可以為空。
但是,同一個 MSDN 頁面還指出:
正常標識符規則
變數、函式和儲存過程的名稱必須符合以下 Transact-SQL 標識符規則。
- 第一個字元必須是以下之一:
* Unicode 標準 3.2 定義的字母。字母的 Unicode 定義包括從 a 到 z、從 A 到 Z 的拉丁字元,以及來自其他語言的字母字元。 * 下劃線 (_)、at 符號 (@) 或數字元號 (#)。
標識符開頭的某些符號在 SQL Server 中具有特殊含義。以 at 符號開頭的正常標識符始終表示局部變數或參數,不能用作任何其他類型對象的名稱。以數字元號開頭的標識符表示臨時表或過程。以雙數字元號 (##) 開頭的標識符表示全域臨時對象。儘管可以使用數字元號或雙數字元號字元來開始其他類型對象的名稱,但我們不推薦這種做法。
因此,可以解釋為,名稱的 1 個字元的最低要求(從頂部引用的部分顯示“1 到 128 個字元”)將通過簡單地具有以下任一
@
或以下來滿足#
:
- 它聲明那些將是“第一個”字元,而不是某種類型的事物類型的外部指示,並且
- 沒有說明當第一個字元是
@
或時,需要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 "@"
PS 我在這裡、Googles 和 Microsoft Connect 上進行了搜尋,但找不到任何對“缺失”或“空”變數名或“標識符”的引用。但是,@MartinSmith 確實指出了在以下 StackOverflow 答案中使用這種“能力”來減少程式碼的字元數:Build an ASCII chart of the most common used words in a given text。
似乎這種行為/能力既已知又不推薦使用。前幾天我正在查看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
然後,我檢查了 MSDN 文件,並在 SQL Server 2016 中已棄用的數據庫引擎功能頁面中的**“SQL Server 未來版本不支持的功能”**部分中的“Transact-SQL”類別下發現了這兩個:
Deprecated feature Replacement Feature ID ----------------------------------- -------------------------------------- ---------- Use of #, ## as temporary table and Use at least one additional character. 185 temporary stored procedure names. Use of @, @@, or @@ as Do not use @ or @@ or names that begin 186 Transact-SQL identifiers. with @@ as identifiers.
我可以在SQL Server 2008 文件中找到有關此棄用通知的最早參考資料。雖然“已棄用的數據庫引擎功能”頁面上的版本下拉列表沒有 SQL Server 2005 條目,但您仍然可以通過https://msdn.microsoft.com/en-us/library訪問該文件/ms143729(v=sql.90).aspx,並看到這些項目都沒有列出。
這些資訊使我得出以下結論:
- 問題第 1 部分(這是錯誤還是預期行為):
它是有意的,儘管是不受歡迎的行為。
- 問題第 2 部分(這種行為有什麼好處):
這裡不僅似乎沒有任何有益的案例,即使有,由於這種行為/能力已被棄用,因此不應該在未來使用,尤其是在新程式碼中,這並不重要/ 項目。