【问题标题】:Stored procedure to create an invoice table entry创建发票表条目的存储过程
【发布时间】:2015-11-07 22:03:55
【问题描述】:

我必须创建一个存储过程来创建发票表条目。该过程应允许用户通过提供新的发票编号 x 和客户 ID y 来插入记录。日期应为当前系统日期,小计、税金和总计字段应为 0。

我为这个问题写了这段代码:

SET SERVEROUTPUT ON

CREATE OR REPLACE PROCEDURE InoviceEntry_step1(X in number, Y in number)
as
begin    
  insert into INVOICE(inv_number, cus_code, inv_date,
                      inv_subtotal, inv_tax, inv_total)
  values (X, Y, sysdate, 0, 0, 0);    
end;
/

CALL InoviceEntry_step1 (1009,11111);

调用引发错误:

Error report -
SQL Error: ORA-02291: integrity constraint (USER.SYS_C00109369) violated - parent key not found
ORA-06512: at "USER.INOVICEENTRY_STEP1", line 6
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause:    A foreign key value has no matching primary key value.
*Action:   Delete the foreign key or add a matching primary key.

我做错了什么,有没有更好的方法可以做到这一点?

【问题讨论】:

    标签: sql oracle plsql foreign-keys ora-02291


    【解决方案1】:

    您在 INVOICE 表列 cus_code 上有一个外键,它引用另一个表中的另一个列(我猜是 CUSTOMER 表的主键或类似的东西)。您在该表中没有客户 ID 为 11111 的客户。在运行此过程之前,您需要在另一个表的引用列中添加一个值为 11111 的行。

    【讨论】:

    • 感谢您的回复,所以我猜我必须插入一个连接来引用客户表以获取 cus_code。此外,我正在发票中创建一个新表条目,因此最初不存在客户 ID 11111。
    • 所以你是在为一个不存在的人开具发票?客户需要先存在才能开票;你可能有外键强制执行。
    【解决方案2】:

    也许,您面临着不受控制的输入情况。您的程序需要自行控制它们。有两种处理错误的方法。

    首先,您可以通过Exceptions 处理错误。

    CREATE OR REPLACE PROCEDURE InoviceEntry_step1
       (X in number, Y in number)
    AS
      parent_not_found exception;
      pragma exception_init(parent_not_found, -2291);
    BEGIN
      INSERT INTO INVOICE(inv_number, cus_code, inv_date, inv_subtotal, inv_tax, inv_total)
      VALUES(X, Y, SYSDATE, 0, 0, 0);
      COMMIT;
    EXCEPTION 
      WHEN parent_not_found
        THEN  DBMS_OUTPUT.PUT_LINE('Error: CUSTOMER_ID = ' || Y || ' is not found.');
      WHEN OTHERS
        THEN DBMS_OUTPUT.PUT_LINE('Error');
    END;
    

    其次,您可以自己处理错误。例如,我在插入发票之前检查客户表中的“cus_code”。

    CREATE OR REPLACE PROCEDURE InoviceEntry_step1
       (X in number, Y in number)
    AS
     CURSOR c_customer IS (SELECT ID FROM CUSTOMER WHERE ID = Y AND ROWNUM =1);
     v_ID NUMBER;
    BEGIN
      OPEN c_customer;
      FETCH c_customer INTO v_ID;
      IF c_customer%NOTFOUND
      THEN
         --Option1: If it shouldn't happend with your designed, you can just let error message without insert data.
         DBMS_OUTPUT.PUT_LINE('Error: CUSTOMER_ID = ' || Y || ' is not found.');
         DBMS_OUTPUT.PUT_LINE('Please create customer profile.');
    
         --Option2:  You may add customer_id first and insert invoice, if you want but I don't recommend.  
         INSERT INTO CUSTOMER (ID) VALUES(Y);
         DBMS_OUTPUT.PUT_LINE('CUSTOMER_ID = ' || Y || ' has been created.');
    
         INSERT INTO INVOICE(inv_number, cus_code, inv_date, inv_subtotal, inv_tax, inv_total)
         VALUES(X, Y, SYSDATE, 0, 0, 0);
         DBMS_OUTPUT.PUT_LINE('INVOICE_NO = ' || X || ' has been created.');
      ELSE
         INSERT INTO INVOICE(inv_number, cus_code, inv_date, inv_subtotal, inv_tax, inv_total)
         VALUES(X, Y, SYSDATE, 0, 0, 0);
         DBMS_OUTPUT.PUT_LINE('INVOICE_NO = ' || X || ' has been created.');
      END IF;
      CLOSE c_customer;
      COMMIT;
    END;
    

    但是,不要忘记“提交”交易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多