Delphi:如何将列表作为参数传递给SQL查询?

nev*_*ves 13 sql sql-server delphi delphi-7

我有一个整数或字符串列表,需要将它作为Delphi DataSet的参数传递.怎么做?

这是一个例子.MyQuery是这样的:

select * from myTable where intKey in :listParam
Run Code Online (Sandbox Code Playgroud)

我将参数设置为列表或数组或其他:

MyQuery.ParamByName('listParam').AsSomething := [1,2,3];
Run Code Online (Sandbox Code Playgroud)

它会导致此查询发送到sql server:

select * from myTable where intKey in (1, 2, 3)
Run Code Online (Sandbox Code Playgroud)

如果解决方案也可以使用字符串,那么这个查询会更好:

select * from myTable where stringKey in :listParam
Run Code Online (Sandbox Code Playgroud)

成为:

select * from myTable where stringKey in ('a', 'b', 'c')
Run Code Online (Sandbox Code Playgroud)

我相信这是一个简单的问题,但"IN"不是搜索网络的好关键字.

请回答我应该如何配置IDE中的参数,查询以及如何传递参数.

我正在使用Delphi 7.

编辑:我正在考虑答案是" 不可能直接做 ".如果有人给我一个非hackish的答案,接受的答案将被更改.

Arn*_*hez 11

AFAIK,不可能直接.

您必须将列表转换为纯文本的SQL列表.

例如:

function ListToText(const Args: array of string): string; overload;
var i: integer;
begin
  result := '(';
  for i := 0 to high(Args) do 
    result := result+QuotedStr(Args[i])+',';
  result[length(result)] := ')';
end;


function ListToText(const Args: array of integer): string; overload;
var i: integer;
begin
  result := '(';
  for i := 0 to high(Args) do 
    result := result+IntToStr(Args[i])+',';
  result[length(result)] := ')';
end;
Run Code Online (Sandbox Code Playgroud)

要这样使用:

SQL.Text := 'select * from myTable where intKey in '+ListToText([1,2,3]);
SQL.Text := 'select * from myTable where stringKey in '+ListToText(['a','b','c']);
Run Code Online (Sandbox Code Playgroud)

  • @neves上面的两个函数不允许SQL注入攻击,因为第一个将"引用"提供的文本,第二个将从整数创建值.使用现代数据库(至少使用我认识的Oracle),它不会很慢 - 只需确保您在密钥上有适当的索引.在内部,DB将准备SQL语句并将整个"in()"表达式作为其执行计划中的一个参数重用.它是SQL:代码你想要的,而不是你希望DB如何检索它. (3认同)
  • @neves,你从哪里期待SQL注入攻击?从您自己提供的列表? (3认同)

Lar*_*tig 5

SQL 仅接受单个值作为参数,因此您无法创建具有一个可以映射到可变数量值的参数的语句,例如您给出的示例。

但是,在这种情况下您仍然可以使用参数化 SQL。解决方案是迭代您拥有的值列表,向 SQL 添加参数标记,并向每个值的参数列表添加一个参数。

使用位置参数而不是命名参数最容易做到这一点,但也可以适用于命名参数(您可能需要调整此代码,因为我没有可用的 Delphi 并且不记得参数创建语法):

 //AValues is an array of variant values
 //SQLCommand is some TDataSet component with Parameters.
 for I := Low(AValues) to High(AValues) do
 begin

    if ParamString = '' then
       ParamString = '?'
    else
      ParamString = ParamString + ', ?';

    SQLCommand.Parameters.Add(AValues[I]);

  end

  SQLCommand.CommandText = 
     'SELECT * FROM MyTable WHERE KeyValue IN (' + ParamString + ')';
Run Code Online (Sandbox Code Playgroud)

这将产生一个注入安全的参数化查询。