1

We use a Java-based application to deploy XML files, which are written to an Oracle database. The XML blobs in the db are stored as NCLOB data types. How would I go about getting the NCLOB XML data from the database and back into XML format? Would I need to use Java (I'm a complete Java noob, BTW), or could I use PowerShell here (my preference)? And depending on the method, how would I do this?

The reason I want to do this is mostly for pre/post deployment validation (compare the XML content before and after it's been deployed).

Thanks in advance, Keith

Keith
  • 1,959
  • 10
  • 35
  • 46

2 Answers2

3

Here's what I've done in the past to read/write XML in a Oracle CLOB using ODAC. This should work for NCLOB with very little modification.

# Load ODAC. This might fail if it is not installed or is the wrong bitness.
$assembly = [System.Reflection.Assembly]::LoadWithPartialName("Oracle.DataAccess")

# Connect to Oracle.
$connStr = 'Data Source=hostname:1521/sidname; User Id=sys; Password=password; DBA Privilege=SYSDBA;'
$conn = New-Object Oracle.DataAccess.Client.OracleConnection -ArgumentList $connStr
$conn.Open()

# Query the table.
$q = "select MY_CLOB_FIELD from My_Table"
$command = new-object Oracle.DataAccess.Client.OracleCommand($q, $conn)

# Process records.
$reader = $command.ExecuteReader()
while ($reader.Read()) {
    # Read the CLOB field and cast to an XML document.
    $xmlDoc = [xml] $reader.getstring(0) # XML

    #... XML Processing Here ....

    # Commit the updated XML.
    $sql = "UPDATE My_Table SET MY_CLOB_FIELD = :1"
    $updateCmd = New-Object Oracle.DataAccess.Client.OracleCommand ($sql, $conn)

    $param = New-Object Oracle.DataAccess.Client.OracleParameter (
        "xml", #Name
        [Oracle.DataAccess.Client.OracleDbType]::Clob, #Type
        $xmlDoc.OuterXml, #Data
        'Input' #Direction
    )

    $newParam = $updateCmd.Parameters.Add($param) 
    $result = $updateCmd.ExecuteNonQuery()
}
Andy Arismendi
  • 50,577
  • 16
  • 107
  • 124
  • Thanks Andy. I will give your solution a try. Quick question, what do I pass in for DataSource? In my PowerShell scripts I usually connect to our dB's using sqlplus syntax (e.g. `username/password@//hostname:Port/SID`). How would this connection string be translated to be used in your script above? – Keith Feb 16 '12 at 03:30
  • @Keith Check out your options under the `.NET Framework Data Provider for Oracle` section [here](http://www.connectionstrings.com/oracle). `Data Source` is a TNS alias but you don't have to use that. Check out the `Omiting tnsnames.ora` options. – Andy Arismendi Feb 16 '12 at 03:40
  • @Keith Don't forget, you'll need to install ODAC to use `Oracle.DataAccess`. – Andy Arismendi Feb 16 '12 at 03:41
  • Andy, thanks again for your feedback. Much appreciated! I'll let you know how things work out. – Keith Feb 16 '12 at 03:48
  • @Keith np, I think you'll also find [this](http://docs.oracle.com/html/E10927_01/featConnecting.htm) helpful. – Andy Arismendi Feb 16 '12 at 03:52
1

This is the code I ended up using:

$Assembly = [System.Reflection.Assembly]::LoadWithPartialName("System.Data.OracleClient")

$conn = New-Object System.Data.OracleClient.OracleConnection( `
“Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=port)) `
(CONNECT_DATA=(SERVICE_NAME=SID)));User Id=username;Password=password;”);

$conn.Open()

# Query the table.
$q = "SELECT column FROM table WHERE column='something'"
$command = New-Object System.Data.OracleClient.OracleCommand ($q, $conn)

$xmlfile = "c:\temp\xml\temp.xml"
# Process records.
$reader = $command.ExecuteReader()
while ($reader.Read()) 
{
    # Read the NCLOB field and cast to an XML document.
    $xmlDoc = [xml] $reader.getstring(0) # XML
    $xmlDoc.Save($xmlfile)
}
$conn.Close()

@Andy, thanks for steering me in the right direction! :-)

Keith
  • 1,959
  • 10
  • 35
  • 46
  • Be warned that - [Types in System.Data.OracleClient are deprecated and will be removed in a future version of the .NET Framework.](http://msdn.microsoft.com/en-us/library/system.data.oracleclient.aspx) – Andy Arismendi Feb 16 '12 at 23:23
  • Dang it! I didn't notice that. Thanks for the heads up. Anyway, the reason I went down this path is because I kept getting errors trying to connect using `Oracle.DataAccess.Client.OracleConnection`. Here is as far as I got before hitting the error: `$assembly = [System.Reflection.Assembly]::LoadWithPartialName("Oracle.DataAccess")` `$conn = New-Object Oracle.DataAccess.Client.OracleConnection( `` “Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=hostname)(PORT=port)) `` (CONNECT_DATA=(SERVICE_NAME=SID)));User Id=username;Password=password;”);` – Keith Feb 17 '12 at 00:09
  • And here is the error message: `New-Object : Exception calling ".ctor" with "1" argument(s): "An attempt was made to load a program with an incorrect format.` – Keith Feb 17 '12 at 00:10
  • I would prefer to use your solution Andy but need to get passed that error. Have had no luck so far. – Keith Feb 17 '12 at 00:41
  • I updated my answer with an example of a connection string that is like what you are used to using. Don't use `DBA Privilege=SYSDBA;` if you don't need it. – Andy Arismendi Feb 17 '12 at 02:26
  • Thanks for the updated code, but I'm still getting the same error. – Keith Feb 17 '12 at 04:54
  • Hmm I actually just copied pasted that from working code I was using yesterday to connect to Oracle 11g with PowerShell. I used ODAC 32 bit so I had to use 32 bit PowerShell since my client is a 64 bit OS. – Andy Arismendi Feb 17 '12 at 15:57
  • That helped. I'm running a 64-bit OS at work and was running 64-bit PowerShell. I switched to 32-bit PowerShell and got through the previous error. However, I have a new error. When I attempt to run `$conn.Open()` I get the following error: `Exception calling "Open" with "0" argument(s): "ORA-12154: TNS:could not resolve the connect identifier specified"` Thoughts? – Keith Feb 17 '12 at 19:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7864/discussion-between-andy-arismendi-and-keith) – Andy Arismendi Feb 17 '12 at 19:18