{"id":1576,"date":"2016-10-12T13:54:17","date_gmt":"2016-10-12T18:54:17","guid":{"rendered":"http:\/\/osric.com\/chris\/accidental-developer\/?p=1576"},"modified":"2016-10-12T13:56:28","modified_gmt":"2016-10-12T18:56:28","slug":"update-rows-with-values-from-a-table-join-in-oracle","status":"publish","type":"post","link":"https:\/\/osric.com\/chris\/accidental-developer\/2016\/10\/update-rows-with-values-from-a-table-join-in-oracle\/","title":{"rendered":"UPDATE rows with values from a table JOIN in Oracle"},"content":{"rendered":"<p>Example use case: I have a database that contains a table of contacts (contact) and table of e-mail addresses (email), joined on contact.id = email.contact_id. I just found out that Example Conglomerate acquired Osric Publishing&#8217;s Oracle consulting business, and so I need to update my contacts database so that all of the Oracle consultants who had @osric.com e-mail addresses now have @example.com e-mail addresses.<\/p>\n<p>How can I change just the affected addresses in the contact database, assuming the username portion of their e-mail addresses remains the same?<br \/>\n<!--more--><\/p>\n<p>The first time I tried it, I used this query:<\/p>\n<pre><code>UPDATE contacts.email ce\r\nSET email = (\r\n    SELECT REPLACE(email, '@osric.com', 'example.com')\r\n    FROM contacts.email e \r\n    INNER JOIN contacts.contact c ON e.contact_id = c.id\r\n    WHERE c.dept_id = 'oracle' \r\n    AND e.email LIKE '%@osric.com'\r\n) WHERE EXISTS (\r\n    SELECT 1\r\n    FROM contacts.email e \r\n    INNER JOIN contacts.contact c ON e.contact_id = c.id\r\n    WHERE c.dept_id = 'oracle' \r\n    AND e.email LIKE '%@osric.com'\r\n);<\/code><\/pre>\n<p>That query returned an error message:<br \/>\n<code>ORA-01427: single-row subquery returns more than one row<\/code><\/p>\n<p>That makes sense, I&#8217;m trying to set a single e-mail address to the entire result-set of e-mail addresses.<\/p>\n<p>What I want is called a <em>correlated subquery<\/em>. &#8220;A correlated subquery conceptually is evaluated once for each row processed by the parent statement.&#8221; (<a href=\"https:\/\/docs.oracle.com\/cd\/E11882_01\/server.112\/e41084\/queries007.htm#SQLRF52357\">Using Subqueries<\/a>). I revised my query:<\/p>\n<pre><code>UPDATE contacts.email ce\r\nSET email = (\r\n    SELECT REPLACE(email, '@osric.com', '@example.com')\r\n    FROM contacts.email e \r\n    INNER JOIN contacts.contact c ON e.contact_id = c.id\r\n    WHERE c.dept_id = 'oracle' \r\n    AND e.email LIKE '%@osric.com'\r\n    AND ce.contact_id = e.contact_id\r\n) WHERE EXISTS (\r\n    SELECT 1\r\n    FROM contacts.email e \r\n    INNER JOIN contacts.contact c ON e.contact_id = c.id\r\n    WHERE c.dept_id = 'oracle' \r\n    AND e.email LIKE '%@osric.com'\r\n    AND ce.contact_id = e.contact_id\r\n);<\/code><\/pre>\n<p>The key is this portion of the WHERE clause:<br \/>\n<code>ce.contact_id = e.contact_id<\/code><br \/>\nThat joins the rows from the parent UPDATE query with the rows from the SELECT subquery.<\/p>\n<p>When I ran the SELECT query on its own it returned 163 rows. However, when I ran the UPDATE query it updated 210 rows.<\/p>\n<p>Uh-oh. Rollback!<\/p>\n<p>Here&#8217;s the SELECT query I ran<\/p>\n<pre><code>SELECT REPLACE(email, '@osric.com', '@example.com')\r\nFROM contacts.email e \r\nINNER JOIN contacts.contact c ON e.contact_id = c.id\r\nWHERE c.dept_id = 'oracle' \r\nAND e.email LIKE '%@osric.com'<\/code><\/pre>\n<p>Users can have multiple email addresses but the UPDATE query is matching on contact ID in the WHERE clause. This would update other addresses associated that contact ID has as well.<\/p>\n<p>Here&#8217;s the query I used. Note the last line, an addition to the WHERE clause at the end, specifying that only rows matching @osric.com should be updated:<\/p>\n<pre><code>UPDATE contacts.email ce\r\nSET email = (\r\n    SELECT REPLACE(email, '@osric.com', '@example.com')\r\n    FROM contacts.email e \r\n    INNER JOIN contacts.contact c ON e.contact_id = c.id\r\n    WHERE c.dept_id = 'oracle' \r\n    AND e.email LIKE '%@osric.com'\r\n    AND ce.contact_id = e.contact_id\r\n) WHERE EXISTS (\r\n    SELECT 1\r\n    FROM contacts.email e \r\n    INNER JOIN contacts.contact c ON e.contact_id = c.id\r\n    WHERE c.dept_id = 'oracle' \r\n    AND e.email LIKE '%@osric.com'\r\n    AND ce.contact_id = e.contact_id\r\n)\r\nAND ce.email LIKE '%@osric.com';<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Example use case: I have a database that contains a table of contacts (contact) and table of e-mail addresses (email), joined on contact.id = email.contact_id. I just found out that Example Conglomerate acquired Osric Publishing&#8217;s Oracle consulting business, and so I need to update my contacts database so that all of the Oracle consultants who &hellip; <a href=\"https:\/\/osric.com\/chris\/accidental-developer\/2016\/10\/update-rows-with-values-from-a-table-join-in-oracle\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">UPDATE rows with values from a table JOIN in Oracle<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[282],"tags":[274,23],"class_list":["post-1576","post","type-post","status-publish","format-standard","hentry","category-oracle-2","tag-oracle","tag-sql"],"_links":{"self":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/1576","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/comments?post=1576"}],"version-history":[{"count":9,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/1576\/revisions"}],"predecessor-version":[{"id":1586,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/posts\/1576\/revisions\/1586"}],"wp:attachment":[{"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/media?parent=1576"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/categories?post=1576"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/osric.com\/chris\/accidental-developer\/wp-json\/wp\/v2\/tags?post=1576"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}