数据库特殊字符存储问题?

数据库特殊字符存储问题?,第1张

您好,你的问题,我之前好像也遇到过,以下是我原来的解决思路和方法,希望能帮助到你,若有错误,还望见谅!数据类型改为 nvarchar(10),也就是以unicode方式存储,即可。,非常感谢您的耐心观看,如有帮助请采纳,祝生活愉快!谢谢!

概述

通过实例 全面而深入的分析oralce的基本数据类型及它们的存储方式 以ORACLE G为基础 介绍oralce g引入的新的数据类型 让你对oracle数据类型有一个全新的认识 揭示一些不为人知的秘密和被忽略的盲点 从实用和优化的角度出发 讨论每种数据类型的特点 从这里开始oracle之旅!

第一部份 字符类型

§ char

定长字符串 会用空格来填充来达到其最大长度 最长 个字节

. 新建一个测试表test_char 只有一个char类型的列 长度为

SQL>create table test_char(colA char( ))

Table created

. 向这个表中插入一些数据

SQL>insert into test_char values( a )

row inserted

SQL>insert into test_char values( aa )

row inserted

SQL>insert into test_char values( aaa )

row inserted

SQL>insert into test_char values( aaaa )

row inserted

SQL>insert into test_char values( aaaaaaaaaa )

row inserted

注意 最多只能插入 个字节 否是就报错

SQL>insert into test_char values( aaaaaaaaaaa )

insert into test_char values( aaaaaaaaaaa )

ORA : value too large for column PUB_TEST TEST_CHAR COLA (actual: maximum: )

. 使用dump函数可以查看每一行的内部存数结构

SQL>select colA dump(colA) from test_char

COLA       DUMP(COLA)

a          Typ= Len= :

aa         Typ= Len= :

aaa        Typ= Len= :

aaaa       Typ= Len= :

aaaaaaaaaa Typ= Len= :

注意 Typ= 表示数据类型的ID Oracle为每一种数据类型都进行了编号 说明char类型的编号是

Len = 表示所在的内部存储的长度(用字节表示) 虽然第一例只存了一个字符 a 但是它还是占用了 个字节的空间

表示内部存储方式 可见oracle的内部存储是以数据库字符集进行存储的

正好是字符a的ASCII码

可以使用chr函数把ASCII码转成字符

SQL>select chr( ) from dual

CHR( )

a

要想知道一个字符的ASCII码 可以使用函数ascii

SQL>select ascii( a ) from dual

ASCII( A )

正好是空格的ascii码值

Char类型是定长类型 它总会以空格来填充以达到一个固定宽度

使用char类型会浪费存储空间

Oracle的数据类型的长度单位是字节

SQL>select dump( 汉 ) from dual

DUMP( 汉 )

Typ= Len= :

可见一个汉字在oracle中是占用了两个字节的

英文字母或符号只占用一个字节

Char( )最多可存放 个汉字

§ varchar

是一种变长的字符类型 最多可占用 字节的存储空间

创建一个表 只有一列 类型为varchar 长度为

SQL>create table test_varchar( col varchar ( ))

Table created

插入一些数据

SQL>insert into test_varchar values( a )

row inserted

SQL>insert into test_varchar values( aa )

row inserted

SQL>insert into test_varchar values( aaa )

row inserted

SQL>insert into test_varchar values( aaaaaaaaaa )

row inserted

SQL>insert into test_varchar values( aaaaaaaaaaa )

用dump函数查看每一行的内部存储结构

SQL>select col dump(col) from test_varchar

COL        DUMP(COL)

a          Typ= Len= :

aa         Typ= Len= :

aaa        Typ= Len= :

aaaaaaaaaa Typ= Len= :

Typ= 说明varchar 类型在oracle中的类型编号为

Len代表了每一行数据所占用的字节数

后面是具体的存储值

由此可见 varchar 是存多少就占用多少空间 比较节省空间的 不会像char那样用空格填充

§ byte 和char

在 g中 字符类型的宽度定义时 可以指定单位

Byte就是字节

Char就是字符

Varchar ( byte) 长度为 个字节

Varchar ( char) 长度为 个字符所占的长度

Char( byte)长度为 个字节

Char( char) 长度为 个字符所占的长度

一个字符占用多少个字节 是由当前系统采用的字符集来决定的

如一个汉字占用两个字节

查看当前系统采用的字符集

SQL>select * from nls_database_parameters where parameter = NLS_CHARACTERSET

PARAMETER                      VALUE

NLS_CHARACTERSET               ZHS GBK

如果在定义类型时 不指定单位 默认是按byte 即以字节为单位的

采用char为单位的好处是 使用多字节的字符集

比如 在ZHS GBK字符集中 一个汉字占用两个字节

把数据表的某一列长度定义为可存放 个汉字 通过下面的定义就可以了

Create table test_varchar(col_char varchar ( char))

这样相对简单一些 在数据库表设计时需要注意

继续实验 新建一个表 包含两列 一列采用byte为单位 一列采用char为单位

SQL>create table test_varchar (col_char varchar ( char) col_byte varchar ( byte))

Table created

Col_char列 定义为可存放 个字符

Col_byte 列 定义为可存放 个字节的字符

当前的系统采用字符集为ZHS GBK 所以一个字符占两个字节

试着在表中插入一些数据

SQL>insert into test_varchar values( a a )

row inserted

SQL>insert into test_varchar values( 袁 a )

row inserted

SQL>insert into test_varchar values( 袁袁袁袁袁袁袁袁袁袁 aaaaaaaaaa )

row inserted

SQL>insert into test_varchar values( 袁袁袁袁袁袁袁袁袁袁 袁袁袁袁袁袁袁袁袁袁 )

insert into test_varchar values( 袁袁袁袁袁袁袁袁袁袁 袁袁袁袁袁袁袁袁袁袁 )

ORA : value too large for column PUB_TEST TEST_VARCHAR COL_BYTE (actual: maximum: )

第一次 在两列中都插入字符a

第二次 在col_char列插入字符 袁 在col_byte插入字符a

第三次 在col_char列中插入 个中文字符 袁 在col_byte插入 个字符a

第四次 在两列中都插入中文字符 袁 时 报错了 第二列长度不够

再看看每一行的存储结构

SQL>select col_char dump(col_char) from test_varchar

COL_CHAR             DUMP(COL_CHAR)

a                    Typ= Len= :

袁                   Typ= Len= :

袁袁袁袁袁袁袁袁袁袁 Typ= Len= :

当我们在col_char列插入 个汉字时 它的长度为

尽管我们在定义的时候是采用varchar ( char)

由此可见 oracle是根据当前数据库采用的字符集 每个字符的所占字节数 X 字段长度来决定了该字段所占的字节数

在本例中 varchar ( char)相当于varchar ( )

不信 我们可以试试看

SQL>desc test_varchar

Name     Type         Nullable Default Comments

COL_CHAR VARCHAR ( ) Y

COL_BYTE VARCHAR ( ) Y

当采用多字节的字符集时 定义字段长度还是采用char为单位指定为佳 因为可以避免字段长度的问题

当不知道当前数据库采用的字符集 一个字符占用多少字节时 可以使用lengthb函数

SQL>select lengthb( 袁 ) from dual

LENGTHB( 袁 )

§ char还是varchar

新建一个表 一列为char类型 一列为varchar 类型

SQL>create table test_char_varchar(char_col char( ) varchar_col varchar ( ))

Table created

向该表中的两列都插入相关的数据

SQL>insert into test_char_varchar values( Hello World Hello World )

row inserted

SQL>select * from test_char_varchar

CHAR_COL             VARCHAR_COL

Hello World          Hello World

以char_col列为条件查询

SQL>select * from test_char_varchar where char_col = Hello World

CHAR_COL             VARCHAR_COL

Hello World          Hello World

以varchar_col列为条件查询

SQL>select * from test_char_varchar where varchar_col = Hello World

CHAR_COL             VARCHAR_COL

Hello World          Hello World

似乎char 和varchar类型没有什么两样 再看看下面的语句

SQL>select * from test_char_varchar where varchar_col =char_col

CHAR_COL             VARCHAR_COL

这已经看出他们并不一样 这涉及到字符串比较的问题

因为已经发生了隐式转换 在与char列char_col进行比较时 char_col列的内容已经转换成了char( ) 在Hello World后面以空格进行填充了 而varchar_col列并没有发生这种转换

如果要让char_col列与varchar_col列相等 有两种方法

第一种是 使用trim把char_col列的空格去掉

第二种是 使遥rpad把varchar_col列用空格进行填充长度为 的字符

SQL>select * from test_char_varchar where trim(char_col) = varchar_col

CHAR_COL             VARCHAR_COL

Hello World          Hello World

SQL>select * from test_char_varchar where char_col = rpad(varchar_col )

CHAR_COL             VARCHAR_COL

Hello World          Hello World

如果使用trim函数 如果char_col列上有索引 那么索引将不可用了

lishixinzhi/Article/program/Oracle/201311/17771

解决办法是将字段改成NChar,NVarchar等类型,在入库的时候每个字符串插入前都加入一个N,如N’lily’、N’Male’,兼容性会更好,作为Nvarchar字段,这是一种推荐做法!

小贴士:

char类型: 对英文(ASCII)字符占用1个字节,对一个汉字占用2个字节,CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间。因为是固定长度,所以速度效率高。

Varchar类型:Varchar 的类型不以空格填满,比如varchar(100),但它的值只是”qian”,则它的值就是”qian” 而char 不一样,比如char(100),它的值是”qian”,而实际上它在数据库中是”qian “(qian后共有96个空格,就是把它填满为100个字节)。

由于char是以固定长度的,所以它的速度会比varchar快得多!但程序处理起来要麻烦一点,要用trim之类的函数把两边的空格去掉!

VARCHAR存储变长数据,但存储效率没有CHAR高。如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么“+1”呢?这一个字节用于保存实际使用了多大的长度。

Nchar类型和Nvarchar类型是怎么一回事呢?为了与其他多种字符的转换,如中文,音标等,对每个英文(ASCII)字符都占用2个字节,对一个汉字也占用两个字节,所有的字符都占用2个字节。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/sjk/9930936.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-03
下一篇2023-05-03

发表评论

登录后才能评论

评论列表(0条)

    保存