3

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 bytes) 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
4

1 回答 1

2

问题出在 FreeTDS 方面。我之前遇到过同样的问题,并通过将返回的字段转换为varchar语句中的select方式成功修复了它。

鉴于您无权修改原始查询,您可以对$sql代码中返回的变量进行一些正则表达式搜索和替换。特别是,如果原始查询有一部分看起来像

SELECT field1, field2, field3 FROM ...

检索查询语句后,您可以运行

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;

当然,如果您的原始语句更复杂,您应该将其打印出来并检查如何使用具有相同精神的通用替换来修改它。或者,您可以要求您的 DBA(或有权访问存储过程的任何人)直接修改实际查询。

希望这可以帮助。

于 2011-08-11T16:05:03.343 回答