web-dev-qa-db-ja.com

列の長さを変更(縮小)するとどうなりますか?

タイプNUMBER(精度とスケールなし)とVARCHAR(300)の2つの列があるとします。これらの列は私のデータには大きすぎるので、NUMBER(11)およびVARCHAR(10)に変更します。したがって、次のSQLステートメントを実行すると、

_ALTER TABLE FOO
    MODIFY(BAR NUMBER(10));
_
  • 空でない列でそれを行うことはできますか?
  • もしそうなら、NUMBER(10)より大きい値が1つある場合、Oracleはそれについて教えてくれますか?
  • 以前に定義されている場合、列のデフォルト値は変更されませんか?
  • 列のNULL可能オプションは変更されませんか?
  • その列の主キー、外部キー、一意キーは変更されませんか?
  • その列を含む制約は変更されませんか?
  • その列のインデックスは変更されませんか?

私の質問に答える公式文書はありますか?

10
mnowotka

Oracle管理者ガイド は次のように述べています。

ALTER TABLE ... MODIFYステートメントを使用して、既存の列定義を変更します。列のデータ型、デフォルト値、列の制約、列式(仮想列の場合)、および列の暗号化を変更できます。

既存のすべてのデータが新しい長さを満たす場合は、既存の列の長さを増やしたり、減らしたりできます。列をバイトセマンティクスからCHARセマンティクスに、またはその逆に変更できます。空でないCHAR列の長さを短くするには、初期化パラメータBLANK_TRIMMING = TRUEを設定する必要があります。

データ型CHARの列の長さを増やすためにテーブルを変更する場合、これは時間がかかる操作であり、特にテーブルに多くの行が含まれている場合は、かなりの追加ストレージが必要になる可能性があることに注意してください。これは、新しい列の長さを満たすために、各行のCHAR値に空白を埋め込む必要があるためです。

Oracle SQL言語リファレンス には、次のような詳細が含まれています。

列のすべての行にnullが含まれている場合は、任意の列のデータ型を変更できます。ただし、マテリアライズド・ビューのコンテナ表の列のデータ型を変更すると、対応するマテリアライズド・ビューが無効になります。

すべての行にnullが含まれるかどうかに関係なく、文字列またはraw列のサイズや数値列の精度をいつでも増やすことができます。データを変更する必要がない限り、列のデータ型のサイズを小さくできます。データベースは既存のデータをスキャンし、新しい長さの制限を超えるデータが存在する場合はエラーを返します。

DATE列をTIMESTAMPまたはTIMESTAMP WITH LOCAL TIME ZONEに変更できます。 TIMESTAMP WITH LOCAL TIME ZONEをDATE列に変更できます。

テーブルが空の場合、日時列または間隔列の先行フィールドまたは小数秒の値を増減できます。テーブルが空でない場合は、日時列または間隔列の先行フィールドまたは小数秒のみを増やすことができます。

CHARおよびVARCHAR2列の場合、長さセマンティクスを変更するには、CHAR(最初はバイトで指定された列の文字セマンティクスを示す)またはBYTE(最初は文字で指定された列のバイトセマンティクスを示す)を指定します。既存の列の長さセマンティクスを知るには、ALL_、USER_、またはDBA_TAB_COLUMNSデータディクショナリビューのCHAR_USED列をクエリします。

上記のドキュメントには、追加情報と制限があります。以下は、Number列の精度を下げ、Varchar2の長さを短くする試みのデモです。他の変更を試して、何が起こるかを知ることができます。

--Setup.
DROP TABLE FOO;
CREATE TABLE FOO (BAR Number, BAR2 VARCHAR2(300));
INSERT INTO FOO (SELECT Level, RPAD(to_char(Level),10*Level,to_char(Level)) 
   FROM DUAL CONNECT BY Level <=20);
COMMIT;
SELECT * FROM FOO;

--Reduce Number to Number(10).
ALTER TABLE FOO MODIFY (BAR NUMBER (10));

--Reduce Varchar2(300) to Varchar2(100) (data would be truncated).
ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(100));

--Reduce Varchar2(300) to Varchar2(200) (no data would be truncated).
ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(200));

Alterステートメントの出力は次のとおりです。

ALTER TABLE FOO MODIFY (BAR NUMBER (10))
Error report:
SQL Error: ORA-01440: column to be modified must be empty to decrease precision or scale
01440. 00000 -  "column to be modified must be empty to decrease precision or scale"

ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(100))
Error report:
SQL Error: ORA-01441: cannot decrease column length because some value is too big
01441. 00000 -  "cannot decrease column length because some value is too big"

table FOO altered.

新しい列を作成して精度を下げます。

ALTER TABLE FOO ADD (BAR3 NUMBER(10));
UPDATE FOO SET Bar3 = Bar;
ALTER TABLE FOO DROP COLUMN BAR;
ALTER TABLE FOO RENAME COLUMN BAR3 TO BAR;
12
Leigh Riffel