我想填充字符串變量以在TQuery中使用。德爾福 - 字符串中的單引號
如何在字符串變量中獲得單引號。在下面的代碼ShowMessage COMAND顯示COMPNAME正確的,因爲「testcomp隔離」,但在sql_str值‘’testcomp隔離'?
我一直在使用QuotedStr嘗試。
我想填充字符串變量以在TQuery中使用。德爾福 - 字符串中的單引號
如何在字符串變量中獲得單引號。在下面的代碼ShowMessage COMAND顯示COMPNAME正確的,因爲「testcomp隔離」,但在sql_str值‘’testcomp隔離'?
我一直在使用QuotedStr嘗試。
你的代碼已經演示了答案通過單引號加倍逃生在一個Delphi串單引號所以這個字符串具有長度1,而單個字符是一個單引號:
''''
這是由文檔清楚地解釋:http://docwiki.embarcadero.com/RADStudio/en/Fundamental_Syntactic_Elements#Character_Strings
引用字符串中的兩個序列撇號表示單個字符,即撇號。
除了你問的問題之外,我必須向你推薦SQL準備好的查詢和參數。他們將刪除引用需求並避免SQL注入的可怕風險。
你的代碼的工作:
CompName := 'TestComp''; DROP TABLE pg_catalog.pg_students; --';
sql_str := 'SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = ''' + CompName + '''';
ShowMessage(sql_str);
但也許我也建議你避免SQL注入通過QuotedStr
:
sql_str := 'SELECT datname '+#13#10+
'FROM pg_catalog.pg_database'+#13#10+
'WHERE lower(datname) = '+QuotedStr(CompName);
示例使用SQL:
Connection.Execute(sql);
假設爲例e使用參數。我不知道語法:
cmd: TADOCommand;
cmd := TADOCommand.Create;
cmd.Connection := Connection;
cmd.CommandText := 'SELECT datname FROM pg_catalog.pg_database'+#13#10+
'WHERE lower(datname) = %datname%';
cmd.AddParameter('datname', DataType_WVarChar);
cmd.ParamByName('datname').SetString(CompName);
cmd.Execute;
cmd.Free;
避免SQL注入的更好方法是使用參數化查詢,而不是手動創建SQL查詢字符串。 –
@RemyLebeau參數化查詢的一個缺點是,您無法看到組件發出的最終SQL。 –
這裏的方法並不能避免注入 –
你說你嘗試使用QuotedStr()
,但你表現出的代碼不使用它。它應該是這樣的:
CompName := 'TestComp';
sql_str := 'SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = ' + QuotedStr(CompName);
ShowMessage(sql_str);
話雖這麼說,你真的應該使用parameterized query,而不是手動構建SQL語句。例如:
Query1.SQL.Text := 'SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = :Name';
Query1.ParamByName('Name').AsString := 'TestComp';
使用參數化查詢有一些重大的好處:
是防止SQL注入攻擊的更安全,更有效的方式,因爲數據庫引擎驗證和格式危險值您。不要手動做!
參數化查詢允許數據庫引擎安全且一致地格式化SQL語句。這對於諸如日期/時間值之類的東西很重要,可以使用任意數量的特定於DB的本地化格式以字符串格式表示日期/時間值。這還允許您以本地數據格式(整數,斑點等)指定任何參數值,而無需手動將其轉換爲字符串。讓數據庫引擎爲您處理所有格式。
需要多次執行但不需要在執行之間更改的SQL語句,可以通過在服務器端預先準備好一次,然後按原樣執行客戶端隨時需要。每次要執行查詢時,創建新的SQL語句的速度更快,效率更高。這包括參數化查詢。由於參數化查詢的語法不改變,你可以預先做準備,然後根據需要多次使用不同的參數值執行它,例如:
Query1.SQL.Text := 'SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = :Name';
Query1.Prepare;
...
Query1.ParamByName('Name').AsString := 'some value';
Query1.Open;
// use result set as needed...
Query1.Close;
...
Query1.ParamByName('Name').AsString := 'some other value';
Query1.Open;
// use result set as needed...
Query1.Close;
...
Query1.UnPrepare;
一個字:使用參數。不要連接SQL查詢,你很容易受到SQL注入! – whosrdaddy
'ShowMessage'和'sql_str'應該產生相同的字符串(除了在每種情況下你所做的不同的間距外)。花點精力理解你自己的問題,這樣你就可以提出一個有意義的問題。並請發佈一個MCVE。 –