重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
ORACLE 支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据。它使数据库工具,错误消息,排序次序,日期,时间,货币,数字,和日历自动适应本地化语言和平台。 影响oracle数据库字符集最重要的参数是NLS_LANG参数。它的格式如下: NLS_LANG = language_territory.charset 它有三个组成部分(语言、地域和字符集),每个成分控制了NLS子集的特性。其中: Language 指定服务器消息的语言,territory 指定服务器的日期和数字格式,charset 指定字符集。如:AMERICAN _ AMERICA. ZHS16GBK 从NLS_LANG的组成我们可以看出,真正影响数据库字符集的其实是第三部分。所以两个数据库之间的字符集只要第三部分一样就可以相互导入导出数据,前面影响的只是提示信息是中文还是英文。 二、 很多人都碰到过因为字符集不同而使数据导入失败的情况。这涉及三方面的字符集,一是oracel server端的字符集,二是oracle client端的字符集;三是dmp文件的字符集。在做数据导入的时候,需要这三个字符集都一致才能正确导入。
日土网站制作公司哪家好,找创新互联!从网页设计、网站建设、微信开发、APP开发、响应式网站等网站项目制作,到程序开发,运营维护。创新互联于2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选创新互联。
实现思路:
第一步:先将所有子集数据进行分组。
sql:select classname from tablename1 group by classname;
第二步:将需要统计的结果用count函数进行计数即可。
sql:select classname, count( username) from tablename1 group by classname;
解释:以上语句就是统计出某个班级的所有同学的个数。
Oracle数据库查看和修改服务器端的字符集的方法是本文主要要介绍的内容,接下来救让我们一起来了解一下这部分内容。
A、oracle server 端字符集查询 select userenv('language') from dual 其中NLS_CHARACTERSET 为server端字符集 NLS_LANGUAGE 为 server端字符显示形式
B、查询oracle client端的字符集 $echo $NLS_LANG 如果发现你select 出来的数据是乱码,请把client端的字符集配置成与linux操作系统相同的字符集。如果还是有乱码,则有可能是数据库中的数据存在问题,或者是oracle服务端的配置存在问题。
C、server端字符集修改 将数据库启动到RESTRICTED模式下做字符集更改: SQL conn /as sysdba Connected. SQL shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL startup mount ORACLE instance started. Total System Global Area 236000356 bytes Fixed Size 451684 bytes Variable Size 201326592 bytes Database Buffers 33554432 bytes Redo Buffers 667648 bytes Database mounted. SQL ALTER SYSTEM ENABLE RESTRICTED SESSION; System altered. SQL ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0; System altered. SQL ALTER SYSTEM SET AQ_TM_PROCESSES=0; System altered. SQL alter database open; Database altered. SQL ALTER DATABASE CHARACTER SET ZHS16GBK; ALTER DATABASE CHARACTER SET ZHS16GBK ERROR at line 1: ORA-12712: new character set must be a superset of old character set 提示我们的字符集:新字符集必须为旧字符集的超集,这时我们可以跳过超集的检查做更改: SQL ALTER DATABASE character set INTERNAL_USE ZHS16GBK; Database altered. SQL select * from v$nls_parameters; 略 19 rows selected. 重启检查是否更改完成: SQL shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL startup ORACLE instance started. Total System Global Area 236000356 bytes Fixed Size 451684 bytes Variable Size 201326592 bytes Database Buffers 33554432 bytes Redo Buffers 667648 bytes Database mounted. Database opened. SQL select * from v$nls_parameters; 略 19 rows selected. 我们看到这个过程和之前ALTER DATABASE CHARACTER SET操作的内部过程是完全相同的,也就是说INTERNAL_USE提供的帮助就是使Oracle数据库绕过了子集与超集的校验。 这一方法在某些方面是有用处的,比如测试;应用于产品环境大家应该格外小心,除了你以外,没有人会为此带来的后果负责。 结语(我们不妨再说一次): 对于DBA来说,有一个很重要的原则就是:不要把你的数据库置于危险的境地! 这就要求我们,在进行任何可能对数据库结构发生改变的操作之前,先做有效的备份,很多DBA没有备份的操作中得到了惨痛的教训。
D、client端字符集修改 在 /home/oracle与 /root用户目录下的。bash_profile中 添加或修改 export NLS_LANG="AMERICAN_AMERICA.UTF8" 语句
希望可以帮到您,谢谢!
需要用exp和imp命令,具体用法如下:
1. 获取帮助
imp help=y
2. 导入一个完整数据库
imp system/manager file=bible_db log=dible_db full=y ignore=y
3. 导入一个或一组指定用户所属的全部表、索引和其他对象
imp system/manager file=seapark log=seapark fromuser=seapark
imp system/manager file=seapark log=seapark fromuser=(seapark,amy,amyc,harold)
4. 将一个用户所属的数据导入另一个用户
imp system/manager file=tank log=tank fromuser=seapark touser=seapark_copy
imp system/manager file=tank log=tank fromuser=(seapark,amy)
touser=(seapark1, amy1)
5. 导入一个表
imp system/manager file=tank log=tank fromuser=seapark TABLES=(a,b)
6. 从多个文件导入
imp system/manager file=(paycheck_1,paycheck_2,paycheck_3,paycheck_4)
log=paycheck, filesize=1G full=y
7. 使用参数文件
imp system/manager parfile=bible_tables.par
bible_tables.par参数文件:
#Import the sample tables used for the Oracle8i Database Administrator's
Bible. fromuser=seapark touser=seapark_copy file=seapark log=seapark_import
8. 增量导入
imp system./manager inctype= RECTORE FULL=Y FILE=A
-------------------------------------------------------------------------------------------------------------------------------------------
1. 获取帮助
exp help=y
2. 导出一个完整数据库
exp system/manager file=bible_db log=dible_db full=y
3. 导出数据库定义而不导出数据
exp system/manager file=bible_db log=dible_db full=y rows=n
4. 导出一个或一组指定用户所属的全部表、索引和其他对象
exp system/manager file=seapark log=seapark owner=seapark
exp system/manager file=seapark log=seapark owner=(seapark,amy,amyc,harold)
注意:在导出用户时,尽管已经得到了这个用户的所有对象,但是还是不能得到这些对象引用的任何同义词。解决方法是用以下的SQL*Plus命令创建一个脚本文件,运行这个脚本文件可以获得一个重建seapark所属对象的全部公共同义词的可执行脚本,然后在目标数据库上运行该脚本就可重建同义词了。
SET LINESIZE 132
SET PAGESIZE 0
SET TRIMSPOOL ON
SPOOL c:\seapark.syn
SELECT 'Create public synonym '||synonym_name
||' for '||table_owner||'.'||table_name||';'
FROM dba_synonyms
WHERE table_owner = 'SEAPARK' AND owner = 'PUBLIC';
SPOOL OFF
5. 导出一个或多个指定表
exp seapark/seapark file=tank log=tank tables=tank
exp system/manager file=tank log=tank tables=seapark.tank
exp system/manager file=tank log=tank tables=(seapark.tank,amy.artist)
6. 估计导出文件的大小
全部表总字节数:
SELECT sum(bytes)
FROM dba_segments
WHERE segment_type = 'TABLE';
seapark用户所属表的总字节数:
SELECT sum(bytes)
FROM dba_segments
WHERE owner = 'SEAPARK'
AND segment_type = 'TABLE';
seapark用户下的aquatic_animal表的字节数:
SELECT sum(bytes)
FROM dba_segments
WHERE owner = 'SEAPARK'
AND segment_type = 'TABLE'
AND segment_name = 'AQUATIC_ANIMAL';
7. 导出表数据的子集(oracle8i以上)
NT系统:
exp system/manager query='Where salad_type='FRUIT'' tables=amy.salad_type
file=fruit log=fruit
UNIX系统:
exp system/manager query=\"Where salad_type=\'FRUIT\'\" tables=amy.salad_type
file=fruit log=fruit
8. 用多个文件分割一个导出文件
exp system/manager
file=(paycheck_1,paycheck_2,paycheck_3,paycheck_4)
log=paycheck, filesize=1G tables=hr.paycheck
9. 使用参数文件
exp system/manager parfile=bible_tables.par
bible_tables.par参数文件:
#Export the sample tables used for the Oracle8i Database Administrator's Bible.
file=bible_tables
log=bible_tables
tables=(
amy.artist
amy.books
seapark.checkup
seapark.items
)
10. 增量导出
“完全”增量导出(complete),即备份整个数据库
exp system/manager inctype=complete file=990702.dmp
“增量型”增量导出(incremental),即备份上一次备份后改变的数据
exp system/manager inctype=incremental file=990702.dmp
“累计型”增量导出(cumulative),即备份上一次“完全”导出之后改变的数据
exp system/manager inctype=cumulative file=990702.dmp
可以先把日期类型通过 TO_CHAR方法转换为字符串,之后在进行月份查询。
sql:select * from tablename WHERE TO_CHAR( dateTime, 'YYYY-MM') = '2015-06';
解释:以上语句就是查询查2015年06月份的所有数据记录。
理解ORACLE数据库字符集
一.引言
ORACLE数据库字符集,即Oracle全球化支持(Globalization Support),或即国家语言支持(NLS)其作用是用本国语言和格式来存储、处理和检索数据。利用全球化支持,ORACLE为用户提供自己熟悉的数据库母语环境,诸如日期格式、数字格式和存储序列等。Oracle可以支持多种语言及字符集,其中oracle8i支持48种语言、76个国家地域、229种字符集,而oracle9i则支持57种语言、88个国家地域、235种字符集。由于oracle字符集种类多,且在存储、检索、迁移oracle数据时多个环节与字符集的设置密切相关,因此在实际的应用中,数据库开发和管理人员经常会遇到有关oracle字符集方面的问题。本文通过以下几个方面阐述,对oracle字符集做简要分析
二.字符集基本知识
2.1字符集
实质就是按照一定的字符编码方案,对一组特定的符号,分别赋予不同数值编码的集合。Oracle数据库最早支持的编码方案是US7ASCII。
Oracle 的字符集命名遵循以下命名规则 :
即: 语言比特位数编码
比如: ZHS16GBK表示采用GBK编码格式、16位(两个字节)简体中文字符集
2.2字符编码方案
2.2.1 单字节编码
(1)单字节7位字符集,可以定义128个字符,最常用的字符集为 US7ASCII
(2)单字节8位字符集,可以定义256个字符,适合于欧洲大部分国家
例如:WE8ISO8859P1(西欧、8位、ISO标准8859P1编码 )
2.2.2 多字节编码
(1)变长多字节编码
某些字符用一个字节表示,其它字符用两个或多个字符表示,变长多字节编码常用于对亚洲语言的支持, 例如日语、汉语、印地语等
例如:AL32UTF8(其中AL代表ALL,指适用于所有语言)、 zhs16cgb231280
(2)定长多字节编码
每一个字符都使用固定长度字节的编码方案,目前oracle唯一支持的定长多字节编码是AF16UTF16,也是仅用于国家字符集
2.2.3 unicode 编码
Unicode 是一个涵盖了目前全世界使用的所有已知字符的单一编码方案,也就是说Unicode为每一个字符提供唯一的编码。UTF-16是unicode的16位编码方式,是一种定长多字节编码,用2个字节表示一个unicode字符,AF16UTF16是UTF-16编码字符集。
UTF-8 是unicode的8位编码方式,是一种变长多字节编码,这种编码可以用1、2、3个字节表示一个unicode字符,AL32UTF8,UTF8、UTFE是UTF-8编码字符集
2.3 字符集超级
当一种字符集(字符集A)的编码数值包含所有另一种字符集(字符集B)的编码数值,并且两种字符集相同编码数值代表相同的字符时,则字符集A是字符集B的超级,或称字符集B是字符集A的子集。
Oracle8i 和oracle9i官方文档资料中备有子集-超级对照表(subset-superset pairs),例如:WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle数据库编码格式,因此有许多字符集是US7ASCII的超集,例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。
2.4 数据库字符集(oracle服务器端字符集)
数据库字符集在创建数据库时指定,在创建后通常不能更改。在创建数据库时,可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。
2.4.1 字符集
(1) 用来存储CHAR, VARCHAR2, CLOB, LONG等类型数据
(2) 用来标示诸如表名、列名以及PL/SQL变量等
(3) 用来存储SQL和PL/SQL程序单元等
2.4.2 国家字符集:
(1) 用以存储NCHAR, NVARCHAR2, NCLOB等类型数据
(2) 国家字符集实质上是为oracle选择的附加字符集,主要作用是为了增强oracle的字符处理能力,因为NCHAR数据类型可以提供对亚洲使用定长多字节编码的支持,而数据库字符集则不能。国家字符集在oracle9i中进行了重新定义,只能在unicode编码中的AF16UTF16和UTF8中选择,默认值是 AF16UTF16
2.4.3查询字符集参数
可以查询以下数据字典或视图查看字符集设置情况
nls_database_parameters 、props$、 v$nls_parameters
查询结果中NLS_CHARACTERSET表示字符集,NLS_NCHAR_CHARACTERSET表示国家字符集
2.4.4 修改数据库字符集
按照上文所说,数据库字符集在创建后原则上不能更改。如果需要修改字符集,通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换,或通过ALTER DATABASE CHARACTER SET语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用ALTER DATABASE CHARACTER SET UTF8。
2.5 客户端字符集(NLS_LANG参数)
2.5.1 客户端字符集含义
客户端字符集定义了客户端字符数据的编码方式,任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用,例如sqlplus,exp/imp等。客户端字符集是通过设置NLS_LANG参数来设定的。
2.5.2 NLS_LANG 参数格式
NLS_LANG=_.
Language: 显示oracle消息,校验,日期命名
Territory :指定默认日期、数字、货币等格式
Client character set :指定客户端将使用的字符集
例如: NLS_LANG=AMERICAN_AMERICA.US7ASCII
AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集
2.5.3 客户端字符集设置方法
1)UNIX 环境
$NLS_LANG=“simplified chinese”_china.zhs16gbk
$export NLS_LANG
编辑oracle用户的profile文件
2)Windows 环境
编辑注册表
Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE—HOME0
2.5.4 NLS 参数查询
Oracle 提供若干NLS参数定制数据库和用户机以适应本地格式,例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,可以通过查询以下数据字典或v$视图查看。
NLS_DATABASE_PARAMETERS-- 显示数据库当前NLS参数取值,包括数据库字符集取值
NLS_SESSION_PARAMETERS-- 显示由NLS_LANG 设置的参数,或经过alter session 改变后的参数值(不包括由NLS_LANG 设置的客户端字符集)
NLS_INSTANCE_PARAMETE-- 显示由参数文件init.ora 定义的参数V$NLS_PARAMETERS--显示数据库当前NLS参数取值
2.5.5 修改NLS参数
使用下列方法可以修改NLS参数
(1)修改实例启动时使用的初始化参数文件
(2)修改环境变量 NLS_LANG
(3)使用ALTER SESSION语句,在oracle会话中修改
(4)使用某些SQL函数
NLS 作用优先级别:Sql functionalter session环境变量或注册表参数文件数据库默认参数
三.导入/导出与字符集转换
3.1 EXP/IMP
Export 和 Import 是一对读写Oracle数据的工具。Export 将 Oracle 数据库中的数据输出到操作系统文件中, Import 把这些文件中的数据读到Oracle 数据库中,由于使用exp/imp进行数据迁移时,数据从源数据库到目标数据库的过程中有四个环节涉及到字符集,如果这四个环节的字符集不一致,将会发生字符集转换。
EXP
____________ _________________ _____________
|imp导入文件|--
------------ ----------------- -------------
IMP
____________ _________________ _____________
|imp导入文件|-|环境变量NLS_LANG|-|数据库字符集|
------------ ----------------- -------------
四个字符集是
(1)源数据库字符集
(2)Export过程中用户会话字符集(通过NLS_LANG设定)
(3)Import过程中用户会话字符集(通过NLS_LANG设定)
(4)目标数据库字符集
3.2导出的转换过程
在Export过程中,如果源数据库字符集与Export用户会话字符集不一致,会发生字符集转换,并在导出文件的头部几个字节中存储Export用户会话字符集的ID号。在这个转换过程中可能发生数据的丢失。
例:如果源数据库使用ZHS16GBK,而Export用户会话字符集使用US7ASCII,由于ZHS16GBK是16位字符集,而US7ASCII是7位字符集,这个转换过程中,中文字符在US7ASCII中不能够找到对等的字符,所以所有中文字符都会丢失而变成“?? ”形式,这样转换后生成的Dmp文件已经发生了数据丢失。
因此如果想正确导出源数据库数据,则Export过程中用户会话字符集应等于源数据库字符集或是源数据库字符集的超集
3.3导入的转换过程
(1)确定导出数据库字符集环境
通过读取导出文件头,可以获得导出文件的字符集设置
(2)确定导入session的字符集,即导入Session使用的NLS_LANG环境变量
(3)IMP读取导出文件
读取导出文件字符集ID,和导入进程的NLS_LANG进行比较
(4)如果导出文件字符集和导入Session字符集相同,那么在这一步骤内就不需要转换,如果不同,就需要把数据转换为导入Session使用的字符集。可以看出,导入数据到数据库过程中发生两次字符集转换
第一次:导入文件字符集与导入Session使用的字符集之间的转换,如果这个转换过程不能正确完成,Import向目标数据库的导入过程也就不能完成。
第二次:导入Session字符集与数据库字符集之间的转换。
然而,oracle8i的这种转换只能在单字节字符集之间进行,oracle8i导入Session不支持多字节字符集之间的转换,因此为了避免第一次转换,导入Session使用的NLS_LANG与导出文件字符集相同,第二次转换(通过SQL*Net)支持任何两种字符集。以上情况在Oracle9i中略有不同
四.乱码问题
oracle在数据存储、迁移过程中经常发生字符乱码问题,归根到底是由于字符集使用不当引起。下面以使用客户端sqlplus向数据库插入数据和导入/导出(EXP/IMP)过程为例,说明乱码产生的原因。
4.1使用客户端sqlplus向数据库存储数据
这个过程存在3个字符集设置
(1)客户端应用字符集
(2)客户端NLS_LANG参数设置
(3)服务器端数据库字符集(Character Set)设置
客户端应用sqlplus中能够显示什么样的字符取决于客户端操作系统语言环境(客户端应用字符集),但在应用中录入这些字符后,这些字符能否在数据库中正常存储,还与另外两个字符集设置紧密相关,其中客户端NLS_LANG参数主要用于字符数据传输过程中的转换判断。常见的乱码大致有两种情形:
(1)汉字变成问号“?”;
当从字符集A 转换成字符集B时,如果转换字符之间不存在对应关系,NLS_LANG使用替代字符“?”替代无法映射的字符
(2)汉字变成未知字符(虽然有些是汉字,但与原字符含义不同)
转换存在对应关系,但字符集A 中的字符编码与字符集B 中的字符编码代表不同含义
4.2发生乱码原因
乱码产生是由于几个字符集之间转换不匹配造成,分以下几种情况:
(注:字符集之间如果不存在子集、超集对应关系时的情况不予考虑,因为这种情况下字符集之间转换必产生乱码)
1)服务器端数据库字符集与客户端应用字符集相同,与客户端NLS_LANG参数设置不同
如果客户端NLS_LANG字符集是其它两种字符集的子集,转换过程将出现乱码。
解决方法:将三种字符集设置成同一字符集,或NLS_LANG字符集是其它两种字符集的超集
2 )服务器端数据库字符集与客户端NLS_LANG参数设置相同,与客户端应用字符集不同
如果客户端应用字符集是其它两种字符集的超集时,转换过程将出现乱码,但对于单字节编码存储中文问题,可参看本文第5章节的分析
3 )客户端应用字符集、客户端NLS_LANG参数设置、服务器端数据库字符集互不相同
此种情况较为复杂,但三种字符集之间只要有不能转换的字符,则必产生乱码
4.3导入/导出过程出现乱码原因
这个过程存在4个字符集设置,在3.1章节中已分析
(1)源数据库字符集
(2)EXP过程中NLS_LANG参数
(3)IMP过程中NLS_LANG参数
(4)目标数据库字符集
出现乱码原因
1 )当源数据库字符集不等于EXP过程中NLS_LANG参数,且源数据库字符集是EXP过程中NLS_LANG的子集,才能保证导出文件正确,其他情况则导出文件字符乱码
2 )EXP过程中NLS_LANG字符集不等于IMP过程中NLS_LANG字符集,且EXP过程中NLS_LANG字符集是IMP过程中NLS_LANG字符集的子级, 才能保证第一次转换正常,否则第一次转换中出现乱码。
3 )如果第一次转换正常,IMP过程中NLS_LANG字符集是目标数据库字符集的子集或相同,才能保证第二次转换正常,否则则第二次转换中出现乱码
五.单字节编码存储中文问题
由于历史的原因,早期的oracle没有中文字符集(如oracle6、oracle7、oracle7.1),但有的用户从那时起就使用数据库了,并用US7ASCII字符集存储了中文,或是有的用户在创建数据库时,不考虑清楚,随意选择一个默认的字符集,如WE8ISO8859P1或US7ASCII,而这两个字符集都没有汉字编码,虽然有些时候选用这种字符集好象也能正常使用,但用这种字符集存储汉字信息从原则上说就是错误的,它会给数据库的使用与维护带来一系列的麻烦。
正常情况下,要将汉字存入数据库,数据库字符集必须支持中文,而将数据库字符集设置为US7ASCII等单字节字符集是不合适的。US7ASCII字符集只定义了128个符号,并不支持汉字。另外,如果在SQL*PLUS中能够输入中文,操作系统缺省应该是支持中文的,但如果在NLS_LANG中的字符集设置为US7ASCII,显然也是不正确的,它没有反映客户端的实际情况。但在实际应用中汉字显示却是正确的,这主要是因为Oracle检查数据库与客户端的字符集设置是同样的,那么数据在客户与数据库之间的存取过程中将不发生任何转换,但是这实际上导致了数据库标识的字符集与实际存入的内容是不相符的。而在SELECT的过程中,Oracle同样检查发现数据库与客户端的字符集设置是相同的,所以它也将存入的内容原封不动地传送到客户端,而客户端操作系统识别出这是汉字编码所以能够正确显示。
在这个例子中,数据库与客户端都没有设置成中文字符集,但却能正常显示中文,从应用的角度看好象没问题。然而这里面却存在着极大的隐患,比如在应用length或substr等字符串函数时,就可能得到意外的结果。
对于早期使用US7ASCII字符集数据库的数据迁移到oracle8i/9i中(使用zhs16gbk),由于原始数据已经按照US7ASCII格式存储,对于这种情况,可以通过使用Oracle8i的导出工具,设置导出字符集为US7ASCII,导出后使用UltraEdit等工具打开dmp文件,修改第二、三字符,修改 0001 为0354,这样就可以将US7ASCII字符集的数据正确导入到ZHS16GBK的数据库中。
六.结束语
为了避免在数据库迁移过程中由于字符集不同导致的数据损失,oracle提供了字符集扫描工具(character set scanner),通过这个工具我们可以测试在数据迁移过程中由于字符集转换可能带来的问题,然后根据测试结果,确定数据迁移过程中最佳字符集解决方案。
参考文献
[1]Biju Thomas , Bob Bryla 《oracle9i DBA基础I 学习指南》电子工业出版社 2002