Informix:如何将单个参数中的多个值传递、使用和执行到存储过程
Posted
技术标签:
【中文标题】Informix:如何将单个参数中的多个值传递、使用和执行到存储过程【英文标题】:Informix: How to pass, use and execute multiple values in a single parameter to a stored procedure 【发布时间】:2012-05-30 23:00:40 【问题描述】:如何将单个参数中的多个值传递给 Informix 中的存储过程?。
这是一个常见的问题,但我没有看到关于 informix 的任何信息。
我找到了post,但它对我不起作用,应该是数据库的版本还是我遗漏了什么?
我正在尝试执行WHERE X IN (SELECT Y FROM TABLE(PARAM))
编辑:
这是我尝试做的一个例子。
CREATE PROCEDURE test_hector
(
C LIST( SET (CHAR(10) NOT NULL ) NOT NULL)
)
RETURNING CHAR(10) AS C, CHAR(10) AS CVE, CHAR(50) AS DESC;
DEFINE vColumna like tclaves.columna;
DEFINE vClave like tclaves.clave;
DEFINE vdescve like tclaves.descve;
FOREACH
select columna, clave, descve
INTO vColumna, vClave,vdescve
from tclaves
where columna in (SELECT * FROM TABLE(C))
RETURN vColumna, vClave,vdescve WITH RESUME;
END FOREACH
END PROCEDURE;
我正在尝试执行它,但我认为我遇到了 sintax 问题
EXECUTE PROCEDURE test_hector( 'stspols,stsrepo');
我收到错误消息[Informix][Informix ODBC Driver][Informix]Invalid collection literal value.
我执行了这个函数execute function se_release()
来获取informix版本,这就是我得到的。
column1
Spatial DataBlade Release 8.21.FC4R1 (Build 238) Compiled on Thu Aug 26 19:42:55 CDT 2010 with: IBM Informix Dynamic Server Version 10.00.FC7 glslib-4.00.UC10
我正在使用Aqua Data Studio 8.0.22
来创建和执行该过程。在Windows 7 Ultimate 32-Bits
上运行
提前致谢。任何帮助
【问题讨论】:
相同的解决方案***.com/questions/11038298/… 【参考方案1】:将参数类型定义为适当的集合类型:LIST、SET、MULTISET(这是我在交叉引用问题的答案中所说的)。
什么不适合你? 您尝试了什么? 您收到的错误消息是什么? 您使用的是哪个版本的 Informix 服务器? 您使用哪个工具或 API 创建存储过程? 您使用哪个工具或 API 来执行存储过程? 您在哪个平台上运行? 您如何调用该过程?感谢您详细说明问题。你说:
EXECUTE PROCEDURE test_hector('stspols,stsrepo');
我收到错误消息
[Informix][Informix ODBC Driver][Informix]Invalid collection literal value.
这可能比表面上看起来更容易解决。该过程的输入类型应该是一个集合——实际上是一个 SET 值的列表——其中每个值都是一个字符串。你可以这样写:
EXECUTE PROCEDURE test_hector(LISTSET'stspols','stsrepo');
我自己创建了一个虚拟程序来测试这个语法:
CREATE PROCEDURE test_hector(c LIST(SET (CHAR(10) NOT NULL ) NOT NULL))
RETURNING CHAR(10) AS C, CHAR(10) AS CVE, CHAR(50) AS DESC;
return "abc", "def", "ghi";
END PROCEDURE;
它的输出和预期的一样:
abc def ghi
请注意,Informix 支持以 开头并以
结尾的注释样式。但是,当
之前的关键字是 SET、MULTISET 或 LIST 之一时,该注释样式会被抑制(是的,这确实使它很难解析!)。您可以通过“在上面的 SQL 中在哪里添加
”来获得巨大(如果变态)的乐趣,而不会改变其含义。 API 有可能识别 Informix
cmets 但无法识别集合异常。在这种情况下,您可能会得到一个语法错误(因为如果您将第一个
解释为开始注释符号,则不需要第二个
)。在这种情况下,请使用以下符号之一。
集合(SET、MULTISET、LIST)文字的表示法随着时间的推移而演变。这种替代符号也有效(并且与您最初尝试的内容更密切相关,并且是最初记录的内容):
EXECUTE PROCEDURE test_hector('LISTSET''stspols'',''stsrepo''');
SET 中的字符串必须用引号括起来,但整个文字本身就是一个字符串,因此您需要将嵌入的引号加倍。您也可以“作弊”并使用双引号和单引号:
EXECUTE PROCEDURE test_hector('LISTSET"stspols","stsrepo"');
EXECUTE PROCEDURE test_hector("LISTSET'stspols','stsrepo'");
从下面的讨论以及替代答案中所述,问题现在似乎与嵌套集合有关。 LISTSET"str1", "str2"
是一个有序列表(其中有一个条目);该条目本身就是一组(不同的)字符串,没有特定的顺序。如果您需要能够重复字符串(但顺序并不重要),您将使用 MULTISET。使用 LIST 很重要,顺序很重要(列表中允许重复)。
听起来你真的只需要选择参数类型,这样它就更简单了。您应该能够有效地使用任何一种集合类型;我可能会提名 SET 以便您不必处理列表中的重复字符串,但 MULTISET 或 LIST 也是有效的选项。将程序重命名为test_3()
:
CREATE PROCEDURE test_3(c SET(CHAR(10) NOT NULL))
RETURNING CHAR(10) AS r;
DEFINE r CHAR(10);
FOREACH SELECT * INTO r FROM TABLE(c)
RETURN r WITH RESUME;
END FOREACH;
END PROCEDURE;
我能够执行以下两个语句,并显示结果:
+ EXECUTE PROCEDURE test_3(SET'stspols','stsrepo');
stspols
stsrepo
+ EXECUTE PROCEDURE test_3('SET''stspols'',''stsrepo''');
stspols
stsrepo
这是使用 ESQL/C 接口。您应该能够获得第二个使用 ODBC;第一个可能会导致 -201 语法错误。
如果您更喜欢 LIST 而不是 SET,则在上面的代码中将 SET 更改为 LIST:
+ CREATE PROCEDURE test_3(c LIST(CHAR(10) NOT NULL))
RETURNING CHAR(10) AS r;
DEFINE r CHAR(10);
FOREACH SELECT * INTO r FROM TABLE(c)
RETURN r WITH RESUME;
END FOREACH;
END PROCEDURE;
+ EXECUTE PROCEDURE test_3(LIST'stspols','stsrepo');
stspols
stsrepo
+ EXECUTE PROCEDURE test_3('LIST''stspols'',''stsrepo''');
stspols
stsrepo
【讨论】:
我编辑了我的问题来回答你的问题。提前感谢您的帮助! 这样写EXECUTE PROCEDURE test_hector(LISTSET'stspols','stsrepo');
抛出 [Informix][Informix ODBC Driver][Informix]A syntax error has occurred.
。像这样写EXECUTE PROCEDURE test_hector('LISTSET''stspols'',''stsrepo''');
throws ` [Informix][Informix ODBC Driver][Informix]尚未实现。 sqlerrm(=any, !=any, =all, or !=all for Collections) ` 'EXECUTE PROCEDURE test_hector('LISTSET"stspols","stsrepo"');'抛出[Informix][Informix ODBC Driver][Informix]Not implemented yet. sqlerrm(=any, !=any, =all, or !=all for Collections)
:(
+1 顺便说一句以获得完整的解释。几乎可以工作,我认为我们缺少一些东西
我怀疑第一次失败是由于 ODBC 驱动程序错误解析 SQL 并试图将
视为注释的开始。第二次失败看起来语法通过了,但是处理它时出了点问题。在这个阶段,我不确定这是 ODBC 问题还是服务器问题。我怀疑我需要为您的存储过程升级我的代理,以便它尝试从字符串集列表中访问数据,看看会发生什么。你试过我的超简单程序吗?它是否引发错误?
你的工作就像一个魅力!,也许问题出在where columna in (SELECT * FROM TABLE(C))
,再次感谢您的宝贵帮助!【参考方案2】:
我以不同的方式尝试了它并找到了解决方案。
我修改了过程以接受一个参数,就像List
,而不是ListSET...
CREATE PROCEDURE test_hector
(
C LIST( CHAR(10) NOT NULL )
)
RETURNING CHAR(10) AS C, CHAR(10) AS CVE, CHAR(50) AS DESC;
DEFINE vColumna like tclaves.columna;
DEFINE vClave like tclaves.clave;
DEFINE vdescve like tclaves.descve;
FOREACH
select columna, clave, descve
INTO vColumna, vClave,vdescve
from tclaves
where columna in (SELECT * FROM TABLE(C))
RETURN vColumna, vClave,vdescve WITH RESUME;
END FOREACH
END PROCEDURE;
并像这样执行它。
EXECUTE PROCEDURE test_hector('LIST''stspols'',''stsrepo''');
或者这样
EXECUTE PROCEDURE test_hector3('LIST"stspols","stsrepo"');
它就像一个魅力。
【讨论】:
以上是关于Informix:如何将单个参数中的多个值传递、使用和执行到存储过程的主要内容,如果未能解决你的问题,请参考以下文章