我相信您所看到的是一个依赖于几个不同事物交互的错误
- 首先,数据库字符集必须是可变宽度字符集(即
AL32UTF8),这样单个字符可能需要最多四个字节的存储空间。
- 第二,列必须用字符长度语义声明
- 第三,从 11.1 开始,Oracle 添加了一项优化,以便如果您向表中添加一个声明为
NOT NULL 并且具有 DEFAULT 的列,Oracle 可以通过更新数据字典来完成此操作,而不是实际更新将默认值存储在表的每一行中。
当这两件事都成立时,返回的值的长度似乎为 4,并用 CHR(0) 字符填充。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
SQL> create table foo( col1 number );
Table created.
SQL> insert into foo values( 1 );
1 row created.
SQL> commit;
Commit complete.
SQL> alter table foo add c char(1 char) default 'N' not null;
Table altered.
SQL> alter table foo add constraint chk_foo check( c in ('Y', 'N') );
alter table foo add constraint chk_foo check( c in ('Y', 'N') )
*
ERROR at line 1:
ORA-02293: cannot validate (SCOTT.CHK_FOO) - check constraint violated
SQL> select c, dump(c) from foo;
C DUMP(C)
---- ------------------------------
N Typ=1 Len=4: 78,0,0,0
如果您实际上强制将该值存储在表中,您将获得没有CHR(0) 填充的预期行为。所以如果我在表中插入一个新行,它就会通过。
SQL> insert into foo(col1) values (2);
1 row created.
SQL> select c, dump(c) from foo;
C DUMP(C)
---- ------------------------------
N Typ=1 Len=4: 78,0,0,0
N Typ=1 Len=1: 78
您还可以发出UPDATE 来更新实际上并未将值存储在表行中的行
SQL> update foo
2 set c = 'N'
3 where c != 'N';
1 row updated.
SQL> select c, dump(c) from foo;
C DUMP(C)
---- ------------------------------
N Typ=1 Len=1: 78
N Typ=1 Len=1: 78