日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

使用SQL:2003 MERGE语句的奥术魔术

發布時間:2023/12/3 数据库 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用SQL:2003 MERGE语句的奥术魔术 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
時不時地,由于以下任何原因,我們不得不將INSERT與UPDATE區分開來感到尷尬:
  • 我們必須至少發表兩個聲明
  • 我們必須考慮性能
  • 我們必須考慮比賽條件
  • 我們必須在[UPDATE; 如果UPDATE_COUNT = 0 THEN INSERT]和[INSERT; 如果例外然后更新]
  • 我們必須對每個更新/插入的記錄執行一次這些語句

總而言之,這是錯誤和挫敗感的重要根源。 同時,使用SQL MERGE語句可能是如此簡單!

MERGE的典型情況

在許多其他用例中,在處理多對多關系時,MERGE語句可能會派上用場。 假設我們有以下模式:

CREATE TABLE documents (id NUMBER(7) NOT NULL,CONSTRAINT docu_id PRIMARY KEY (id));CREATE TABLE persons (id NUMBER(7) NOT NULL,CONSTRAINT pers_id PRIMARY KEY (id));CREATE TABLE document_person (docu_id NUMBER(7) NOT NULL,pers_id NUMBER(7) NOT NULL,flag NUMBER(1) NULL,CONSTRAINT docu_pers_pk PRIMARY KEY (docu_id, pers_id),CONSTRAINT docu_pers_fk_docu FOREIGN KEY (docu_id) REFERENCES documents(id),CONSTRAINT docu_pers_fk_pers FOREIGN KEY (pers_id) REFERENCES persons(id));

上表用于模擬哪個人已閱讀(flag = 1)/已刪除(flag = 2)哪個文檔。 為簡單起見,通常將“ document_person”實體與“ documents”外部聯接,以便“ document-person”記錄的存在或不存在可能具有相同的語義:“ flag IS NULL”表示未讀文檔。
現在,當您要將文檔標記為已讀時,必須決定是插入一個新的“ document_person”,還是更新現有的“ document_person”。 與刪除相同。 與將所有文檔標記為已讀或刪除所有文檔相同。

改用MERGE

您可以一口氣做到這一切! 假設您要插入/更新一條記錄,以將一個文檔標記為已讀:

-- The target tableMERGE INTO document_person dst-- The data source. In this case, just a dummy recordUSING (SELECT :docu_id as docu_id, :pers_id as pers_id, :flag as flagFROM DUAL) src-- The merge condition (if true, then update, else insert)ON (dst.docu_id = src.docu_id AND dst.pers_id = src.pers_id)-- The update actionWHEN MATCHED THEN UPDATE SETdst.flag = src.flag-- The insert actionWHEN NOT MATCHED THEN INSERT (dst.docu_id,dst.pers_id,dst.flag)VALUES (src.docu_id,src.pers_id,src.flag)

這看起來很相似,但是比MySQL的INSERT .. ON DUPLICATE KEY UPDATE語句冗長得多,這更加簡潔。

發揮到極致

但是,您可以走得更遠! 如前所述,您可能還希望將給定人員的所有文檔標記為已讀。 合并沒問題。 如果指定:docu_id,則以下語句與上一條相同。 如果將其保留為空,它將僅將所有文檔標記為:flag:

MERGE INTO document_person dst-- The data source is now all "documents" (or just :docu_id) left outer-- joined with the "document_person" mappingUSING (SELECT d.id as docu_id, :pers_id as pers_id, :flag as flagFROM documents dLEFT OUTER JOIN document_person d_p ON d.id = d_p.docu_id AND d_p.pers_id = :pers_id-- If :docu_id is set, select only that documentWHERE (:docu_id IS NOT NULL AND d.id = :docu_id)-- Otherwise, select all documentsOR (:docu_id IS NULL)) src-- If the mapping already exists, update. Else, insertON (dst.docu_id = src.docu_id AND dst.pers_id = src.pers_id)-- The rest stays the sameWHEN MATCHED THEN UPDATE SETdst.flag = src.flagWHEN NOT MATCHED THEN INSERT (dst.docu_id,dst.pers_id,dst.flag)VALUES (src.docu_id,src.pers_id,src.flag)

jOOQ中的MERGE支持

jOOQ也完全支持MERGE。 有關更多詳細信息,請參見手冊(滾動至底部):
http://www.jooq.org/manual/JOOQ/Query/
合并愉快!

參考:我們的JCG合作伙伴 Lukas Eder在JAVA,SQL和JOOQ博客上使用SQL:2003 MERGE語句 編寫了 奧術魔術 。

相關文章 :

  • Java中的數據庫架構導航
  • ORM問題
  • SQL或NOSQL:這是問題嗎?
  • 什么是NoSQL?
  • 按匯總分組/多維數據集

翻譯自: https://www.javacodegeeks.com/2011/12/arcane-magic-with-sql2003-merge.html

總結

以上是生活随笔為你收集整理的使用SQL:2003 MERGE语句的奥术魔术的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。