chenkehao 发表于 2016-11-7 04:27:02

Merge Sql

  我们经常遇到的一个需求是,先判断数据是否存在,如果存在则更新,否则就插入,以前比较土是用java自己做了。这个在多线程或者多机的情况下就会有些问题,有时候还得让db报个唯一性约束才行。
  
  最近和一个同事(以前是oracle的)做项目,发现他写了个牛逼的sql(或者说自己见识太短浅了),特此膜拜下
  
  类似这样的
  

MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHEREb.status != 'VALID'
WHEN NOT MATCHED THEN
INSERT (object_id, status)
VALUES (b.object_id, b.status)
WHEREb.status != 'VALID';

   查了些资料发现这种merge sql早就被支持了,只是自己还不知道而已。
  
  <--------------------------------------不华丽的分界线--------------------------------------------------------------------->
  
  例如wiki上的  http://en.wikipedia.org/wiki/Merge_%28SQL%29
  

Merge (SQL)

From Wikipedia, the free encyclopedia

Jump to: navigation
,
search








It has been suggested that Upsert

be merged
into this article or section. (Discuss
)
  A relational database management system
uses SQL
MERGE
(upsert
) statements to INSERT

new records or UPDATE

existing records depending on whether or not a condition
matches. It was officially introduced in the SQL:2008
standard.



Contents

[hide
]



[*]
1
Usage
[*]
2
Other non-standard implementations
[*]
3
References
[*]
4
External links



 
Usage


MERGE INTO table_name
USING table_reference
ON (condition
)
WHEN MATCHED THEN
UPDATE SET column1
= value1
[, column2
= value2
...]
WHEN NOT MATCHED THEN
INSERT (column1
[, column2
...]) VALUES (value1
[, value2 ...



Other non-standard implementations

  Some other database management systems support this, or very similar behavior, through their own, non-standard SQL extensions.
  MySQL
, for example, supports the use of INSERT ... ON DUPLICATE KEY UPDATE
syntax[
1]

which can be used to achieve the same effect. It also supports REPLACE INTO
syntax[
2]

, which first deletes the row, if exists, and then inserts the new one.
  SQLite
's INSERT OR REPLACE INTO
works similarly.
  Firebird
supports both MERGE INTO
and a single-row version, UPDATE OR INSERT INTO tablename (columns) VALUES (values)
,
but the latter does not give you the option to take different actions
on insert vs. update (e.g. setting a new sequence value only for new
rows, not for existing ones.)

 
References



[*]
^

MySQL :: MySQL 5.1 Reference Manual :: 12.2.4.3 INSERT ... ON DUPLICATE KEY UPDATE Syntax
[*]
^

MySQL 5.1 Reference Manual: 11.2.6 REPLACE Syntax

 
External links



[*]
HyperSQL (HSQLDB) documentation
[*]
Oracle 11g Release 2 documentation
on MERGE

[*]
Firebird 2.1 documentation
on MERGE

[*]
DB2 v9 MERGE statement
[*]
SQL Server 2008 documentation
[*]
H2 (1.2) SQL Syntax page
  
  <---------------------------------------------不华丽的分界线--------------------------------------------------------------->
  同时也找了
  http://www.oracle-base.com/articles/10g/MergeEnhancements10g.php
  

MERGE Statement Enhancements in Oracle Database 10g
  
Oracle 10g includes a number of amendments to the MERGE
statement making it more flexible.


[*]
Test Table
[*]
Optional Clauses
[*]
Conditional Operations
[*]
DELETE Clause

Test Table
  
The following examples use the table defined below.


CREATE TABLE test1 AS
SELECT *
FROM   all_objects
WHERE1=2;

Optional Clauses
  
The MATCHED
and NOT MATCHED
clauses are now optional making all of the following examples valid.


-- Both clauses present.
MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHEN NOT MATCHED THEN
INSERT (object_id, status)
VALUES (b.object_id, b.status);
-- No matched clause, insert only.
MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN NOT MATCHED THEN
INSERT (object_id, status)
VALUES (b.object_id, b.status);
-- No not-matched clause, update only.
MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status;

Conditional Operations
  
Conditional inserts and updates are now possible by using a WHERE
clause on these statements.


-- Both clauses present.
MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHEREb.status != 'VALID'
WHEN NOT MATCHED THEN
INSERT (object_id, status)
VALUES (b.object_id, b.status)
WHEREb.status != 'VALID';
-- No matched clause, insert only.
MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN NOT MATCHED THEN
INSERT (object_id, status)
VALUES (b.object_id, b.status)
WHEREb.status != 'VALID';
-- No not-matched clause, update only.
MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHEREb.status != 'VALID';

DELETE Clause
  
An optional DELETE WHERE
clause can be used to clean up after a merge operation. Only those rows which match both the ON
clause and the
DELETE WHERE
clause are deleted.


MERGE INTO test1 a
USING all_objects b
ON (a.object_id = b.object_id)
WHEN MATCHED THEN
UPDATE SET a.status = b.status
WHEREb.status != 'VALID'
DELETE WHERE (b.status = 'VALID');
  
For further information see:


[*]
MERGE
页: [1]
查看完整版本: Merge Sql