【问题标题】:sql - insert if not existssql - 如果不存在则插入
【发布时间】:2011-11-18 16:01:40
【问题描述】:

我在使用 sql 查询时遇到问题。如果同一行不存在,我需要插入一行。这是我目前所拥有的:

DECLARE
BEGIN
   FOR FOLDER_ROW IN (SELECT FOLDERID, USERID FROM DATA1.FOLDERS)
      LOOP                       
          IF NOT EXISTS (SELECT * FROM DATA1.FOLDER_USER WHERE FOLDER_ID = FOLDER_ROW.FOLDERID AND USER_ID = FOLDER_ROW.USERID) 
          INSERT INTO DATA1.FOLDER_USER (FOLDER_ID, USER_ID) VALUES (FOLDER_ROW.FOLDERID, FOLDER_ROW.USERID);
     END LOOP;
    COMMIT;
END;

我对 sql 不是很熟悉,尤其是 not exists 语法,所以当我执行时出现以下错误:

ORA-06550:第 37 行,第 11 列:PLS-00103:遇到符号 “INSERT”当期望以下之一时:

然后和或

符号“then”被替换为“INSERT”以继续。

ORA-06550: line 38, column 10:
PLS-00103: Encountered the symbol "LOOP" when expecting one of the following:

   if
ORA-06550: line 40, column 5:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:

   end not pragma final instantiable order overriding static
   member constructor map

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    全部在 SQL 中完成,而不是将上下文切换到 PL/SQL:

    INSERT INTO DATA1.FOLDERS
    (folder_id,
     user_id)
    SELECT f1.folder_id,
           f1.user_id
      FROM DATA1.FOLDERS f1
     WHERE NOT EXISTS (SELECT 1
                         FROM DATA1.FOLDERS f2
                        WHERE f1.folder_id = f2.folder_id
                          AND f1.user_id = f2.user_id);
    

    【讨论】:

    • ++1 IF EXISTS()...INSERT 通常不是原子的,这意味着可能会在存在检查和插入之间插入冲突记录。
    • @M_M - Oracle 中的 SQL 语句始终是原子的。如果没有唯一索引,您最终可能会发生冲突,因为插入的另一个会话没有看到该行,因为第一个会话尚未提交。
    • 我不能谈论 Oracle 的行为,但会相信你的话。我知道一些 DBMS 将 IF EXISTS(...) THENINSERT INTO 视为两条语句,而不是一条,但这也取决于事务隔离级别等。
    【解决方案2】:

    更好的(Oracle 特定?)解决方案可能是 MERGE 语句。

    请参阅此处以获得很好的解释,并附有示例:

    http://www.oracle-base.com/articles/10g/MergeEnhancements10g.php

    希望对您有所帮助。

    【讨论】:

    • MERGE 不是 Oracle 特定的。它实际上是SQL:2008 的一部分。例如,DB2(至少从 v9 开始用于 z/OS,9.5 用于 LUW)和SQL Server,从 2008 年开始。
    • 感谢 galador,我几乎完全是 Oracle 人,所以我不确定 MERGE 是 SQL 标准还是 Oracle 扩展。感谢您的澄清。
    【解决方案3】:

    你忘记了THEN

    IF condition THEN  
       ...
    ELSE
        ...
    END IF;
    

    【讨论】:

      【解决方案4】:
      DECLARE
          N_COUNTS NUMBER;
      BEGIN
          select count(ID) into N_COUNTS from TABLE_NAME where ID = 1;
          IF N_COUNTS=0 THEN
              INSERT QUERY....
          ELSE
              UPDATE QUERY....
          END IF;
      END;
      

      【讨论】:

        【解决方案5】:

        Sqlite 需要类似的东西

        我需要插入一个 sqlite 数据库,但前提是密钥不存在。

        id 是自动递增的主键。
        key 是唯一的字符串。

        主令牌表

        id |  key   |   created    | active
         1 | test   |   2022-01-07 |  1
         2 | 2ndOne |   2021-12-19 |  1
        

        最后,如果项目已经存在,那么我想要那个 id,但如果它是刚刚插入的,那么我想要那个新 id。

        有效的查询——基于答案

        insert into maintoken (key)  
              select $key 
               where not exists 
               (select key from maintoken where key=$key);
               select id from maintoken where key=$key and active=1;
        
        1. 这会将 $key 值插入到 maintoken 表中 仅当 $key 不存在时。
        2. 插入新的唯一键后,它将选择并获取新的 ID 值并返回。
        3. 如果新键不是唯一的,它将返回现有键的 ID 值。

        【讨论】:

          猜你喜欢
          • 2018-09-17
          • 2021-02-19
          • 1970-01-01
          • 1970-01-01
          • 2011-09-01
          • 1970-01-01
          • 2023-03-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多