我在用dbExpress调用Oracle的存储过程返回数据集时遇到了奇怪的问题,请各位高手指教。
调试过程与现象如下:
1.建立包:
Create Or Replace Package ChargePKG 
  As
    Type ChargeCursor Is REF Cursor;
End ChargePKG;
2.当存储过程为
Create Or Replace Procedure GetCarSortChargeData(Dep VARCHAR2,
                                                 ClassNO VARCHAR2,
                                                 MorningShiftOnDuty VARCHAR2,
                                                 MorningShiftOffDuty VARCHAR2,
                                                 MiddleShiftOnDuty VARCHAR2,
                                                 MiddleShiftOffDuty VARCHAR2,
                                                 NightShiftOnDuty VARCHAR2,
                                                 NightShiftOffduty VARCHAR2) 
Is
Begin
  Insert Into TempGratisCarTable(CarID,CarTpye,CriterionWeight,WholeWeight) Values(1,2,3,4);
End GetCarSortChargeData;
时,执行“SQLStoredProc1.ExecProc;”正常
3.当存储过程为
Create Or Replace Procedure GetCarSortChargeData(Dep Number,
                                                 ClassNO Number,
                                                 MorningShiftOnDuty VARCHAR2,
                                                 MorningShiftOffDuty VARCHAR2,
                                                 MiddleShiftOnDuty VARCHAR2,
                                                 MiddleShiftOffDuty VARCHAR2,
                                                 NightShiftOnDuty VARCHAR2,
                                                 NightShiftOffduty VARCHAR2) 
Is
Begin
  Insert Into TempGratisCarTable(CarID,CarTpye,CriterionWeight,WholeWeight) Values(1,2,3,4);
End GetCarSortChargeData;
时(即包既具有数字型输入变量,又具有字符串型输入变量),执行“SQLStoredProc1.ExecProc;”时提示“BCD overflow”错误。
4.将存储过程改为
Create Or Replace Procedure GetCarSortChargeData(Dep VARCHAR2,
                                                 ClassNO VARCHAR2,
                                                 MorningShiftOnDuty VARCHAR2,
                                                 MorningShiftOffDuty VARCHAR2,
                                                 MiddleShiftOnDuty VARCHAR2,
                                                 MiddleShiftOffDuty VARCHAR2,
                                                 NightShiftOnDuty VARCHAR2,
                                                 NightShiftOffduty VARCHAR2,
                                                 CarSortChargeCursor Out ChargePKG.ChargeCursor) 
Is
Begin
  Insert Into TempGratisCarTable(CarID,CarTpye,CriterionWeight,WholeWeight) Values(1,2,3,4);
  Open CarSortChargeCursor For Select * From TempGratisCarTable;
End GetCarSortChargeData;
时(即在输入变量均为字符串型变量的基础上,增加了游标型输出变量),执行“SQLStoredProc1.Open;”时提示如下错误
ORA-06550:第1行,第1列;
PLS-00306:调用'GetCarSortChargeData'时参数个数或类型错误
ORA-06550:第1行,第1列;
PLS-00306:调用'GetCarSortChargeData'时参数个数或类型错误
ORA-06550:第1行,第1列;
PL/SQL:Statement ignored.
请大侠门指教是怎么回事?是dbexpress的bug吗?

解决方案 »

  1.   

    http://www.delphibbs.com/keylife/iblog_show.asp?xid=4018
      

  2.   

    ado.net对oracle的支持的确不错,用起来很方便
      

  3.   

    dbexpress沒用過呢,不過問題的提示比較明顯
    “参数个数或类型错误” 
    參數少了?參數類型是否正確,Oracle里面的各個參數和sql相同?我也不大清楚,自己查詢下
      

  4.   

    谢谢各位的关注,我也参考了http://www.delphibbs.com/keylife/iblog_show.asp?xid=4018这个帖子,安装这个帖子的方法,先将存储过程放在包内,提示错误“Accessiolation at address 022C1A09 in module 'dbexpora.dll',write of address 00000000”。后将存储过程放到包外,就出现本帖所述的现象。参数个数和类型应该没有错误的,因为按照步骤1测试正常,再按步骤4增加了游标型输出变量就出错了。另,我在TSQLStoredProc中操作的方法如下:
      SQLStoredProc1.Close;
      SQLStoredProc1.Params.Clear;
      SQLStoredProc1.PackageName:='';
      SQLStoredProc1.StoredProcName:='GETCARSORTCHARGEDATA';
      SQLStoredProc1.Params.CreateParam(ftString,'Dep',ptInput);
      SQLStoredProc1.Params.CreateParam(ftString,'ClassNO',ptInput);
      SQLStoredProc1.Params.CreateParam(ftString,'MorningShiftOnDuty',ptInput);
      SQLStoredProc1.Params.CreateParam(ftString,'MorningShiftOffDuty',ptInput);
      SQLStoredProc1.Params.CreateParam(ftString,'MiddleShiftOnDuty',ptInput);
      SQLStoredProc1.Params.CreateParam(ftString,'MiddleShiftOffDuty',ptInput);
      SQLStoredProc1.Params.CreateParam(ftString,'NightShiftOnDuty',ptInput);
      SQLStoredProc1.Params.CreateParam(ftString,'NightShiftOffduty',ptInput);
      SQLStoredProc1.Params.CreateParam(ftCursor,'CARSORTCHARGECURSOR',ptOutput);
      SQLStoredProc1.ParamByName('Dep').Value:='1';
      SQLStoredProc1.ParamByName('ClassNO').Value:='2';
      SQLStoredProc1.ParamByName('MorningShiftOnDuty').Value:='2008-8-30 8:55:00';
      SQLStoredProc1.ParamByName('MorningShiftOffDuty').Value:='2008-9-29 16:5:00';
      SQLStoredProc1.ParamByName('MiddleShiftOnDuty').Value:='2008-8-30 15:55:00';
      SQLStoredProc1.ParamByName('MiddleShiftOffDuty').Value:='2008-9-30 00:05:00';
      SQLStoredProc1.ParamByName('NightShiftOnDuty').Value:='2008-8-30 23:55:00';
      SQLStoredProc1.ParamByName('NightShiftOffduty').Value:='2008-9-30 9:5:00';
      SQLStoredProc1.Open;
      

  5.   

    据说如果是d7的话需要打一个sp1的补丁
      

  6.   

    d7的话需要打一个sp1的补丁
    这是一定的
      

  7.   

    你应该更新一下这个
    DbExpress升级包http://www.delphifans.com/SoftView/SoftView_55.html
      

  8.   

    感谢hongqi162!我用的数据库是Oracle。有dbExpress for Oracle的升级包或更新版的驱动吗?
      

  9.   

    http://www.delphifans.com/softview/SoftView_53.html
      

  10.   

    感谢hongqi162!这个升级包(Delphi7.1 Update)我安装不了。我的Delphi版本是企业版,安装了“Delphi7企业版 Update 1.1”升级包,还是解决不了问题。
      

  11.   

    Create Or Replace Procedure GetCarSortChargeData(Dep VARCHAR2, 
                                                    ClassNO VARCHAR2, 
                                                    MorningShiftOnDuty VARCHAR2, 
                                                    MorningShiftOffDuty VARCHAR2, 
                                                    MiddleShiftOnDuty VARCHAR2, 
                                                    MiddleShiftOffDuty VARCHAR2, 
                                                    NightShiftOnDuty VARCHAR2, 
                                                    NightShiftOffduty VARCHAR2, 
                                                    CarSortChargeCursor Out ChargePKG.ChargeCursor
    注意这个定义,既然用了包里面的类型,那就必要是在包当中.
      

  12.   

    To unsigned:
    我在包ChargePKG中声明的游标ChargeCursor是公有游标,在包外的存储过程是不是应该可以引用呢?在“http://topic.csdn.net/t/20031014/12/2353495.html”这个帖子就是这么做的。但我不知道为什么JCC0128大侠能成功,我却不能成功。郁闷!
      

  13.   

    其实在我这里也是能够成功的,我这里是Oracle 9i,RAD 2007 + DBExpress 4
      

  14.   

    unsigned大侠,我上面的代码在你的环境能成功吗?我的环境是Oracle 10g+Delphi 7.0,不知在Delphi 7.0下写的代码到RAD 2007下有没有改动。还有我要移植到Kylix 3.0下面的。
      

  15.   

    unsigned大侠,能麻烦你帮我测试一下上面的代码吗?如果行那可能就是DbExpress的Bug了,我也就只能放弃这个方案了。
      

  16.   

    1,2不有测试
    3正常
    4异常:改为下面的代码后,4正常:
    Create Or Replace Package ChargePKG 
      As 
        Type ChargeCursor Is REF Cursor; 
    Procedure GetCarSortChargeData(Dep VARCHAR2, 
                                                    ClassNO VARCHAR2, 
                                                    MorningShiftOnDuty VARCHAR2, 
                                                    MorningShiftOffDuty VARCHAR2, 
                                                    MiddleShiftOnDuty VARCHAR2, 
                                                    MiddleShiftOffDuty VARCHAR2, 
                                                    NightShiftOnDuty VARCHAR2, 
                                                    NightShiftOffduty VARCHAR2, 
                                                    CarSortChargeCursor Out ChargeCursor) ;    
    End ChargePKG; 
    /
    CREATE OR REPLACE PACKAGE BODY ChargePKG AS
    Procedure GetCarSortChargeData(Dep VARCHAR2, 
                                                    ClassNO VARCHAR2, 
                                                    MorningShiftOnDuty VARCHAR2, 
                                                    MorningShiftOffDuty VARCHAR2, 
                                                    MiddleShiftOnDuty VARCHAR2, 
                                                    MiddleShiftOffDuty VARCHAR2, 
                                                    NightShiftOnDuty VARCHAR2, 
                                                    NightShiftOffduty VARCHAR2, 
                                                    CarSortChargeCursor Out ChargeCursor) 
    Is 
    Begin 
      Insert Into TempGratisCarTable(CarID,CarTpye,CriterionWeight,WholeWeight) Values(1,2,3,4); 
      Open CarSortChargeCursor For Select * From TempGratisCarTable; 
      return;
    End GetCarSortChargeData; 
    END ChargePKG;
      

  17.   

    9i你直接使用sys_refcursor就可以不需要自己定义动态游标
      

  18.   

    非常感谢unsigned。我再试试。
      

  19.   

    To unsigned:
    我试过了,还是不行,错误提示是“Access violation at address 05F91A09 in module 'dbexpora.dll',write of address 00000000”。
      

  20.   

    这个可能跟你的DBExpress组件有关系.实际上DBExpress4当中非IDE设计期无法刷出存储过程的参数.翻了一下CodeGear的QC,二月份就有人提出来有问题了,但是一直是Open状态.
      

  21.   

    谢谢unsigned。看来是DBExpress组件的问题了。
      

  22.   

    要不你试一下使用ADOConnection+ADOStoredProc.为存储过程增加参数的时候,忽略掉ref cursor.
      

  23.   

    感谢unsigned:
    恐怕不能用ADOConnection+ADOStoredProc了,我要移植到Kylix下。
      

  24.   

    我的意思是让你试一下看是否是环境存在问题.也可以试一下ODAC
      

  25.   

    18L
    正解!!
    用到Cursor
    就应该在包里进行定义!