<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-27150551</id><updated>2011-11-09T00:06:23.637-08:00</updated><title type='text'>Mark Malakanov poorly maintained blog</title><subtitle type='html'>Here I sporadically post some notes about interesting (to me at least) Oracle, MSSQL, MySQL, OLAP and datawarehousing things....</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-27150551.post-5370715234927633035</id><published>2010-01-23T09:46:00.000-08:00</published><updated>2010-01-23T10:53:05.318-08:00</updated><title type='text'>How to recover a dropped or overriden PL/SQL using Flashback.</title><content type='html'>Well, things happen. Just recently I've mistakenly run an older script that does "CREATE OR REPLACE PACKAGE ...". :(&lt;br /&gt;And that happen the latest changes I've made using SQL*Developer have gone also. :(&lt;br /&gt;&lt;br /&gt;So, what to do?&lt;br /&gt;I could restore the entire DB to the point in time before the change.&lt;br /&gt;But, I just was too lazy to do it. Also, in some cases such a global approach can eliminate other recent works. It was not mine case though, but you have to consider it.&lt;br /&gt;&lt;br /&gt;Fortunately Oracle has a Flashback!&lt;br /&gt;&lt;br /&gt;So I decided to try this. My plan was to execute following&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;SELECT * FROM DBA_SOURCE AS OF TIMESTAMP&lt;br /&gt;TO_TIMESTAMP('2010-01-20 16:00:00', 'YYYY-MM-DD HH24:MI:SS')&lt;br /&gt;WHERE TEXT LIKE '%1.0.1.38%';&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Here &lt;span style="font-family: courier new;"&gt;1.0.1.38 &lt;/span&gt;is a version number in a comment line that I usually embed into my code.&lt;br /&gt;And the older version of my PL/SQL, that had been written over is &lt;span style="font-family: courier new;"&gt;1.0.1.37&lt;/span&gt;.&lt;br /&gt;So, I needed my &lt;span style="font-family: courier new;"&gt;1.0.1.38&lt;/span&gt; back.&lt;br /&gt;However the result returned by the above query always was the current package code with a version 1.0.1.37, which was not my target.&lt;br /&gt;&lt;br /&gt;Then I've decided to try with querying the table directly. The table is SYS.SOURCE$.&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;SELECT * FROM SYS.SOURCE$ AS  OF TIMESTAMP&lt;br /&gt;TO_TIMESTAMP('2010-01-20 16:00:00', 'YYYY-MM-DD  HH24:MI:SS')&lt;br /&gt;WHERE TEXT LIKE '%1.0.1.38%';&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Voila! It was there!&lt;br /&gt;&lt;br /&gt;Then I just took the proper OBJ# and spooled all rows of that object into a text file.&lt;br /&gt;Ta-daa!&lt;br /&gt;&lt;br /&gt;However, to be successful with this method, you have to be really quick.&lt;br /&gt;Otherwise you can receive following error if some significant time has gone from the moment of overriding.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;ORA-01555: snapshot too old: rollback segment number 6 with name "_SYSSMU6_1192467665$" too small&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;01555. 00000 -  "snapshot too old: rollback segment number %s with name \"%s\" too small"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;*Cause:    rollback records needed by a reader for consistent read are&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;           overwritten by other writers&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;*Action:   If in Automatic Undo Management mode, increase undo_retention&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;           setting. Otherwise, use larger rollback segments&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In this case you have to resort to traditional recovery methods, like a point-in-time DB recovery or an import, or a Log Miner if archived logs for that time have not been removed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-5370715234927633035?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/5370715234927633035/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=5370715234927633035' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/5370715234927633035'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/5370715234927633035'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2010/01/how-to-recover-dropped-or-overriden.html' title='How to recover a dropped or overriden PL/SQL using Flashback.'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-7831521207212284483</id><published>2008-02-23T17:26:00.000-08:00</published><updated>2008-02-23T17:46:42.422-08:00</updated><title type='text'>Oracle Audit Vault 10g against 11g source.</title><content type='html'>When Oracle Audit Vault is being configured to collect audit data from Oracle 11g database, it can throw Java SQL exception originated from ORA-27452 when you add REDO Collector.&lt;br /&gt;In a log file you can find the call of &lt;span style="font-family: courier new;"&gt;dbms_src_streams_collector.setup_collector(...av_dbname =&gt; 'AV.REGRESS.RDBMS.DEV.US.ORACLE.COM' ...) &lt;span style="font-family: arial;"&gt;&lt;br /&gt;The default global name of AV Server database (&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;AV.REGRESS.RDBMS.DEV.US.ORACLE.COM) &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;span style="font-family: arial;"&gt;is longer than 30 characters, this probably causes an error &lt;/span&gt;&lt;/span&gt;ORA-27452 during adding of REDO Collector.&lt;br /&gt;To work this issue around I had to rename the global name of AV Server DB to something shorter.&lt;br /&gt;&lt;br /&gt;&lt;img src="file:///F:/Temp/mark/moz-screenshot-1.jpg" alt="" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-7831521207212284483?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/7831521207212284483/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=7831521207212284483' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/7831521207212284483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/7831521207212284483'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2008/02/oracle-audit-vault-10g-against-11g.html' title='Oracle Audit Vault 10g against 11g source.'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-3945492830863096158</id><published>2008-01-21T13:21:00.000-08:00</published><updated>2008-01-21T14:08:28.117-08:00</updated><title type='text'>How to call Oracle stored procedure from MS SQL</title><content type='html'>It is really a pain if you need to call Oracle stored procedure from MSSQL.&lt;br /&gt;MSSQL throws an error 7212 if remote procedure does not return any recordset. Oracle procedures usually don't return recordset.&lt;br /&gt;One way was to create a dummy table, create trigger on it, from where stored proc is called. Then to update this table from MSSQL.&lt;br /&gt;&lt;br /&gt;Matt Meleski has published really excellent way of calling oracle stored procedures from MS SQL! It does not require the trigger at all!&lt;br /&gt;He's placed quite thorow example on his BLOG &lt;a href="http://objectsharp.com/cs/blogs/matt/archive/2005/06/13/2221.aspx"&gt;http://objectsharp.com/cs/blogs/matt/archive/2005/06/13/2221.aspx&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By the way, the example can be simplified to very short code. Main thing - the Oracle stored procedure must have at least one output parameter type of indexed PL/SQL table. Indexed - it is important. Instead of creating a custom type in PL/SQL package, one can use readily available DBMS_OUTPUT.CHARARR.&lt;br /&gt;&lt;br /&gt;Here is an example.&lt;br /&gt;&lt;br /&gt;Make stored proc in Oracle:&lt;br /&gt;&lt;br /&gt;create or replace procedure SCOTT.PROC4MS(OUTPUT OUT dbms_output.chararr) is&lt;br /&gt;begin&lt;br /&gt;-- you do not have to assign anything to OUTPUT if you don't need it.&lt;br /&gt;OUTPUT(1):='one';&lt;br /&gt;OUTPUT(2):='two';&lt;br /&gt;OUTPUT(3):='three';&lt;br /&gt;end;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;Then call it from MS SQL. And here is the trick - use curly braces and a magic "resultset 25" parameter.&lt;br /&gt;&lt;br /&gt;select * from openquery(MYORADB, '{CALL SCOTT.PROC4MS({resultset 25, OUTPUT})}');&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;Other helpful links:&lt;br /&gt;- How To Retrieve a Recordset from an Oracle Stored Procedure Using ADO on ASP &lt;a href="http://support.microsoft.com/kb/229919"&gt;http://support.microsoft.com/kb/229919&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-3945492830863096158?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/3945492830863096158/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=3945492830863096158' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/3945492830863096158'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/3945492830863096158'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2008/01/it-is-really-pain-if-you-need-to-call.html' title='How to call Oracle stored procedure from MS SQL'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-6398293616151618417</id><published>2007-07-27T17:24:00.000-07:00</published><updated>2007-07-27T18:26:58.504-07:00</updated><title type='text'>SSIS 2005. Fast load into non-MS OLE DB destination</title><content type='html'>&lt;div style="text-align: center;"&gt;or&lt;br /&gt;&lt;/div&gt;&lt;p class="MsoNormal" style="text-align: center;" align="center"&gt;&lt;span style="font-size:130%;"&gt;&lt;b style=""&gt;&lt;span lang="EN-US"&gt;SSIS 2005. How to &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b style=""&gt;&lt;span lang="EN-US"  style="font-size:14;"&gt;&lt;span style="font-size:130%;"&gt;avoid Autocommit when load into OLE DB destination.&lt;/span&gt;&lt;span style=""&gt;   &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;span style="" lang="EN-US"&gt;An example w&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;ith using of Oracle OLE DB driver&lt;/span&gt;&lt;span style="" lang="EN-US"&gt; on a destination side.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;I have heard from my friend that he is experiencing very slow load into Oracle database. He used SSIS 2005. Which is funny, because Oracle Warehouse Builder is available. Anyway.&lt;br /&gt;The cause of slowness of SSIS, when it loads into non-Microsoft OLE DB target, appeared to be the commit after every insert. Since the ‘Autocommit’ is set to be ‘ON’ by OLE DB standard, a driver propagates this mode to the da&lt;/span&gt;&lt;span lang="EN-US"&gt;tabase. The only way to turn it off, is to switch OLE DB datasource into a Transactional mode by issuing a BeginTransaction() call.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;SSIS does issue this call when Batch Size option is specified for MS SQL OLE DB Native Sqlserver driver. But it does not d&lt;/span&gt;&lt;span lang="EN-US"&gt;o it for any other OLE DB driver like Oracle’s or even for MSSQL .Net OLE DB.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;As a result, SSIS demonstrates very poor performance when loading into Oracle OLEDB Destination.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span lang="EN-US"&gt;What to do?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;I’ve suggested to start transaction in Destination OLE DB session before any insert comes, then do a Commit and start transaction again after some number of rows inserted in order to simulate “Batch size”.&lt;/span&gt;&lt;/p&gt;    &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span lang="EN-US"&gt;How to do?&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;b style=""&gt;&lt;span lang="EN-US"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;I would be curious to know if anybody have found a more elegant and efficient way to fix this situation, however my way is b&lt;/span&gt;&lt;span lang="EN-US"&gt;y using Script Component.&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-US"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;ol style="margin-top: 0cm;" start="1" type="1"&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span lang="EN-US"&gt;Create Any kind of Data Source, i.e. an OLE DB Source. It      should have fields that can be easily put into a target table. &lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span lang="EN-US"&gt;Add Script Component as a Destination and feed it from data      source above.&lt;/span&gt;&lt;/li&gt;&lt;li class="MsoNormal" style=""&gt;&lt;span lang="EN-US"&gt;Double-click on it to open Script Transformation Editor&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Select input columns&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqUt0uxMqI/AAAAAAAAAC0/F3oujmuwWgU/s1600-h/image002.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqUt0uxMqI/AAAAAAAAAC0/F3oujmuwWgU/s400/image002.jpg" alt="" id="BLOGGER_PHOTO_ID_5092045843665597090" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="" lang="EN-US"&gt;Select Connection Manager form where add New connection manager.&lt;/span&gt;&lt;br /&gt;&lt;span style="" lang="EN-US"&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="" lang="EN-US"&gt; Rename new “Connection” to “oraxeConnection” just for distinction.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqVo0uxMsI/AAAAAAAAADE/XE3AwGGv8LE/s1600-h/image003.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqVo0uxMsI/AAAAAAAAADE/XE3AwGGv8LE/s400/image003.png" alt="" id="BLOGGER_PHOTO_ID_5092046857277878978" border="0" /&gt;&lt;/a&gt;&lt;span style="" lang="EN-US"&gt;In Connection Manager Column choose “&lt;new&gt;New Connection” item&lt;/new&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="" lang="EN-US"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="" lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_X5TKwaqnQiw/RqqVpEuxMuI/AAAAAAAAADU/KBCdtwTuhxk/s1600-h/image005.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_X5TKwaqnQiw/RqqVpEuxMuI/AAAAAAAAADU/KBCdtwTuhxk/s400/image005.png" alt="" id="BLOGGER_PHOTO_ID_5092046861572846306" border="0" /&gt;&lt;/a&gt;&lt;span style="" lang="EN-US"&gt;Select “ADO.NET” type&lt;/span&gt;&lt;br /&gt;&lt;span style="" lang="EN-US"&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="" lang="EN-US"&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqUt0uxMqI/AAAAAAAAAC0/F3oujmuwWgU/s1600-h/image002.jpg"&gt;&lt;br /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_X5TKwaqnQiw/RqqUgUuxMnI/AAAAAAAAACc/Dfz9AsQahUI/s1600-h/image007.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_X5TKwaqnQiw/RqqUgUuxMnI/AAAAAAAAACc/Dfz9AsQahUI/s400/image007.png" alt="" id="BLOGGER_PHOTO_ID_5092045611737363058" border="0" /&gt;&lt;/a&gt;&lt;span style="" lang="EN-US"&gt;In a dialog “Configure OLE DB Connection Manager” click New.&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="" lang="EN-US"&gt;Choose Provider. In my simple case “.Net Providers for OleDb\Microsoft OLE DB Provider for SQL Server”&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_X5TKwaqnQiw/RqqUDkuxMkI/AAAAAAAAACE/tYZXP0EYoSM/s1600-h/image009.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_X5TKwaqnQiw/RqqUDkuxMkI/AAAAAAAAACE/tYZXP0EYoSM/s400/image009.png" alt="" id="BLOGGER_PHOTO_ID_5092045117816123970" border="0" /&gt;&lt;/a&gt;Test and click OK&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_X5TKwaqnQiw/RqqT8UuxMiI/AAAAAAAAAB0/OoRJtsAm6jE/s1600-h/image011.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_X5TKwaqnQiw/RqqT8UuxMiI/AAAAAAAAAB0/OoRJtsAm6jE/s400/image011.png" alt="" id="BLOGGER_PHOTO_ID_5092044993262072354" border="0" /&gt;&lt;/a&gt;Click OK&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="" lang="EN-US"&gt;Choose newly created Connection Manager in “Connection Manager” column&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size:100%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqTt0uxMfI/AAAAAAAAABc/vhGK0eqUgKE/s1600-h/image014.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqTt0uxMfI/AAAAAAAAABc/vhGK0eqUgKE/s400/image014.png" alt="" id="BLOGGER_PHOTO_ID_5092044744153969138" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style="text-align: center;"&gt;&lt;span style="" lang="EN-US"&gt;Select “Script” item in left list&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-size:100%;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqTl0uxMdI/AAAAAAAAABM/QGH0IbghG-A/s1600-h/image016.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqTl0uxMdI/AAAAAAAAABM/QGH0IbghG-A/s400/image016.png" alt="" id="BLOGGER_PHOTO_ID_5092044606715015634" border="0" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;Click [Design Script…] button&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;  &lt;div style="text-align: left;"&gt;&lt;span style="font-size:100%;"&gt;Create following script&lt;br /&gt;&lt;/span&gt;&lt;p class="MsoNormal" style=""&gt;&lt;span  lang="EN-US" style="font-family:courier new;"&gt;' Microsoft SQL Server Integration Services user script component&lt;br /&gt;' This is your new script component in Microsoft Visual Basic .NET&lt;br /&gt;' ScriptMain is the entrypoint class for script components&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span  lang="EN-US" style="font-family:courier new;"&gt;Imports&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;span style="font-family:courier new;"&gt; System&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Imports&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; System.Data&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Imports&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; System.Math&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Imports&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Microsoft.SqlServer.Dts.Pipeline.Wrapper&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Imports&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Microsoft.SqlServer.Dts.Runtime.Wrapper&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Imports&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; System.Data.OleDb&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Imports&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; System.Data.Common&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Public&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Class&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; ScriptMain&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Inherits&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; UserComponent&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Dim&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; rowcnt &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Int64&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Dim&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; out_batch_sz &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Int64&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Dim&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; connMgr &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; IDTSConnectionManager90&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Dim&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; oledbconn &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; OleDbConnection&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Dim&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; oledbtran &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; OleDbTransaction&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Dim&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; oledbCmd &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; OleDbCommand&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Dim&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; oledbParam &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; OleDbParameter&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Public&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Overrides&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; PreExecute()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;out_batch_sz = 8 * 1024&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;rowcnt = 0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:green;"  &gt;'MsgBox("PreExecute")&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbCmd = &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;New&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; OleDbCommand(&lt;/span&gt;&lt;span style=";font-family:courier new;color:maroon;"  &gt;"INSERT INTO MM_TST_B2(C, D) VALUES(?, ?)"&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;, oledbconn)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbParam = &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;New&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; OleDbParameter(&lt;/span&gt;&lt;span style=";font-family:courier new;color:maroon;"  &gt;"@C"&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;, OleDbType.VarChar, 7)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbCmd.Parameters.Add(oledbParam)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbParam = &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;New&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; OleDbParameter(&lt;/span&gt;&lt;span style=";font-family:courier new;color:maroon;"  &gt;"@D"&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;, OleDbType.VarChar, 7)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbCmd.Parameters.Add(oledbParam)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbtran = oledbconn.BeginTransaction()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbCmd.Transaction = oledbtran&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:green;"  &gt;'MsgBox("First Transaction began")&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;MyBase&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.PreExecute()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;End&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Public&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Overrides&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; AcquireConnections(&lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;ByVal&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Transaction &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Object&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;connMgr = &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Me&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.Connections.oraxeConnection&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbconn = &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;CType&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;(connMgr.AcquireConnection(&lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Nothing&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;), OleDb.OleDbConnection)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:green;"  &gt;'MsgBox(oledbconn.Provider &amp; " " &amp;amp; oledbconn.ConnectionString)&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;End&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Public&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Overrides&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Input0_ProcessInputRow(&lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;ByVal&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Row &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;As&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; Input0Buffer)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;With&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; oledbCmd&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.Parameters(&lt;/span&gt;&lt;span style=";font-family:courier new;color:maroon;"  &gt;"@C"&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;).Value = Row.C&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.Parameters(&lt;/span&gt;&lt;span style=";font-family:courier new;color:maroon;"  &gt;"@D"&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;).Value = Row.D&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.ExecuteNonQuery()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;End&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;With&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;rowcnt = rowcnt + 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;If&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; (rowcnt &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Mod&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; out_batch_sz) = 0 &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Then&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;MsgBox(&lt;/span&gt;&lt;span style=";font-family:courier new;color:maroon;"  &gt;"Batch Commit "&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &amp; rowcnt)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbtran.Commit()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbtran = oledbconn.BeginTransaction()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbCmd.Transaction = oledbtran&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;            &lt;/span&gt;&lt;span style=";font-family:courier new;color:green;"  &gt;'MsgBox("Batch Transaction began")&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;End&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;If&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;End&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Public&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Overrides&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; PostExecute()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:green;"  &gt;'MsgBox("PostExecute")&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;MyBase&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.PostExecute()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;End&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Public&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Overrides&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;Sub&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; ReleaseConnections()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:green;"  &gt;'MsgBox("ReleaseConnections")&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;oledbtran.Commit()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;MyBase&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;.ReleaseConnections()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    &lt;/span&gt;&lt;span style=";font-family:courier new;color:blue;"  &gt;End&lt;/span&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;span style="color:blue;"&gt;&lt;span style="font-family:courier new;"&gt;Sub&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;!--[endif]--&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:100%;"  &gt;&lt;span  lang="EN-US" style="color:green;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;span lang="EN-US"&gt;Save and exit.&lt;/span&gt;&lt;br /&gt;Run&lt;br /&gt;&lt;p class="MsoNormal" style="margin-left: 18pt;"&gt;&lt;span lang="EN-US"&gt;Comparison of this Script Destination method with the basic OLE DB Destination, where both work via the same Oracle OLE DB Driver, shows that the Script method is times faster.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;span lang="EN-US"&gt;&lt;/span&gt;&lt;/div&gt;&lt;p class="MsoNormal" style=""&gt;&lt;span lang="EN-US"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="" lang="EN-US"&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-6398293616151618417?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/6398293616151618417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=6398293616151618417' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/6398293616151618417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/6398293616151618417'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2007/07/ssis-2005-fast-load-into-non-ms-ole-db.html' title='SSIS 2005. Fast load into non-MS OLE DB destination'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_X5TKwaqnQiw/RqqUt0uxMqI/AAAAAAAAAC0/F3oujmuwWgU/s72-c/image002.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-115513781947962755</id><published>2006-08-09T08:12:00.000-07:00</published><updated>2006-08-09T08:37:01.736-07:00</updated><title type='text'>Restoration of RPM database.</title><content type='html'>This article may help you, if your RPM database has corrupted, and that’s what happened to mine. In fact, I tried to use `rpm --rebulddb' command on it in an attempt to fix it. Unfortunately, most of package’s meta-information had gone. However, all, or so I hoped, files remained on the filesystem. I have decided that this could be a my source of restoration of the RPM database.&lt;br /&gt;Fortunately( to me :) ) other people have encountered this problem already, and some solutions exist. Here is the URL for this document: &lt;a href="http://www.informatimago.com/linux/rpm-rebuilddb.html"&gt;http://www.informatimago.com/linux/rpm-rebuilddb.html&lt;/a&gt;. This one actually worked for me as a starting point. It is based on comparison of actual files and rpm'ed files by names, deriving an rpm name where filenames match. It could have been a good solution, if there would be only one version of rpm packages. But in real life we have many. I have downloaded all packages from &lt;a href="http://download.fedoralegacy.org/redhat/9/os/i386/"&gt;http://download.fedoralegacy.org/redhat/9/os/i386/&lt;/a&gt; and &lt;a href="http://download.fedoralegacy.org/redhat/9/updates/i386/"&gt;http://download.fedoralegacy.org/redhat/9/updates/i386/&lt;/a&gt;. As a result, there were multiple versions of packages. Which one to apply? I have decided to use some more information about the file that will uniquely identify it. Sure it was MD5 check sum. The idea was to create two lists, speaking relation database language, tables, and then to join them.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Table DISK_CONTENT ( filename, bytesize, md5sum ) &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Table RPM_CONTENT ( rpmfullname, filename, bytesize, md5sum )&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Then I planned to load the data into these tables for joining using SQL language. When joining, ideally, a package suggested to be previously installed if all of its files exist on the filesystem, and the sizes and MD5 checksums are identical. But, some files, like config files, can be modified during or after installation, and the size/md5 will not match. Thus I decided to assign a merit 0 (zero) to files that md5 match, merit 1 where just size matches, merit 3 where only name matches, and merit 4 where file exist in a package but does not exist on the filesystem.&lt;br /&gt;&lt;br /&gt;So, I started from gathering the metadata of actual files&lt;br /&gt;&lt;br /&gt;1. On a machine where RPM database has been severely damaged I gather information about all files, including absolute path, byte size and md5 checksum&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;find / -fstype ext3 -type f -printf '%s' -exec md5sum {} \;  &gt;/tmp/disk-contents&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;note: I have only ext3 filesystems, thus I specified -fstype ext3 to exclude /proc and network mounted filesystems. Ideally /tmp, /opt and /home should be excluded as well, but I didn't bother.&lt;br /&gt;&lt;br /&gt;The format of a disk-contents file is &lt;span style="font-family:courier new;"&gt;"filenamesizemd5sum&lt;space&gt;&lt;space&gt;filename",&lt;/span&gt; because md5sum just types this way. I removed the last filename using sed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;sed 's/  \//\\//' /tmp/disk-contents &gt;/tmp/disk-contents-n &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;2. On a machine where I have all rpms downloaded I gathered meta-information about all files that sit inside rpms, including the rpm file name, absolute path, byte size and md5 checksum&lt;br /&gt;Note: it can be the same machine, but due to space constraints I made it on a separate one. It can sound funny, but I've done it on a Windows machine using Cygwin's utilities, &lt;span style="font-family:courier new;"&gt;bash&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;rpm&lt;/span&gt;. (yes we can have rpm in windows!)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;RPMDIR=g:/download/Linux/RH9/os cd $RPMDIR rm /tmp/rpm-contents&lt;br /&gt;for f in *.rpm ; do     rpm -q  --nopgp --queryformat='[%{FILENAMES}%{FILESIZES}%{FILEMD5S}'$f'\n]'  -p $f &gt;&gt; /tmp/rpm-contents done &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;I decided to introduce one more table that keeps some info about the whole RPM. Particularly, the fields NAME, PROVIDES, VERSION. That will allow me to group by NAME to group together packages of different versions like lvm-1.0.3-12.i386.rpm and lvm-1.0.3-12.1.legacy.i386.rpm. Why do this? The idea is to check all the files for packages. The package that is most closely presented by the filesystem files will win. &lt;span style="font-size:85%;"&gt;(Later I found that the fields PROVIDES and VERSION are not necessery)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;RPMDIR=g:/download/Linux/RH9/os cd $RPMDIR rm /tmp/rpm-info&lt;br /&gt;for f in *.rpm ; do     rpm -q  --nopgp --queryformat=$f'%{NAME}%{VERSION}%{PROVIDES}%{PROVIDENAME}%{PROVIDEVERSION}\n'  -p $f &gt;&gt; /tmp/rpm-info&lt;br /&gt;done &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;3. Load to RDBMS. I decided to go with MySQL(5.0), although I prefer Oracle, I thought that MySQL example can be more helpful to linux people, because of its simplicity and availability.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;drop table DISK_CONTENT; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;create table DISK_CONTENT (bytes decimal, md5sum varchar(64), filename varchar(2000) );&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;load data infile 'E:/cygwin/tmp/disk-contents-n' into table DISK_CONTENT fields terminated by ''; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;create index DISK_CONTENT_IX01 on DISK_CONTENT( filename );&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;drop table RPM_CONTENT; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;create table RPM_CONTENT (filename varchar(2000), bytes decimal, md5sum varchar(64), rpmfilename varchar(128));&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;load data infile 'E:/cygwin/tmp/rpm-contents' into table RPM_CONTENT fields terminated by '';&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alter table RPM_CONTENT drop index RPM_CONTENT_IX01; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alter table RPM_CONTENT add index RPM_CONTENT_IX01 ( filename ); alter table RPM_CONTENT drop index RPM_CONTENT_IX02;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alter table RPM_CONTENT add index RPM_CONTENT_IX02 ( rpmfilename );&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;drop table RPM_INFO; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;create table RPM_INFO (rpmfilename varchar(128), name varchar(128), version  varchar(128),                 provides  varchar(128), providename varchar(128), provideversion  varchar(128));&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;load data infile 'E:/cygwin/tmp/rpm-info' into table RPM_INFO fields terminated by '';&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;alter table RPM_INFO add index RPM_INFO_IX01  ( rpmfilename );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;Good. All files metadata has been loaded successfully.&lt;br /&gt;&lt;br /&gt;4. Deriving of RPMs. Now I need to find out the RPMs that are supposedly have been previously installed. I wanted to do that in a single query:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;select distinct rpmfilename from ( select rpmfilename,  case when name=@N then @R:=@R+1 else @R:=1 end Rank, @N:=name r from (select @R:=1, @N:='') r, (select name, rpmfilename, sum(proximity) sumprox from (select I.name, R.filename R_filename, D.filename D_filename,  case     when (D.filename is not NULL and D.bytes=R.bytes and D.md5sum = R.md5sum) then 0     when (D.filename is not NULL and D.bytes=R.bytes and D.md5sum != R.md5sum) then 1     when (D.filename is not NULL and D.bytes=R.bytes and R.md5sum is NULL ) then 2     when (D.filename is not NULL and D.bytes!=R.bytes) then 3     when (D.filename is NULL) then 4  end proximity,  R.rpmfilename, D.md5sum D_md5sum, R.md5sum R_md5sum  from RPM_INFO I   inner join RPM_CONTENT R on I.rpmfilename=R.rpmfilename   left outer join DISK_CONTENT D on D.filename=R.filename  /*where R.filename like '/sbin/%'*/  /*order by 1, 4*/ ) v group by name, rpmfilename having count(D_filename)&gt;0 order by 1, 3) v2 ) v3 where Rank=1;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;This query works but it requires enormous amount of space for temporary results, gigabytes. I had just 2.5 Gb of free space in my %TEMP% disk, so it has failed.&lt;br /&gt;To resolve this, I’ve split this query to be run sequentially, implicitly storing temporary results in a table rpm_files_tmp.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;drop table rpm_files_tmp; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;/* place the join into a temp table*/&lt;br /&gt;create table rpm_files_tmp as &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;select I.name, R.rpmfilename, D.filename D_filename, /*R.filename R_filename, */  &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  case&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     when (D.filename is not NULL and D.bytes=R.bytes and D.md5sum = R.md5sum) then 0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     when (D.filename is not NULL and D.bytes=R.bytes and D.md5sum != R.md5sum) then &lt;/span&gt;&lt;span style="font-family:courier new;"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     when (D.filename is not NULL and D.bytes=R.bytes and R.md5sum is NULL ) then 2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;     when (D.filename is not NULL and D.bytes!=R.bytes) then 3     when (D.filename is NULL) then 4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  end proximity&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  from RPM_INFO I&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   inner join RPM_CONTENT R on I.rpmfilename=R.rpmfilename&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;   left outer join DISK_CONTENT D on D.filename=R.filename;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;/* here I rank packages by a composite merit - sum(proximity), which ideally equals 0. But may be greater, when some files don't match exactly or absent. I selected packages with a best possible match.*/&lt;br /&gt;select distinct rpmfilename into outfile 'E:/cygwin/tmp/rpm-to-install.lst' lines terminated by '\n' &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;from ( select rpmfilename,  case when name=@N then @R:=@R+1 else @R:=1 end Rank, @N:=name r&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; from (select @R:=1, @N:='') r,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; (select name, rpmfilename, sum(proximity) sumprox&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  from rpm_files_tmp v&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  group by name, rpmfilename&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  having count(D_filename)&gt;0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  order by 1, 3) v2 ) v3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt; where Rank=1;&lt;br /&gt;&lt;br /&gt;drop table rpm_files_tmp; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;5. Install rpms from the list produced in previous step.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;# Reinitialize a new rpm database. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;mv /var/lib/rpm /var/lib/rpm-damaged-beyond-hope mkdir /var/lib/rpm rpm --initdb &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;# install GPG keys rpm --import &lt;/span&gt;&lt;a href="http://www.redhat.com/security/db42a60e.txt"&gt;&lt;span style="font-family:courier new;"&gt;http://www.redhat.com/security/db42a60e.txt&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new;"&gt; rpm --import &lt;/span&gt;&lt;a href="http://www.fedoralegacy.org/FEDORA-LEGACY-GPG-KEY"&gt;&lt;span style="font-family:courier new;"&gt;http://www.fedoralegacy.org/FEDORA-LEGACY-GPG-KEY&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;# install packages into RPM database only, do not touch files on filesystems.&lt;br /&gt;rpm -i -v --justdb --nodeps --noscripts --notriggers `cat ~/rpm/rpm-to-install.lst`&lt;br /&gt;&lt;br /&gt;# check&lt;br /&gt;rpm -qa&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;Done!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-115513781947962755?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/115513781947962755/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=115513781947962755' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/115513781947962755'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/115513781947962755'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2006/08/restoration-of-rpm-database.html' title='Restoration of RPM database.'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-114743758603543716</id><published>2006-05-12T05:36:00.000-07:00</published><updated>2006-05-12T05:39:46.043-07:00</updated><title type='text'>Oracle ANSI join security bug. Bad news again.</title><content type='html'>Trying to figure out a workaround, I have found that these DMLs that break authorization, also can not be AUDIT TRAILED.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-114743758603543716?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/114743758603543716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=114743758603543716' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114743758603543716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114743758603543716'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2006/05/oracle-ansi-join-security-bug-bad-news.html' title='Oracle ANSI join security bug. Bad news again.'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-114675710516327834</id><published>2006-05-04T08:36:00.000-07:00</published><updated>2006-05-04T08:38:25.176-07:00</updated><title type='text'>Followup: Oracle block size limit on different platforms</title><content type='html'>There was a long and annoying dispute on one of the forums about why a maximum block size on Windows (and Linux) platform is 16K, while on "serious" platforms like HP, and Sun, it is 32K. I had a wild suggestion, a bold guess, that the limit has been set based on some business strategy, that should push users to migrate from "minor" platforms towards "serious" ones. My assumption was (and still is) based on a fact, that couple of years ago Oracle had different prices for Intel and RISC CPUs, and having a 32Kb block size could be  one more reason for users to migrate on more expensive RISC platforms.I never believed in arguments of other people that the 16K limitation had been caused by some technical deficiencies of "minor" platforms. Sure, it is clear that in Windows, in Linux and even in DOS, it is possible to do I/O by 32Kb chunks. However, nobody could neither confirm nor disprove that the idea of 16Kb limit was a business driven decision. Bill S,  has kindly contacted Tom Kyte and the OakTable members. But, to my understanding, nobody could remember the reasoning (&lt;a href="http://dizwell.com/forum/index.php?topic=253.30"&gt;http://dizwell.com/forum/index.php?topic=253.30&lt;/a&gt;). So, I have decided to contact Oracle Support. I have created a "Request for Improvement". My idea was: Support people may point out for me a technical incapability of "minor" platforms, if there is such.Oracle had accepted this RFI and registered as a Bug(!) #5196815. &lt;em&gt;Funny, they call requests for improvements "bugs". May be because people are bugging them by their requests? :)))&lt;br /&gt;&lt;/em&gt;&lt;a href="https://metalink.oracle.com/metalink/plsql/ml2_documents.showFrameDocument?p_database_id=BUG&amp;p_id=5196815" target="new"&gt;&lt;span style="font-family:courier new;"&gt;BLOCK SIZE LIMIT THE SAME ON ALL PLATFORMS&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new;"&gt; Doc ID 5196815 &lt;/span&gt;&lt;br /&gt;&lt;a href="https://metalink.oracle.com/metalink/plsql/ml2_documents.showFrameDocument?p_database_id=BUG&amp;p_id=5196815"&gt;&lt;span style="font-family:courier new;"&gt;https://metalink.oracle.com/metalink/plsql/ml2_documents.showFrameDocument?p_database_id=BUG&amp;amp;p_id=5196815&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:courier new;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;However, they have not answered why it had been decided to have 16K on Windows and Linux. That indirectly confirms my suggestion about a "business driven decision".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-114675710516327834?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/114675710516327834/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=114675710516327834' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114675710516327834'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114675710516327834'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2006/05/followup-oracle-block-size-limit-on.html' title='Followup: Oracle block size limit on different platforms'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-114640493400800544</id><published>2006-04-30T06:47:00.000-07:00</published><updated>2006-04-30T06:48:54.016-07:00</updated><title type='text'>Oracle-like ROWNUM in MySQL</title><content type='html'>It needs sometimes to exactly mimic Oracle's ROWNUM where is no possibility to initiate a counter in previous statement by &lt;span style="font-family:courier new;"&gt;SET @rownum:=0&lt;/span&gt;;.&lt;br /&gt;&lt;br /&gt;It is still possible in a single SQL.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SELECT @rownum:=@rownum+1 rownum, t.*FROM (SELECT @rownum:=0) r, mytable t;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-114640493400800544?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/114640493400800544/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=114640493400800544' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114640493400800544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114640493400800544'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2006/04/oracle-like-rownum-in-mysql.html' title='Oracle-like ROWNUM in MySQL'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-114628013771595600</id><published>2006-04-28T19:28:00.000-07:00</published><updated>2006-04-28T20:08:57.723-07:00</updated><title type='text'>Things are even worse</title><content type='html'>Today I have found that this vulnerability can be exploited not only when a select privilege granted on a table, but also if select has been granted to a view. The view must keep keys of table though, that is to be updateable.&lt;br /&gt;Even if a view is not updateable, oracle passes DMLs through security control, then it says that view is not updateable.&lt;br /&gt;Select on a view can be granted to user directly or via role, or via chain of roles, it does not make a difference.&lt;br /&gt;&lt;br /&gt;I have granted SELECT_CATALOG_ROLE to a role that is granted to another role that is granted to an account ("hacker"). And the attack returned&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;HACKER&gt;update (...censored code to access DBA_USERS...)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;4  set password='xxx' where username='HACKER'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;set password='xxx' where username='HACKER'    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;*ERROR at line 4:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;ORA-01779: cannot modify a column which maps to a non key-preserved table&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span &gt;It means that if the view would preserve a key, that would be updateable. &lt;/span&gt;&lt;br /&gt;&lt;span &gt;And there are many views in SYS that are updatable.&lt;/span&gt;&lt;br /&gt;Resume: &lt;strong&gt;be very careful when grant any access to dictionary views&lt;/strong&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-114628013771595600?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/114628013771595600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=114628013771595600' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114628013771595600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114628013771595600'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2006/04/things-are-even-worse.html' title='Things are even worse'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-27150551.post-114619953535536071</id><published>2006-04-27T21:08:00.000-07:00</published><updated>2006-05-04T20:05:44.420-07:00</updated><title type='text'>Oracle security bug. select privilege escalation via view</title><content type='html'>&lt;p&gt;I already read about the bug on Red Database Security page "Read-only user can modify data" &lt;a href="http://www.red-database-security.com/advisory/oracle_modify_data_via_views.html"&gt;http://www.red-database-security.com/advisory/oracle_modify_data_via_views.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;This problem has been discussed on some web forums. However no clear mitigation instructions were proposed. Initially it was simple: revoke CREATE VIEW from CONNECT role and enjoy. But Andrew Max has discovered something more dangerous. &lt;&lt;a href="http://andrewmax.blogspot.com/2006/04/yet-another-security-alert.html"&gt;http://andrewmax.blogspot.com/2006/04/yet-another-security-alert.html&lt;/a&gt;&gt;&lt;br /&gt;It has not taken too much of my time to crack oracle security just having "CREATE SESSION" system privilege and "SELECT" privilege on a table of other user (see example on Andrew Max blog). I will not provide you with details how I have managed to crack an oracle authorization control.&lt;br /&gt;But I will try to provide you with some recommendations how temporarily to mitigate the threat.&lt;br /&gt;First of all, check what accounts in database have direct "SELECT" privilege on tables of other's accounts. Check both the privilege that has been granted directly to account, and granted via some role or chain of roles. &lt;/p&gt;&lt;p&gt;&lt;br /&gt;Here is an example. I create users "hacker" and "towner" (table owner).&lt;br /&gt;Hacker is a regular user that has only CREATE SESSION system privilege.&lt;br /&gt;Towner will have a table and grant select to hacker, just SELECT object privilege.&lt;br /&gt;I will not repeat the attack here. Trust me, hacker account can do whatever he wants with data in towner.emp table. That is delete, insert and update. &lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt; connect system...&lt;br /&gt;SQL&gt;create user towner identified by password 2 default tablespace users quota 1M on users;&lt;br /&gt;User created.&lt;br /&gt;SQL&gt;create user hacker identified by password;&lt;br /&gt;User created.&lt;br /&gt;SQL&gt;grant create session to hacker ;&lt;br /&gt;Grant succeeded.&lt;br /&gt;SQL&gt;create table towner.emp (id number primary key, sal number) tablespace users;&lt;br /&gt;Table created.&lt;br /&gt;SQL&gt;insert into towner.emp values (1,100);&lt;br /&gt;1 row created.&lt;br /&gt;SQL&gt;commit;&lt;br /&gt;Commit complete.&lt;br /&gt;SQL&gt;SQL&gt;grant select on towner.emp to hacker ;&lt;br /&gt;Grant succeeded.&lt;br /&gt;SQL&gt; SELECT U.USERNAME, U.ACCOUNT_STATUS, U.LOCK_DATE&lt;br /&gt;FROM DBA_USERS U WHERE ACCOUNT_STATUS='OPEN';&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;USERNAME ACCOUNT_STATUS&lt;br /&gt;------------------------------ ----------------&lt;br /&gt;SYS OPEN&lt;br /&gt;SYSTEM OPEN&lt;br /&gt;DBSNMP OPEN&lt;br /&gt;HACKER OPEN&lt;br /&gt;TOWNER OPEN &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:courier new;"&gt;&lt;p&gt;&lt;br /&gt;&lt;/span&gt;We do not bother about expired and locked accounts.&lt;br /&gt;We also can trust SYS, SYSTEM and DBSNMP*.&lt;br /&gt;Lets look who have direct access to somebody's tables (&lt;em&gt;this SQL does not show privileges acquired via roles, may be later I will write this. However the procedure below does traverse roles.)&lt;/em&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;SQL&gt;col GRANTEE format A10&lt;br /&gt;SQL&gt;col TABLE format A40&lt;br /&gt;SQL&gt;SELECT P.GRANTEE, P.OWNER'.'P.TABLE_NAME "TABLE"&lt;br /&gt;FROM DBA_TAB_PRIVS P, DBA_TABLES T, DBA_USERS U&lt;br /&gt;WHERE P.OWNER=T.OWNER AND P.TABLE_NAME=T.TABLE_NAME&lt;br /&gt;AND P.GRANTEE=U.USERNAME&lt;br /&gt;AND U.ACCOUNT_STATUS='OPEN'&lt;br /&gt;AND P.PRIVILEGE='SELECT'&lt;br /&gt;AND P.GRANTEE not in ('SYS','SYSTEM')ORDER BY 1,2;&lt;br /&gt;GRANTEE TABLE&lt;br /&gt;---------- -----------------------&lt;br /&gt;HACKER TOWNER.EMP&lt;br /&gt;ETLJOB FINANCE.GENERAL_LEDGER &lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:courier new;"&gt;&lt;p&gt;&lt;br /&gt;&lt;/span&gt;We see that above tables are potentially vulnerable for privilege escalation attack.&lt;br /&gt;Further we should figure out, who/what are these HACKER and REPORTJOB accounts. We should find out why these accounts do need direct SELECT privilege to tables.&lt;br /&gt;Lets imagine that HACKER is a legitimate human user (not a real hacker at all). All he needs is to run his reports.&lt;br /&gt;ETLJOB is an account that is used by some ETL procedure to load data warehouse.&lt;br /&gt;It is totally on your discretion, to trust or not to trust.&lt;br /&gt;How we can make sure that these accounts can not be used for attack?&lt;br /&gt;The only way I see to temporary mitigate this vulnerability is to create triggers. Statement level triggers before insert/update/delete. As a fast remedy, triggers can hardcode usernames, allowing some users to proceed, and rising an exception for others. It is very simple and fast, but may be not flexible enough in more or less rapidly changing environments or databases with large number of users and complex role based security. It can create maintenance problem when DBA has to ajust triggers all the time after users permissions or roles changed. Better way to do it is to mimic Oracle's proper, planned behavior. Oracle gets information about access privileges from its dictionary, so we can do.&lt;br /&gt;Here is an example of such trigger. &lt;em&gt;I just have created it, did not test it thoroughly, did not benchmark. Thus you should test it if you going to apply it&lt;/em&gt;. &lt;/p&gt;&lt;p&gt;I will create procedure in a SYS schema first, to get easy acces to dictionary views. This proc checks if user has Insert, Update or Delete privileges on given table, directly or via roles.&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;create or replace procedure check_obj_privs(&lt;br /&gt;owner in string, table_name in string, grantee in string,&lt;br /&gt;insertable out char, updateable out char, deleteable out char&lt;br /&gt;) as&lt;br /&gt;owner_ DBA_TAB_PRIVS.OWNER%TYPE:=owner;&lt;br /&gt;table_name_ DBA_TAB_PRIVS.TABLE_NAME%TYPE:=table_name;&lt;br /&gt;grantee_ DBA_TAB_PRIVS.GRANTEE%TYPE:=grantee;&lt;br /&gt;begin&lt;br /&gt;SELECT&lt;br /&gt;max(case when OBJ_PRIV='INSERT' then 'Y'&lt;br /&gt;when SYS_PRIV='INSERT ANY TABLE' then 'Y'&lt;br /&gt;else 'N'&lt;br /&gt;end ) INSERTABLE,&lt;br /&gt;max(case when OBJ_PRIV='UPDATE' then 'Y'&lt;br /&gt;when SYS_PRIV='UPDATE ANY TABLE' then 'Y'&lt;br /&gt;else 'N'&lt;br /&gt;end ) UPDATEABLE,&lt;br /&gt;max(case when OBJ_PRIV='DELETE' then 'Y'&lt;br /&gt;when SYS_PRIV='DELETE ANY TABLE' then 'Y'&lt;br /&gt;else 'N'&lt;br /&gt;end ) DELETEABLE&lt;br /&gt;INTO insertable, updateable, deleteable&lt;br /&gt;FROM (&lt;br /&gt;SELECT P.PRIVILEGE OBJ_PRIV, S.PRIVILEGE SYS_PRIV&lt;br /&gt;FROM&lt;br /&gt;(SELECT ROLE, GRANTED_ROLE&lt;br /&gt;FROM ROLE_ROLE_PRIVS P&lt;br /&gt;CONNECT BY PRIOR GRANTED_ROLE = ROLE&lt;br /&gt;START WITH ROLE IN (SELECT S.GRANTED_ROLE&lt;br /&gt;FROM DBA_ROLE_PRIVS S WHERE GRANTEE=grantee_)) R&lt;br /&gt;LEFT OUTER JOIN DBA_TAB_PRIVS P ON P.GRANTEE IN (R.GRANTED_ROLE, R.ROLE, grantee_)&lt;br /&gt;LEFT OUTER JOIN DBA_SYS_PRIVS S ON S.GRANTEE IN (R.GRANTED_ROLE, R.ROLE, grantee_)&lt;br /&gt;AND S.PRIVILEGE IN ('INSERT ANY TABLE','UPDATE ANY TABLE','DELETE ANY TABLE')&lt;br /&gt;WHERE P.OWNER=owner_ AND P.TABLE_NAME=table_name_ );&lt;br /&gt;end;&lt;br /&gt;/&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;grant execute on sys.check_obj_privs to public;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Then I create trigger.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;create or replace trigger towner.PROTECT_EMP_BIUD&lt;br /&gt;before insert or update or delete&lt;br /&gt;on towner.emp&lt;br /&gt;declare i char; u char; d char;&lt;br /&gt;begin&lt;br /&gt;if user not in ('SYS','SYSTEM','TOWNER') then&lt;br /&gt;sys.check_obj_privs( 'TOWNER', 'EMP', user, i, u, d);&lt;br /&gt;--dbms_output.put_line(i':'u':'d);&lt;br /&gt;if (inserting and i!='Y')&lt;br /&gt;or(deleting and d!='Y')&lt;br /&gt;or(updating and u!='Y')&lt;br /&gt;then&lt;br /&gt;raise_application_error(-20031, 'insufficient privileges');&lt;br /&gt;end if;&lt;br /&gt;end if;&lt;br /&gt;end;&lt;br /&gt;/&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Test&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;HACKER&gt;select * from session_roles;&lt;br /&gt;ROLE&lt;br /&gt;------------------------------&lt;br /&gt;SELECT_TNAME_EMP_ROLE&lt;br /&gt;1 row selected.&lt;br /&gt;HACKER&gt;select * from session_privs;&lt;br /&gt;PRIVILEGE&lt;br /&gt;-----------------------------------&lt;br /&gt;CREATE SESSION&lt;br /&gt;1 row selected.&lt;br /&gt;HACKER&gt;select id, sal from towner.emp;&lt;br /&gt;ID SAL&lt;br /&gt;---------- ----------&lt;br /&gt;1 100&lt;br /&gt;1 row selected.&lt;br /&gt;Hacker can select, that is OK.&lt;br /&gt;HACKER&gt;update towner.emp set sal=0;&lt;br /&gt;update towner.emp set sal=0&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:ORA-01031: insufficient privileges&lt;br /&gt;Hacker can not update, which is OK too.&lt;br /&gt;&lt;br /&gt;HACKER&gt;UPDATE&lt;br /&gt;(&lt;em&gt;&lt;span style="color:#990000;"&gt;censored code of specifically crafted dynamic view to TOWNER.EMP table&lt;/span&gt;)&lt;/em&gt;&lt;br /&gt;SET SAL=0; &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;UPDATE&lt;br /&gt;*&lt;br /&gt;ERROR at line 1:&lt;br /&gt;ORA-20031: insufficient privileges&lt;br /&gt;ORA-06512: at "TOWNER.PROTECT_EMP_BIUD", line 13&lt;br /&gt;ORA-04088: error during execution of trigger 'TOWNER.PROTECT_EMP_BIUD'&lt;/span&gt;&lt;/p&gt;&lt;p&gt;It works!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/27150551-114619953535536071?l=markmal.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://markmal.blogspot.com/feeds/114619953535536071/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=27150551&amp;postID=114619953535536071' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114619953535536071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/27150551/posts/default/114619953535536071'/><link rel='alternate' type='text/html' href='http://markmal.blogspot.com/2006/04/oracle-security-bug-select-privilege.html' title='Oracle security bug. select privilege escalation via view'/><author><name>Mark Malakanov</name><uri>http://www.blogger.com/profile/00911083264678502296</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
