开发者

DBI::Sybase data-conversion resulted in overflow

开发者 https://www.devze.com 2023-03-17 15:24 出处:网络
I am writing a Perl script that is using the DBI module and is connecting to a Sybase DB. I am calling a stored procedure (one that I don\'t have access to so I cannot post sample code) and when I get

I am writing a Perl script that is using the DBI module and is connecting to a Sybase DB. I am calling a stored procedure (one that I don't have access to so I cannot post sample code) and when I get data back I get an error that reads "error_handler: Data-conversion resulted in overflow". I still get data back and after doing some intensive research it seems that some data types in the columns (such as BigInt, nvarchar, etc) are the culprits. Now the question is, how can I fix this? Can this be fixed on the client side or can it only be fixed on the server side?

my $dbh = DBI->connect("DBI:Sybase:server=$server", $username, $password, {PrintError => 0}) or die;
$dbh->do("use $database") or die;
my $sql = &getQuery;
my $sth = $dbh->prepare($sql) or die;
$sth->execute() or die;
while ($rowRef = $sth->fetchrow_arrayref) #Error seems to occur here
{
     #Parse through each row
}

Part of the FreeTDS 0.82 log that explains the problem:

_ct_bind_data(): column 7 is type 38 and has length 8
_ct_get_server_type(0)
_ct_get_client_type(type 38, user 0, size 8)
cs_convert(0x18dfed40, 0x7fff73216050, 0x18e44250, 0x7fff73215fa0, 0x18e387c0, 0x18e45a64)
_ct_get_server_type(30)
_ct_get_server_type(0)
converting type 127 (8 byte开发者_如何学Gos) to type = 47 (9 bytes)
cs_convert() calling tds_convert
cs_convert() tds_convert returned 10
cs_prretcode(0)
cs_convert() returning  CS_FAIL
cs_convert-result = 1


The problem is on the FreeTDS side. I've had the same problem before and successfully fixed it by converting the returned fields to varchar in the select statement.

Given you don't have access to modify the original query, you can do some regex search and replace on the returned $sql variable in your code. In particular, if the original query has a part that looks like

SELECT field1, field2, field3 FROM ...

After you retrieve the query statement, you may run

my $new_sql;
if ($sql =~ /SELECT\s+(.*)\s+FROM/i) {  # match selected field string
    my $field_str = $1;
    my @fields = split ",", $field_str; # parse individual fields
    map s/\s//g, @fields;               # get rid of spaces
    my $new_str = join ", ", (map {sprintf "convert(varchar, $_)"} @fields);    # construct new query string
    my $quoted_field_str = quotemeta($field_str);   # prepare regex replacement string
    $new_sql = $sql;    
    $new_sql =~ s/$quoted_field_str/$new_str/i  # actual replacement
}
print $new_sql;

Of course, if your original statement is more complex, you should print it out and check how to modify it with a generic replacement bearing the same spirit. Alternatively, you can ask your DBA (or whoever has access to the stored procedure) to modify the actual query directly.

Hope this helps.

0

精彩评论

暂无评论...
验证码 换一张
取 消