DBI :: преобразование данных Sybase привело к переполнению - PullRequest
3 голосов
/ 07 июля 2011

Я пишу сценарий Perl, который использует модуль DBI и подключается к базе данных Sybase. Я вызываю хранимую процедуру (к которой у меня нет доступа, поэтому я не могу опубликовать пример кода), и когда я получаю данные обратно, я получаю сообщение об ошибке «error_handler: преобразование данных привело к переполнению». Я все еще возвращаю данные, и после некоторых интенсивных исследований кажется, что некоторые типы данных в столбцах (такие как BigInt, nvarchar и т. Д.) Являются виновниками. Теперь вопрос, как я могу это исправить? Это можно исправить на стороне клиента или только на стороне сервера?

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
}

Часть журнала FreeTDS 0.82, которая объясняет проблему:

_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

1 Ответ

2 голосов
/ 11 августа 2011

Проблема на стороне 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;

Конечно, если ваш исходный оператор большесложный, вы должны распечатать его и проверить, как изменить его с помощью общей замены, несущей тот же дух.Кроме того, вы можете попросить своего администратора БД (или любого, кто имеет доступ к хранимой процедуре) напрямую изменить фактический запрос.

Надеюсь, это поможет.

...