我相信,你看到的是依赖于几个不同的东西互动
- 首先一个错误,数据库字符集必须是可变宽度字符集(即
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
行如果只值是“N”或“Y” ,为什么不做(1字节)? – tbone 2012-03-26 16:25:04
尝试重写你的检查约束为'CHECK(C IN(TO_NCHAR('N'),TO_NCHAR('Y')))'。我不确定在检查约束中是否允许调用函数,但它至少值得一试。 – 2012-03-26 16:51:54