2015-10-13 74 views
0

我正在访问的数据库有几个包中的存储过程(几百个)的完整API。我正在研究新的客户端软件与这个数据库进行交互,我需要使用OCI调用这些存储过程。由于我是新手,我决定先从最简单的一个开始。它不工作。运行存储的oracle PL/SQL过程的意外错误

如果我能得到存储过程的实际PL/SQL代码将会很有帮助。该软件包不驻留在我的用户架构中,但我对它有执行权限。当我查询ALL_SOURCE视图时,我得到包声明,但没有包体。我也尝试了dbms_metadata.get_ddl视图,但它只是说“在模式中找不到包的PTAPI”。是否有其他方法从包体获取实际的PL/SQL代码?

这是我正在尝试使用的示例过程的PL/SQL包声明。这个特定的错误消息给出了错误代码和一些依赖于特定错误代码的可选参数。

-- format an error message from ERRMSGS table 
    PROCEDURE formatmessage(
     p_error IN  errmsgs.error%TYPE -- index into ERRMSGS 
    , p_errnum OUT  errmsgs.error%TYPE -- adjusted error number 
    , p_errmsg OUT  errmsgs.MESSAGE%TYPE -- formatted message 
    , p_a  IN  VARCHAR2 DEFAULT NULL 
    , p_b  IN  VARCHAR2 DEFAULT NULL 
    , p_c  IN  VARCHAR2 DEFAULT NULL 
    , p_d  IN  VARCHAR2 DEFAULT NULL 
    , p_e  IN  VARCHAR2 DEFAULT NULL 
    ); -- formatmessage 

我的代码来调用这个程序是低于[声明和ERR是OCI句柄传递给这个函数从上涨]

char errmsg[256]; //buffer to receive the error message 
long errnum; //buffer to receive the adjusted error number 
memset(errmsg,0,256); errnum = 0; //start the message buffer empty 
OCIBind* bind1 = NULL, *bind2 = NULL; //to receive the bind handles 
ub4 curelep1 = 1; //1 errnum element 
ub4 curelep2 = 1; //1 errmsg element 
ub2 alenp1 = sizeof(long); //errnum element size 
ub2 alenp2 = 256; //errmsg element size 
char sql[] = "BEGIN PTAPI.FORMATMESSAGE(193,:P_ERRNUM,:P_ERRMSG, '','','','',''); END;\0" 
OCIStmtPrepare(statement,err,(text*)sql,strlen(sql),OCI_NTV_SYNTAX, OCI_DEFAULT); //parse the SQL statement 
OCIBindByName(statement,&bind1,err,(text*)":P_ERRNUM",-1,&errnum, sizeof(long),SQLT_INT,NULL,&alenp1,NULL,1,&curelep1,OCI_DEFAULT); //bind errnum 
OCIBindByName(statement,&bind2,err,(text*)":P_ERRMSG",-1,errmsg,256, SQLT_STR,NULL,&alenp2,NULL,1,&curelep2,OCI_DEFAULT); //bind errmsg 
if(OCIStmtExecute(svcctx,statement,err,1,0,NULL,NULL,OCI_DEFAULT) != OCI_SUCCESS) //execute the statement 
{ 
    long errcode; 
    char errbuf[512]; 
    OCIErrorGet (err,1,NULL,(sb4*)&errcode,(OraText*)errbuf,512, OCI_HTYPE_ERROR); //check to see what the error was 
    printf("ERROR %d - %s\n",errcode,errbuf); 
    return FAIL; 
} 

语句解析正确和两个结合成功,但我得到执行时出错。我得到的错误是

ERROR 6550 - ORA-06550: line 1, column 7: 
PLS-00306: wrong number or types of arguments in call to 'FORMATMESSAGE' 
ORA-06550: line 1, column 7: 
PLS-00306: wrong number or types of arguments in call to 'FORMATMESSAGE' 
ORA-06550: line 1, column 7: 
PL/SQL: Statement ignored 

我对这个错误感到困惑,因为我模仿一个电话从正常运行旧的客户端软件来此相同的功能。我肯定有正确的数量和类型的论据。任何想法,为什么我会得到这个错误?

---- ---- UPDATE

我发现了更好的示例过程进行测试。这个不是存储在一个包中的,它是一个独立的过程,所以我有完整的PL/SQL代码。我得到了完全相同的错误。这与我如何援引他们有关。感谢您的任何想法。

这一个从数据库中删除某种类型的项目(3个不同表格上的项目)。

这里是PL/SQL

PROCEDURE DELSTL(comp IN 3DCOMPS.COMPID%TYPE, 
      rowcount OUT integer, 
      errorcode OUT number) 
AS 
     tempcount INTEGER; 
BEGIN 
     errorcode := 0; 
     DELETE FROM 3DCOMPS WHERE COMPID = comp; 
     tempcount := sql%rowcount; 
     IF (sql%rowcount < 1) THEN 
      errorcode := 330; 
     END IF; 
     DELETE FROM IDINF WHERE COMPID = comp; 
     IF (sql%rowcount < 1) THEN 
      errorcode := 332; 
     ELSIF (tempcount < sql%rowcount) THEN 
      tempcount := sql%rowcount; 
     END IF; 
     rowcount := tempcount; 
     DELETE FROM ATTLOC WHERE COMPID1 = comp OR COMPID2 = comp; 
END; 

这是我对这个新的测试程序

long errnum; //buffer to receive the error number 
long rowcnt; //buffer to receive the row count 
OCIBind* bind1 = NULL, *bind2 = NULL; //to receive the bind handles 
ub4 curelep1 = 1; //1 errnum element 
ub4 curelep2 = 1; //1 rowcnt element 
ub2 alenp1 = sizeof(long); //errnum element size 
ub2 alenp2 = sizeof(long); //rowcnt element size 
char sql[] = "BEGIN DELSTL('FAKEIDNUM',:P_ROWCNT,:P_ERRNUM); END;\0" 
OCIStmtPrepare(statement,err,(text*)sql,strlen(sql),OCI_NTV_SYNTAX, OCI_DEFAULT); //parse the SQL statement 
OCIBindByName(statement,&bind1,err,(text*)":P_ERRNUM",-1,&errnum, sizeof(long),SQLT_INT,NULL,&alenp1,NULL,1,&curelep1,OCI_DEFAULT); //bind errnum 
OCIBindByName(statement,&bind2,err,(text*)":P_ROWCNT",-1,&rowcnt, sizeof(long),SQLT_INT,NULL,&alenp2,NULL,1,&curelep2,OCI_DEFAULT); //bind rowcnt 
if(OCIStmtExecute(svcctx,statement,err,1,0,NULL,NULL,OCI_DEFAULT) != OCI_SUCCESS) //execute the statement 
{ 
    long errcode; 
    char errbuf[512]; 
    OCIErrorGet (err,1,NULL,(sb4*)&errcode,(OraText*)errbuf,512, OCI_HTYPE_ERROR); //check to see what the error was 
    printf("ERROR %d - %s\n",errcode,errbuf); 
    return FAIL; 
} 

我用“FAKEIDNUM”,因为我显然不希望在实际删除任何东西稍微修改代码这个测试。由于这些表不存在,rowcnt应该为0,当过程结束时,errnum应该是332。

我得到与其他程序完全相同的错误。

ERROR 6550 - ORA-06550: line 1, column 7: 
PLS-00306: wrong number or types of arguments in call to 'DELSTL' 
ORA-06550: line 1, column 7: 
PLS-00306: wrong number or types of arguments in call to 'DELSTL' 
ORA-06550: line 1, column 7: 
PL/SQL: Statement ignored 

这是否给任何人任何想法? 谢谢!

+0

错误表中列的实际数据类型是什么? –

+0

errmsgs.error是NUMBER类型,errmsgs.message是VARCHAR2类型,列宽度为255个字符 – Josh

+0

您确定旧客户端和新客户端连接到相同的数据库和相同的模式 - 您不仅看到不同版本的包比你想象的,也许是一个旧的或新的副本,已被修改?如果您作为与客户相同的用户进行连接并描述该软件包,您会看到什么? (听起来很明显,但不妨排除它......) –

回答

0

我觉得你并不需要指定空参数,你已经有DEFAULT NULL用于此目的

所以可能是这样:

char sql[] = "BEGIN PTAPI.FORMATMESSAGE(193,:P_ERRNUM,:P_ERRMSG); END;\0" 
+0

给它一个镜头,没有变化,还是一样的错误。谢谢你的想法! – Josh

1

我得到它的工作。

问题出在我的绑定调用中。我改变了他们如下;

OCIBindByName(statement,&bind1,err,(text*)":P_ERRNUM",-1,&errnum, sizeof(long),SQLT_INT,NULL,***NULL***,NULL,0,***NULL***,OCI_DEFAULT); //bind errnum 
OCIBindByName(statement,&bind2,err,(text*)":P_ROWCNT",-1,&rowcnt, sizeof(long),SQLT_INT,NULL,***NULL***,NULL,0,***NULL***,OCI_DEFAULT); //bind rowcnt 

改变的参数是curelep,alenp和maxarr_len。这些参数与绑定ARRAYS有关。由于我正在使用的过程采用单个值进/出,因此我已将这些输入配置为数组大小为1的数组。在数组中,具有1个项目的项目数组与单个项目并不相同(在oracle的想法中)。因此,我的参数的数据类型是错误的,因为它是一个整数ARRAY和一个数组ARRAY,第一个是varchar(255)的一个ARRAY。

如果适用,将所有这些参数设置为0或NULL将解决问题。

感谢您的阅读!