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);
【讨论】:
++1IF EXISTS()...INSERT
通常不是原子的,这意味着可能会在存在检查和插入之间插入冲突记录。
@M_M - Oracle 中的 SQL 语句始终是原子的。如果没有唯一索引,您最终可能会发生冲突,因为插入的另一个会话没有看到该行,因为第一个会话尚未提交。
我不能谈论 Oracle 的行为,但会相信你的话。我知道一些 DBMS 将 IF EXISTS(...) THEN
和 INSERT 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 - 如果不存在则插入的主要内容,如果未能解决你的问题,请参考以下文章