Oracle 插入、选择和不存在

Posted

技术标签:

【中文标题】Oracle 插入、选择和不存在【英文标题】:Oracle INSERT, SELECT and NOT EXISTS 【发布时间】:2021-10-22 20:43:24 【问题描述】:

我有一个程序,它运行良好。有时将相同的 VALUES 传递到过程中并生成唯一的 KEY 违规。

我知道这可以通过使用轻松解决 通常的解决方案 将错误记录到 子句,或使用 /*+ ignore_row_on_dupkey_index ... */

我看到了这个链接,并试图通过查看 VALUES 是否已经在 PRIMARY KEY 中来实施 @OMG Ponies NOT EXISTS 解决方案,但经过数小时的研究和尝试不同的方法我没有成功

Avoid duplicates in INSERT INTO SELECT query in SQL Server

我很好奇如何在我的情况下实施此解决方案。

提前感谢所有回复的人以及您的帮助、耐心和专业知识。

我的工作测试 CASE 在下面(未修改)在下面。顺便说一句,我在实时 SQL 中进行测试,以防有人想使用相同的环境。


ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';

create table schedule(
      seq_num NUMBER  GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
       schedule_id NUMBER(4),
       location_id number(4),
       base_date DATE,
       start_date DATE,
       end_date DATE,
          constraint schedule_pk primary key (schedule_id, location_id, base_date),
         CONSTRAINT start_min check (start_date=trunc(start_date,'MI')),   
       CONSTRAINT end_min check (end_date=trunc(end_date,'MI')),
 CONSTRAINT end_gt_start CHECK (end_date >= start_date)
      );
/


    CREATE TABLE locations AS
    SELECT level AS location_id,
       'Door ' || level AS location_name,

    CASE round(dbms_random.value(1,3)) 
            WHEN 1 THEN 'A' 
            WHEN 2 THEN 'T' 
            WHEN 3 THEN 'G' 
         END AS location_type

    FROM   dual
    CONNECT BY level <= 15;


     ALTER TABLE locations 
         ADD ( CONSTRAINT locations_pk
       PRIMARY KEY (location_id));


CREATE OR REPLACE PROCEDURE CREATE_SCHEDULE
 (
  i_schedule_id IN PLS_INTEGER,
  i_base_date IN DATE,
  i_offset IN PLS_INTEGER DEFAULT 0, 
i_incr IN PLS_INTEGER DEFAULT 10,
  i_duration         IN PLS_INTEGER DEFAULT 5
)
 AS 
 
l_offset  interval day to second;
   l_incr interval day to second;
  l_duration interval day to second;

BEGIN

l_offset :=
NUMTODSINTERVAL(i_offset, 'SECOND') ;

l_incr :=
NUMTODSINTERVAL(i_incr, 'MINUTE') ;

l_duration :=
NUMTODSINTERVAL(i_duration, 'MINUTE') ;

        INSERT INTO schedule(
                schedule_id
              ,location_id
              ,base_date
              ,start_date
              ,end_date
          )
    SELECT   i_schedule_id
    ,        l.location_id
    ,        i_base_date
    ,      i_base_date + l_offset
                  + (l_incr * (ROWNUM - 1)) AS start_date
    ,      i_base_date + l_offset
                  + (l_incr * (ROWNUM - 1))
                + l_duration         AS end_date
    FROM      locations l;
END;
/


EXEC CREATE_SCHEDULE(1,TRUNC(SYSDATE))

【问题讨论】:

【参考方案1】:

使用MERGE 声明:

CREATE OR REPLACE PROCEDURE CREATE_SCHEDULE(
  i_schedule_id IN PLS_INTEGER,
  i_base_date   IN DATE,
  i_offset      IN PLS_INTEGER DEFAULT 0, 
  i_incr        IN PLS_INTEGER DEFAULT 10,
  i_duration    IN PLS_INTEGER DEFAULT 5
)
AS 
  l_offset   interval day to second;
  l_incr     interval day to second;
  l_duration interval day to second;
BEGIN
  l_offset   := NUMTODSINTERVAL(i_offset, 'SECOND') ;
  l_incr     := NUMTODSINTERVAL(i_incr, 'MINUTE') ;
  l_duration := NUMTODSINTERVAL(i_duration, 'MINUTE') ;

  MERGE INTO schedule dst
  USING (
    SELECT   i_schedule_id AS schedule_id,
             l.location_id,
             i_base_date AS base_date,
             i_base_date + l_offset + (l_incr * (ROWNUM - 1))
               AS start_date,
             i_base_date + l_offset + (l_incr * (ROWNUM - 1)) + l_duration
               AS end_date
    FROM     locations l
  ) src
  ON (   src.schedule_id = dst.schedule_id
     AND src.location_id = dst.location_id
     AND src.base_date   = dst.base_date
  )
  WHEN NOT MATCHED THEN
    INSERT (
      schedule_id,
      location_id,
      base_date,
      start_date,
      end_date
    ) VALUES (
      src.schedule_id,
      src.location_id,
      src.base_date,
      src.start_date,
      src.end_date
    );
END;
/

【讨论】:

以上是关于Oracle 插入、选择和不存在的主要内容,如果未能解决你的问题,请参考以下文章

将现有和不存在的数据框混合插入到 sql

oracle表中如果存在就不更新,如果不存在就插入的语句怎么写

Oracle存在则更新,不存在则插入应用-merge

Oracle整合Mybatis实现list数据插入时,存在就更新,不存在就插入以及随机抽取一条记录

如果在过程中不存在 Oracle 插入

由于 DST 时钟向前,perl DateTime 和不存在的时间用户输入