Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Re: Sql problem in Win32::ODBC

by monktim (Friar)
on Aug 07, 2003 at 16:31 UTC ( [id://281959]=note: print w/replies, xml ) Need Help??


in reply to Sql problem in Win32::ODBC

Check the ID column and see if it is defined as an integer column. It may be a char, varchar, etc. Then you'll need the quotes as the above poster mentioned.

You may want to make the ID column your identity column. You can give this column that attribute which will automatically create a unique number and insert it for you. The column may actually already have this attribute and passing an ID value will cause your error.

If the ID column has the identity attribute then the uniqueness is already defined and managed for you. But if you don't want ID to be an identity and still want to insure uniqueness you may want to create a unique constraint on the ID column in the dB. A unique constraint will protect the table from being updated by other client processes that don't check to see if the ID already exists before doing an INSERT, thus corrupting your table.

You can also formulate your sql code to use EXISTS. Doing this you only send one message to the dB. This reduces network traffic and database server processing. It also simplifies your perl code a lot.
IF NOT EXISTS (SELECT * FROM ENTITIES WHERE ID = $MaxEntityId) INSERT INTO ENTITIES (ID,TYPE,NAME) VALUES ($MaxEntityID, '$type', '$name')
But if the ID column is an identity column then all you have to do is this (assuming type and name together also uniquely identify a row (they're an alternate or candidate key)):
IF NOT EXISTS (SELECT * FROM ENTITIES WHERE TYPE = $type AND NAME = $name) INSERT INTO ENTITIES (TYPE, NAME) VALUES ('$type', '$name')
Making the ID column have the identity property you can reduce your perl code to this:
################ NOTE: UNTESTED CODE use strict; use warnings; use Win32::ODBC; my $dB = new Win32::ODBC("DSN=name;UID=user;PWD=password;"); die 'Cannot connect to dB.' if !$dB; my %tests = ( COUNTRY => 'UNITED_STATES', PERSON => 'FRED', PERSON => 'JOE' ); my ($type, $name); while (($type, $name) = each %tests) { my $query = qq( IF NOT EXISTS ( SELECT * FROM ENTITIES WHERE TYPE = '$type' AND NAME = '$name' ) INSERT INTO ENTITIES (TYPE, NAME) VALUES ('$type', '$name') ); my $rc = $dB->Sql($query); die "Query failed: $query ".Win32::ODBC::Error() if $rc; }
Another problem can be that your script doesn't have permission to modify the table. Set the permission on the ENTITIES table to public and try your script again. If it works then you can decide what the correct table permissions should be.
Good luck

Replies are listed 'Best First'.
Re: Re: Sql problem in Win32::ODBC
by fletcher_the_dog (Friar) on Aug 07, 2003 at 18:05 UTC
    Well, it turns out it was a permissions problem. It seems to work fine now. Thanks!
      Great! Database object permissions are highly overlooked problems when used with Perl. OBDC's error messages are painted with a pretty broad stroke so they're not easy to detect.

      If you print the sql code out from the script then cut and paste it to sql and it runs you can be sure the problem isn't in Perl. Chances are it is permissions on the dB object, the ODBC data source is set up incorrectly or you are connected to the wrong database. The problem can also be that the sql server is disconnected. ODBC does give you a good error message when the connection doesn't exist.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2024-04-24 00:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found