{"id":87,"date":"2012-01-12T19:30:42","date_gmt":"2012-01-12T09:30:42","guid":{"rendered":"http:\/\/www.alphastar.net.au\/blog\/?p=87"},"modified":"2012-01-16T18:05:11","modified_gmt":"2012-01-16T08:05:11","slug":"replicating-a-row-in-oracle-using-java","status":"publish","type":"post","link":"https:\/\/alphastar.net.au\/weblog\/2012\/01\/12\/replicating-a-row-in-oracle-using-java\/","title":{"rendered":"Replicating a row in Oracle using Java"},"content":{"rendered":"<p>This is a method of duplicating a row in an Oracle with a few specified column values to be changed\/updated.<\/p>\n<p>I needed to find an easy way to do this and could not find anything on the net so I made my own method of doing it. This is only really of any use if the table has a large number of columns in it, with most columns retaining their original value and a few column values changing. Otherwise it&#8217;s probably better to use INSERT INTO &lt;table&gt; SELECT FROM&#8230;.<\/p>\n<p>Basically, this method will replicate a row and apply updates to columns which are specified by you. Column updates are entered in as a key value pair in a\u00c2\u00a0 HashMap. Therefore you are not limited to the number of columns you can change\/update. Obviously the primary key AS A MINIMUM will need to change else there will be a duplicate row error.<\/p>\n<p>The key to getting this working is to store the row in a temporary table, modify the data slightly and then copy it back in.<\/p>\n<p><span style=\"text-decoration: underline;\">Initial Setup<\/span><\/p>\n<ul>\n<li>An Oracle database is needed. Oracle Express 10g was used for this demo.<\/li>\n<\/ul>\n<ul>\n<li> JDBC drivers are also required (usually ojdb5.jar or ojdbc6.jar)<\/li>\n<\/ul>\n<p><span style=\"text-decoration: underline;\">Creating Example database<\/span><\/p>\n<p>Log in and create a schema\/user. e.g. &#8220;replicate&#8221;<\/p>\n<p>Create a table and insert some test data<\/p>\n<p>[code lang=&#8221;SQL&#8221;]<\/p>\n<p>create table employee (id INTEGER PRIMARY KEY, first_name varchar2(32),last_name varchar2(32), dob date,department varchar2(16),joined date,salary number(6))<\/p>\n<p>insert into employee values (1,&#8217;bob&#8217;, &#8216;jones&#8217;,to_date(&#8217;16\/06\/1980&#8242;,&#8217;dd\/mm\/yyyy&#8217;),&#8217;finance&#8217;,sysdate-300,95000);<br \/>\ninsert into employee values (2,&#8217;mary&#8217;, &#8216;smith&#8217;,to_date(&#8217;16\/03\/1966&#8242;,&#8217;dd\/mm\/yyyy&#8217;),&#8217;hr&#8217;,sysdate-600,95000);<br \/>\ninsert into employee values (3,&#8217;steven&#8217;, &#8216;briggs&#8217;,to_date(&#8217;16\/03\/1946&#8242;,&#8217;dd\/mm\/yyyy&#8217;),&#8217;hr&#8217;,sysdate-1210,122000);<br \/>\n[\/code]<\/p>\n<p><!--more-->After insertion, verify. Should look like this<\/p>\n<p><a href=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2012\/01\/rows-initial.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-102\" title=\"rows-initial\" src=\"http:\/\/www.alphastar.net.au\/blog\/wp-content\/uploads\/2012\/01\/rows-initial.jpg\" alt=\"\" width=\"579\" height=\"163\" \/><\/a><\/p>\n<p>The following code will insert a replicated row with department value changing for row 3.<\/p>\n<p>Usage: new ReplicateRow().replicateQuery(table_query,tmpTableName, originalTableForFinalInsert, hm);<\/p>\n<p>1=query<\/p>\n<p>2=temporary table<\/p>\n<p>3=table to re-insert row into (same table as specified in 1)<\/p>\n<p>4=Map of columns and values to update<\/p>\n<p>[code lang=&#8221;Java&#8221;]<\/p>\n<p>package alphastar;<\/p>\n<p>import java.sql.PreparedStatement;<br \/>\nimport java.sql.ResultSet;<br \/>\nimport java.sql.Statement;<br \/>\nimport java.sql.Connection;<br \/>\nimport java.sql.DriverManager;<br \/>\nimport java.sql.SQLException;<br \/>\nimport java.util.HashMap;<br \/>\nimport java.util.Iterator;<br \/>\nimport java.util.Map;<br \/>\nimport java.util.Set;<\/p>\n<p>public class ReplicateRow {<\/p>\n<p>public Connection conn;<\/p>\n<p>\/**<br \/>\n* @param args<br \/>\n*\/<br \/>\npublic static void main(String[] args) {<br \/>\nnew ReplicateRow().process();<br \/>\n}<\/p>\n<p>public void getConnection() {<br \/>\ntry {<br \/>\nClass.forName(&#8220;oracle.jdbc.driver.OracleDriver&#8221;);<br \/>\nString url = &#8220;jdbc:oracle:thin:@\/\/192.168.0.104:1521\/XE&#8221;;<br \/>\nconn = DriverManager.getConnection(url,&#8221;replicate&#8221;,&#8221;password&#8221;);<br \/>\nif (conn!=null) System.out.println(&#8220;have connection!&#8221;); else System.out.println(&#8220;don&#8217;t have connection&#8221;);<br \/>\n} catch (Exception e) {<br \/>\ne.printStackTrace();<br \/>\n}<br \/>\n}<\/p>\n<p>public void process() {<br \/>\ngetConnection();<br \/>\nString employee_query= &#8220;select e.* &#8221;<br \/>\n+ &#8220;from employee e &#8221;<br \/>\n+ &#8220;where &#8221;<br \/>\n+ &#8220;1=1 &#8221;<br \/>\n+ &#8220;and salary=122000 &#8220;;<br \/>\nString tmpTableName = &#8220;temptable&#8221;;<br \/>\nString originalTableForFinalInsert = &#8220;employee&#8221;;<br \/>\nMap&lt;String,String&gt; hm = new HashMap&lt;String,String&gt;();<\/p>\n<p>\/\/ build up the columns to change<br \/>\nhm.put(&#8220;id&#8221;, &#8220;999&#8221;); \/\/ really should do this properly. ie get 1 + last value in DB<br \/>\nhm.put(&#8220;department&#8221;,&#8221;marketing&#8221;);<\/p>\n<p>replicateQuery(employee_query,tmpTableName, originalTableForFinalInsert, hm);<br \/>\n}<\/p>\n<p>private boolean replicateQuery(<br \/>\nString queryToTmpTable,<br \/>\nString tmpTableName,<br \/>\nString originalTableToReInsert,<br \/>\nMap columnChangesMap) {<\/p>\n<p>int updateQuery = 0;<\/p>\n<p>try {<br \/>\nPreparedStatement ps = conn.prepareStatement(queryToTmpTable);<br \/>\nResultSet rs = ps.executeQuery();<br \/>\nStatement stmt = conn.createStatement();<\/p>\n<p>boolean tableExists = checkTableExists(tmpTableName);<br \/>\nif (tableExists) {<br \/>\nString flushToEmpty = &#8220;delete from &#8220;+tmpTableName;<br \/>\nupdateQuery = stmt.executeUpdate(flushToEmpty); \/\/ if hanging, commit in benthic<br \/>\nSystem.out.println(updateQuery+&#8221; table exists&#8221;);<br \/>\n} else {<br \/>\nString cs = copyStructure(queryToTmpTable, tmpTableName);<br \/>\nSystem.out.println(cs);<br \/>\nupdateQuery = stmt.executeUpdate(cs);<br \/>\nSystem.out.println(updateQuery+&#8221; table doen&#8217;t exist. create it&#8221;);<br \/>\n}<br \/>\n\/\/ insert data to temp table<br \/>\nString insert=&#8221;INSERT into &#8220;+tmpTableName+&#8221; &#8220;+queryToTmpTable;<br \/>\nint res = stmt.executeUpdate(insert);<br \/>\nSystem.out.println(res+&#8221; done insertion to &#8220;+tmpTableName+&#8221;\\n&#8221;);<\/p>\n<p>doUpdateOfColsOnTempTable(tmpTableName, columnChangesMap);<\/p>\n<p>String queryToTable = &#8220;select * from &#8220;+tmpTableName;<br \/>\ninsertRowToOriginalTable(originalTableToReInsert, queryToTable); \/\/ e.g. txn_event,xyz_new<\/p>\n<p>stmt.close();<br \/>\nconn.close();<br \/>\nreturn true;<\/p>\n<p>} catch (SQLException ex) {<br \/>\nSystem.err.println(ex);<br \/>\nreturn false;<br \/>\n}<\/p>\n<p>}<\/p>\n<p>\/**<br \/>\n*<br \/>\n* @param table<br \/>\n* @return true if the table exists. false otherwise<br \/>\n* @throws SQLException<br \/>\n*\/<br \/>\nprivate boolean checkTableExists(String table) throws SQLException {<br \/>\nString tableUC = table.toUpperCase();<br \/>\nboolean status = false;<\/p>\n<p>String checkExists = &#8220;&#8221;<br \/>\n+ &#8220;SELECT COUNT(1) &#8221;<br \/>\n+ &#8220;FROM USER_TABLES &#8221;<br \/>\n+ &#8220;WHERE TABLE_NAME = &#8216;&#8221;+tableUC+&#8221;&#8216; &#8220;; \/\/ must be UC<br \/>\nStatement stmt = conn.createStatement();<br \/>\nResultSet rs = stmt.executeQuery(checkExists);<br \/>\nboolean rowFound = rs.next();<br \/>\nif (rowFound== false) status = false;<br \/>\nString countVal = rs.getString(1);<\/p>\n<p>if (countVal.equals(&#8220;1&#8221;)) {<br \/>\nstatus = true;<br \/>\n} else if (countVal.contains(&#8220;0&#8221;)) {<br \/>\nstatus = false;<br \/>\n} else {<br \/>\n\/\/ shouldn&#8217;t get here<br \/>\nstatus = false;<br \/>\n}<br \/>\nreturn status;<br \/>\n}<\/p>\n<p>private boolean doUpdateOfColsOnTempTable(String tableName, Map colsAndVals) throws SQLException {<br \/>\nSet entrySet = colsAndVals.entrySet();<br \/>\nIterator i = entrySet.iterator();<br \/>\nMap.Entry me = null;<br \/>\nStringBuffer updateQuery = new StringBuffer();<br \/>\nupdateQuery.append(&#8220;update &#8220;+tableName+&#8221; &#8220;);<br \/>\nint counter = 0;<br \/>\nwhile (i.hasNext()) {<br \/>\nme = (Map.Entry) i.next();<br \/>\nif (counter == 0) updateQuery.append(&#8220;set &#8220;);<br \/>\nif (counter &gt;= 1) updateQuery.append(&#8220;,&#8221;);<br \/>\nupdateQuery.append(me.getKey()+&#8221;='&#8221;+me.getValue()+&#8221;&#8216;&#8221;);<br \/>\nSystem.out.println(&#8220;key = &#8220;+me.getKey());<br \/>\nSystem.out.println(&#8220;val = &#8220;+me.getValue()+&#8221;\\n&#8221;);<br \/>\ncounter++;<br \/>\n}<br \/>\nif (counter == 0) return false;<\/p>\n<p>Statement stmt = conn.createStatement();<br \/>\nint res = stmt.executeUpdate(updateQuery.toString());<br \/>\nstmt.close();<br \/>\nSystem.out.println(res+&#8221; done the set statement with keyset&#8221;);<br \/>\nreturn true;<br \/>\n}<\/p>\n<p>private String copyStructure(String in, String tmpTableName) {<br \/>\n\/\/ 1=0 will ensure that only the structure is copied. not data<br \/>\nString newTable = &#8220;create table &#8220;+tmpTableName+&#8221; as &#8220;+in+&#8221; and 1=0&#8243;;<br \/>\nreturn newTable;<br \/>\n}<\/p>\n<p>\/**<br \/>\n* This will insert the newly modified row back to the original table<br \/>\n*\/<br \/>\nprivate boolean insertRowToOriginalTable(String origTable, String queryToTable) throws SQLException {<br \/>\nString insert = &#8220;INSERT INTO &#8220;+origTable+&#8221; &#8220;+queryToTable;<br \/>\nStatement stmt = conn.createStatement();<br \/>\nint res = stmt.executeUpdate(insert);<br \/>\nSystem.out.println(res+&#8221; done insert into Original table\\n&#8221;);<br \/>\nif (res==1) return true;<br \/>\nelse return false;<br \/>\n}<\/p>\n<p>}<\/p>\n<p>[\/code]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a method of duplicating a row in an Oracle with a few specified column values to be changed\/updated. I needed to find an easy way to do this&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-87","post","type-post","status-publish","format-standard","hentry","category-coding"],"_links":{"self":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/87","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/comments?post=87"}],"version-history":[{"count":29,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/87\/revisions"}],"predecessor-version":[{"id":112,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/posts\/87\/revisions\/112"}],"wp:attachment":[{"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/media?parent=87"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/categories?post=87"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alphastar.net.au\/weblog\/wp-json\/wp\/v2\/tags?post=87"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}