数据库字符集引发的血案

以前开发的时候,大家用的都是SQL Server,.net开发,一直都用的没什么问题,但是最近开发用的Oracle,本来开发的好好的,方法写的也没什么问题,但是重新装了一次系统以后,就发现我的程序不能查询根据汉子查询,如果SQL语句中出现了汉子,那么查询的结果就为空,但是表里边命名有数据,后来发现原来是数据库字符集搞的鬼。不知道大家有没有遇到这个问题,网上查了许多资料,经过一个一个实践,发现了几个方法。

什么叫字符集:

也许字符集这个概念不清楚,但是大家一定知道ASCII,他就是一个字符集,还有就是UTF-8等,因为计算机要处理不同的语言,有人开发纯英文,但是咱们中国人开发还是会出现中文的,计算机要处理不同的文字,所以也就有了很多的字符集,这样计算机根据咱们的设置,来特定处理某些文字,但是如果字符集和你写的驴唇不对马嘴,那么抱歉,乱码就出来了,所以我们变成的时候才回出现乱码。说了这么多,咱们改咱们解决呢。

方法一、设置数据库字符集。

如果出现了大家查询语句中有汉子的话,但是返回的结果是一个Null,那么大家首先就可以考虑一下是不是咱们的数据库的字符集设置有问题,所以咱们先尝试的改一下。

查询字符集

打开SQLPlus

SQL> select * from v$nls_parameters;

然后查看咱们的字符集,如果和服务器不一致要设置成一致。影响Oracle数据库字符集最重要的参数是NLS_LANG参数。 它的格式如下: NLS_LANG = language_territory.charset

它有三个组成部分(语言、地域和字符集),每个成分控制了NLS子集的特性。

其中:

Language: 指定服务器消息的语言, 影响提示信息是中文还是英文

Territory: 指定服务器的日期和数字格式,

Charset:  指定字符集。

如:AMERICAN _ AMERICA. ZHS16GBK

修改字符集

在SQL*PLUS 中,以DBA登录

conn 用户名 as sysdba

然后执行以下命令

>shutdown immediate; (把database停了)

>startup mount; (把database重开去可更改情況)

>alter system enable restricted session;

>alter system set job_queue_processes=0;

>alter system set aq_tm_processes=0;

>alter database open;

>alter database character set utf8;

OR

>alter database character set internal_use utf8;

>shutdown immediate;

>startup; (重开正常oracle)

从NLS_LANG的组成我们可以看出,真正影响数据库字符集的其实是第三部分。

所以两个数据库之间的字符集只要第三部分一样就可以相互导入导出数据,前面影响的只是提示信息是中文还是英文。当然我们在数据库中改,在环境变量里边也要改,右击我的电脑--》高级设置--》环境变量--》新建--》NLS_LANG=CHINESE_CHINA.ZHS16GBK .

当时这个方法好像在我这不给力,于是紧接着又找了一个方法

方法二、修改程序

因为我们是合作开发,我主要是负责界面,而另一个人为我提供接口,因为我不可能需要所有的数据,他返回的datatable的信息我是需要筛选的,所以我每次都是Dt.Select(xxxx=‘xxxx‘),但是里边是汉字就是不可以。于是找了很多的方法,最后只能修改程序,开始我们的方式是直接写一条SQL语句,例如‘select t.sex from T_student where t.studentName = ‘张三‘,直接在数据库中查询没问题,但是在程序中就不行,后来我们发现也许是,NET的字符集和数据库的字符集不一样,这样是不是导致了解析出现的问题,后来就用了参数的方式,下边是我们的程序的代码,大家可以看一下。

       StringBuilder sql2 = new StringBuilder();
       sql2.Append( "select c.s_keypartid from kpm_dict_i_scale c ");
       sql2.Append(" where c.s_traintempid =:S_TRAINTEMPID ");
       sql2.Append("   and c.s_repairlevel = :S_REPAIRLEVEL");

       OracleParameter[] parameters = {
			new OracleParameter(":S_TRAINTEMPID", OracleType.VarChar,20),
                        new OracleParameter(":S_REPAIRLEVEL", OracleType.VarChar,20)};

      parameters[0].Value = s_traintempid;
      parameters[1].Value = "转向架收支";

       DataTable dtpart = OracleHelper.ExecuteQuery(OracleHelper.ConnectionString, CommandType.Text, sql2.ToString(), parameters);

        if (dtpart != null && dtpart.Rows.Count > 0)
        {
              ***//数据转换
        }

上边的程序是给我接口人的程序,但是这样调用以后,我发现就没有问题了,因为用了OracleParameter 的OracleType,这样才让两个程序的程序集一样。

后来在网上找了挺多资料的,也没有什么别的解决方式,所以只能修改程序。所以经过这次的经历,咱们以后开发,如果是自己开发,直接设置自己电脑的字符集就可以了,但是如果是合作开发,大家一定要提前注意,一定要和服务器的编码方式一样,这样才不会出现后期改代码的悲哀。

思考

当我开始发现这个问题的时候,还以为是自己的数据库出现了问题,后来发现数据库能查的出来,那就肯定不是数据库本身安装的问题,那么接下来就是我程序的问题,我的程序没有能正确的翻译SQL语句,以至于传到数据库中的时候SQL语句就变了,所以就是这个中间出现了问题。

那么我们首先想到的就应该是中间计算机的编译没有正确的执行,既然一条语句在数据库中能执行,在程序中就不行,那么就是中间的字符集的这个过程了,因为程序就是根据字符集来编译的。所以我们首先想到的就是数据库中的字符集的设置,但是如果设置了不行怎么办,既然修改了数据库不可以,那就只能修改程序了,所以接下来就是利用传参,然后一方面能够设置传参的字符集类型,一方面还能防止SQL语句的注入。

这个过程看起来简单,但是也废了我不少力气,希望能帮组到想我这样的程序猿们吧。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-27 08:44:08

数据库字符集引发的血案的相关文章

一段mongo数据库数据丢失 引发的血案

2017年1月8日上无,一个晴朗的早上(大周末的晴朗的早上),我还在梦境中,被一个电话吵醒,众所周知,做运维的最怕在休息期间接到公司同仁电话! 起因:同事说线上的某个功能不能用了!(这个功能就是在mongo数据库中获取数据返给前端进行渲染) 经过:之前也出现过类似的问题,排查故障后是因为mongo实例挂掉(某种原因造成),这次没想到事情比之前的故障还要叫人毛骨悚然----------mongo的数据丢了 我的个天啊.里面存放了不到5千万条的数据啊.丢了这可咋弄啊? 解决:把mongo数据丢失关键

openstack运维实战系列(十三)之glance更改路径引发的"血案"

1. 背景说明 glance在openstack中负责镜像相关的服务,支持将运行的虚拟机转换为快照,镜像和快照都存储在glance中,glance的后端支持多种存储方式,包括本地的文件系统,http,glusterfs,ceph,swift等等. 默认情况下,glance采用本地文件系统的方式存储image,存储的路径为/var/lib/glance/images,随着时间的推移,当镜像越来越多的时候,根目录的空间将会越来越大,所以对于glance的路径来说,需要提前做好规划和准备,如划分一个单

JVM--JVM finalize实现原理与由此引发的血案

原创内容,转载请注明出处 本文由一桩因为使用了JAVA finalize()而引发的血案入手,讲解了JVM中finalize()的实现原理和它的陷阱所在,希望能够对广大JAVA开发者起到一点警示作用.除此之外,本文从实际问题出发,描述了解决问题的过程和方法.如写模拟程序来重现问题,使用jmap工具进行分析等,希望对大家提供借鉴. 本文分三个章节,先介绍实际项目中遇到的问题,随后介绍了问题重现和分析方法,最后对问题的元凶,override finalize()的实现原理和陷阱进行了讲解和介绍.篇幅

ASP.NET Button控件的UseSubmitBehavior属性引发的血案

这里先不说标题上的UseSubmitBehavior属性是什么,先说下面这种情况. 通常,在我们写一个表单页面的时候,最下方会有"提交"和"返回"字样的两个按钮.顾名思义,它们的功能大家都知道,但是一般情况下我们会给表单的内容加上一些验证,这样就出现了一个问题.因为两个按钮是服务器控件(有runat="Server"属性),所以点击按钮之后会先进行验证(无论这里你用的是前台的jQuery.validate验证或者是ASP.NET自带的后台验证控件

事务隔离级别引发的"血案"

事务引发的"血案"见的多了也麻木了,这回遇到个事务隔离级别的"案子",坑了我小半天的时间...也怪自己细节不牢.. 敲着代码遇到这么一个怪事情: class XXXService{ @Transactional public void demo(){ //一堆业务逻辑 rpc.insertOne(); //dubbo调用远程服务插入一条数据 getOne(); //获取刚才插入的数据 } } 其中getOne()的事务的传播属性是required, 因为dubbo是

一个无锁消息队列引发的血案:怎样做一个真正的程序员?(二)——月:自旋锁

前续 一个无锁消息队列引发的血案:怎样做一个真正的程序员?(一)——地:起因 一个无锁消息队列引发的血案:怎样做一个真正的程序员?(二)——月:自旋锁 平行时空 在复制好上面那一行我就先停下来了,算是先占了个位置,虽然我知道大概要怎么写,不过感觉还是很乱. 我突然想到,既然那么纠结,那么混乱,那么不知所措,我们不如换个视角.记得高中时看过的为数不多的长篇小说<穆斯林的葬礼>,作者是:霍达(女),故事描写了两个发生在不同时代.有着不同的内容却又交错扭结的爱情悲剧,一个是“玉”的故事,一个是“月”

修改Oracle数据库字符集

Oracle数据库字符集在创建后原则上不能更改.如果需要修改字符集,通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换,或通过ALTER DATABASE CHARACTER SET语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前字符集的超集时才能修改数据库字符集,例如UTF8是US7ASCII的超集,修改数据库字符集可使用 ALTER DATABASE CHARACTER SET UTF8 Oracle 字符集的查看和修改 一.什么是Oracle字符集 O

一个无锁消息队列引发的血案(六)——RingQueue(中) 休眠的艺术 [续]

目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的艺术 [续] 开篇 这是第五篇的后续,这部分的内容同时会更新和添加在 第五篇:RingQueue(中) 休眠的艺术 一文的末尾. 归纳 紧接上一篇的末尾,我们把 Windows 和 Linux 下的休眠策略归纳总结一下,如下图: 我们可以看到,Linux 下的 sched_yield() 虽然包括了

修改mysql数据库字符集为UTF8的

第一种 一.修改my.ini配置文件(MySQL配置文件) character_set_server = utf8 #设置字符集 重启mysql数据库服务 查看当前数据库字符集 show VARIABLES like 'character%'; 二.修改数据库字符集 alter database 数据库名 character set utf8; ps:修改完数据库字符集,需要重启MySQL数据库. 三.修改表字符集 ALTER TABLE  表名 DEFAULT CHARACTER SET ut