如何将值列表作为 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 版本。
- 创建一个table类型
- 创建一个函数,将您的字符串转换为您的 table 类型
在子查询中使用 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;
我有一个 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 版本。
- 创建一个table类型
- 创建一个函数,将您的字符串转换为您的 table 类型
在子查询中使用 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;