如何将值列表作为 TOraQuery 的参数传递?

How can I pass a list of values as a parameter for a TOraQuery?

我有一个 TOraQuery SQL 定义了这样的东西

SELECT ML.ID, Ml.detail1, Ml.detail2
FROM MY_LIST ML 
WHERE 
    ML.ID in (:My_IDS)

如果我要即时构建这个查询,我自然会得到这样的结果:

SELECT ML.ID, Ml.detail1, Ml.detail2
FROM MY_LIST ML 
WHERE 
    ML.ID in (14001,14002,14003)

不过,我想传入14001,14002,14003作为参数。

  myListQuery.Active := False;
  myListQuery.ParamByName('My_IDS').AsString := '14001,14002,14003';
  myListQuery.Active := True;

但当然会生成 ORA-01722: invalid number。除了即时构建查询之外,我还有其他选择吗?

据我所知,直接是不可能的。

您必须将列表转换为 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;

这样使用:

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

或者你的情况:

myListQuery.SQL.Text := 'SELECT ML.ID, Ml.detail1, Ml.detail);
myListQuery.SQL.Add('FROM MY_LIST ML ');
myListQuery.SQL.Add('WHERE ');
myListQuery.SQL.Add('ML.ID in ') +  ListToText([14001,14002,14003]);

您可以做到,但需要一些额外的设置。希望这适用于您的 Oracle 版本。

  1. 创建一个table类型
  2. 创建一个函数,将您的字符串转换为您的 table 类型
  3. 在子查询中使用 CAST。使用与代码中相同的东西(即 ParamByName('').AsString)将您的值传递给绑定变量。

    create or replace type myTableType as table of varchar2 (255);
    
    create or replace function in_list( p_string in varchar2 ) return myTableType as 
        l_string        long default p_string || ',';
        l_data          myTableType := myTableType();
        n               number;
    begin
      loop
          exit when l_string is null;
          n := instr( l_string, ',' );
          l_data.extend;
          l_data(l_data.count) := 
                 ltrim( rtrim( substr( l_string, 1, n-1 ) ) );
          l_string := substr( l_string, n+1 );
      end loop;
    
    return l_data;
    end;
    
    select * from THE ( select cast( in_list(:MY_BIND_VARIABLE) as mytableType ) from dual ) a
    

如果这对您有用,答案和示例代码归功于运行 asktom.com 的 Oracle 的 Tom Kyte。 https://asktom.oracle.com/pls/asktom/f?p=100:11:0%3a%3a%3a%3aP11_QUESTION_ID:210612357425

您可以使用 "Macro"

不是我想要的,但它比动态构建 SQL 更接近参数。

像这样创建 TOraQuery

SELECT ML.ID, Ml.detail1, Ml.detail2
FROM MY_LIST ML 
WHERE 
    ML.ID in (&My_IDS)

现在我可以将 14001,14002,14003 作为宏传入。

myListQuery.Active := False;
myListQuery.MacroByName('My_IDS').value := '14001,14002,14003';
myListQuery.Active := True;