再定義したい次の表があります。
_create table tq84_redefinition (
id number primary key,
ts1 timestamp not null,
ts2 timestamp
);
_
列_not null
_の_ts1
_制約に注意してください。
_dbms_redefinition
_を使用して、特に_copy_constraints => true
_を使用します。
_create table tq84_redefinition_int (
id number, -- Note: no primary key to prevent «ORA-01408: such column list already indexed»
ts1 date,
ts2 date,
duration_minutes as ((ts2 - ts1) * 24 * 60)
);
begin
dbms_redefinition.start_redef_table(
user, 'tq84_redefinition', 'tq84_redefinition_int',
'id, ' ||
'to_date(to_char(ts1, ''ddmmyyyyhh24miss''), ''ddmmyyyyhh24miss'') ts1, ' ||
'to_date(to_char(ts2, ''ddmmyyyyhh24miss''), ''ddmmyyyyhh24miss'') ts2');
end;
/
-- set serveroutput on
declare
cnt_errors binary_integer;
begin
dbms_redefinition.copy_table_dependents(
user, 'tq84_redefinition', 'tq84_redefinition_int',
-------------------------------------------------------
copy_indexes => dbms_redefinition.cons_orig_params,
copy_triggers => true,
copy_constraints => true,
copy_privileges => true,
ignore_errors => false,
num_errors => cnt_errors,
copy_statistics => true,
copy_mvlog => false);
if cnt_errors > 0 then
dbms_output.put_line('There were ' || cnt_errors || ' errors.');
end if;
end;
/
exec dbms_redefinition.sync_interim_table(user, 'tq84_redefinition', 'tq84_redefinition_int');
exec dbms_redefinition.finish_redef_table(user, 'tq84_redefinition', 'tq84_redefinition_int');
_
SQL * Plusのdesc
が_not null
_制約を正しく表示しないことを除いて、すべてが正常に機能しているようです。
_...> desc tq84_redefinition;
Name Null? Type
--------------------------- -------- ---------------
ID NUMBER
TS1 DATE
TS2 DATE
DURATION_MINUTES NUMBER
_
ただし、どこかに、null以外の制約が設定されています。を発行してそれを見ることができます
_select constraint_type, constraint_name, search_condition
from user_constraints
where table_name = 'TQ84_REDEFINITION';
_
また、レコード[insert into tq84_redefinition (id) values (999999)
]を挿入しようとすると、(正しい)エラーメッセージORA-01400: cannot insert NULL into ("META"."TQ84_REDEFINITION"."TS1")
が表示されます。
編集:バージョン(v $ version)は次のとおりです。
_BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for 32-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
_
編集2 @Munchi、提案されたselectステートメントの結果
_select
column_name as "Name",
nullable as "Null?",
concat(concat(concat(data_type,'('),data_length),')') as "Type"
from
user_tab_columns
where
table_name = 'TQ84_REDEFINITION'
_
です
_Name N Type
------------------------------ - --------------
ID Y NUMBER(22)
TS1 Y DATE(7)
TS2 Y DATE(7)
DURATION_MINUTES Y NUMBER(22)
_
これは既知のバグです(説明は残念ながら公開されていません):
Bug:4396234 ET10.2OREDEF:* _TAB_COLUMNSテーブルのNULL可能なCOLはオンラインREDEF後に更新されません
NOT NULL制約はNOVALIDATEとしてコピーされ、手動でVALIDATE状態に設定する必要があります。例:
ALTER TABLE t84_redefenition ENABLE VALIDATE CONSTRAINT constraint_name;
主な主要な問題は同様ですが、そのために報告されたバグはありません。ただし、無効にして再度有効にすると問題が解決することを発見しました。
ALTER TABLE t84_redefinition DISABLE PRIMARY KEY;
ALTER TABLE t84_redefinition ENABLE PRIMARY KEY;
テーブル列定義の_Not Null
_句は、_$sys$cols
_にフラグを設定し、列に_sys_xxxxxx
_制約を生成します。
_dbms_redef
_は、_sys_xxxxxxx
_制約をコピーするだけで、フラグの設定を省略します。 「Nullable?」にデコードされるのはこのフラグです。テーブルのSQLDeveloper列タブに(たとえば)表示します。
これの効果は何ですか-
まあ、参照整合性は維持されます-制約が存在する列にnullを挿入しようとしても失敗します。
ただし、CBOが特定のクエリの最適化の一部として_$sys$cols
_フラグ(制約ではない)を調べることをどこかで読みました(その記事をもう一度見つける必要があります)。
Null以外の列に基づくインデックスについて考えます。このインデックスは、FTSを実行するのではなく、select count(*)
タイプのクエリを満たす候補になる場合があります。 _$sys$cols
_自体がnull(再定義によって設定されない)の場合、そのインデックスは考慮されません。
あなたの再定義コードにステップを追加する努力の価値があると思います
再定義後-制約からnullでないcolの名前を保存します
-nullではない制約を削除-_alter table modify col not null
_句で再適用
Java開発者のうめき声を静めるためでさえ、前と後の違いを見つけます。