Я полагаю, что то, что вы видите, является ошибкой, основанной на взаимодействии нескольких разных вещей
- Во-первых, набор символов базы данных должен быть набором символов переменной ширины (т. Е.
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