Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

DBI: data types, binding and insertions

by Sandy (Curate)
on Dec 13, 2008 at 00:47 UTC ( [id://730087]=perlquestion: print w/replies, xml ) Need Help??

Sandy has asked for the wisdom of the Perl Monks concerning the following question:

I am trying, for the very first time, to insert a bunch of data into a database.

I have read DBI over and over, but I cannot seem to resolve my problem.

In DBI it states clearly that one cannot change the data type of bound variables

The data type for a bind variable cannot be changed after the first bind_col call. In fact the whole \%attr parameter is 'sticky' in the sense that a driver only needs to consider the \%attr parameter for the first call for a given $sth and column.
But I have string data that is sometimes empty, and when I try to insert that row, the database complains.

I have tried many different combinations, but the only thing that seems to work is if I replace the empty string with a string of at least one character.

Sample code is shown below (most of my error checking has been removed to simplify the code)

#!/usr/bin/perl use strict; use warnings; use DBI; use DBD::ODBC; use DBI qw(:sql_types); use Data::Dumper; my $username = 'user'; my $password = "password"; my $stat; # connect my $oracle_db = $ENV{ORACLE_DB}; my $dbh; eval { $dbh = DBI->connect( "DBI:ODBC:$oracle_db", "$username", "$pass +word" ); }; unless ($dbh) { die "couldn't connect, $DBI::errstr"; } my $sql = 'INSERT INTO xyz.table (id,num, name,descr) VALUES (?,?,?,?)'; my $sth = $dbh->prepare($sql); $stat = $sth->execute("302","1","Next",'descr 4'); print Dumper \$stat; $stat = $sth->execute("302","1","Another",' '); print Dumper \$stat; $stat = $sth->execute("302","1","Yet",''); print Dumper \$stat; $stat = $sth->execute("302","1","Again",undef); print Dumper \$stat; $sth->bind_param(1,"302",SQL_VARCHAR); $sth->bind_param(2,"1",SQL_VARCHAR); $sth->bind_param(3,"AACH",SQL_VARCHAR); $sth->bind_param(4,"",SQL_VARCHAR); $stat = $sth->execute(); print Dumper \$stat; exit;
I have also tried inserting $sth->finish() in-between each attempt, to no avail.

Next and Another will be inserted into the db, but nothing else will.

I am using ODBC to connect to an Oracle database using "DataDirect" wire protocol. One of the error messages is (added /n to make it easier to read):

DBD::ODBC::st execute failed: [DataDirect][ODBC Oracle Wire Protocol driver] Data type for parameter 4 has changed since first SQLExecute call. (SQL-HY000) (DBD: st_execute/SQLExecute err=-1) at question.pl line 33.

Notes: If I comment out the insertions of Next and Another, then the other rows will be inserted (i.e. there is no restriction to empty or null values for the 4th parameter)

So, my question is... how do I make an empty string look to be the same datatype as a non-empty string?

Sandy

Replies are listed 'Best First'.
Re: DBI: data types, binding and insertions
by almut (Canon) on Dec 13, 2008 at 02:24 UTC
    Data type for parameter 4 has changed since first SQLExecute call.

    I think this isn't really a DBI issue, but rather a driver specific (mis)feature...

    You could try WorkArounds=536870912 (no, not kidding :) — or, as I dimly recall 'WorkArounds' not being applicable with the wire protocol driver (see the readme), try the other suggestion (SQLFreeStmt) made in the thread I linked to.  Good luck!

      Yes, thank you. It worked like a charm! (it referring to the workaround solution.)

Re: DBI: data types, binding and insertions
by runrig (Abbot) on Dec 13, 2008 at 02:47 UTC
    I've had the same problem with the Sybase DataDirect ODBC driver (I've resorted to re-preparing every SQL statement before every execute). For Oracle, I've used the "Oracle in OraClient10g_home1" driver (I haven't even tried the DataDirect driver for Oracle though I do have it) and I have no problems with your code (though you should think about using RaiseError in the connect).

    Update: And ever since ActivePerl has started coming bundled with with the DBD::Oracle module (using the native Oracle driver rather than ODBC), I've used that with no issues also (though some things still use ODBC). And almut's workaround looks like it's worth a try though I don't know when or if I'll get around to trying it :-)

Re: DBI: data types, binding and insertions
by roboticus (Chancellor) on Dec 13, 2008 at 12:49 UTC
    Sandy:

    If you never want a '' in that column in your database, perhaps you can use something (hideous) like:

    INSERT INTO xyz.table (id,num, name,descr) select id, num, name, case when descr='' then null else descr end from (select ? as id, ? as num, ? as name, ? as descr) A

    and then use '' instead of undef to insert a null into the descr column...

    ...roboticus

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://730087]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (2)
As of 2024-04-24 23:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found