zoukankan      html  css  js  c++  java
  • 关于SQL SERVER的N前缀的理解

    加N前缀指定后面的字符串为UNICODE常量, SQL Server 的 Unicode 数据类型是基于 SQL-92 标准中的国家字符数据类型。SQL-92 使用前缀字符 N 标识这些数据类型及其值。 
    1, Unicode 数据使用 SQL Server 中的 ncharvarcharntext 数据类型进行存储。对于存1储来源于多种字符集的字符的列,可采用这些数据类型。当列中各项所包含的 Unicode 字符数不同时(至多为 4000),使用 nvarchar 类型。当列中各项为同一固定长度时(至多为 4000Unicode 字符),使用 nchar 类型。当列中任意项超过 4000 个 Unicode字符时,使用 ntext 类型。
    
    在 Microsoft SQL Server  2000 中,传统上非 Unicode 数据类型允许使用由特定字符集定义的字符。字符集是在安装 SQL Server 时选择的,不能更改。使用 非Unicode 数据类型存储数据时,如varchar, char, text等,如果未指定字符排序序列时(字符集),使用默认的字符集,即使为某个字段指定了字符排序序列时,如果SQL Server 默认的排序序列与指定字段的排序序列不同时,不加N的话也会产生乱码,如默认的字符集是单字节的字符集如拉丁字符集(Collation name为Latin1_General_CI_AS)的时候,如果定义Name为Varchar类型,字符集为中文字符集时(Collation name为Chinese_PRC_CI_AS),用如下的插入语句也会乱码
    
    insert a(name) values ('AA中'),因为数据插入的时候,默认还是用Latin1_General_CI_AS字符集送到服务器,再转换为Collation name为Chinese_PRC_CI_AS时,产生乱码,但如果改为如下的时候: insert a(name) values (N'AA中') 则能正确插入,因为通过N前缀,以UNICODE的形式送到SQLSERVER,然后再转换成Chinese_PRC_CI_AS时,就不会产生乱码。
    
    2,UNICODE和非UNICODE之间的转换
    2-1 UNICODE--〉非UNICODE:Convert(varchar(50), name Collate Chinese_PRC_CS_AS_KS_WS)--name 是nvarvhar类型的,如name是'AA中'的时候
    
    Select DATALENGTH(Convert(varchar(50), name Collate Chinese_PRC_CS_AS_KS_WS)) from x, 返回的长度为4(UNICODE的时候为6)
    
    2-2 非UNICODE--〉UNICODE的时候:Convert(nvarchar(50), name)--name是varchar类型的时候如name是'AA中'的时候
    
    Select DATALENGTH(Convert(nvarchar(50), name)) from x, 返回的长度为6(非UNICODE的时候为4)
    
    3, 试验归类
    测试SQL:
    ------------------------------------------------------------
    drop table a
    create table a(a varchar(2))
    
    insert into a values('a')
    insert into a values(N'a')
    insert into a values('深圳')
    insert into a values(N'深圳')
    select a, len(a), datalength(a) from a
    
    drop table #a
    create table a(a varchar(2))
    
    insert into #a values('a')
    insert into #a values(N'a')
    insert into #a values('深圳')
    insert into #a values(N'深圳')
    select a, len(a), datalength(a) from #a
    
    ------------------------------------------------------------
    drop table a
    create table a(a varchar(8000))
    
    insert into a select REPLICATE('a', 8000) 
    insert into a select REPLICATE('', 8000) 
    insert into a select REPLICATE(N'a', 8000) 
    insert into a select REPLICATE(N'', 8000) 
    select a, len(a), datalength(a) from a
    
    
    3-1. 字符集是支持双字节的字符集如中文字符集(Collation name为Chinese_PRC_CI_AS)
    
    <1>. 定义varchar(2)
    
       (1) 正式表
        总结:在中文字符集下,定义varchar(x),
         不论使用不使用N'',英文字符都占1个字节,即可以存x个英文字符;
         不论使用不使用N'',中文字符都占2个字节,即可以存(x / 2)个中文,select结果为汉字本身,不是乱码;
         
       (2) 临时表
        总结:在中文字符集下,定义varchar(x), 
         和正式表表现一样;
      
    <2>. 定义nvarchar(2)
    
       (1) 正式表
        总结:在中文字符集下,定义nvarchar(x),
         不论使用不使用N'',英文字符都占2个字节,即可以存x个英文字符;
         不论使用不使用N'',中文字符都占2个字节,即可以存x个中文,select结果为汉字本身,不是乱码;
         
       (2) 临时表
        总结:在中文字符集下,定义nvarchar(x), 
         和正式表表现一样;
        
    <3>. 类型为varchar时,长度 x 和 datalength()对应,都指字节大小;
         英文len() = datalength();
         中文len() = datalength() / 2;
        
        类型为nvarchar时,长度 x 和 len()对应,都指字符长度; 
        
    3-2. 字符集是支持单字节的字符集如拉丁字符集(Collation name为Latin1_General_CI_AS)
      
    <1>. 定义varchar(2)
    
       (1) 正式表
        总结:在英文字符集下,定义varchar(x),
         不论使用不使用N'',英文字符都占1个字节,即可以存x个英文字符;
         不论使用不使用N'',中文字符都占1个字节,即可以存x个中文,但只保存前半截中文编码,所以select结果为乱码;
         (特殊:如果使用N'',此时插入的字符数最大为4000)
         英文和中文 len() = datalength();
         
       (2) 临时表
        总结:在英文字符集下,定义varchar(x),
         不论使用不使用N'',英文字符都占1个字节,即可以存x个英文字符;
         不使用N''时,中文占1个字节,可以存x个汉字,但都只存入汉字前半截字符编码,显示为乱码;
         使用N''时,中文占2个字节,只可以存 x/2 个汉字,没有乱码,取出仍为汉字,说明在英文字符集下通过使用N''是可以保存汉字的;
        
         除用N''保存的中文外,其余英文和中文 len() = datalength();
         用N''保存的中文字符len() = datalength() / 2<2>. 定义nvarchar(2)
    
       (1) 正式表
        总结:在英文字符集下,定义nvarchar(x),
         不论使用不使用N'',英文字符都占2个字节,即可以存x个英文字符;(注意每个字符比varchar用的空间大)
         不论使用不使用N'',中文字符都占2个字节,即可以存x个中文字符,
         但不使用N''只保存前半截中文编码,所以select结果为乱码;
         使用N''则保存和取出都为汉字本身;
         
       (2) 临时表
        总结:在英文字符集下,定义nvarchar(x), 
         和正式表表现相同;
        
    <3>. 类型为varchar时,长度 x 和 datalength()对应,都指字节大小;
         (临时表中N''中文字符长度比较特殊;)
        类型为nvarchar时,长度 x 和 len()对应,都指字符长度; 
    
    4、 使用归类
    varchar和nvarchar类型的最大长度,得到以下经验:
    <1> 最大长度问题
       1. 在中文字符集下使用varchar,最大长度可定义8000,这个8000是指字节数(datalength()),即最大可以保存8000个英文字符,4000个中文字符;
        特殊:若存入字符N'a',则最大能保存4000个字符,但其所占空间为4000字节;
       2. 在中文字符集下使用nvarchar,最大长度可定义4000,这个4000是指字符个数(len()),即最大可以保存4000个英文字符,4000个中文字符;
    
       3. 在英文字符集下使用varchar,最大长度可定义8000,这个8000是指字节数(datalength()),由于中文英文都保存为1字节,故最大可以保存8000个英文、中文字符;
       4. 在英文字符集下使用nvarchar,最大长度可定义4000,这个4000是指字符个数(len()),即最大可以保存4000个英文字符,4000个中文字符;
    <2> 文字显示问题
       1. N''要和数据类型nvarchar, nchar一起使用,如果对varchar, char字段类型强制使用N'',则会产生一些特殊现象,甚至无法控制; 
       2. 在英文字符集下,想要保存特殊符号字符、中文等双字节字符,在定义表结构时要使用nvarchar或者nchar,在保存时要用N''3. 在中文字符集下,数据库系统缺省已经可以保存特殊符号字符、中文等双字节字符。即使用不使用N'',都按双字节处理。但为了统一期间建议:
        在定义表结构时如果使用nvarchar或者nchar,在保存时要用N'',
        在定义表结构时如果使用varchar和char,此时不要使用N''操作;
       4. SUBSTRING ( expression , start , length ) 
        length:是一个整数,指定子串的长度(要返回的字符数或字节数)。
        中文字符集中按字符数取;
        英文字符集中,char, varchar按字节数取,nchar, nvarchar按字符数取;
  • 相关阅读:
    搭建hexo个人博客
    Scanner类使用close()方法问题
    记录一次Ubuntu基础配置和美化
    Linux更换默认Shell
    python-成员修饰符
    ysoserial项目之URLDNS利用分析
    Apereo Cas4.x 反序列化漏洞复现之复现分析与利用
    JAVA反序列化漏洞之调试环境搭建(含ysoserial项目)
    虚拟机window7忘记密码,如何重置?
    多种类型SQL注入
  • 原文地址:https://www.cnblogs.com/yingsi/p/4593869.html
Copyright © 2011-2022 走看看