栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

OdbcConnection返回汉字为“?”

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

OdbcConnection返回汉字为“?”

字符集的问题很常见,让我尝试给出一些一般性注释。

原则上,您必须考虑 四种 不同的字符集设置。

1和2:
NLS_CHARACTERSET
以及
NLS_NCHAR_CHARACTERSET

例:

AL32UTF8

它们 在您的数据库上定义,您可以使用

    SELECt *     FROM V$NLS_PARAMETERS     WHERe PARAMETER IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');

这些设置定义了哪些字符(以哪种格式)可以存储在数据库中-不多也不少。如果必须在现有数据库上进行更改,则需要付出一些努力(请参阅“
字符集迁移”和/或“
Oracle Unipre数据库迁移助手”)。

3:
NLS_LANG

例:

AMERICAN_AMERICA.AL32UTF8

此值
在您的客户端上定义。NLS_LANG与将字符存储在数据库中的能力无关。它用于使Oracle知道您在客户端使用的是什么字符集。当您设置NLS_LANG值(例如,设置为AL32UTF8)时,您只是告诉Oracle数据库“我的客户端使用字符集AL32UTF8”
–并不一定意味着您的客户端确实在使用AL32UTF8!(请参阅下面的#4)

NLS_LANG可以由环境变量定义,也可以

NLS_LANG
由Windows注册表定义
HKLMSOFTWAREWow6432NodeORACLEKEY_%ORACLE_HOME_NAME%NLS_LANG
(对于32位)。
HKLMSOFTWAREORACLEKEY_%ORACLE_HOME_NAME%NLS_LANG
(适用于64位)。根据您的应用程序,可能还有其他方法可以指定NLS_LANG,但让我们坚持基础知识。如果未提供NLS_LANG值,则Oracle默认将其设置为
AMERICAN_AMERICA.US7ASCII

NLS_LANG的格式为

NLS_LANG=language_territory.charset
。NLS_LANG 的{ charset }部分

显示在任何系统表或视图中。在NLS_LANG定义的所有组件都是可选的,所以下面的定义都是有效的:
NLS_LANG=.WE8ISO8859P1
NLS_LANG=_GERMANY
NLS_LANG=AMERICAN
NLS_LANG=ITALIAN_.WE8MSWIN1252
NLS_LANG=_BELGIUM.US7ASCII

如上所述,

NLS_LANG
在任何系统表/视图或任何函数中,数据库的{charset}部分均不可用。严格来说,这是正确的,但是您可以运行以下查询:

SELECt DISTINCT CLIENT_CHARSETFROM V$SESSION_CONNECT_INFOWHERe (SID, SERIAL#) = (SELECt SID, SERIAL# FROM v$SESSION WHERe AUDSID = USERENV('SESSIONID'));

它应该从当前

NLS_LANG
设置返回字符集-但是根据我的经验,该值通常为NULL或
Unknown
,即不可靠。

在此处找到更多非常有用的信息:NLS_LANG常见问题解答

请注意,某些技术没有利用

NLS_LANG
,那里的设置没有任何效果,例如:

  • ODP.NET托管驱动程序不

    NLS_LANG
    敏感。它仅对.NET语言环境敏感。(请参阅.NET开发人员指南的数据提供程序)

  • OraOLEDB(来自Oracle)始终使用UTF-16(请参阅OraOLEDB提供程序特定的功能)

  • 基于Java的JDBC(例如SQL Developer)具有自己的处理字符集的方法(有关更多详细信息,请参见《数据库JDBC开发人员指南-全球化支持》)。

4:终端,应用程序或
.sql
文件编码的“真实”字符集

例:

UTF-8

如果您在Windows终端上工作(即使用SQL * plus),则可以

chcp
在Unix / Linux
上使用command询问代码页,等效于
locale charmap
or
echo$LANG
。您可以从此处获取所有Windows代码页标识符的列表:代码页标识符。请注意,关于UTF-8(
chcp65001
)存在一些问题,请参见此讨论。

如果使用

.sql
文件和TOAD或SQL-
Developer之类的编辑器,则必须检查保存选项。通常你可以选择喜欢的值
UTF-8
ANSI
ISO-8859-1

ANSI
指Windows的ANSI代码,通常
CP1252
,你可以在你注册处查询
HKLMSYSTEMControlSet001ControlNlsCodePageACP
或浏览:国家语言支持(NLS)API参考

[Microsoft删除了此参考,将其形成为Web归档
国家语言支持(NLS)API参考
]

如何设置所有这些值?

最重要的一点是匹配

NLS_LANG
和终端的“真实”字符集。应用程序或
.sql
文件编码

一些常见的对是:

  • CP850->

    WE8PC850

  • CP1252或ANSI(对于“西方” PC)->

    WE8MSWIN1252

  • ISO-8859-1->

    WE8ISO8859P1

  • ISO-8859-15->

    WE8ISO8859P15

  • UTF-8->

    AL32UTF8

或运行此查询以获取更多信息:

SELECt VALUE AS ORACLE_CHARSET, UTL_I18N.MAP_CHARSET(VALUE) AS IANA_NAMEFROM V$NLS_VALID_VALUESWHERe PARAMETER = 'CHARACTERSET';

有些技术使您的生活更轻松,例如Oracle的ODP.NET(非驱动程序驱动程序)或ODBC驱动程序会自动从

NLS_LANG
值继承字符集,因此以上条件始终为真。

是否需要将客户端NLS_LANG值设置为等于数据库

NLS_CHARACTERSET
值?

不,不一定!例如,如果您具有 数据库 字符集

NLS_CHARACTERSET=AL32UTF8
客户端
字符集,
NLS_LANG=.ZHS32GB18030
则它们可以正常工作(前提是您的客户端确实使用GB18030),尽管这些字符集完全不同。GB18030是中文常用的字符集,就像
UTF-8
它支持所有Unipre字符一样。

例如

NLS_CHARACTERSET=AL32UTF8
,如果您有,
NLS_LANG=.WE8ISO8859P1
它也将起作用(同样,只要您的客户确实使用ISO-8859-P1)。但是,数据库可能会存储您的客户端无法显示的字符,而是客户端将显示一个占位符(例如
¿
)。

无论如何,具有匹配的NLS_LANG和NLS_CHARACTERSET值(如果适用)是有益的。如果它们相等,则可以确保可以显示可能存储在数据库中的任何字符,并且您在终端中输入或在.sql文件中写入的任何字符也可以存储在数据库中,并且不会被占位符代替。

补充

您可以阅读很多次建议,例如“ NLS_LANG字符集必须与您的数据库字符集相同”(也在SO上找到)。这根本不是事实,而是一个流行的神话!

这是证明:

C:>set NLS_LANG=.AL32UTF8C:>sqlplus ...SQL> SET SERVEROUTPUT ONSQL> DECLARE  2  CharSet VARCHAr2(20);  3  BEGIN  4     SELECt VALUE INTO Charset FROM nls_database_parameters WHERe parameter = 'NLS_CHARACTERSET';  5     DBMS_OUTPUT.PUT_LINE('Database NLS_CHARACTERSET is '||Charset);  6     IF UNISTR('20AC') = '€' THEN  7  DBMS_OUTPUT.PUT_LINE ( '"€" is equal to U+20AC' );  8     ELSE  9  DBMS_OUTPUT.PUT_LINE ( '"€" is not the same as U+20AC' ); 10     END IF; 11  END; 12  /Database NLS_CHARACTERSET is AL32UTF8"€" is not the same as U+20ACPL/SQL procedure successfully completed.

客户端和数据库字符集都为

AL32UTF8
,但是字符不匹配。原因是,我
cmd.exe
以及SQL * Plus也使用Windows
CP1252。因此,我必须相应地设置NLS_LANG:

C:>chcpActive pre page: 1252C:>set NLS_LANG=.WE8MSWIN1252C:>sqlplus ...SQL> SET SERVEROUTPUT ONSQL> DECLARE  2  CharSet VARCHAr2(20);  3  BEGIN  4     SELECt VALUE INTO Charset FROM nls_database_parameters WHERe parameter = 'NLS_CHARACTERSET';  5     DBMS_OUTPUT.PUT_LINE('Database NLS_CHARACTERSET is '||Charset);  6     IF UNISTR('20AC') = '€' THEN  7  DBMS_OUTPUT.PUT_LINE ( '"€" is equal to U+20AC' );  8     ELSE  9  DBMS_OUTPUT.PUT_LINE ( '"€" is not the same as U+20AC' ); 10     END IF; 11  END; 12  /Database NLS_CHARACTERSET is AL32UTF8"€" is equal to U+20ACPL/SQL procedure successfully completed.

还请考虑以下示例:

CREATE TABLE ARABIC_LANGUAGE (    LANG_CHAR VARCHAr2(20),     LANG_NCHAR NVARCHAr2(20));INSERT INTO ARABIC_LANGUAGE VALUES ('العربية', 'العربية');

您将需要

NLS_LANG
为单个语句设置两个不同的值-这是不可能的。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/385231.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号