如果不存在则插入数据的过程pl sql

Posted

技术标签:

【中文标题】如果不存在则插入数据的过程pl sql【英文标题】:Procedure to insert data if not exist pl sql 【发布时间】:2020-12-04 10:49:34 【问题描述】:

我有一个包含这些列(id、first_name、birth)的表。我想创建一个仅在表中不存在插入的 id 时才插入新客户的过程。如果它已经存在,则不要插入它。到目前为止,这是我的代码,但出现错误“忽略第 3 行 sql 语句”。任何的想法?我需要在 oracle 中使用过程和 pl sql。谢谢!

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

【问题讨论】:

如果 ID 是一个 PK,或者至少是 UNIQUE,那么您不需要先检查它(“如果已经存在,则不要插入它”)。只做插入。如果 ID 已经存在,它将抛出一个异常,您可以根据需要处理该异常。 【参考方案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】:

在没有 FROM 子句的情况下,Oracle SELECT 不起作用(其他 DBMS 产品不同)。所以你需要提供一张桌子;你可以使用 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 );

【讨论】:

以上是关于如果不存在则插入数据的过程pl sql的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL 错误问题

使用 PL/SQL 在触发器中中止插入/更新操作

MSSQL更新数据,某主键存在则更新,不存在则插入

Mysql插入数据:不存在则插入,存在则跳过或更新

Oracle PL/SQL - 由其他团队调用的用于插入数据的过程。正在从 Java 调用过程

数据库:如果存在则“更新”如果不存在则插入 [重复]