Thanks for the tip. I thought that using placeholders can help with 
execution plan caching. Nonetheless, at this point optimization is not my 
#1 priority.

Here is a new peculiarity that I've discovered. For the T-SQL code bellow, 
DBD::ODBC will return a single record set containing @ret and @b, while 
DBD::Sybase returns 3 record sets:

1) 0  -- return code for the overall code block
2) 321 -- output @b parameter
3) 42, 321 -- results of the 'select' statement

Details are in DBD::Sybase docs under "Handling Multiple Result Sets". 
Suggested work around include using while($sth->{syb_more_results}) loop. 
Suffice to say that this is not exactly a cross-drive solution. Luckily, 
DBD::ODBC contains an equivalent 'odbc_more_results'. Thus, the code 
becomes

##############################

my $query = qq|
    begin
        declare @ret int, @b int
        exec @ret = dbo.foo $a, @b out
        select @ret, @b
    end|;
 
my $sth = $db->prepare($query) or die $db->errstr;
$sth->execute();

my ($d, $next_rs_flag);
if ($^O eq 'MSWin32')  {
        $next_rs_flag = 'obdc_more_results';
} else {
        $next_rs_flag = 'syb_more_results';
}

do {
   while ($d = $sth->fetch) {
        # 2 params returned by 'SELECT' recordset
        # talk about "hackiness"
      if (2 == @$d) {
         print scalar @$d . "\n";
      }
   }
} while ($sth->{$next_rs_flag});
 
##############################

Thought you'd like to know.

Best,

Dmitry





David Goodman <[EMAIL PROTECTED]> 
02/10/2005 01:19 PM

To
[email protected]
cc

Subject
[Spam: 05.3] Re: DBD::ODBC, DBD::Sybase and parameters to stored 
procedures






Placeholders are only supported for values in select
statements. For your exec, you will need to substitute
in values with perl variables.

That's the essence of the error message.

regards,

David
--- [EMAIL PROTECTED] wrote:

> Hi all,
> 
> Trying to solve a puzzle -- how to write a
> cross-platform code to call 
> stored procedure with output parameters and return
> codes.
> 
> Environment:
> - MS SQL 2000 database
> - Win32, ActivePerl - 5.8.6, DBD::ODBC
> - Linux, perl 5.8.0, DBD::Sybase (freeTDS)
> 
> Stored procedure:
> 
> ----------------------------------------------------
> CREATE proc dbo.foo
>         @a      int,
>         @b      int OUTPUT
> as
> set @b = 321
> return 42
> GO
> ----------------------------------------------------
> 
> Perl code snippet:
> 
> ##############################
> 
> my $query = q|
>     begin
>         declare @ret int, @b int
>         exec @ret = dbo.foo ?, @b out
>         select @ret, @b
>     end|;
> 
> my $sth = $db->prepare($query) or die $db->errstr;
> $sth->execute($a);
> 
> my (@d) = $sth->fetchrow_array;
> $ret = $d[0];
> $b = $d[1]; 
> 
> ##############################
> 
> The code runs with DBD::ODBC but blows up in
> DBD::Sybase with:
> 
> Panic: dynamic SQL (? placeholders) are not
> supported by the server you 
> are connecting to at ...
> 
> Hence, the questions:
> 
> 1. Do newer versions (> 1.61) of DBD::Sybase support
> dynamic placeholders?
> 
> 2. Is there a better way to write the above
> cross-driver code?
> 
> Prior to this hackiness I tried variations of a
> "clean" approach -- using 
> $sth->bind_param_inout(). These mostly break down in
> DBD::Sybase.
> 
> 
> Thanks,
> 
> Dmitry.


Reply via email to