Stored procedure to create an invoice table entry

1.8k Views Asked by At

I have to create a stored procedure to create an invoice table entry. The procedure should allow the user to insert a record by providing a new invoice number x and customer id y. The date should be the current system date and the subtotal, tax and total fields should be 0.

I have written this code for this question:

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);

The call raises the error:

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.

What am I doing wrong and could there be a better way to do this possibly?

2

There are 2 best solutions below

0
On BEST ANSWER

Maybe, you are faced with uncontrolled input situation. Your program need to control them by itself. There are 2 way for handling error.

First, you can handle the error by 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;

Second, you can handle the error by yourself. Example, I check "cus_code" in customer table before insert into invoice.

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;

However, Don't forgot to "commit" the transactions.

2
On

You have a foreign key on the INVOICE table column cus_code that references another column in another table (I'm guessing the primary key of the CUSTOMER table or something similar). You have no customer in that table with a customer id of 11111. You either need to add a row with a value of 11111 to the referenced column of the other table before running this procedure.