PLS-00306:调用“ABCINPUT”时参数的数量或类型错误
Posted
技术标签:
【中文标题】PLS-00306:调用“ABCINPUT”时参数的数量或类型错误【英文标题】:PLS-00306: wrong number or types of arguments in call to 'ABCINPUT' 【发布时间】:2020-07-03 08:34:02 【问题描述】:我的PLSQL如下:
CREATE TYPE VARCHARTYPE AS TABLE OF VARCHAR2(5);
CREATE OR REPLACE PACKAGE ABC AS
TYPE VARCHARTYPE IS TABLE OF VARCHAR2(5);
PROCEDURE ABCINPUT (TESTVALUE IN VARCHARTYPE);
END ABC;
/
CREATE OR REPLACE PACKAGE BODY ABC AS
PROCEDURE ABCINPUT (TESTVALUE IN VARCHARTYPE) IS
BEGIN
INSERT INTO CDR.TESTAWS (STNID) VALUES ('AAA');
COMMIT;
END ABCINPUT;
END ABC;
/
我的 C++ 代码如下:
stmt = con->createStatement("begin ABC.ABCINPUT(:1); end;");
std::vector<string> values;
values.push_back("A");
setVector(stmt, 1, values, "VARCHARTYPE");
stmt->executeUpdate();
con->commit();
con->terminateStatement(stmt);
但是运行c++程序时提示如下错误: ORA-06550:第 1 行,第 7 列:
如何解决,谢谢。
【问题讨论】:
请提供minimal reproducible example。什么是setVector
?
setvector是occi的内置函数,详细可以看docs.oracle.com/cd/B28359_01/appdev.111/b28390/…
尽管如此:您的示例仍然不包含 minimal reproducible example。
你为什么要定义两次varchartype,在数据库中又在包中?
该过程使用包内定义的 VARCHARTYPE 定义,而调用代码将引用模式级别定义。他们对精神相同的内容他们的定义是不一样的。搜索 Oracle 范围规则。
【参考方案1】:
我想,我明白你想要达到的目标。首先,在 cmets 中已经提到的一些修正。您在模式级别和包级别声明表类型。根据您的代码,C++ 使用模式级别类型,包中的对象使用包级别类型。即使它们的定义相同,它们也被认为是不同的对象。
现在回到其他调整。从包中删除 TYPE VARCHARTYPE IS TABLE OF VARCHAR2(5);
后,我们将摆脱错误 PLS-00306: wrong number or types of arguments in call to 'ABCINPUT'
。但是我们仍在将常量写入您的测试表,而不是从 C++ 传递下来的值。这可以通过添加INSERT INTO testaws (stnid) SELECT /*+ dynamic_sampling(t 2) */ column_value FROM TABLE(testvalue) t;
来解决,它将表格类型变量转换为表格,我们可以通过从表格中选择插入多个值。
-- Test table
CREATE TABLE testaws (
stnid VARCHAR2(5)
);
-- Schema level type
CREATE OR REPLACE TYPE varchartype AS TABLE OF VARCHAR2(5);
-- Package definition
CREATE OR REPLACE PACKAGE abc AS
PROCEDURE abcinput(testvalue IN varchartype);
END abc;
/
-- Package body
CREATE OR REPLACE PACKAGE BODY abc AS
PROCEDURE abcinput(testvalue IN varchartype) IS
BEGIN
INSERT INTO testaws
(stnid)
SELECT /*+ dynamic_sampling(t 2) */
column_value
FROM TABLE(testvalue) t;
--
COMMIT;
END abcinput;
END abc;
/
-- PL/SQL test
BEGIN
abc.abcinput(varchartype('TEST1','TEST2'));
END;
/
-- Check if it worked
select * from testaws t;
编辑:
根据您在 cmets 中的问题,在包中使用 type 有一些限制,例如不能在 SELECT
中使用 type。因此,我们必须将插入语句更改为FOR
循环或更好的FORALL
批量处理。但这可能需要调整您的 C++ 代码,例如:setVector(stmt, 1, values, "ABC.VARCHARTYPE");
,我不确定这是否适用于 C++。
-- Test table
CREATE TABLE testaws (
stnid VARCHAR2(5)
);
-- Package definition
CREATE OR REPLACE PACKAGE abc AS
TYPE varchartype IS TABLE OF VARCHAR2(5);
--
PROCEDURE abcinput(testvalue IN abc.varchartype);
END abc;
/
-- Package body
CREATE OR REPLACE PACKAGE BODY abc AS
PROCEDURE abcinput(testvalue IN abc.varchartype) IS
BEGIN
FORALL i IN 1 .. testvalue.COUNT
INSERT INTO testaws
(stnid)
VALUES
(testvalue(i));
--
COMMIT;
END abcinput;
END abc;
/
-- PL/SQL test
BEGIN
abc.abcinput(abc.varchartype('TEST1','TEST2'));
END;
/
-- Check if it worked
select * from testaws t;
【讨论】:
以上是关于PLS-00306:调用“ABCINPUT”时参数的数量或类型错误的主要内容,如果未能解决你的问题,请参考以下文章
PLS-00306:调用 oracle 函数时参数的数量或类型错误
PLS-00306:调用过程 PROC_T 时参数的数量或类型错误
PLS-00306: 调用 'SYNCRN' 时参数个数或类型错误