我有一個對 SQL 查詢使用大量字串插值的應用程式。我知道這是一個 SQL 注入威脅,這是客戶和我們都知道的事情,希望我們可以專注于下一次重大重構。我這么說是為了理解{Root Container.property}來自 GUI的東西。
我有這個查詢
IF ({Root Container.UserSelectedProduct}=1)
begin
DECLARE @TestNumbers {Root Container.SQLProductType};
INSERT INTO @TestNumbers SELECT * FROM {Root Container.DBTable};
SELECT *
FROM {Root Container.SQLProductFunction} (@TestNumbers)
WHERE [ID] = {Root Container.Level};
end
else
Select 0
在用戶選擇產品之前,它看起來像這樣
IF (0=1)
BEGIN
DECLARE @TestNumbers myDataType;
INSERT INTO @TestNumbers SELECT * FROM [MySchema].[TheWrongTable];
SELECT * FROM [dbo].[myfunction] (@TestNumbers)
WHERE [ID] = 1;
END
ELSE
SELECT 0
這給了我錯誤:
列名或提供的值數量與表定義不匹配。
我知道為什么會出現此錯誤,我從中選擇的表不是為該資料型別制作的。
但是,為什么它甚至在我嘗試運行第一個 IF 子句時IF (0=1)- 為什么這部分不僅被跳過而SELECT 0僅運行?我原以為這就是它應該如何作業,但我不斷收到有關列名/編號與表定義不匹配的錯誤。當用戶確實選擇了一個產品并且我得到IF (1=1)并且我有適當的表/函式/資料型別時,一切都可以順利進行。我只是不知道為什么它會在 IF(1=0) 之前拋出一個錯誤。為什么會發生這種情況/我如何才能得到我的BEGIN\END第一個 IF 陳述句下的所有內容都不會運行的預期行為,除非運算式為真。
uj5u.com熱心網友回復:
不解釋 T-SQL。無論運行時條件如何,它都必須有意義。事實上,它甚至不做短路。您的代碼無效,并且無法訪問它并不重要 - T-SQL 不會僅僅因為它可以被消除而忽略一段無效代碼,這是錯誤的常見來源(例如在 C 中)在模板中很常見)。
只要確保在沒有選擇產品的情況下您仍然獲得有效的 SQL;如果必須,請使用錯誤的表(或輔助表)。
uj5u.com熱心網友回復:
答案很簡單: SQL 代碼在執行之前完全由服務器編譯,所以這基本上是一個編譯錯誤。這有點像嘗試在 C# 中編譯以下內容
if(someBoolWhichIsFalse)
intValue = "hello";
它根本無效。
運行時代碼甚至還沒有被執行,它仍處于決議和詞法分析階段。沒有任何內容被跳過,它只需要是完全有效的代碼,而不管運行時條件如何。
這發生在每個范圍內,即在每次呼叫程序或臨時批處理時,該代碼必須是可編譯的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/323262.html
標籤:sql sql-server 查询语句 sql-server-2016
