sql - 如果不存在则插入

Posted

技术标签:

【中文标题】sql - 如果不存在则插入【英文标题】:sql - insert if not exists 【发布时间】: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

【问题讨论】:

【参考方案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;
    这会将 $key 值插入到 maintoken 表中 仅当 $key 不存在时。 插入新的唯一键后,它将选择并获取新的 ID 值并返回。 如果新键不是唯一的,它将返回现有键的 ID 值。

【讨论】:

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

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

如果结果不存在,则 MS SQL 插入

SQL 查询 - 如果存在则更新,否则插入

如果不存在则插入 Spark SQL 中的其他更新

Postgres:如果不存在则插入

HSQLDB 如果不存在则插入,如果存在则更新