UPDATE语句不在存储过程中工作;没有错误&没有例外

时间:2013-03-28 13:24:27

标签: sql stored-procedures plsql oracle10g sql-update

我在Oracle中创建了一个存储过程。该过程编译成功,没有错误。该过程有3个UPDATE查询,更新3个表'TBLHOTEL','TBLHOTELDETAIL'和& 'TBLHOTELFARE'。

在每个Update语句之后,变量successCnt1递增以获得成功插入查询的数量。最后,successCnt1被分配给successCnt以存储最终结果。如果在任何查询中发生异常,则将其设置为0,表示不发生插入。

问题没有发生异常,也没有更新数据库。

这是我的代码:

架构:

TBLHOTEL架构: {DATE1(DATE),ACROOMS(NUMBER),NACROOMS(NUMBER),HOTELID(VARCHAR2(10))}

TBLHOTELFARE架构: {HOTELID(VARCHAR2(10)),CLASS(VARCHAR2(5)),FARE(NUMBER)}

TBLHOTELDETAIL架构: {HOTELID(VARCHAR2(10)),PLACE(VARCHAR2(15)),HOTELNAME(VARCHAR2(15))}

程序:

CREATE OR REPLACE PROCEDURE TableUpdateByParameter (acrooms   in number,
                                           nacrooms  in number,
                                           date1      in date,
                                           hotelid   in varchar2,
                                           fare in number,
                                           place in varchar2,
                                           hotelname in varchar2,
                                           class in varchar2,
                                           successCnt  out number) IS

successCnt1 number(6) NOT NULL := 0;
rowUpdated1 number(6) NOT NULL := 0;
rowUpdated2 number(6) NOT NULL := 0;
rowUpdated3 number(6) NOT NULL := 0;

BEGIN
  SAVEPOINT before;

  UPDATE tblhotel
     SET acrooms = acrooms, nacrooms = nacrooms
   WHERE date1 = (to_date(date1, 'mm/dd/yyyy'))
     AND hotelid = 'hotelid' ;

rowUpdated1 := SQL%RowCount;
successCnt1 := successCnt1 + 1;

   dbms_output.put_line('Successful Insertion tblhotel. count ='||successCnt1);
   dbms_output.put_line('Successful Insertion tblhotel. Row Updated ='||rowUpdated1);

  UPDATE tblhoteldetail
 SET place = 'place', hotelname = 'hotelname'
   WHERE hotelid = 'hotelid' ;

rowUpdated2 := SQL%RowCount;
successCnt1 := successCnt1 + 1;

dbms_output.put_line('Successful Insertion tblhoteldetail. count ='||successCnt1);
dbms_output.put_line('Successful Insertion tblhoteldetail. Row Updated= '||rowUpdated2);

  UPDATE tblhotelfare
     SET fare = fare
   WHERE hotelid = 'hotelid' 
     AND class = 'class';

rowUpdated3 := SQL%RowCount;
successCnt1 := successCnt1 + 1;
successCnt := successCnt1;

 COMMIT;

 dbms_output.put_line('Successful Insertion tblhotelfare. count ='||successCnt);
dbms_output.put_line('Successful Insertion tblhotelfare. Row Updated= '||rowUpdated3);

EXCEPTION
  WHEN Others THEN
    successCnt1 := 0;
    successCnt := successCnt1;
    dbms_output.put_line('An error has occured. count ='||successCnt);

    ROLLBACK TO before;

END;

致电声明

DECLARE 
 C  number;

BEGIN

   TableUpdateByParameter (140,200,TO_DATE('03/24/2013','MM/DD/YYYY'),'H1',3000,'GANGTOK','TRIPTI','AC',C);
END;

DBMS OUTPUT:

Successful Insertion tblhotel. count =1
Successful Insertion tblhotel. Row Updated =0
Successful Insertion tblhoteldetail. count =2
Successful Insertion tblhotel. Row Updated =0
Successful Insertion tblhotelfare. count =3
Successful Insertion tblhotel. Row Updated =0

请帮我确定问题所在。如果需要额外信息,请告诉我。

3 个答案:

答案 0 :(得分:4)

UPDATE语句 正在运行,但会更新0行,如您的日志所示(Row Updated =0)。这不是错误,您的更新评估where子句,找到0行匹配,并执行0修改。在Oracle中,与where子句中的任何行都不匹配的更新仍然是成功的。

现在为什么会这样。我们来看你的第一次更新:

UPDATE tblhotel
   SET acrooms = acrooms, nacrooms = nacrooms
 WHERE date1 = (to_date(date1, 'mm/dd/yyyy'))
   AND hotelid = 'hotelid' ;

我认为您希望使用作为参数传递的值更新具有列hotelid的行。这有一些问题:

  • 首先,您不是要比较列和参数,而是将列与常量进行比较。参数不使用引号。常量(VARCHAR2)可以。
  • 其次,您不应该调用与列名称相同的参数,这会导致混淆,甚至可能导致variable shadowing。我建议使用一个前缀,在您的架构中没有任何列使用。参数的一个常见前缀是p_
  • 最后,如果您的参数属于良好类型,则不需要转换函数(因为参数p_date1的类型为date,您不需要to_date函数)。

因此,如果您重命名参数p_hotelidp_date1,则您的语句应为:

UPDATE tblhotel
   SET acrooms = acrooms, nacrooms = nacrooms
 WHERE date1 = p_date1
   AND hotelid = p_hotelid;

在这种情况下,不存在混淆或转换错误。


一个不相关的说明:

答案 1 :(得分:1)

如果hotelid是数据库中的列,则几乎可以肯定不要重载该名称以将其用作过程参数的名称。这样做会使得在SQL语句中使用参数相当复杂。大多数人制定某种惯例来区分这两者。我更喜欢使用p_为参数名称添加前缀,这是一种相对常见的约定。

CREATE OR REPLACE PROCEDURE TableUpdateByParameter (p_acrooms   in number,
                                           p_nacrooms  in number,
                                           p_date1      in date,
                                           p_hotelid   in varchar2,
                                           p_fare in number,
                                           p_place in varchar2,
                                           p_hotelname in varchar2,
                                           p_class in varchar2,
                                           p_successCnt  out number) 
IS

您的SQL语句将成为

 WHERE tblhoteldetail.hotelid = p_hotelid

如果您真的想要重载参数名称,则必须在参数名称前加上过程名称。但是,当你无意中编写像

这样的代码时,这通常会让你感到悲伤
 WHERE tblhoteldetail.hotelid = hotelid

并无意中更新了表格中的每一行。

答案 2 :(得分:0)

您的每个where语句与此类似:

AND hotelid = 'hotelid'

这会将表格上的hotelid列与每次字符串文字“hotelid”匹配,而不是传递给proc的值。

要让他们引用参数,您需要使用以下内容:

AND tblhotel.hotelid = TableUpdateByParameter.hotelid

其中左侧是表格上的列,右侧是您的proc参数。

另一种方法是使用命名约定,所有参数都以“p”为前缀,以便您可以使用:

AND tblhotel.hotelid = photelid