#sql #oracle #plsql #sql-insert
#sql #Oracle #plsql #sql-вставка
Вопрос:
У меня есть таблица с этими столбцами (id, first_name, birth). Я хочу создать процедуру, которая вставляет нового клиента, только если вставленный идентификатор не существует в таблице. Если они уже существуют, не вставляйте их. Пока это мой код, но я получил сообщение об ошибке «игнорируется строка 3 sql-инструкции». Есть идеи? Мне нужно использовать procedure и pl sql в oracle. Спасибо!
CREATE OR REPLACE PROCEDURE add_emp(v_id IN int,
v_name IN varchar2,
v_bday IN date) IS
BEGIN
INSERT INTO Employees
(Id, First_name, Birth)
SELECT *
FROM (SELECT v_id, v_name, v_bday) AS tmp
WHERE NOT EXISTS (SELECT Id FROM Employees WHERE Id = v_id);
END;
/
DECLARE
m_id int := 3;
m_name varchar2 := 'John';
m_bday date := '16-Dec-1990';
BEGIN
add_cust(m_id, m_name, m_bday);
END;
/
Комментарии:
1. Если ID является PK или, по крайней мере, УНИКАЛЬНЫМ, вам не нужно сначала проверять его («если он уже существует, тогда не вставляйте его»). Просто выполните вставку. Если идентификатор уже существует, он выдаст исключение, которое вы можете обработать по своему усмотрению.
Ответ №1:
В вашей процедуре есть некоторая проблема с синтаксисом, которая исправлена в следующем коде:
CREATE OR REPLACE PROCEDURE ADD_EMP (
V_ID IN INT,
V_NAME IN VARCHAR2,
V_BDAY IN DATE
) IS
BEGIN
INSERT INTO EMPLOYEES (
ID,
FIRST_NAME,
BIRTH
)
SELECT V_ID,
V_NAME,
V_BDAY
FROM DUAL -- FROM clause was missing
WHERE NOT EXISTS (
SELECT ID
FROM EMPLOYEES
WHERE ID = V_ID
);
END;
/
Кроме того, ваш вызывающий блок PL / SQL имеет некоторые проблемы, которые исправлены в следующем коде:
DECLARE
M_ID INT := 3;
M_NAME VARCHAR2(10) := 'John'; -- varchar2 must be declared with size
M_BDAY DATE := DATE '1990-12-16'; -- added date literal to convert string to date
BEGIN
ADD_CUST(M_ID, M_NAME, M_BDAY);
END;
/
Ответ №2:
В Oracle SELECT не работает без предложения FROM (другие продукты СУБД отличаются). Итак, вам нужно предоставить таблицу; вы можете использовать DUAL, которая является фиктивной таблицей, предоставляемой Oracle, которая гарантированно возвращает одну строку.
INSERT INTO Employees(Id,First_name,Birth)
SELECT v_id, v_name, v_bday
from dual
WHERE NOT EXISTS (
SELECT Id FROM Employees WHERE Id = v_id
);
Ответ №3:
Ваш оператор INSERT будет работать с небольшим изменением
CREATE OR REPLACE PROCEDURE add_emp(v_id Employees.Id%type,
v_name Employees.First_name%type,
v_bday Employees.Birth%type) IS
BEGIN
INSERT INTO Employees
(Id, First_name, Birth)
SELECT v_id, v_name, v_bday
FROM dual
WHERE NOT EXISTS (SELECT * FROM Employees WHERE Id = v_id);
END;
/
Вы можете заменить инструкцию INSERT на MERGE в качестве альтернативного DML, такого как
MERGE INTO Employees e1
USING
(SELECT v_id AS id, v_name AS First_name, v_bday AS birth
FROM dual) e2
ON ( e1.id = e2.id )
WHEN MATCHED THEN UPDATE SET e1.First_name = e2.First_name,
e1.Birth = e2.Birth -- If you need to change for the matching case
WHEN NOT MATCHED THEN INSERT( e1.id, e1.First_name, e1.birth )
VALUES( e2.id, e2.First_name, e2.birth );