小谈MySQL字符集(转)

[不指定 2006/02/22 23:27 | by ipaddr ]
首先,这片文章纯粹是我的个人经验之谈,适用于我常见的环境及项目中.
个人建议,数据库字符集尽量使用utf8(utf-8),以使你的数据能很顺利的实现迁移,因为utf8字符集是目前最适合于实现多种不同字符集之间的转换的字符集,尽管你在命令行工具上无法正确查看数据库中的内容,我依然强烈建议使用utf8作为默认字符集.
接下来是完整的一个例子:
1.创建数据库表
mysql>CREATE DATABASE IF NOT EXISTS my_db default charset utf8 COLLATE utf8_general_ci;
#注意后面这句话 "COLLATE utf8_general_ci",大致意思是在排序时根据utf8变码格式来排序
#那么在这个数据库下创建的所有数据表的默认字符集都会是utf8了

mysql>create table my_table (name varchar(20) not null default '')type=myisam default charset utf8;
#这句话就是创建一个表了,制定默认字符集为utf8

2.写数据
例子1是通过php直接插入数据:
a.php
<?php
mysql_connect('localhost','user','password');
mysql_select_db('my_db');

//请注意,这步很关键,如果没有这步,所有的数据读写都会不正确的
//它的作用是设置本次数据库联接过程中,数据传输的默认字符集
mysql_query("set names utf8;");

//必须将gb2312(本地编码)转换成utf-8,也可以使用iconv()函数
mysql_query(mb_convet_encoding("insert into my_table values('测试');", "utf-8", "gb2312"));
?>

例子是通过页面提交插入数据2:
b.php
<?php
//输出本页编码为utf-8
header("content-type:text/html; charset=utf-8");

mysql_connect('localhost','user','password');
mysql_select_db('my_db');

if(isset($_REQUEST['name'))
{
   //由于上面已经指定本页字符集为utf-8了,因此无需转换编码
   mysql_query(sprintf("insert into my_table values('%s');", $_REQUEST['name']));
}

$q = mysql_query("select * from my_table");
while($r = mysql_fetch_row($q))
{
   print_r($r);
}
?>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<form action="" method="post">
<input type="text" name="name" value="">
<input type="submit" value='submit'>
</form>

自此,使用utf8字符集的完整的例子结束了.
如果你想使用gb2312编码,那么建议你使用latin1作为数据表的默认字符集,这样就能直接用中文在命令行工具中插入数据,并且可以直接显示出来.而不要使用gb2312或者gbk等字符集,如果担心查询排序等问题,可以使用binary属性约束,例如:
create table my_table ( name varchar(20) binary not null default '')type=myisam default charset latin1;


附:旧数据升级办法
以原来的字符集为latin1为例,升级成为utf8的字符集。原来的表: old_table (default charset=latin1),新表:new_table(default charset=utf8)。
第一步:导出旧数据
mysqldump --default-character-set=latin1 -hlocalhost -uroot -B my_db --tables old_table > old.sql
第二步:转换编码
iconv -t utf-8 -f gb2312 -c old.sql > new.sql
在这里,假定原来的数据默认是gb2312编码。
第三步:导入
修改old.sql,增加一条sql语句: "SET NAMES utf8;",保存。
mysql -hlocalhost -uroot my_db < new.sql
大功告成!!

SQLServer的ISNULL应用举例

[不指定 2006/02/09 23:28 | by ipaddr ]
ISNULL
使用指定的替换值替换 NULL。

语法
ISNULL ( check_expression , replacement_value )

参数
check_expression

将被检查是否为 NULL的表达式。check_expression 可以是任何类型的。

replacement_value

在 check_expression 为 NULL时将返回的表达式。replacement_value 必须与 check_expresssion 具有相同的类型。

返回类型
返回与 check_expression 相同的类型。

注释
如果 check_expression 不为 NULL,那么返回该表达式的值;否则返回 replacement_value。

示例
A. 将 ISNULL 与 AVG 一起使用
下面的示例查找所有书的平均价格,用值 $10.00 替换 titles 表的 price 列中的所有 NULL 条目。

USE pubs
GO
SELECT AVG(ISNULL(price, $10.00))
FROM titles
GO

下面是结果集:

--------------------------
14.24                      

(1 row(s) affected)

B. 使用 ISNULL
下面的示例为 titles 表中的所有书选择书名、类型及价格。如果一个书名的价格是 NULL,那么在结果集中显示的价格为 0.00。

USE pubs
GO
SELECT SUBSTRING(title, 1, 15) AS Title, type AS Type,
  ISNULL(price, 0.00) AS Price
FROM titles
GO

C. 在Full Join情况下使用ISNULL
表A:
tid
uid
anum

表B:
tbid
uid
bnum1
bnum2
需要通过uid全连接两个表:
select a.tid,a.uid,a.anum,b.bnum1,b.bnum2 from a full join b on a.uid=b.uid
全连接会有很多为空的情况,可以使用ISNull来解决,改为:
select isnull(a.tid,b.tid),isnull(a.uid,b.uid),isnull(a.anum,0),isnull(b.bnum1,0),isnull(b.bnum2,0) from a full join b on a.uid=b.uid

前部分引用SQL参考手册(一直漂注)

MySQL集群配置

[不指定 2006/02/07 23:28 | by ipaddr ]
转载自CU。

发表于: 2005-11-3 22:38      [引用]  [投诉] [快速回复]  


--------------------------------------------------------------------------------

一、介绍
========
这篇文档旨在介绍如何安装配置基于2台服务器的MySQL集群。并且实现任意一台服务器出现问题或宕机时MySQL依然能够继续运行。

注意!
虽然这是基于2台服务器的MySQL集群,但也必须有额外的第三台服务器作为管理节点,但这台服务器可以在集群启动完成后关闭。同时需要注意的是并不推荐在集群启动完成后关闭作为管理节点的服务器。尽管理论上可以建立基于只有2台服务器的MySQL集群,但是这样的架构,一旦一台服务器宕机之后集群就无法继续正常工作了,这样也就失去了集群的意义了。出于这个原因,就需要有第三台服务器作为管理节点运行。

另外,可能很多朋友都没有3台服务器的实际环境,可以考虑在VMWare或其他虚拟机中进行实验。

下面假设这3台服务的情况:

Server1: mysql1.vmtest.net 192.168.0.1
Server2: mysql2.vmtest.net 192.168.0.2
Server3: mysql3.vmtest.net 192.168.0.3

Servers1和Server2作为实际配置MySQL集群的服务器。对于作为管理节点的Server3则要求较低,只需对Server3的系统进行很小的调整并且无需安装MySQL,Server3可以使用一台配置较低的计算机并且可以在Server3同时运行其他服务。


二、在Server1和Server2上安装MySQL
=================================
从http://www.mysql.com上下载mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
注意:必须是max版本的MySQL,Standard版本不支持集群部署!

以下步骤需要在Server1和Server2上各做一次
# mv mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz /usr/local/
# cd /usr/local/
# groupadd mysql
# useradd -g mysql mysql
# tar -zxvf mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# rm -f mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# mv mysql-max-4.1.9-pc-linux-gnu-i686 mysql
# cd mysql
# scripts/mysql_install_db --user=mysql
# chown -R root  .
# chown -R mysql data
# chgrp -R mysql .
# cp support-files/mysql.server /etc/rc.d/init.d/mysqld
# chmod +x /etc/rc.d/init.d/mysqld
# chkconfig --add mysqld

此时不要启动MySQL!



三、安装并配置管理节点服务器(Server3)
=====================================
作为管理节点服务器,Server3需要ndb_mgm和ndb_mgmd两个文件:

从http://www.mysql.com上下载mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz

# mkdir /usr/src/mysql-mgm
# cd /usr/src/mysql-mgm
# tar -zxvf mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# rm mysql-max-4.1.9-pc-linux-gnu-i686.tar.gz
# cd mysql-max-4.1.9-pc-linux-gnu-i686
# mv bin/ndb_mgm .
# mv bin/ndb_mgmd .
# chmod +x ndb_mg*
# mv ndb_mg* /usr/bin/
# cd
# rm -rf /usr/src/mysql-mgm

现在开始为这台管理节点服务器建立配置文件:

# mkdir /var/lib/mysql-cluster
# cd /var/lib/mysql-cluster
# vi config.ini

在config.ini中添加如下内容:

[NDBD DEFAULT]
NoOfReplicas=2
[MYSQLD DEFAULT]
[NDB_MGMD DEFAULT]
[TCP DEFAULT]
# Managment Server
[NDB_MGMD]
HostName=192.168.0.3 #管理节点服务器Server3的IP地址
# Storage Engines
[NDBD]
HostName=192.168.0.1 #MySQL集群Server1的IP地址
DataDir= /var/lib/mysql-cluster
[NDBD]
HostName=192.168.0.2 #MySQL集群Server2的IP地址
DataDir=/var/lib/mysql-cluster
# 以下2个[MYSQLD]可以填写Server1和Server2的主机名。
# 但为了能够更快的更换集群中的服务器,推荐留空,否则更换服务器后必须对这个配置进行更改。
[MYSQLD]
[MYSQLD]

保存退出后,启动管理节点服务器Server3:
# ndb_mgmd

启动管理节点后应该注意,这只是管理节点服务,并不是管理终端。因而你看不到任何关于启动后的输出信息。



四、配置集群服务器并启动MySQL
=============================
在Server1和Server2中都需要进行如下改动:

# vi /etc/my.cnf

[mysqld]
ndbcluster
ndb-connectstring=192.168.0.3 #Server3的IP地址
[mysql_cluster]
ndb-connectstring=192.168.0.3 #Server3的IP地址

保存退出后,建立数据目录并启动MySQL:

# mkdir /var/lib/mysql-cluster
# cd /var/lib/mysql-cluster
# /usr/local/mysql/bin/ndbd --initial
# /etc/rc.d/init.d/mysqld start

可以把/usr/local/mysql/bin/ndbd加到/etc/rc.local中实现开机启动。
注意:只有在第一次启动ndbd时或者对Server3的config.ini进行改动后才需要使用--initial参数!


五、检查工作状态
================
回到管理节点服务器Server3上,并启动管理终端:

# /usr/bin/ndb_mgm
键入show命令查看当前工作状态:(下面是一个状态输出示例)

[root@mysql3 root]# /usr/bin/ndb_mgm
-- NDB Cluster -- Management Client --
ndb_mgm> show
Connected to Management Server at: localhost:1186
Cluster Configuration
---------------------
[ndbd(NDB)]     2 node(s)
id=2    @192.168.0.1  (Version: 4.1.9, Nodegroup: 0, Master)
id=3    @192.168.0.2  (Version: 4.1.9, Nodegroup: 0)

[ndb_mgmd(MGM)] 1 node(s)
id=1    @192.168.0.3  (Version: 4.1.9)

[mysqld(API)]   2 node(s)
id=4   (Version: 4.1.9)
id=5   (Version: 4.1.9)

ndb_mgm>

如果上面没有问题,现在开始测试MySQL:
注意,这篇文档对于MySQL并没有设置root密码,推荐你自己设置Server1和Server2的MySQL root密码。

在Server1中:

# /usr/local/mysql/bin/mysql -u root -p
> use test;
> CREATE TABLE ctest (i INT) ENGINE=NDBCLUSTER;
> INSERT INTO ctest () VALUES (1);
> SELECT * FROM ctest;

应该可以看到1 row returned信息(返回数值1)。

如果上述正常,则换到Server2上重复上面的测试,观察效果。如果成功,则在Server2中执行INSERT再换回到Server1观察是否工作正常。
如果都没有问题,那么恭喜成功!


六、破坏性测试
==============
将Server1或Server2的网线拔掉,观察另外一台集群服务器工作是否正常(可以使用SELECT查询测试)。测试完毕后,重新插入网线即可。

如果你接触不到物理服务器,也就是说不能拔掉网线,那也可以这样测试:
在Server1或Server2上:

# ps aux | grep ndbd
将会看到所有ndbd进程信息:

root      5578  0.0  0.3  6220 1964 ?        S    03:14   0:00 ndbd
root      5579  0.0 20.4 492072 102828 ?     R    03:14   0:04 ndbd
root     23532  0.0  0.1  3680  684 pts/1    S    07:59   0:00 grep ndbd

然后杀掉一个ndbd进程以达到破坏MySQL集群服务器的目的:

# kill -9 5578 5579

之后在另一台集群服务器上使用SELECT查询测试。并且在管理节点服务器的管理终端中执行show命令会看到被破坏的那台服务器的状态。
测试完成后,只需要重新启动被破坏服务器的ndbd进程即可:

# ndbd
注意!前面说过了,此时是不用加--inital参数的!

至此,MySQL集群就配置完成了!


MySQL错误(errno: 144)的修复

[不指定 2005/11/22 15:47 | by ipaddr ]
由于服务器硬盘空间耗尽,导致Mysql出错,一阵操作后,PHPMyadmin提示

Can't open file: 'tblUser.MYI'. (errno: 144)

可按如下方法修复:

myisamchk -f tblUser.MYI

就可以修复。
mysql4.1以上版本连接时出现Client does not support authentication protocol问题解决办法
shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

官方的说法是

MySQL 4.1 and up uses an authentication protocol based on a password hashing algorithm that is incompatible with that used by older clients. .....



如果你升级mysql到4.1以上版本后遇到以上问题,请先确定你的mysql client 是4.1或者更高版本.(WINDOWS下有问题你就直接跳到下面看解决方法了,因为MYSQL 在WINDOWS是client和server一起装上了的)

请使用以下两种方法之一

其一:

mysql> SET PASSWORD FOR
 -> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');

其二:

mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd')
 -> WHERE Host = 'some_host' AND User = 'some_user';
mysql> FLUSH PRIVILEGES;


方法三:

修改my.cnf,在mysqld段加入:

old_passworld=1

SQLServer更所对象所有者

[不指定 2005/06/09 21:50 | by ipaddr ]
使用存储过程更改SQLServer的对象的所有者。

打开查询器,以DBO身份连接到数据库,执行存储过程sp_changeobjectowner即可,如下:

sp_changeobjectowner 'owner1.objectname' 'dbo'

其中owner1是原所有者,dbo是新所有者,objectname是对象名.
当安装程序安装到:
安装程序正在安装ms数据访问组件
时,屏幕出现错误提示:
command line option syntax error,type command/? for help

然后点确定继续,结果到:
安装程序正在安装HTML帮助
时,屏幕又出现标题为html help 1.32 update错误警对话框提示:
command line option syntax error,type command/? for help

然后我再点确定继续,安装程序开始复制文件,复制完文件后又出现错误提示:
无法找到动态连接库sqlunirl.dll于指定路径
点确定后安装程序停止运行,让查看安装日志

解决方法:

引起这问题的原因是,SQLServer的安装文件,放在中文目录下.

将SQLServer的安装文件,拷到英文目录,安装就OK

比如将:

D:\软件\Sqlserver

中的"软件"去掉.
经验总结:

联机日志分为当前联机日志和非当前联机日志,非当前联机日志的损坏是比较简单的,一般通过clear命令就可以解决问题。
损坏非当前联机日志:
1、启动数据库,遇到ORA-00312 or ORA-00313错误,如:
ORA-00313: open failed for members of log group 4 of thread 1
ORA-00312: online log 3 thread 1: '/opt/oracle/db04/oradata/ORCL/redo03.log'
从这里我们知道日志组1的数据文件损坏或丢失了
从报警文件可以看到更详细的信息
2、查看V$log视图:
SQL> select group#,sequence#,archived,status from v$log;
   GROUP#  SEQUENCE# ARC STATUS
---------- ---------- --- ----------------
        1         54 YES INACTIVE
        2         55 NO  CURRENT
3             53 YES INACTIVE

可以知道,该组是非当前状态,而且已经归档。
3、用CLEAR命令重建该日志文件
SQL>alter database clear logfile group 3;
如果是该日志组还没有归档,则需要用
SQL>alter database clear unarchived logfile group 3;
4、打开数据库,重新备份数据库
SQL>alter database open;
说明:
1)、如果损坏的是非当前的联机日志文件,一般只需要clear就可以重建该日志文件,但是如果该数据库处于归档状态但该日志还没有归档,就需要强行clear。
2)、建议clear,特别是强行clear后作一次数据库的全备份。
3)、此方法适用于归档与非归档数据库。
损坏当前联机日志:
归档模式下当前日志的损坏有两种情况,
一、是数据库是正常关闭,日志文件中没有未决的事务需要实例恢复,当前日志组的损坏就可以直接用alter database clear unarchived logfile group n来重建。
二、是日志组中有活动的事务,数据库需要媒体恢复,日志组需要用来同步,有两种补救办法
A. 最好的办法就是通过不完全恢复,可以保证数据库的一致性,但是这种办法要求在归档方式下,并且有可用的备份
B. 通过强制性恢复,但是可能导致数据库不一致。
下面分别用来说明这两种恢复方法
5.1.2.1 通过备份来恢复
1、打开数据库,会遇到一个类似的错误
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: 'D:\ORACLE\ORADATA\TEST\REDO01.LOG'
ORA-27041: unable to open file
OSD-04002: unable to open file
O/S-Error: (OS 2) 系统找不到指定的文件

2、查看V$log,发现是当前日志
SQL> select group#,sequence#,archived,status from v$log;

GROUP# SEQUENCE# ARCHIVED STATUS
---------- ---------- -------- ----------------
1 1 NO CURRENT
2 2 YES INACTIVE
3 3 YES INACTIVE

3、发现clear不成功
SQL> alter database clear unarchived logfile group 1;
alter database clear unarchived logfile group 1
*
ERROR at line 1:
ORA-01624: log 1 needed for crash recovery of thread 1
ORA-00312: online log 1 thread 1: 'D:\ORACLE\ORADATA\TEST\REDO01.LOG'

4、拷贝有效的数据库的全备份,并不完全恢复数据库
可以采用获取最近的SCN的办法用until scn恢复或用until cnacel恢复
recover database until cancel
先选择auto,尽量恢复可以利用的归档日志,然后重新
recover database until cancel
这次输入cancel,完成不完全恢复,也就是说恢复两次。
如:
SQL> recover database until cancel;
Auto
......
SQL> recover database until cancel;
Cancel;
5、利用alter database open resetlogs打开数据库
说明:
1、这种办法恢复的数据库是一致的不完全恢复,会丢失当前联机日志中的事务数据
2、这种方法适合于归档数据库并且有可用的数据库全备份。
3、恢复成功之后,记得再做一次数据库的全备份。
4、建议联机日志文件一定要实现镜相在不同的磁盘上,避免这种情况的发生,因为任何数据的丢失对于生产来说都是不容许的。





如果没有备份,进行强制性恢复
1、打开数据库,会遇到一个类似的错误
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: 'D:\ORACLE\ORADATA\TEST\REDO01.LOG'
ORA-27041: unable to open file
OSD-04002: unable to open file
O/S-Error: (OS 2) 系统找不到指定的文件

2、查看V$log,发现是当前日志
SQL> select group#,sequence#,archived,status from v$log;

GROUP# SEQUENCE# ARCHIVED STATUS
---------- ---------- -------- ----------------
1 1 NO CURRENT
2 2 YES INACTIVE
3 3 YES INACTIVE

3、发现clear不成功
SQL> alter database clear unarchived logfile group 1;
alter database clear unarchived logfile group 1
*
ERROR at line 1:
ORA-01624: log 1 needed for crash recovery of thread 1
ORA-00312: online log 1 thread 1: 'D:\ORACLE\ORADATA\TEST\REDO01.LOG'

4、把数据库down掉
SQL>shutdown immediate

5、在init.ora中加入如下参数
_allow_resetlogs_corruption=TRUE

6、重新启动数据库,利用until cancel恢复
SQL>recover database until cancel;
Cancel
如果出错,不再理会,发出
SQL>alter database open resetlogs;

7、数据库被打开后,马上执行一个full export

8、shutdown数据库,去掉_all_resetlogs_corrupt参数

9、重建库

10、import并完成恢复

11、建议执行一下ANALYZE TABLE ...VALIDATE STRUCTURE CASCADE;
说明:
1、该恢复方法是没有办法之后的恢复方法,一般情况下建议不要采用,因为该方法可能导致数据库的不一致
2、该方法也丢失数据,但是丢失的数据没有上一种方法的数据多,主要是未写入数据文件的已提交或未提交数据。
3、建议成功后严格执行以上的7到11步,完成数据库的检查与分析
4、全部完成后做一次数据库的全备份
5、建议联机日志文件一定要实现镜相在不同的磁盘上,避免这种情况的发生,因为任何数据的丢失对于生产来说都是不容许的。

Mysql双机数据同步

[不指定 2004/12/27 23:59 | by ipaddr ]
  mysql从3.23.15版本以后提供数据库复制功能。利用该功能可以实现两个数据库同步,主从模式,互相备份模式的功能。

  数据库同步复制功能的设置都在mysql的设置文件中体现。mysql的配置文件(一般是my.cnf)

  在unix环境下在/etc/mysql/my.cnf 或者在mysql用户的home目录下面的my.cnf。

  window环境中,如果c:根目录下有my.cnf文件则取该配置文件。当运行mysql的winmysqladmin.exe工具时候,该工具会把c:根目录下的my.cnf 命名为mycnf.bak。并在winnt目录下创建my.ini。mysql服务器启动时候会读该配置文件。所以可以把my.cnf中的内容拷贝到my.ini文件中,用my.ini文件作为mysql服务器的配置文件。

设置方法:
设置范例环境:
  操作系统:window2000 professional
  mysql:4.0.4-beta-max-nt-log
  A ip:10.10.10.22
  B ip:10.10.10.53
A:设置
  1.增加一个用户最为同步的用户帐号:
GRANT FILE ON *.* TO backup@'10.10.10.53' IDENTIFIED BY ‘1234'
  2.增加一个数据库作为同步数据库:
create database backup
B:设置
  1.增加一个用户最为同步的用户帐号:
GRANT FILE ON *.* TO backup@'10.10.10.22' IDENTIFIED BY ‘1234'
  2.增加一个数据库作为同步数据库:
create database backup


  主从模式:A->B
  A为master
  修改A mysql的my.ini文件。在mysqld配置项中加入下面配置:
server-id=1
log-bin
#设置需要记录log 可以设置log-bin=c:mysqlbakmysqllog 设置日志文件的目录,
#其中mysqllog是日志文件的名称,mysql将建立不同扩展名,文件名为mysqllog的几个日志文件。
binlog-do-db=backup #指定需要日志的数据库

  重起数据库服务。
  用show master status 命令看日志情况。

  B为slave
  修改B mysql的my.ini文件。在mysqld配置项中加入下面配置:
server-id=2
master-host=10.10.10.22
master-user=backup #同步用户帐号
master-password=1234
master-port=3306
master-connect-retry=60 预设重试间隔60秒
replicate-do-db=backup 告诉slave只做backup数据库的更新

  重起数据库
  用show slave status看同步配置情况。

  注意:由于设置了slave的配置信息,mysql在数据库目录下生成master.info
  所以如有要修改相关slave的配置要先删除该文件。否则修改的配置不能生效。

  双机互备模式。

  如果在A加入slave设置,在B加入master设置,则可以做B->A的同步。
  在A的配置文件中 mysqld 配置项加入以下设置:
master-host=10.10.10.53
master-user=backup
master-password=1234
replicate-do-db=backup
master-connect-retry=10

  在B的配置文件中 mysqld 配置项加入以下设置:
log-bin=c:mysqllogmysqllog
binlog-do-db=backup

  注意:当有错误产生时*.err日志文件。同步的线程退出,当纠正错误后要让同步机制进行工作,运行slave start

  重起AB机器,则可以实现双向的热备。

  测试:
  向B批量插入大数据量表AA(1872000)条
  A数据库每秒钟可以更新2500条数据。

---- 在国内外大中型数据库管理系统中,把ORACLE作为数据库管理平台的用户比较多。ORACLE 不论是数据库管理能力还是安全性都是无可非议的,但是,它在汉字信息的显示方面着实给中国用户带来不少麻烦,笔者多年从事ORACLE数据库管 理,经常收到周围用户和外地用户反映有关ORACLE数据库汉字显示问题的求援信,主要现象是把汉字显示为不可识别的乱码,造成原来大量信息无法使用。本文将就这一问题产生的原因和解决办法进行一些探讨,供存在这方面问题的用户朋友参考。  
---- 1、原因分析  
 
---- 通过对用户反映情况的分析,发现字符集的设置不当是影响ORACLE数据库汉字显示的关键问题。那么字符集是怎么一会事呢?字符集是ORACLE 为适应不同语言文字显示而设定的。用于汉字显示的字符集主要有ZHS16CGB231280,US7ASCII,WE8ISO8859P1等。字符集不仅需在服务器端存在,而且客户端也必须有字符集注册。服务器端,字符集是在安装ORACLE时指定的,字符集登记信息存储在ORACLE数据库字典的V$NLS_PARAMETERS表中;客户端,字符集分两种情况,一种情况是sql*net 2.0以下版本,字符集是在windows的系统目录下的oracle.ini 文件中登记的;另一种情况是sql*net 2.0以上(即32位)版本,字符集是在 windows的系统注册表中登记的。要在客户端正确显示ORACLE 数据库汉字信息,首先必须使服务器端的字符集与客户端的字符集一致;其次是加载到ORACLE数据库的数据字符集必须与服务器指定字符集一致。因此,把用户存在的问题归纳分类,产生汉字显示异常的原因大致有以下几种:  
 
---- 1. 1服务器指定字符集与客户字符集不同,而与加载数据字符集一致。  
 
---- 这种情况是最常见的,只要把客户端的字符集设置正确即可,解决办法见
2.1。  
 
---- 1. 2服务器指定字符集与客户字符集相同,与加载数据字符集不一致。  
 
---- 这类问题一般发生在ORACLE版本升级或重新安装系统时选择了与原来服务器端不同的字符集,而恢复加载的备份数据仍是按原字符集卸出的场合,以及加载从其它使用不同字符集的ORACLE数据库卸出的数据的情况。这两种情况中,不管服务器端和客户端字符集是否一致都无法显示汉字。解决办法见2.2。  
 
---- 1.3服务器指定字符集与客户字符集不同,与输入数据字符集不一致。  
 
---- 这种情况是在客户端与服务器端字符集不一致时,从客户端输入了汉字信息。输入的这些信息即便是把客户端字符集更改正确,也无法显示汉字。解决办法见2.3。  
 
---- 2.解决办法  
 
---- 下面将分别对上述三种情况给出解决办法。为了叙述方便,假设客户端使用WINDOWS95/98环境,并已成功地配置了TCP/IP协议,安装了ORACLE的sql*net,sql*pluse产品。  
 
---- 2.1 设置客户端字符集与服务器端字符集一致  
 
---- 假设当前服务器端使用US7ASCII字符集。  
 
---- (1)查看服务器端字符集  
 
---- 通过客户端或服务器端的sql*plus登录ORACLE的一个合法用户,执行下列SQL语句:  
 
SQL > select * from V$NLS_PARAMETERS  
parameter value
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
.... ....
NLS_CHARACTERSET US7ASCII
NLS_SORT BINARY
NLS_NCHAR_CHARACTERSET US7ASCII
 
---- 从上述列表信息中可看出服务器端ORACLE数据库的字符集为'US7ASCII'。  
 
---- (2)按照服务器端字符集对客户端进行配置  
 
---- 配置方法有两种:  
 
安装ORACLE的客户端软件时指定  
---- 在安装ORACLE的客户端产品软件时,选择与ORACLE服务端一致的字符集(本例为US7ASCII)即可。  
 
修改注册信息的方法  
---- 根据ORACLE 客户端所选sql*net 的版本分为下列两种情况:  
 
---- a. 客户端为 sql*net 2.0 以下版本  
 
---- 进入Windows的系统目录,编辑oracle.ini文件,用US7ASCII替换原字符集,重新启动计算机,设置生效。  
 
---- b. 客户端为 sql*net 2.0 以上版本  
 
---- 在WIN98 下 运 行REGEDIT,第一步选HKEY_LOCAL_MACHINE,第二步选择SOFTWARE, 第三步选择 ORACLE, 第四步选择 NLS_LANG, 键 入 与服 务 器端 相 同 的 字 符 集(本例为:AMERICAN_AMERICAN.US7ASCII)。  
 
---- 2.2 强制加载数据字符集与服务器端字符集一致  
 
---- 假设要加载数据从原ORACLE数据库卸出时的字符集为US7ASCII,当前ORACLE服务器字符集为WE8ISO8859P1。  
 
---- 下面提供三种解决方法:  
 
---- (1) 服务器端重新安装ORACLE  
 
---- 在重新安装ORACLE 时选择与原卸出数据一致的字符集(本例为US7ASCII)。  
 
---- 加载原卸出的数据。  
 
---- 这种情况仅仅使用于空库和具有同一种字符集的数据。  
 
---- (2)强行修改服务器端ORACLE当前字符集  
 
---- 在用imp命令加载数据前,先在客户端用sql*plus登录system DBA用户,执行下列SQL语句进行当前ORACLE数据库字符集修改:  
 
SQL > create database character set US7ASCII
* create database character set US7ASCII
ERROR at line 1:
ORA-01031: insufficient privileges
 
---- 你会发现语句执行过程中,出现上述错误提示信息,此时不用理会,实际上ORACLE数据库的字符集已被强行修改为US7ASCII,接着用imp命令装载数据。等数据装载完成以后,shutdown 数据库,再startup 数据库,用合法用户登录ORACLE数据库,在sql>命令提示符下,运行select * from V$NLS_PARAMETERS,可以看到ORACLE数据库字符集已复原,这时再查看有汉字字符数据的表时,汉字已能被正确显示。  
 
---- (3)利用数据格式转储,避开字符集限制  
 
---- 这种方法主要用于加载外来ORACLE数据库的不同字符集数据。其方法如下:  
 
---- 先将数据加载到具有相同字符集的服务器上,然后用转换工具卸出为foxbase 格式或access格式数据库,再用转换工具转入到不同字符集的ORACLE数据库中,这样就避免了ORACLE字符集的困扰。目前数据库格式转换的工具很多,象Power builder5.0以上版本提供的pipeline,Microsoft Access数据库提供的数据导入/导出功能等。转换方法参见有关资料说明。.  
 
---- 2.3匹配字符集替换汉字  
 
---- 对于1.3提到的情况,没有很好的办法,只能先把客户端与服务器端字符集匹配一致后,根据原输入汉字的特征码替换汉字字符部分。

分页: 5/5 第一页 上页 1 2 3 4 5 最后页 [ 显示模式: 摘要 | 列表 ]