{"id":785,"date":"2007-07-10T15:42:00","date_gmt":"2007-07-10T15:42:00","guid":{"rendered":"\/blogs\/bobb\/post\/MERGE-JOINS-and-determinism.aspx"},"modified":"2007-07-10T15:42:00","modified_gmt":"2007-07-10T15:42:00","slug":"merge-joins-and-determinism","status":"publish","type":"post","link":"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/","title":{"rendered":"MERGE, JOINS, and determinism"},"content":{"rendered":"<p>\nSQL Server 2008 will contain an ANSI SQL standard MERGE statement with extensions. Listening to the <a href=\"https:\/\/connect.microsoft.com\/SQLServer\/content\/content.aspx?ContentID=5553\">webcast<\/a> last Friday, there&#39;s a fairly straightforward way to describe how this works.\n<\/p>\n<p>\nLet&#39;s go back to first principals. Relational databases support two ways to do UPDATE and DELETE; positioned updates and searched updates. In a positioned update, you open an updatable cursor over a set of rows, navigate to the row you want, and issue an &quot;UPDATE&#8230;WHERE CURRENT OF&quot; statement. The searched update (UPDATE foo SET x=y WHERE z=1) is a SELECT and UPDATE in one statement. You specify the rows you want and also update them. The way you specify\/gather the rows to update is mostly up to you, SQL Server even supports using a JOIN to do this.\n<\/p>\n<p>\nupdate&nbsp;t<br \/>\nset t.name = s.name, t.age&nbsp; = s.age <br \/>\nfrom [target] t <br \/>\njoin [source] s on t.id = s.id;<br \/>\ngo\n<\/p>\n<p>\nMERGE in SQL Server 2008 is a searched operation that can operate on up to three different rowsets depending on how you specify the MERGE statement. These are actually the three rowsets you can get from a FULL OUTER JOIN. The statement:\n<\/p>\n<p>\nselect [target] t <br \/>\ninner join [source] s on t.id = s.id;\n<\/p>\n<p>\ngets the rows in table T with a matching id value in table S. Let&#39;s call this rowset1. A left outer join will also include the rows in T that do not match S (rowset2); right outer join includes the rows in T that don&#39;t match S (rowset3), and FULL OUTER JOIN contains all three rowsets.\n<\/p>\n<p>\nIn MERGE, you can get up to all three rowsets (INNER, LEFT, and RIGHT join rowsets)\n<\/p>\n<p>\nmerge [target] t<br \/>\n&nbsp;using [source] s on t.id = s.id<br \/>\n&nbsp;when matched then update t.name = s.name, t.age = s.age&nbsp;&#8212; use &quot;rowset1&quot;<br \/>\n&nbsp;when not matched then insert values(id,name,age) &#8212; use &quot;rowset2&quot;<br \/>\n&nbsp;when source not matched then delete; &#8212; use &quot;rowset3&quot;\n<\/p>\n<p>\nThe query&nbsp;processor will do the appropriate type of join to gather the rowsets that you need, as all clauses are not required. This optimizes performance over multiple statements, as you only have to gather the rows to process once.\n<\/p>\n<p>\nEven, if you use only &quot;when matched&quot;, MERGE is an improvement over our first &quot;update using a join&quot;. If more than one row in the source matches one row in the target&#8230;\n<\/p>\n<p>\ninsert into t values(1, &#39;Fred&#39;, 42)<br \/>\ninsert into s values(1, &#39;Buddy&#39;, 43)<br \/>\ninsert into s values(1, &#39;Sam&#39;, &#39;95)\n<\/p>\n<p>\nThe update using a join non-deterministically picks a row in the source to do the update, it could be Buddy or Sam. MERGE throws the following exception.\n<\/p>\n<p>\nMsg 8672, Level 16, State 1, Line 1<br \/>\nThe MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE\/DELETE the same row of the target table multiple times. Refine the ON clause to&nbsp; ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.\n<\/p>\n<p>\nMERGE can actually do more than three operations using predicates in the &quot;match\/no match&nbsp;clauses&quot;, but that&#39;s it for now.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>SQL Server 2008 will contain an ANSI SQL standard MERGE statement with extensions. Listening to the webcast last Friday, there&#39;s a fairly straightforward way to describe how this works. Let&#39;s go back to first principals. Relational databases support two ways to do UPDATE and DELETE; positioned updates and searched updates. In a positioned update, you [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[29,40],"tags":[],"class_list":["post-785","post","type-post","status-publish","format-standard","hentry","category-sql-server-2008","category-transact-sql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.9.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>MERGE, JOINS, and determinism - Bob Beauchemin<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"MERGE, JOINS, and determinism - Bob Beauchemin\" \/>\n<meta property=\"og:description\" content=\"SQL Server 2008 will contain an ANSI SQL standard MERGE statement with extensions. Listening to the webcast last Friday, there&#039;s a fairly straightforward way to describe how this works. Let&#039;s go back to first principals. Relational databases support two ways to do UPDATE and DELETE; positioned updates and searched updates. In a positioned update, you [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/\" \/>\n<meta property=\"og:site_name\" content=\"Bob Beauchemin\" \/>\n<meta property=\"article:published_time\" content=\"2007-07-10T15:42:00+00:00\" \/>\n<meta name=\"author\" content=\"Bob Beauchemin\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bob Beauchemin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"3 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/\",\"name\":\"MERGE, JOINS, and determinism - Bob Beauchemin\",\"isPartOf\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\"},\"datePublished\":\"2007-07-10T15:42:00+00:00\",\"dateModified\":\"2007-07-10T15:42:00+00:00\",\"author\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SQL Server 2008\",\"item\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/sql-server-2008\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"MERGE, JOINS, and determinism\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website\",\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/\",\"name\":\"Bob Beauchemin\",\"description\":\"SQL Server Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e\",\"name\":\"Bob Beauchemin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g\",\"caption\":\"Bob Beauchemin\"},\"sameAs\":[\"http:\/www.sqlskills.com\/blogs\/bobb\/\"],\"url\":\"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"MERGE, JOINS, and determinism - Bob Beauchemin","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/","og_locale":"en_US","og_type":"article","og_title":"MERGE, JOINS, and determinism - Bob Beauchemin","og_description":"SQL Server 2008 will contain an ANSI SQL standard MERGE statement with extensions. Listening to the webcast last Friday, there&#39;s a fairly straightforward way to describe how this works. Let&#39;s go back to first principals. Relational databases support two ways to do UPDATE and DELETE; positioned updates and searched updates. In a positioned update, you [&hellip;]","og_url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/","og_site_name":"Bob Beauchemin","article_published_time":"2007-07-10T15:42:00+00:00","author":"Bob Beauchemin","twitter_misc":{"Written by":"Bob Beauchemin","Est. reading time":"3 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/","name":"MERGE, JOINS, and determinism - Bob Beauchemin","isPartOf":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website"},"datePublished":"2007-07-10T15:42:00+00:00","dateModified":"2007-07-10T15:42:00+00:00","author":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e"},"breadcrumb":{"@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/merge-joins-and-determinism\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/"},{"@type":"ListItem","position":2,"name":"SQL Server 2008","item":"https:\/\/www.sqlskills.com\/blogs\/bobb\/category\/sql-server-2008\/"},{"@type":"ListItem","position":3,"name":"MERGE, JOINS, and determinism"}]},{"@type":"WebSite","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#website","url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/","name":"Bob Beauchemin","description":"SQL Server Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sqlskills.com\/blogs\/bobb\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/62bfa986c5b5d28fcffd8b4fc409c73e","name":"Bob Beauchemin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sqlskills.com\/blogs\/bobb\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f80e6cc667410857fa6a21931dc528b8092f4d112bf7a8ff7c267674d44ee37?s=96&d=mm&r=g","caption":"Bob Beauchemin"},"sameAs":["http:\/www.sqlskills.com\/blogs\/bobb\/"],"url":"https:\/\/www.sqlskills.com\/blogs\/bobb\/author\/bobb\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/785","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/comments?post=785"}],"version-history":[{"count":0,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/posts\/785\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/media?parent=785"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/categories?post=785"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sqlskills.com\/blogs\/bobb\/wp-json\/wp\/v2\/tags?post=785"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}