Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle12:lpad函数不像Oracle11那样管理2字节字符_Oracle_Oracle11g_Character Encoding_Oracle12c_Cyrillic - Fatal编程技术网

Oracle12:lpad函数不像Oracle11那样管理2字节字符

Oracle12:lpad函数不像Oracle11那样管理2字节字符,oracle,oracle11g,character-encoding,oracle12c,cyrillic,Oracle,Oracle11g,Character Encoding,Oracle12c,Cyrillic,我面临一个非常奇怪的问题,Oracle 12c没有像Oracle 11g那样管理2字节字符,这导致了一些函数(如LPAD)出现问题 我们有两个数据库,一个是11g,一个是12c,具有相同的NLS参数,但是11g在LPAD之类的函数中将西里尔字符管理为1字节,而12c将它们管理为2字节,这导致了一些问题:如果我们需要某个值的长度为40个字符,那么在填充时,其中的每个西里尔字符将计为2字节,但将显示为1个字符,这意味着将5个西里尔字符添加到40实际上将生成一个长度为35的值 Oracle官方文档()

我面临一个非常奇怪的问题,Oracle 12c没有像Oracle 11g那样管理2字节字符,这导致了一些函数(如LPAD)出现问题

我们有两个数据库,一个是11g,一个是12c,具有相同的NLS参数,但是11g在LPAD之类的函数中将西里尔字符管理为1字节,而12c将它们管理为2字节,这导致了一些问题:如果我们需要某个值的长度为40个字符,那么在填充时,其中的每个西里尔字符将计为2字节,但将显示为1个字符,这意味着将5个西里尔字符添加到40实际上将生成一个长度为35的值

Oracle官方文档()中描述了这种行为,但有几个版本(包括11g)都有这种行为,因此我不清楚为什么这两个版本在相同的设置下会有不同的行为,以及如何管理这种行为

重要提示:

  • 这两个数据库都管理欧洲字符(包括一些东欧字母中的特殊字符,如希腊字母等)和俄语字符(西里尔字母),因此将该地区转换为“俄罗斯”并不是一个真正的选择
  • 使用nvarchar2而不是varchar2解决了这个问题(它会切换到国家字符集UTF16),但这意味着将4 TB数据库中的所有varchar2列切换到nvarchar2,这非常麻烦,可能会导致大量空间浪费
  • 问题发生在管理数据库中已经存储的数据的存储过程中,因此这看起来不像是客户端配置错误
  • NLS参数的数据库属性(我删除了日期和货币格式,因为它们并不相关):

    V$参数属性(相同,删除日期):

    来自12c数据库的示例:

    SELECT 'This is a test данные испытаний' as "Original",
           lpad(nvl('This is a test данные испытаний', ' '), 40) as "LPADded",
           lpad(nvl('данные испытаний', ' '), 40) as "Cyrillic only",
           lpad(nvl('This is a test', ' '), 40) as "Non-cyrillic only",
           lpad(nvl(to_nchar('данные испытаний'), ' '), 40) as "NChar cyrillic only",
           lpad(nvl(to_nchar('This is a test данные испытаний'),
                    ' '),
                40) as "NChar mixed"
      FROM dual;
    
    结果:

    This is a test данные испытаний           (original - 31 chars)
    This is a test данные испыта              (std lpad - 28 chars)
             данные испытаний                 (std lpad cyrillic only - 25 chars)
                              This is a test  (std lpad non-cyrillic only - 40 chars)
                            данные испытаний  (nchar lpad cyrillic only - 40 chars)
             This is a test данные испытаний  (nchar lpad mixed - 40 chars)
    
    在11g数据库中,上述所有字符(当然,原始字符除外)的长度均为40个字符


    谢谢

    我认为问题与UNICODE中的不明确字体有关。您可以在此处找到描述:

    在oracle中,如果使用

    lengthc function 
    
    始终返回字符的实际长度, 而

     lenghtb function 
    
    返回字符的字节占用

    一种可能的解决方案是使用以下形式:

    我尝试使用占用2字节的UNISTR('\4F4F')

     select lpad('pippo'||UNISTR('\4F4F'),10+lengthc(UNISTR('\4F4F')),'x') from dual;
    

    并且显示的长度是所需的长度

    。。。我想知道您是否可以使用lengthb做一些事情,然后添加所需的字符数,如此建议?请您使用
    LPAD
    查询和每个版本的输出示例来回答这个问题。@MT0添加了一些examples@jad实际上不是一个选项,因为这需要更改对LPAD的所有调用,SUBSTR等在所有存储过程、视图、查询等中都有函数,但由于外部约束,我不能这样做。
     lenghtb function 
    
     select lpad('pippo'||UNISTR('\4F4F'),10+lengthc(UNISTR('\4F4F')),'x') from dual;