2011-07-06 6 views
3

DBIモジュールを使用してSybase DBに接続しているPerlスクリプトを作成しています。私はストアドプロシージャ(私はサンプルコードを投稿することはできませんので、私はアクセス権がありません)を呼び出すときに、私は "error_handler:データ変換の結果、オーバーフローが発生しました"というエラーが表示されます。私はまだデータを取り戻し、いくつかの集中的な研究を行った後、列内のいくつかのデータ型(BigInt、nvarcharなど)が原因であるようです。今問題は、どうすればこの問題を解決できますか?これはクライアント側で修正できますか、またはサーバー側でのみ修正できますか?DBI :: Sybaseデータ変換でオーバーフローが発生しました

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 
+0

私はDBD :: Sybaseは使用しませんが、他のDBDの負荷を使います。既知のバグでない限り、誰もがこの質問に答えようとしているのではないかと疑う。最低限、Perlがプロシージャを呼び出すときに、返されるべきスキーマとデータの例とその入手方法を記載してください。 – bohica

+0

これはFreeTDS警告です。私たちが知らないことは、DBD :: Sybaseが内部的に間違った仮定をしているかどうか、適切な型変換を強制するために賢明なSQLでストアドプロシージャ呼び出しをラップできるかどうかなどです。 ["function trace andドライバでの "info"](http://www.freetds.org/userguide/freetdsconf.htm)のデバッグを参照してください。どのソースタイプとオクテット長がどの宛先タイプとオクテット長に変換されているかを確認する必要があります。 – pilcrow

+1

こんにちは、私はあなたが尋ねたことをしたし、私は原因を見つけたと信じています。 FreeTDSがやっていることは、BigIntの値(10桁の数字)を9バイトの文字列に変換しようとしていることです。値に9桁以上あるので、オーバーフローがあります。このエラーがデータベース側から来ているのか、それともFreeTDSのバグなのかはわかりません。私はFreeTDSを使用しているレコードのために0.82 – Dan

答えて

2

問題はFreeTDSの側にあります。私は前に同じ問題を抱えており、返されたフィールドを 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(またはストアドプロシージャへのアクセス権を持つ者)に実際のクエリを直接変更するよう依頼することもできます。

これが役に立ちます。

関連する問題