Perl、DBD::Oracle 和 Oracle 10g 中的字符集问题

3
我们的Oracle 10g数据库中出现了基本ASCII字符集之外的字符,这些字符会以倒置的问号形式出现。
我有以下脚本用于加载一些测试数据。该脚本在Komodo IDE上保存为Latin-1/ISO-8859-1格式,并存储在远程UNIX服务器上:
#!/wload/espd/app/perl/bin/perl

use strict; 
use warnings;
use Encode;
use esp_libs_db;
my $dbh = espDbConnectNew();

my $sql = q{ INSERT INTO DBUSER.test VALUES ('qwérty')};

#$sql = encode("iso-8859-1", $sql);

my $rows = $dbh->do($sql)  or Carp::croak "ERROR: PM_DB_0010:[" . $DBI::errstr . "]   Cannot run stmt:\n";;
print $rows;
$dbh->commit();
$dbh->disconnect();



sub espDbConnectNew {
    my ( $database ) = @_;    
    my %connectionStrings = &esp_libs_db::espGetConnectionStrings( $database );

    # Set Environment Variables
    $ENV{ORACLE_SID}=$connectionStrings{"SID"};
    $ENV{ORACLE_HOME}=$connectionStrings{"HOME"};
    my $dbh = DBI->connect("dbi:Oracle:SID=$connectionStrings{'SID'};HOST=$connectionStrings{'HOST'};PORT=$connectionStrings{'PID'}",
    "$connectionStrings{'USER'}","$connectionStrings{'PWD'}",
    {PrintError=>0,
    RaiseError => 0,
    AutoCommit => 0}
) or Carp::croak "ERROR: PM_DB_0003:  Cant connect to db:\n";


    return $dbh;
} #espDbConnect

它所加载的数据库是一个Oracle 10g数据库,具有以下参数:
NLS_NCHAR_CHARACTERSET  AL16UTF16
NLS_LANGUAGE    ENGLISH
NLS_TERRITORY   UNITED KINGDOM
NLS_CHARACTERSET    WE8ISO8859P1

测试表中的单列类型为VARCHAR2(255)。

尽管我整天都在阅读这些问题,但我真的不知道该怎么做才能解决/诊断出确切的问题。

我已经尝试过使用Encode对SQL字符串进行编码和不进行编码来执行它。

谢谢

1个回答

1
你在获取数据时遇到倒置的问号,是怎样检索数据的?在检索数据的客户端上,NLS_LANG 环境变量是什么?
在 SQL*Plus 中,你能否运行?
SELECT dump( column_name, 1013 ), column_name
  FROM DBUSER.test

并发布结果?DUMP函数显示实际存储在数据库中的内容--这将显示问题是在存储重音字符还是在检索重音字符。


我正在使用PLSQL,但不确定如何确定它正在使用的NLS_LANG。注册表中是AMERICAN_AMERICA.WE8MSWIN1252,但我不知道是否有任何东西可以覆盖它。如果我运行转储,那么我会得到Typ=1 Len=6 CharacterSet=WE8ISO8859P1: 113,119,191,114,116,121 qw¿rty。如果我在UNIX服务器上选择数据,则会遇到相同的问题。这只是一个小测试脚本,以消除像内容类型字符集这样的因素。 - Nick
澄清一下,我在使用DBI时没有在UNIX客户端上明确设置NLS_LANG。 - Nick
我不确定 "in PL/SQL" 是什么意思。你是指 SQL*Plus 吗? 根据DUMP输出,似乎问题出在存储字符上(ISO 8859-1 中的191是倒置的问号字符)。在运行脚本之前,可以在UNIX客户端上将NLS_LANG设置为AMERICAN_AMERICA.WE8ISO8859P1吗? - Justin Cave
抱歉 - 我漏掉了一个非常关键的词...我指的是由allround automations开发的'PLSQL Developer'。我尝试在设置ORACLE_HOME之后添加一行代码$ENV{NLS_LANG} = 'AMERICAN_AMERICA.WE8ISO8859P1';。然后,当我尝试连接到数据库时出现错误。不幸的是,$DBI::errstr只是说它在检索错误文本时遇到问题。我设置NLS_LANG有问题吗? - Nick
我已经在我们的新系统上测试了同样的事情,该系统拥有更新的DBI、DBD和Oracle客户端版本,并且设置NLS_LANG可以正常存储字符。现在我只需要考虑升级我们当前的系统。谢谢。 - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接