Процедура для вставки данных, если не существует pl sql

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