在实时数据库中更改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帮助?
NLS_LENGTH_SEMANTICS
使您可以使用字节长或字符长度语义创建CHAR
和VARCHAR2
列。现有列不受影响。这意味着现有数据没有风险。
但是,将NLS_LENGTH_SEMANTICS
参数设置为CHAR
可能会导致许多现有的安装脚本出乎意料地创建具有字符长度语义的列,从而导致运行时错误,包括缓冲区溢出。要点下,您需要确保在运行任何Oracle"内部"脚本(如补丁,升级等)时设置NLS_LENGTH_SEMANTICS=BYTE
。
在本文中,当字符长度语义设置为字节时,我提供了PL/SQL缓冲区溢出和表插入错误的示例。在这些示例中,更改为char语义清除了错误。
这是一个缓冲区溢出,并修复。
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设置为字节可能会导致缓冲区溢出。实际上,我提供了三个示例,其中将nls_length_semantics更改为char是此类错误的修复!
参数nls_length_semantics在Oracle 9i中引入。从12C开始,该手册进行了修订,其中包括有关缓冲溢出的警告。该警告在博客中重复了,包括Don Burleson的。
如果您在实例级别上未将NLS_LENGTH_SEMANTICS设置为char,但是您的应用程序可以存储多键字符,然后确保当您创建表格以明确声明每个列的char时。
。否则,多年来可能发生的事情是,随着外语名称(街道,城市,大学等)被添加到您的应用程序中,在不同的地方出现了相同的错误。
您最好将表中的NLS_LENGTH_SEMANTICS设置为在应用程序生命周期的早期。
原始海报询问:"更改现场数据库中的NLS_LENGTH_SEMANTICS是个好主意?"做两件事:
- 将所有字符列更改为char语义。
- 将实例nls_length_semantics更改为char。