On 08/09/10 21:24, Roode, Eric wrote: > Hello all, > > I am trying to implement error handling in our stored procedures, > but when I raise exceptions in the SQL code, they seem to disappear on > their way back to the Perl app. I've searched the archives, but > haven't found an answer. > > I'm using DBI 1.609 with DBD::ODBC 1.23 under strawberry Perl 5.12 > on Windows 7, against a SQL Server 2000 database elsewhere on our LAN. > > I've created a simple sproc to generate an error, as follows: > > create procedure error_test (@p1 varchar(50), @p2 int output) > as > set @p2=45; > raiserror ('An error was raised. Input was "%s".', 16, 1, @p1) > return 55 > GO > > Here is a simple Perl program to invoke it: > > use Modern::Perl; > use DBI; > > sub handle_error > { > my ($state, $msg, $native) = @_; > say qq{handle_error: \$state is "$state".}; > say qq{handle_error: \$msg is "$msg".}; > say qq{handle_error: \$native is "$native".}; > return 1; > } > > my $dbh = DBI->connect('DBI:ODBC:driver={SQL > Server};Server=xxxxx;Database=xxxxx, > 'xxxxx', 'xxxxx', > {odbc_cursortype => 2, > odbc_default_bind_type => DBI::SQL_VARCHAR, > odbc_err_handler => \&handle_error, > RaiseError => 1, > PrintError => 0, > }); > > my $sth = $dbh->prepare('{? = call error_test(?, ?)}'); > > # Set up parameters > my $retval; > my $p1 = 'Some input parameter'; > my $p2 = 75; > $sth->bind_param_inout(1, \$retval, 4000, DBI::SQL_VARCHAR); > $sth->bind_param (2, $p1, DBI::SQL_VARCHAR); > $sth->bind_param_inout(3, \$p2, 32, DBI::SQL_INTEGER); > > # Execute > $sth->execute; > > # Show what we got > $_ = defined($_)? qq{"$_"} : '{NULL}' for ($retval, $p1, $p2); > say qq{After execute: \$retval is $retval.}; > say qq{After execute: \$p1 is $p1.}; > say qq{After execute: \$p2 is $p2.}; > say 'Done.'; > > > Sadly, handle_error never gets called. The output of the program is: > > After execute: $retval is {NULL}. > After execute: $p1 is "Some input parameter". > After execute: $p2 is "75". > Done. > > On the other hand, if I do something like try to call a nonexistent > stored procedure, handle_error does get invoked, and the output looks > like: > handle_error: $state is "42000". > handle_error: $msg is "[Microsoft][ODBC SQL Server Driver][SQL > Server]Could not find stored procedure 'blefh_error_test'.". > handle_error: $native is "2812". > > > What do I have to do to detect the SQL exception? > > Thanks, > -- Eric > >
Works fine for me (although possibly under different conditions): use DBI; use strict; sub handle_error { my ($state, $msg, $native) = @_; print qq{handle_error: \$state is "$state".}, "\n"; print qq{handle_error: \$msg is "$msg".}, "\n"; print qq{handle_error: \$native is "$native".}, "\n"; return 1; } my $dbh = DBI->connect('dbi:ODBC:baugi','sa','easysoft', {odbc_err_handler => \&handle_error}); eval { local $dbh->{PrintError} = 0; $dbh->do("drop procedure t_raiserror"); }; $dbh->do(<<'EOT'); CREATE PROCEDURE t_raiserror (@p1 varchar(50), @p2 int output) AS set @p2=45; raiserror ('An error was raised. Input was "%s".', 16, 1, @p1) return 55 EOT sub test() { my $sth = $dbh->prepare("{? = call t_raiserror(?,?)}"); my ($p1, $p2) = ('fred', undef); $sth->bind_param_inout(1, \my $retval, 4000); $sth->bind_param(2, $p1); $sth->bind_param_inout(3, \$p2, 32); $sth->execute(); print qq{After execute: \$retval is $retval.}, "\n"; print qq{After execute: \$p1 is $p1.}, "\n"; print qq{After execute: \$p2 is $p2.}, "\n"; } #$dbh->{odbc_err_handler} = \&handle_error; test(); $dbh->disconnect; perl raiserror.pl handle_error: $state is "42000". handle_error: $msg is "[unixODBC][Easysoft][SQL Server Driver][SQL Server]An error was raised. Input was "fred".". handle_error: $native is "50000". DBD::ODBC::st execute failed: [unixODBC][Easysoft][SQL Server Driver][SQL Server]An error was raised. Input was "fred". (SQL-42000) at raiserror.pl line 37. After execute: $retval is . After execute: $p1 is fred. After execute: $p2 is . I had to take out odbc_cursortype and odbc_default_bind_type as they produced other errors with the driver I was using. You could send me a level 15 trace and I might see something but it looks like raiserror in your case is not raising an error. I was using Perl 5.10.1, DBD::ODBC 1.24_3, DBI 1.609 on Ubuntu Linux with the Easysoft SQL Server ODBC Driver. Martin -- Martin J. Evans Easysoft Limited http://www.easysoft.com