提交函式時的括號與引數
本頁只處理使用者自訂函式:提交之後補到哪一步、兩個開關怎麼分。 INSERT 欄位、EXEC 參數與預留值的挑選見展開內容, 安全寫回見整句展開。
提交函式時補上括號
括號在 T-SQL 裡不是選擇性的:SELECT dbo.fn_DueDate 不是「呼叫但沒傳引數」, 而是一個語法錯誤;沒有參數的函式也一樣要寫 ()。所以提交一個使用者自訂函式時 一併補上一對空括號,游標停在中間(SELECT dbo.dtoc(|))。
這一步不查中繼資料,也就不必等:括號要不要補只跟「被選中的是不是函式」有關。 括號成對寫進去,刻意不只寫左括號讓自動配對接手——那一份有自己的 開關,而且游標右邊還有字時本來就不補,任一不成立時留下的是缺一半的 dbo.dtoc(。
接著要填什麼由兩份提示接手,各管各的名稱。SSMS 的「陳述式完成 → 參數資訊」不會自己 浮出來——它掛在 TYPECHAR 上,而這對括號是提交那一次編輯寫進去的,沒有經過殼層的 命令派送。差的只有那一次派送,所以提交後補送一次 Edit.ParameterInfo (Ssms22/Editor/SqlShellParameterInfo),內建函式那一條 共用它。它一律不理的純量函式由參數提示自己補上,同時請出, 浮得出來的只會有一份。提示中途被收掉之後怎麼請回來見參數提示。
括號裡要不要填預留值
「括號裡填入引數預留值」預設關著,與其他四種展開相反。開著時才依參數型別填值, 游標停在第一個引數上:
SELECT dbo.fn_DueDate(NULL)
FROM dbo.fn_LoansByReader(0, NULL, N'')那四種展開省下來的是使用者本來就要一列一列打出來的東西;這一份只是照型別猜的字面值, 接著每一個都要換掉,而且填進去之後游標旁邊站的是 NULL,參數叫什麼反而看不到—— 空括號把那一格讓給參數資訊。
兩個開關是包含而不是並列:括號都不補就沒有地方放引數。所以開著預留值時照樣先寫 那一對空括號,引數是接著蓋上來的第二次編輯——少了這一步,中繼資料取不到(連不上、 權限不足)時整句只剩 dbo.dtoc,一個把「補上括號」開著的人卻拿到語法錯誤。 判斷只有一份,在 Core/Completion/SqlFunctionCallInsertion;提交那一端問「補不補括號」、 展開那一端問「要不要查參數」問的是同一個答案,各問一次的症狀是兩邊都補。
引數怎麼排
排版與 EXEC 正好相反,因為 T-SQL 對兩者的要求相反:EXEC 收具名傳值, 所以那一支每個參數一列、對齊 @、在右邊註明型別,有預設值的參數還可以整列刪掉; 函式只收位置引數,dbo.fn_DueDate(@days = 1) 不合法,有預設值的參數也不能省略 (省略的寫法是 DEFAULT 這個關鍵字,位置照留)。因此這一支排成一行、只有值, 連參數名稱都寫不進去——而它本來就常常出現在運算式中間,拆成多列會把使用者 正在寫的那句話撐開。型別看不到不是資訊遺失:滑鼠停留提示與浮動預覽本來就列著 整份參數清單,在編輯器裡再寫一次只是讓他多刪一次註解。
預留值與 INSERT/EXEC 共用同一份 Core/Statements/SqlLiteralDefaults: 數值 0、字串 ''/N''、日期 NULL、uniqueidentifier 是 NEWID()。 各寫一份的下場是其中一份給日期填了空字串,而那會安靜地存進 1900-01-01。
要不要補由被選中的東西決定,不由位置決定——括號要不要寫跟前面是 SELECT 還是 FROM 無關。唯一的例外是 ALTER/DROP FUNCTION:那裡是宣告位置, 補上括號會讓那句 DDL 語法錯誤,所以擋的是 CompletionTarget.Function 這個目標。 APPLY 因此必須有自己的目標,否則兩種位置分不開。
參數一個都撈不到、或細節整個取不到(連不上、權限不足)時,留下的就是那對空括號。 這與 INSERT 骨架「欄位撈不到就整個放棄」相反,因為兩者的失敗長得不一樣: 沒有欄位的 INSERT 是一句跑得動卻錯的話,而 () 本來就是沒有參數的函式的正確寫法。
等待期間使用者動過那對括號的話這一次就不補,兩種情形要分開擋:括號裡打了東西 (dbo.fn_DueDate(@d)落在追蹤範圍內,比對開頭的那一關看不出來,蓋上去等於把他 打好的引數刪掉,所以要求那一段仍是一對空括號;右括號後面又打了一個左括號則落在 範圍外(EdgeExclusive),範圍裡的字一個都沒變,只有看下一個字元才看得出來, 補上去的結果會是 dbo.fn_DueDate(NULL)(。
T-SQL 的內建函式不走這條路:它們的左括號寫在建議項自己的插入文字裡 (Core/Keywords/SqlFunctionCatalog),那一份不查資料庫,也不受這個開關影響。 右括號則由自動配對在提交那一次編輯 一起補上——插入文字結尾的左括號與使用者自己打的那一個,條件與結果都相同。