跳转到内容

SQL 方言参考/编写查询/替换查询

来自维基教科书,开放世界中的开放书籍

替换查询

[编辑 | 编辑源代码]

替换查询在没有具有此主键的行时插入新行,或者如果存在则更新现有行。SQL:2003 标准引入了 MERGE 语句来实现此功能,而其他实现提供了名为“REPLACE”的类似查询或所谓的“Upsert”查询(UPDATE 和 INSERT 的混合词)。

标准 MERGE 语句可用于执行替换查询
MERGE INTO table_name1 USING table_name2 ON (condition)
WHEN MATCHED THEN UPDATE SET column1 = value1 [, column2 = value2 ...]
WHEN NOT MATCHED THEN INSERT columns VALUES (values)

请注意,MERGE 的功能远不止执行替换查询。

DB2 MERGE 语句
MERGE INTO phonebook AS p
   USING ( VALUES ('john doe', '1234' ) ) AS v(name, extension)
   ON ( p.name = v.name )
   WHEN MATCHED
      UPDATE SET p.extension = v.extension
   WHEN NOT MATCHED
      INSERT VALUES ( v.name, v.extension )
Firebird MERGE 语句
MERGE INTO phonebook B
USING (
  SELECT name
  FROM phonebook
  WHERE name = 'john doe') E
ON (B.name = E.name)
WHEN MATCHED THEN
  UPDATE SET B.extension = '1234'
WHEN NOT MATCHED THEN
  INSERT (name, extension)
  VALUES ('john doe', '1234);

非标准简化形式

UPDATE OR INSERT INTO phonebook (name, extension)
VALUES ('john doe', '1234')
MATCHING (name)
Ingres ?
Linter ?
MonetDB ?
MSSQL MERGE 语句(从版本SQL Server 2008开始)
DECLARE @UnitMeasureCode nchar(3) = 'ABC'
DECLARE @Name varchar(25) = 'Test name'

MERGE INTO Production.UnitMeasure AS target
    USING (SELECT @UnitMeasureCode, @Name) AS source (UnitMeasureCode, Name)
    ON (target.UnitMeasureCode = source.UnitMeasureCode)
    WHEN MATCHED THEN 
        UPDATE SET Name = source.Name
	WHEN NOT MATCHED THEN	
	    INSERT (UnitMeasureCode, Name)
	    VALUES (source.UnitMeasureCode, source.Name)
MySQL 允许 3 种语法:非标准 REPLACE 查询、(从 4.1 开始)INSERT ... ON DUPLICATE KEY UPDATE 以及 IF EXISTS 的变体。
REPLACE [INTO] table [(columns)] VALUES (values)
INSERT INTO table (columns) VALUES (values) ON DUPLICATE KEY UPDATE column1=value1, column2=value2
IF EXISTS( SELECT * FROM phonebook WHERE name = 'john doe' )
THEN UPDATE phonebook SET extension = '1234' WHERE name = 'john doe'
ELSE INSERT INTO phonebook VALUES( 'john doe','1234' )
END IF
Oracle MERGE 语句
MERGE INTO phonebook B
USING (
  SELECT name_id
  FROM phonebook
  WHERE name = 'john doe') E
ON (B.name = E.name)
WHEN MATCHED THEN
  UPDATE SET B.extension = '1234'
WHEN NOT MATCHED THEN
  INSERT (B.name, B.extension)
  VALUES ('john doe', '1234);
  • 多语句形式
IF EXISTS( SELECT * FROM phonebook WHERE name = 'john doe' )
UPDATE phonebook SET extension = '1234' WHERE name = 'john doe'
ELSE
INSERT INTO phonebook VALUES( 'john doe','1234' )
PostgreSQL 从版本 9.5 开始,INSERT INTO...ON CONFLICT... 语法受 MySQL 启发
INSERT INTO distributors (did, dname)
    VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
    ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;
SQLite REPLACE 语句
REPLACE [INTO] table [(columns)] VALUES (values)

(始终删除旧行)

Virtuoso ?
华夏公益教科书