web-dev-qa-db-ja.com

テーブルをドロップして再作成せずに、Oracleの特定の位置に列を挿入する方法は?

Oracleの既存のテーブルに2つの新しい列を挿入する必要がある特定のシナリオがあります。テーブルのドロップと再作成はできません。だから、それは何らかの手段で達成できますか?

22
Amit

アミット

テーブルが作成されたら、テーブルの最後以外の場所に列を追加できるとは思わない。 1つの解決策は、これを試すことです。

CREATE TABLE MY_TEMP_TABLE AS
SELECT *
FROM TABLE_TO_CHANGE;

列を追加するテーブルをドロップします。

DROP TABLE TABLE_TO_CHANGE;

これは、既存のテーブルを最初から再構築して、必要な列に追加できる時点です。この演習では、「COL2 and COL3」という名前の列を追加するとします。

次に、データを新しいテーブルに挿入します。

INSERT INTO TABLE_TO_CHANGE (COL1, COL2, COL3, COL4) 
SELECT COL1, 'Foo', 'Bar', COL4
FROM MY_TEMP_TABLE;

データが「新しい」テーブルに挿入されると、一時テーブルを削除できます。

DROP TABLE MY_TEMP_TABLE;

これは、特定の場所に列を追加するときによく行うことです。これが実稼働のオンラインシステムである場合、明らかに実用的ではありませんが、1つの潜在的なアイデアにすぎません。

-CJ

19
CJ Travis

(まだ)ALTER TABLEを使用して列の位置を選択することはできません。テーブルの最後にのみ追加できます。当然、任意の順序で列を選択できるため、SELECT * FROM列の順序を使用している場合を除き、大したことはないはずです。

本当に特定の順序でそれらを持たなければならず、テーブルをドロップして再作成できない場合、代わりにカラムをドロップして再作成できるかもしれません:

最初にテーブルをコピーします

CREATE TABLE my_tab_temp AS SELECT * FROM my_tab;

次に、挿入する列の後に配置する列をドロップします

ALTER TABLE my_tab DROP COLUMN three;

次に、新しい列(この例では2つ)と削除した列を追加します。

ALTER TABLE my_tab ADD (two NUMBER(2), three NUMBER(10));

最後に、再作成された列のデータを追加し直します

UPDATE my_tab SET my_tab.three = (SELECT my_tab_temp.three FROM my_tab_temp WHERE my_tab.one = my_tab_temp.one);

明らかに、更新はより複雑になる可能性が高く、インデックスと制約を処理する必要があり、場合によってはこれを使用できなくなります(LOB列など)。さらに、これはこれを行うための非常に恐ろしい方法ですが、テーブルは常に存在しているので、必要な順序で列が作成されます。しかし、列の順序は本当にそれほど重要ですか?

5
Lunc

これはやや古いですが、列の順序を実際に変更するわずかに改善されたバージョンを追加したいと思います。手順は次のとおりです(列COL1、COL2、COL3を持つテーブルTAB1があると仮定します)。

  1. テーブルTAB1に新しい列を追加します。
alter table TAB1 add (NEW_COL number);
  1. 列の順序を変更しながらテーブルを一時名に「コピー」し、新しい列の名前を変更します。
create table tempTAB1 as select NEW_COL as COL0, COL1, COL2, COL3 from TAB1;
  1. 既存のテーブルを削除します。
drop table TAB1;
  1. temp tablenameの名前を、削除されたtablenameに変更します。
rename tempTAB1 to TAB1;
5
Gerd

12cでは、非表示から表示に設定された列が表の最後の列として表示されるという事実を利用できます。 ヒントとコツ:Oracle Database 12cの非表示列

@ jeffrey-kempが彼のコメントで話していた「トリック」かもしれませんが、そこのリンクはもう機能しません。

例:

ALTER TABLE my_tab ADD (col_3 NUMBER(10));
ALTER TABLE my_tab MODIFY (
  col_1 invisible,
  col_2 invisible
);
ALTER TABLE my_tab MODIFY (
  col_1 visible,
  col_2 visible
);

これで、col_3が最初にSELECT * FROM my_tabステートメント。

注:これにより、ディスク上の列の物理的な順序は変更されませんが、ほとんどの場合、それはとにかくしたいことではありません。物理的な順序を本当に変更したい場合は、DBMS_REDEFINITIONパッケージを使用できます。

0
dr fu manchu