我正在嘗試在使用某些變數的情況下執行以下查詢。下面的 SQL 代碼是存盤程序的一部分。想法是基于FileKey.
DECLARE @TargetColNames nvarchar(max) = '';
DECLARE @SourceColNames nvarchar(max) = '';
DECLARE @SourceColNamesInsert nvarchar(max) = '';
DECLARE @UpdateColumns nvarchar(max) = '';
SELECT
CASE
WHEN @FileKey IN ('s_1','s_2')
THEN @TargetColNames = @TargetColNames ' [CreatedUser], [UpdatedUser], [CreatedDateTime],[UpdatedDateTime],[IsDeleted],[DeletedOn]'
ELSE @TargetColNames = @TargetColNames ' [CreatedUser], [UpdatedUser], [CreatedDateTime], [UpdatedDateTime]'
END,
@SourceColNames = CONCAT('CreatedUser','UpdatedUser','CreatedDateTime', 'UpdatedDateTime'),
@SourceColNamesInsert = CONCAT(''',@User, ''',''',@User, ''', 'Getdate()', 'Getdate()' ),
CASE
WHEN @FileKey IN ('s_1','s_2')
THEN @UpdateColumns = CONCAT('Target.UpdatedUser= ''',@User,''', 'Target.[IsDeleted]=0','Target.[DeletedOn]=null')
ELSE @UpdateColumns = CONCAT('Target.UpdatedUser= ''',@User,''', 'Target.UpdatedDateTime=Getdate()')
END
上面的 SQL 陳述句拋出錯誤:
訊息 102,級別 15,狀態 1,程序 uspDynamicStageToPropLayer1,第 165 行 [批處理開始第 5 行]
'=' 附近的語法不正確。
我在這里想念什么?也許這是一個非常愚蠢的錯誤......
uj5u.com熱心網友回復:
此外,通過對參考的部分進行 concat,您可能允許將 sql 注入到您的查詢中,甚至可以動態構建。如果用戶名(或強制引數有前導單引號,那么垃圾注入如
@User = ';drop table X --
話雖如此,有些東西可以更簡化,例如
SELECT
@TargetColNames = @TargetColNames
' [CreatedUser], [UpdatedUser], [CreatedDateTime], [UpdatedDateTime]'
CASE WHEN @FileKey IN ('s_1','s_2')
THEN ', [IsDeleted], [DeletedOn]'
else ''
end
對于插入,您可能會失敗。如果您查看@User 的可能結果
@SourceColNamesInsert = concat(''',@User, ''',''',@User, ''',
'Getdate()', 'Getdate()' ),
將導致低于我認為的值。注意值之間沒有逗號,因為三重 ' 正在創建開始和結束文字,并且在列插入值之間沒有留下實際的逗號。
',@User, '',@User, 'Getdate()Getdate()
但反而 ...
select concat('''@User'', ''@User''', ', Getdate(), Getdate()' );
這將導致...
'@User', '@User', Getdate(), Getdate()
''' 實際上創建了一個開頭的帶引號的字串,它后面的值,然后 '' (double) 關閉帶引號的字串,但還在下一個 '' (double) 之前添加逗號分隔符以啟動第二個用戶和 '' ' (三重)關閉第二個@User,然后添加逗號和兩個 getdate() 呼叫。
'@User', '@User', Getdate(), Getdate()
現在,如果@User 的值為“Bob”,并且您的意圖是將字串輸出為
'Bob', 'Bob', Getdate(), Getdate()
改為選擇 concat('''', @User, ''', ','''', @User, '''', ', Getdate(), Getdate()' );
''''(四邊形)意味著我想打開一個字串,做一個單引號(通過內部的兩個''),然后將其作為自己的字串關閉。然后獲取@User 的值。然后是一個打開的字串 ' 和 '' 用于關閉名稱周圍的引號,然后打開單引號以開始下一個,逗號在開始第二個用戶的下一個引號之前并通過 '''' 關閉它,然后再次使用用戶的 VALUE,最后用關閉引號 '''' 關閉第二個用戶。最后添加一個逗號和 getdate() 呼叫。是的,參考中愚蠢的棘手。
沒有 CONCAT() 的更簡單的實作只是在每個顯式部分之間使用 ,例如
select '''' @User '''' ', ' '''' @User '''' ', Getdate(), getdate()' ;
其中每個 '''' 是一個單引號,從而導致
' Bob ' , ' Bob ' , Getdate(), getdate()
導致
'Bob', 'Bob', Getdate(), getdate()
我會將最終的 UpdateColumns 留給您確認您的預期輸出。
但是,如前所述,當您動態構建具有嵌入式引數值的 sql 陳述句時,請注意可能的 SQL 注入,因為這似乎正在做。
uj5u.com熱心網友回復:
這是解決此問題的另一種方法:
Declare @FileKey varchar(10) = 's_3'
, @TargetColNames nvarchar(max) = ''
, @SourceColNames nvarchar(max) = ''
, @SourceColNamesInsert nvarchar(max) = ''
, @UpdateColumns nvarchar(max) = '';
Set @TargetColNames = concat_ws(', ', '[CreatedUser]', '[UpdatedUser]', '[CreatedDateTime]', '[UpdatedDateTime]');
If @FileKey In ('s_1', 's_2')
Set @TargetColNames = concat_ws(', ', @TargetColNames, '[UpdatedDateTime]', '[IsDeleted]', '[DeletedOn]');
Print @TargetColNames;
Set @SourceColNames = concat_ws(', ', '[CreatedUser]', '[UpdatedUser]', '[CreatedDateTime]', '[UpdatedDateTime]');
Set @SourceColNamesInsert = concat_ws(', ', quotename('@User', char(39)), quotename('Getdate()', char(39)), quotename('Getdate()', char(39)));
Print @SourceColNames;
Print @SourceColNamesInsert;
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/475226.html
