oracle 是否建议在活动数据库中将NLS_LENGTH_SEMANTICS从BYTE更改为'CHAR

gzszwxb4  于 2023-03-17  发布在  Oracle
关注(0)|答案(2)|浏览(282)

在活动数据库中更改NLS_LENGTH_SEMANTICS是否是个好主意?数据库字符集使用多字节字符编码方案。因此,应用程序会收到无法重新创建的随机错误。在大多数情况下,ORA-06502: PL/SQL: numeric or value error会引发。因此,为了解决此问题,我们计划更改NLS_LENGTH_SEMANTICS参数值。对于该应用程序,建议的NLS_LENGTH_SEMANTICS设置为CHAR,但在创建DB示例时未将其设置为该值。仅仅将值更改为CHAR会有帮助吗?还是使用NLS_LENGTH_SEMANTICS = 'CHAR'创建一个新的DB示例,然后导出旧DB并将其导入到新DB会有帮助?

gt0wga4j

gt0wga4j1#

NLS_LENGTH_SEMANTICS使您能够使用字节或字符长度语义创建CHARVARCHAR2列。**现有列不受影响。**这意味着现有数据没有风险。
但是,将NLS_LENGTH_SEMANTICS参数设置为CHAR可能会导致许多现有安装脚本意外创建具有字符长度语义的列,从而导致运行时错误,包括缓冲区溢出。要解决此问题,您需要确保在运行任何Oracle“内部”脚本(如补丁程序、升级等)时设置NLS_LENGTH_SEMANTICS=BYTE

qzwqbdag

qzwqbdag2#

在本文中,我提供了当字符长度语义设置为BYTE时PL/SQL缓冲区溢出和表插入错误的示例,在这些示例中,更改为CHAR语义可以清 debugging 误。
这里有一个缓冲区溢出,并修复。

show parameter nls_length_semantics;
NAME                 TYPE   VALUE 
-------------------- ------ ----- 
nls_length_semantics string BYTE 

declare
    l_name varchar2(100) := 'What Are Em Dashes ( — ) And How Do You Use Them?';
    l_sub varchar2(100);
    l_buf varchar2(30);
begin
    l_sub := substr(l_name, 1, 30);
    dbms_output.put_line(l_sub);
    dbms_output.put_line('lengthb: ' || lengthb(l_sub));
    l_buf := l_sub;
end;
/
ORA-06502: PL/SQL: numeric or value error: character string buffer too small

alter session set nls_length_semantics=char;
Session altered.

What Are Em Dashes ( — ) And H
lengthb: 32

以下是列插入错误和修复:

show parameter nls_length_semantics;
NAME                 TYPE   VALUE 
-------------------- ------ ----- 
nls_length_semantics string BYTE 

create table cathedrals(
   name  varchar2(30)
);
Table CATHEDRALS created.

insert into cathedrals (name) values (q'{Kölner Dom St. Peter und Maria}');
ORA-12899: value too large for column "USR"."CATHEDRALS"."NAME" (actual: 31, maximum: 30)

alter table cathedrals modify name varchar2(30 char);
Table CATHEDRALS altered.

insert into cathedrals (name) values (q'{Kölner Dom St. Peter und Maria}');
1 row inserted.

即使这样,您仍然容易受到运行时缓冲区溢出的攻击。

show parameter nls_length_semantics;
NAME                 TYPE   VALUE 
-------------------- ------ ----- 
nls_length_semantics string BYTE  
declare
  l_name varchar2(30);
begin
  select name into l_name from cathedrals;
end;
/
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
alter session set nls_length_semantics=char;
PL/SQL procedure successfully completed.

Oracle声称将nls_length_semantics设置为BYTE会导致缓冲区溢出。事实上,我已经提供了三个示例,其中将nls_length_semantics更改为CHAR可以修复此类错误!
参数nls_length_semantics是在Oracle 9 i中引入的。从12 c开始,手册被修改以包括关于缓冲区溢出的警告。这个警告在博客中重复出现,包括Don伯莱森的博客。
如果没有在示例级将nls_length_semantics设置为CHAR,但应用程序可以存储多字节字符,则请确保在创建表时为每列显式声明CHAR。
否则,多年来可能发生的情况是,当外语名称(街道、城市、大学等)添加到应用程序中时,相同的错误会出现在不同的地方。
最好在应用程序生命周期的早期将表中的nls_length_semantics设置为CHAR。
楼主问:“更改活动数据库中的NLS_LENGTH_SEMANTICS是否是一个好主意?”请执行以下两项操作:
1.将所有字符列更改为CHAR语义。
1.将示例nls_length_semantics更改为CHAR。

相关问题