使用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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/373978.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/373978.shtml
英文地址,請注明出處:http://en.pswp.cn/news/373978.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Swing 學習小記

初學Swing一路問題,一路學習 問題一:JPanel中動態組件添加,刷新問題? 錯誤一:使用repaint()方法,以為可以刷新,可行不通。 錯誤繼續發生:還是使用repaint()方法,與之前不…

leetcode Spiral Matrix

題目連接 https://leetcode.com/problems/spiral-matrix/ Spiral Matrix Description Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. For example, Given the following matrix: [   [ 1, 2, 3 ],   [ 4, 5…

python學生類出不來中文_Python 這類看起來學習門檻低的語言,是否真的適合入門編程學習?...

Python(計算機程序設計語言)Python是一種跨平臺的計算機程序設計語言。 是一個高層次的結合了解釋性、編譯性、互動性和面向對象的腳本語言。最初被設計用于編寫自動化腳本(shell),隨著版本的不斷更新和語言新功能的添加,越多被用于獨立的、大型項目的開…

克隆可序列化和不可序列化的Java對象

開發人員經常依靠3d方庫來避免重新發明輪子,尤其是在Java世界中,Apache和Spring這樣的項目如此盛行。 在處理這些框架時,我們通常很少或根本無法控制其類的行為。 這有時會導致問題。 例如,如果您想深度克隆不提供合適克隆方法的對…

2014編程之美資格賽

2014 編程之美挑戰賽 --- 資格賽真題 題目1 : 同構 時間限制:2000ms單點時限:1000ms內存限制:256MB描述 給定2個樹A和B,保證A的節點個數>B的節點個數。 現在你需要對樹A的邊進行二染色。 一個好的染色方案,指不存在一個樹A中的連通塊,同時…

JavaScript之面向對象學習六原型模式創建對象的問題,組合使用構造函數模式和原型模式創建對象...

一、仔細分析前面的原型模式創建對象的方法,發現原型模式創建對象,也存在一些問題,如下: 1、它省略了為構造函數傳遞初始化參數這個環節,結果所有實例在默認的情況下都將取得相同的屬性值,這還不是最大的問題! 2、最大的問題是原型…

stand up meeting 12/11/2015

part組員今日工作工作耗時/h明日計劃工作耗時/hUI馮曉云完成單詞釋義熱度排序;允許用戶自主添加釋義;完成了button位置的修正(finally)和彈窗的美化; 6try the backup plan 6PDF Reader朱玉影 完成了pdf文件的打…

ssrf漏洞內網滲透_滲透技巧之SSRF

SSRF——服務端請求偽造,上一篇,我談到了CSRF客戶端請求偽造,這個是我們通過攻擊用戶,引誘客戶點擊我們偽造好的表單,從而達到我們攻擊的目的,是從客戶端發起的,那么SSRF服務端請求偽造當然是通…

引入故意緩存

幾周前,我參加了ThoughtWorks 技術雷達研討會。 我在ThoughtWorks工作了多年,想想是否有人知道這些人在軟件開發方面的發展趨勢。 在技??巧上帶有上升箭頭的數字中,第17位被稱為“周到緩存”。 和斯科特肖一起喝酒時,我問他是什…

(小議)面向對象

什么是面向對象?如果讓我理解,只有一句話:它是一個與面向過程相對的概念,是一種進化或者升級。人們所設計的程序幾乎都是線性思維,即一步一步往下執行。對于一個沒有人機交互的簡單程序來說,這是簡單易行的…

int類型究竟占幾個字節

最近在看深入理解計算機系統這本書,上面提到了在32位機器和64機器中int類型都占用4個字節。后來,查了The C Programming language這本書,里面有一句話是這樣的:Each compiler is free to choose appropriate sizes for its own ha…

python fieldnames_csvreader.fieldnames在python中未被識別為csv reader對象的屬性

我試圖使用CSV模塊在Python中提取CSV文件的標題.CSV文件非常扁平,看起來像:This, That, The Other1, 2, 3我正在做以下事情:>讀入CSV文件并制作閱讀器對象>將讀者的迭代器推到下一行,強制它至少訪問第一行一次(來自csv模塊文檔:“如果在…

Spring Insight – Web應用程序分析

您是否正在使用Spring Framework編寫Web應用程序? 您是否曾經想過引擎蓋下發生了什么? 為什么您的應用程序響應如此緩慢? 在您仍然等待應用程序響應的同時,為什么窗外的蝸牛如此之快地消失在遠處? 您應該:)&#xff0c…

創建動態鏈接庫時設置導出函數的方法

有兩種方法1.使用模塊定義文件, 2.在要導出的函數前加上 __declspec(dllexport) 我們用VS2008新建個DLL工程,工程名為“TestDLL” 把默認的源文件后綴 .CPP改為.C(C文件) int _stdcall MyFunction(int iVariant){return 0; } 1. 使用傳統的模…

javascript的瀏覽器Bom詳解,window、location、history對象

BOM(BrowserObjectModel)也叫瀏覽器對象模型,描述與瀏覽器進行交互的方法和接口。BOM由多個對象組成, 其中代表瀏覽器窗口的Window對象是BOM的頂層對象,其他對象都是該對象的子對象。 JavaScript由三部分組成:ECMAScript,BOM&…

python右斜杠_Python中的左斜杠、右斜杠(正斜杠和反斜杠)

首先,"/"左傾斜是正斜杠,"\"右傾斜是反斜杠,可以記為:除號是正斜杠一般來說對于目錄分隔符,Unix和Web用正斜杠/,Windows用反斜杠,但是現在Windows(一)目錄中的斜杠們python讀文件需要輸入的目錄參…

重用生成的JAXB類

在本文中,我將演示如何利用– XJC擴展來重用以前從XML模式生成的類。 當其他XML架構導入XML架構并且您不想每次都生成相同的類時,這很有用。 導入的架構(Product.xsd) 以下XML模式代表有關產品的基本信息。 產品是此示例域中的常…

MySQL的Master/Slave群集安裝和配置

本文介紹MySQL的Master/Slave群集安裝和配置,版本號安裝最新的穩定版GA 5.6.19。 為了支持有限HA。我們用Master/Slave讀寫簡單孤立的集群。有限HA這是當Master不可用,數據不會丟失。但在Master寫的,必須手工處理故障。假設要支持更高的可用性…

動態申請二維數組

以下是動態申請a[m][n]的源代碼 代碼一&#xff1a; /* 編譯器&#xff1a;DEV C */ #include<stdio.h> #include<stdlib.h> int main() {int **a;int i,j,m,n;scanf("%d%d",&m,&n); a (int **)malloc(sizeof(int *)*m);for (i0;i<m; i){a[i…

判斷線段和直線相交 POJ 3304

1 // 判斷線段和直線相交 POJ 33042 // 思路&#xff1a;3 // 如果存在一條直線和所有線段相交&#xff0c;那么平移該直線一定可以經過線段上任意兩個點&#xff0c;并且和所有線段相交。4 5 #include <cstdio>6 #include <cstring>7 #include <iostream>8 …