我正在尝试填充要在TQuery中使用的字符串变量。
如何在字符串变量中获得单引号。在下面的代码中,ShowMessage命令将CompName显示为' TestComp"但是sql_str中的值是'' TestComp''?
我尝试过使用QuotedStr。
CompName := 'TestComp';
ShowMessage('SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = ''' + CompName + '''');
sql_str := 'SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = ''' + CompName + '''';
答案 0 :(得分:9)
您说您尝试使用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的本地化格式以字符串格式表示。这还允许您以其本机数据格式(整数,blob等)指定任何参数值,而无需手动将它们转换为字符串。让数据库引擎为您处理所有格式。
需要多次执行但不需要在执行之间更改的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;
答案 1 :(得分:2)
您的代码已经证明了答案。通过将单引号加倍来逃避Delphi字符串中的单引号。所以这个字符串的长度为1,单个字符是单引号:
''''
文档清楚地解释了这一点:http://docwiki.embarcadero.com/RADStudio/en/Fundamental_Syntactic_Elements#Character_Strings
带引号的字符串中的两个连续撇号表示单个字符,即撇号。
除了你问的问题,我必须向你推荐SQL准备好的查询和参数。它们将消除引用的需要并避免SQL注入的可怕风险。
答案 2 :(得分:0)
您的代码有效:
CompName := 'TestComp''; DROP TABLE pg_catalog.pg_students; --';
sql_str := 'SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = ''' + CompName + '''';
ShowMessage(sql_str);
但是我也建议你使用QuotedStr
来避免SQL注入:
sql_str := 'SELECT datname '+#13#10+
'FROM pg_catalog.pg_database'+#13#10+
'WHERE lower(datname) = '+QuotedStr(CompName);
使用SQL的示例:
Connection.Execute(sql);
使用参数的假设示例。我不知道语法:
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;