Хранимая процедура для создания записи таблицы счетов
Я должен создать хранимую процедуру для создания записи таблицы счетов. Процедура должна позволить пользователю вставить запись, указав новый номер счета x и идентификатор клиента 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.
Что я делаю не так, и может ли быть лучший способ сделать это, возможно?
2 ответа
Возможно, вы столкнулись с неконтролируемой ситуацией ввода. Ваша программа должна контролировать их сама. Есть 2 способа обработки ошибок.
Во-первых, вы можете обработать ошибку с помощью исключений.
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;
Тем не менее, не забывайте "совершать" транзакции.
У вас есть внешний ключ в столбце таблицы INVOICE cus_code, который ссылается на другой столбец в другой таблице (я предполагаю первичный ключ таблицы CUSTOMER или что-то подобное). В этой таблице нет ни одного клиента с идентификатором клиента 11111. Перед выполнением этой процедуры необходимо добавить строку со значением 11111 в столбец, указанный в ссылке другой таблицы.