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' 时参数个数或类型错误

PLS-00306:调用“ADD_MONTHS”时参数的数量或类型错误

PLS-00306:函数调用中的参数数量或类型错误

ORA-06550:PLS-00306: 调用中的参数数量或类型错误;ORA-06550: