2011-07-06 2 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) 드라이버에서 디버깅 할 때 소스 유형 및 옥텟 길이가 대상 유형 및 8 진수 길이로 변환되는 것을 확인해야합니다. – 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 (또는 스토어드 프로 시저에 액세스 권한이있는 사람)에게 실제 쿼리를 직접 수정하도록 요청할 수 있습니다.

희망이 도움이됩니다.

관련 문제