1. 程式人生 > >Oracle 數據庫實現數據合並:merge

Oracle 數據庫實現數據合並:merge

com hiberna 下使用 不可 copy href 條件 ron har

1、使用update進行數據更新

  1)最簡單的更新

  update tablea a set a.price=1.00

  2)帶條件的數據更新

  update tablea a set a.price = 2.00 where a.id=‘02‘

  3)兩張表關聯更新為固定值

  update tablea a set a.price =3.00 where exits(select 1 from tableb b where a.id=b.id)

  將a,b相同id的 a表的price 字段更新為 3.00

  4)關聯更新數據來源第二張表

  update tablea a set a.price=(select price from tablec c ) where exits (select 1 from tablec c where a.id=c.id)

  將a表price字段 更新為 id和c表id相同的數據

  5)關聯更新多個字段

  update tablea a set ( a.price,a.type)=(select c.price,c.type from tablec c ) where exits (select 1 from tablec c where a.id=c.id)

  更新a表的price 和 type 字段  

  6)使用視圖方式更新

  update (select a.price old,c.price as new from tablea a ,tablec c where a.id=c.id) set old=new

以上為自己了解到的Update使用方式,需要註意 a.id 和c.id需要一一對應。即c表只有一條id 與a表id對應,否則會報錯

ORA-01427:"single-row subquery returns more than one row"

單行查詢返回多行結果。是不能進行更新的。

2、merge 更新使用

  工作中要對一個字段:次數 進行更新 表數據量在 13w+ 需要兩表關聯 也就是 兩個 13w+ 的表進行關聯。

  在使用update進行更新的時候,效率問題大大降低。加上限制條件更新 100條數據還用了6-8S,所以 update並不適用。

  查閱資料看到merge 更新,便學習記錄。

  MERGE 在SQL Server、Oracle數據庫中可用,MySQL、PostgreSQL中不可用。可以同時進行更新和插入操作。執行效率要高於INSERT+UPDATE。

  語法:

  MERGE INTO [your table-name] [rename your table here]
  USING ( [ your query ] )[rename your query-sql and using just like a table]
  ON ([conditional expression ] AND [...]...)
  WHEN MATHED THEN [here you can execute some update sql or something else ]
  WHEN NOT MATHED THEN [execute something else here ! ]

  示例

  merge into tablea a ----要更新或者操作的表

  using tablec c     ----源表 using (select * from tablec ) c

  on a.id=c.id      --匹配條件

  when matched then set a.price=c.price --當匹配時進行更新操作

  when not matched then     --不匹配進行插入操作

  insert values values(c.id,c.price)

  using 後不僅可以使用 表 也可以是 視圖或者子查詢 using (select * from tablec ) c

  not matched 可以沒有 就是當不匹配什麽也不做。

  

  總結:

  之前說的使用update更新100行數據都需要6-8S 使用merge 更新全部數據(13W+ 與13W+ 關聯)只用了10S左右。更新效率可見要比update高很多。

SQL Server 2008 開始支持 MERGE語句 
 
-- 源表
CREATE TABLE test_from (id INT, val VARCHAR(20));
 
-- 目標表
CREATE TABLE test_to (id INT, val VARCHAR(20));
 
-- 插入源表
INSERT INTO test_from VALUES (1, ‘A‘);
INSERT INTO test_from VALUES (2, ‘B‘);
 
-- 合並 源表到目標表
MERGE test_to USING test_from
ON ( test_to.id = test_from.id )    -- 條件是 id 相同
WHEN MATCHED THEN UPDATE SET test_to.val = test_from.val   -- 匹配的時候,更新
WHEN NOT MATCHED THEN INSERT VALUES(test_from.id, test_from.val) -- 源表有,目標表沒有,插入
WHEN NOT MATCHED BY SOURCE THEN DELETE; -- 目標表有,源表沒有,目標表該數據刪除.
 
-- 第一次檢查 目標表數據.
SELECT * FROM test_to;
 
id          val
----------- --------------------
          1 A
          2 B
 
 
-- 更新源表
UPDATE test_from SET val = ‘A2‘ WHERE id = 1;
-- 刪除源表
DELETE FROM test_from WHERE id = 2;
-- 插入源表
INSERT INTO test_from VALUES (3, ‘C‘);
 
 
-- 合並 源表到目標表
MERGE test_to USING test_from
ON ( test_to.id = test_from.id )    -- 條件是 id 相同
WHEN MATCHED THEN UPDATE SET test_to.val = test_from.val   -- 匹配的時候,更新
WHEN NOT MATCHED THEN INSERT VALUES(test_from.id, test_from.val) -- 源表有,目標表沒有,插入
WHEN NOT MATCHED BY SOURCE THEN DELETE; -- 目標表有,源表沒有,目標表該數據刪除.
 
-- 再次檢查 目標表數據.
SELECT * FROM test_to;
 
id          val
----------- --------------------
          1 A2
          3 C

Merge-數據庫風格的合並
數據的合並(merge)和連接(join)是我們在數據分析和挖掘中不可或缺的,是通過一個或一個以上的鍵連接的。pandas的合並(merge)的的絕大功能和數據庫操作類似的。具有如下參數:

pd.merge(left, right, how=’inner’, on=None, left_on=None, right_on=None, left_index=False,right_index=False, sort=False, suffixes=(‘_x’, ‘_y’), copy=True, indicator=False, validate=None)

各個參數的含義:
left、right:左右連接對象

how:連接方式,共有’inner’,’left’,right’,’outer’

on:根據連接的鍵

left_on、right_on:在連接的鍵名不同的情況下使用,left_on傳入左對象的鍵,right_on傳入右對象的鍵

left_index、right_index:設置索引是否作為連接的鍵,通常 left_on=??和right_index=True, right_on=??和left_index=True,或者left_index=True和right_index=True

sort:對連接後的結果是否排序,當數據巨大的時候為了追求效率可以設置為False

suffixes:對於不作為鍵的同名列,在其列名後添加的後綴

copy:將左右對象的內容復制過來,默認為True
---------------------

MERGE語句是SQL語句的一種。在SQL Server、Oracle數據庫中可用,MySQL、PostgreSQL中不可用。MERGE是Oracle9i新增的語法,用來合並

UPDATE和INSERT語句。通過MERGE語句,根據一張表(原數據表,source table)或子查詢的連接條件對另外一張(目標表,target table)表

進行查詢,連接條件匹配上的進行UPDATE,無法匹配的執行INSERT。這個語法僅需要一次全表掃描就完成了全部工作,執行效率要高於INSERT

+UPDATE.具體來說,MERGE語句會檢查原數據表記錄和目標表記錄。如果記錄在原數據表和目標表中均存在,則目標表中的記錄將被原數據表中的

記錄所更新(執行Update操作);如果目標表中不存在的某(些)記錄,在原數據表中存在,則原數據表的這(些)記錄將被插入到目標表中(

執行Insert操作)。在Oracle 10g之前,merge語句支持匹配更新和不匹配插入兩種簡單的用法,在10g中Oracle對merge語句做了增強,增加了

條件選項和DELETE操作。

Merge語法

  MERGE [hint] INTO [schema ] table [t_alias]

  USING [schema ] { table | view | subquery } [t_alias]

  ON ( condition )

  WHEN MATCHED THEN merge_update_clause

  WHEN NOT MATCHED THEN merge_insert_clause;

代碼及說明

  1.MERGE INTO test T1

  2.USING (SELECT OWNER, OBJECT_NAME, MAX(ID) ID FROM T GROUP BY OWNER, OBJECT_NAME) T

  3.ON (T,OWNER = T1,OWNER AND T.OBJECT_NAME = T1,TABLE_NAME)

  4.WHEN MATCHED THEN UPDATE SET T1,ID = T,ID

  5.WHEN NOT MATCHED THEN INSERT VALUES (T,ID, T,OWNER, T,OBJECT_NAME);

  第一行 命名目標表並給別名T1

  第二行 using子句提供merge操作的數據源,命名T

  第三行 on子句指定合並的條件

  第四行 when matched then 子句判定條件符合則對表T1做什麽改變(或刪除)

  第五行 when not matched then 子句判斷條件不符合則插入的操作

上面為數據庫中merge,下面為hibernate中merge和update的區別

1. 數據庫記錄已存在,更改person的name為一個新的name。

merge方法打印出的日誌如下:
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from person person0_ where person0_.id=?
Hibernate: update person set name=? where id=?

update方法打印出的日誌如下:
Hibernate: update person set name=? where id=?

2. 數據庫記錄已存在,更改person的name和數據庫裏對應id記錄的name一樣的值。

merge方法打印出的日誌如下:
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from person person0_ where person0_.id=?
此處相對於第一種情形少了update的動作

update方法打印出的日誌如下:
Hibernate: update person set name=? where id=?

3. 數據庫記錄不存在時,也就是你傳的實體bean的ID在數據庫沒有對應的記錄。

merge方法打印出的日誌如下:
Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from person person0_ where person0_.id=?
Hibernate: insert into person (name) values (?)
如果沒有對應的記錄,merge會把該記錄當作新的記錄來插入。此處我很疑惑,因為我傳得person實體對象裏寫明了id值的,它為什麽還會做插入的動作呢?

Oracle 數據庫實現數據合並:merge