我想填充字符串变量以在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。 –