我想像这样使用查询参数:
SELECT * FROM MATABLE
WHERE MT_ID IN (368134, 181956)
所以我想到了这个
SELECT * FROM MATABLE
WHERE MT_ID IN (:MYPARAM)
但它不起作用......
有办法做到这一点吗?
我实际上使用的是IBX和Firebird 2.1
我不知道IN子句中有多少参数。
答案 0 :(得分:9)
对谁还有兴趣。我使用另一个受此帖子启发的存储过程在Firebird 2.5中完成了它。
How to split comma separated string inside stored procedure?
CREATE OR ALTER PROCEDURE SPLIT_STRING (
ainput varchar(8192))
RETURNS (
result varchar(255))
AS
DECLARE variable lastpos integer;
DECLARE variable nextpos integer;
DECLARE variable tempstr varchar(8192);
BEGIN
AINPUT = :AINPUT || ',';
LASTPOS = 1;
NEXTPOS = position(',', :AINPUT, LASTPOS);
WHILE (:NEXTPOS > 1) do
BEGIN
TEMPSTR = substring(:AINPUT from :LASTPOS for :NEXTPOS - :LASTPOS);
RESULT = :TEMPSTR;
LASTPOS = :NEXTPOS + 1;
NEXTPOS = position(',', :AINPUT, LASTPOS);
suspend;
END
END
当您将SP传递给以下列表时
CommaSeperatedList = 1,2,3,4
并致电
SELECT * FROM SPLIT_STRING(:CommaSeperatedList)
结果将是:
RESULT
1
2
3
4
可以使用如下:
SELECT * FROM MyTable where MyKeyField in ( SELECT * FROM SPLIT_STRING(:CommaSeperatedList) )
答案 1 :(得分:5)
我最终在Firebird中使用全局临时表,首先插入参数值并检索结果我使用常规JOIN
而不是WHERE ... IN
子句。临时表是特定于事务的,并在提交时清除(ON COMMIT DELETE ROWS
)。
答案 2 :(得分:4)
也许你应该这样做:
SELECT * FROM MATABLE
WHERE MT_ID IN (:MYPARAM1 , :MYPARAM2)
答案 3 :(得分:3)
我不认为这是可以做到的。是否有任何特殊原因导致您不想自己构建查询?
我曾经多次使用过这种方法,但它并没有使用参数。它使用stringlist和它的属性DelimitedText。您创建一个IDList并使用您的ID填充它。
Query.SQL.Add(Format('MT_ID IN (%s)', [IDList.DelimitedText]));
答案 4 :(得分:3)
您可能还有兴趣阅读以下内容:
http://www.sommarskog.se/dynamic_sql.html
和
http://www.sommarskog.se/arrays-in-sql-2005.html
使用'in'子句和所有排序来覆盖动态sql。非常有趣。
答案 5 :(得分:2)
参数是单个值的占位符,这意味着接受以逗号分隔的值列表的IN子句不能与参数一起使用。
这样想:无论我在哪里放置一个值,我都可以使用参数。
所以,在一个如下的子句中:IN(:param)
我可以将变量绑定到一个值,但只能绑定1个值,例如:IN(4)
现在,如果您考虑“IN子句值表达式”,则会得到一串值:IN(1,4,6) - >这是他们之间逗号的3个值。这是SQL字符串的一部分,不是值的一部分,这就是它不能被参数绑定的原因。
显然,这不是你想要的,但它是唯一可能带参数的东西。
答案 6 :(得分:1)
Yurish的回答是三分之二的解决方案:
但是如果你想拥有任意数量的元素,有时根本没有元素,那么你可以动态生成SLQ语句。使用格式有帮助。
答案 7 :(得分:1)
SELECT * FROM MATABLE 在MT_ID IN(:MYPARAM)中,而不是将MYPARAM与:一起使用,请使用参数名称。
喜欢 SELECT * FROM MATABLE WHERE MT_ID IN(SELECT REGEXP_SUBSTR(** MYPARAM ,'[^,] +',1,LEVEL) 来自双重 通过REGEXP_SUBSTR连接( MYPARAM ,'[^,] +',1,LEVEL)IS NOT NULL))**
MYPARAM-'368134,181956'
答案 8 :(得分:0)
如果您使用的是Oracle,那么您一定要查看Tom Kyte关于此主题的博文(link)。
在Kyte先生的带领下,这是一个例子:
SELECT *
FROM MATABLE
WHERE MT_ID IN
(SELECT TRIM(substr(text, instr(text, sep, 1, LEVEL) + 1,
instr(text, sep, 1, LEVEL + 1) -
instr(text, sep, 1, LEVEL) - 1)) AS token
FROM (SELECT sep, sep || :myparam || sep AS text
FROM (SELECT ',' AS sep
FROM dual))
CONNECT BY LEVEL <= length(text) - length(REPLACE(text, sep, '')) - 1)
在您的情况下,您可以将:MYPARAM
绑定到'368134,181956'
。
答案 9 :(得分:0)
这是我过去用来解决'IN'语句问题的一种技巧。它根据参数(唯一)指定的值的数量构建一个“OR”列表。然后,我所要做的就是按照它们出现在提供的值列表中的顺序添加参数。
var
FilterValues: TStringList;
i: Integer;
FilterList: String;
Values: String;
FieldName: String;
begin
Query.SQL.Text := 'SELECT * FROM table WHERE '; // set base sql
FieldName := 'some_id'; // field to filter on
Values := '1,4,97'; // list of supplied values in delimited format
FilterList := '';
FilterValues := TStringList.Create; // will get the supplied values so we can loop
try
FilterValues.CommaText := Values;
for i := 0 to FilterValues.Count - 1 do
begin
if FilterList = '' then
FilterList := Format('%s=:param%u', [FieldName, i]) // build the filter list
else
FilterList := Format('%s OR %s=:param%u', [FilterList, FieldName, i]); // and an OR
end;
Query.SQL.Text := Query.SQL.Text + FilterList; // append the OR list to the base sql
// ShowMessage(FilterList); // see what the list looks like.
if Query.ParamCount <> FilterValues.Count then
raise Exception.Create('Param count and Value count differs.'); // check to make sure the supplied values have parameters built for them
for i := 0 to FilterValues.Count - 1 do
begin
Query.Params[i].Value := FilterValues[i]; // now add the values
end;
Query.Open;
finally
FilterValues.Free;
end;
希望这有帮助。
答案 10 :(得分:0)
使用反向SQL LIKE
条件有一个技巧。
您将列表作为字符串(VARCHAR
)参数传递,例如'~12~23~46~567~'
然后你有像查询
where ... :List_Param LIKE ('%~' || CAST( NumField AS VARCHAR(20)) || '~%')
答案 11 :(得分:0)
CREATE PROCEDURE TRY_LIST (PARAM_LIST VARCHAR(255)) RETURNS (FIELD1....)
AS
BEGIN
/* Check if :PARAM_LIST begins with colon "," and ands with colon ","
the list should look like this --> eg. **",1,3,4,66,778,33,"**
if the format of list is right then GO if not just add then colons
*/
IF (NOT SUBSTRING(:PARAM_LIST FROM 1 FOR 1)=',') THEN PARAM_LIST=','||PARAM_LIST;
IF (NOT SUBSTRING(:PARAM_LIST FROM CHAR_LENGTH(:PARAM_LIST) FOR 1)=',') THEN PARAM_LIST=PARAM_LIST||',';
/* Now you are shure thet :PARAM_LIST format is correct */
/ * NOW ! */
FOR SELECT * FROM MY_TABLE WHERE POSITION(','||MY_FIELD||',' in :PARAM_LIST)>0
INTO :FIELD1, :FIELD2 etc... DO
BEGIN
SUSPEND;
END
END
How to use it.
SELECT * FROM TRY_LIST('3,4,544,87,66,23')
or SELECT * FROM TRY_LIST(',3,4,544,87,66,23,')
if the list have to be longer then 255 characters then just change the part of header f.eg. like PARAM_LIST VARCHAR(4000)