使用UTF-8编码从Oracle数据库假脱机文件时的编码问题

hyrbngr7  于 2023-03-17  发布在  Oracle
关注(0)|答案(3)|浏览(155)

问题描述:

我有一个在Oracle数据库(Windows或Unix操作系统)上运行的脚本。它提取数据,然后将其假脱机到.txt文件。
为了确保文件不变,在运行脚本时对数据进行散列,然后在Web应用程序中重新计算此散列。这可以工作9/10次,但有时会出现不匹配,即使文件完全相同,我将其隔离为编码问题。
为了确定文件使用的编码,脚本向文件中写入3个NONASCII字符,这些字符在不同的编码方案中采用不同的编码方式,稍后Map到后端。

--Encoding related information
SPOOL &&file_desc/Encoding.txt
SELECT ('€'||';'||'ƒ'||';'||'‰') FROM sys.dual;
SPOOL off

预期结果

在使用UTF-8编码的数据库上,应该正确假脱机具有NONASCII字符的数据,并且还应该正确假脱机3个NONASCII字符。

实际结果

当使用.AL32UTF8系统字符集(与DB相同)时,数据被正确地假脱机,但用于编码的3个字符却没有。这使得我无法确定使用了哪种编码方案。

数据库具有以下字符集(从database_properties获取):

NLS_字符集:AL32UTF8
NLS_NCHAR_字符集:AL16UTF16

SQL开发人员工作

当使用SQL-Developer时(在将编码设置为UTF8之后),我没有任何问题。日语和希腊语字符都正确显示,并且用于编码的字符也正确显示,从而在稍后重新计算时成功进行哈希匹配。

SQL*Plus不工作

我需要它也能在SQL*Plus中工作,但我遇到了一些问题。我尝试了一系列不同的变体。DB是Oracle 18 c express edition:

在SQL*Plus上尝试了变体

1.仅将字符代码页设置为与DB chcp 65001对应的utf-8(utf-8的代码)NLS_LANG字符集:.WE8MSWIN1252表名包含日语字符的文件给出编码“错误”:包含3个字符的文件用于确定编码,效果很好:° C;

  1. No changes to code page, but updated NLS_LANG charset NLS_LANG charset: .AL32UTF8 The file with the tablename including the japanese character shows fine now: JAPANESE世 The file with the 3 chars used to determine encoding is now suddenly ‘empty’ however: ;;
  2. Set NLS_LANG to same as DB and updated code pages chcp 65001 (code for utf-8) NLS_LANG charset: .AL32UTF8 The file with the tablename including the japanese character shows fine now: JAPANESE世 The file with the 3 chars used to determine encoding is now suddenly ‘empty’ however: ;;
    1.将NLS_LANG设置为NLS_NCHAR_Characterset。以防万一,我还尝试将系统字符集设置为AL 16 UTF 16,它等于NLS_NCHAR_Characterset,认为这可能有助于解决问题,但随后我得到了以下错误:初始化SQL*PLUS时出现错误19此操作系统环境的NLS字符集无效

结论/问题

代码页并不重要,因为它只关心输出到命令窗口。
正如所料,当使用WE 8 MSWIN 1252时,NONASCII字符的假脱机不起作用,因为它不知道这些字符。
然而,当使用AL 32 UTF8时,从sys.dual中假脱机3个NONASCII字符不再起作用,即使它确实知道这些字符。
我花了几天时间来隔离这个问题,我不知道为什么是后者,有人能帮助我吗?

*编辑,k提供了解决方案,虽然还不能100%确定为什么会这样。那么,如果有人知道呢?

如果我们将select语句替换为以下语句,它就可以工作:

select unistr('\20AC;\0192;\2030') from dual;
ny6fqffe

ny6fqffe1#

sqlplus从父窗口cmd继承代码页/编码。NLS_LANG告诉数据库客户端使用哪个字符集/编码。

chcp 65001
set NLS_LANG=.AL32UTF8
sqlplus ....

chcp 1252 (the default)
set NLS_LANG=.WE8MSWIN1252
sqlplus ....

那么原则上你做的是正确的。但是,windows cmd不完全支持UTF-8,请参见How to use unicode characters in Windows command line?和/或https://community.oracle.com/tech/developers/discussion/600575/how-to-use-sqlplus-with-utf8-on-windows-command-line
您可能必须使用sqlplus以外的其他工具来创建文件。
另请参见OdbcConnection返回中文字符“?”

iaqfqrcu

iaqfqrcu2#

我不太确定问题出在哪,但如果你尝试:

select unistr('\20AC;\0192;\2030') from dual;

我认为它可以绕过让SQL*Plus从.sql文件中读取正确字符值的问题。

lndjwyie

lndjwyie3#

如果SELECT没有返回任何结果,则可能会出现错误Invalid UTF8 encoding

相关问题