Apa yang terjadi ketika Anda memodifikasi (mengurangi) panjang kolom?

10

Katakanlah saya memiliki dua kolom tipe NUMBER(tanpa presisi, dan skala) dan VARCHAR(300). Saya melihat bahwa kolom ini terlalu besar untuk data saya, jadi saya ingin memodifikasinya menjadi NUMBER(11)dan VARCHAR(10). Jadi, jika saya menjalankan pernyataan SQL ini:

ALTER TABLE FOO
    MODIFY(BAR NUMBER(10));
  • Apakah saya dapat melakukannya di kolom kosong?
  • Jika demikian, bagaimana Jika ada satu nilai yang lebih besar dari itu NUMBER(10), apakah oracle akan memberi tahu saya tentang hal itu?
  • Apakah nilai default kolom tetap tidak berubah jika ditentukan sebelumnya?
  • Apakah opsi kolom nullable tetap tidak berubah?
  • Apakah kunci utama, asing, unik pada kolom itu tidak akan berubah?
  • Akankah kendala yang melibatkan kolom tetap tidak berubah?
  • Akankah indeks pada kolom itu tetap tidak berubah?

Apakah ada dokumentasi resmi yang menjawab pertanyaan saya?

mnowotka
sumber

Jawaban:

12

The Oracle Administrator Panduan mengatakan berikut:

Gunakan pernyataan ALTER TABLE ... MODIFY untuk mengubah definisi kolom yang ada. Anda dapat mengubah tipe data kolom, nilai default, batasan kolom, ekspresi kolom (untuk kolom virtual) dan enkripsi kolom.

Anda bisa menambah panjang kolom yang ada, atau menguranginya, jika semua data yang ada memenuhi panjang baru. Anda dapat mengubah kolom dari semantik byte ke semantik CHAR atau sebaliknya. Anda harus mengatur parameter inisialisasi BLANK_TRIMMING = BENAR untuk mengurangi panjang kolom CHAR yang tidak kosong.

Jika Anda memodifikasi tabel untuk menambah panjang kolom tipe data CHAR, sadari bahwa ini bisa memakan waktu lama dan membutuhkan penyimpanan tambahan yang substansial, terutama jika tabel tersebut berisi banyak baris. Ini karena nilai CHAR di setiap baris harus kosong untuk memenuhi panjang kolom baru.

The Oracle SQL Language Reference memiliki lebih detail termasuk berikut:

Anda dapat mengubah tipe data kolom apa pun jika semua baris kolom berisi nol. Namun, jika Anda mengubah tipe data kolom dalam tabel tampilan wadah terwujud, maka Oracle Database membatalkan tampilan terwujud yang sesuai.

Anda selalu dapat meningkatkan ukuran karakter atau kolom mentah atau ketepatan kolom numerik, apakah semua baris mengandung nol atau tidak. Anda bisa mengurangi ukuran tipe data kolom selama perubahan tidak memerlukan data untuk dimodifikasi. Basis data memindai data yang ada dan mengembalikan kesalahan jika data ada yang melebihi batas panjang baru.

Anda dapat memodifikasi kolom TANGGAL ke TIMESTAMP atau TIMESTAMP DENGAN ZONA WAKTU LOKAL. Anda dapat memodifikasi TIMESTAMP DENGAN ZONA WAKTU LOKAL ke kolom TANGGAL.

Jika tabel kosong, maka Anda bisa menambah atau mengurangi bidang terkemuka atau nilai pecahan kedua kolom datetime atau interval. Jika tabel tidak kosong, maka Anda hanya bisa menambah bidang terkemuka atau pecahan detik dari kolom waktu atau interval.

Untuk kolom CHAR dan VARCHAR2, Anda dapat mengubah semantik panjang dengan menentukan CHAR (untuk menunjukkan semantik karakter untuk kolom yang awalnya ditentukan dalam byte) atau BYTE (untuk menunjukkan byte semantik untuk kolom yang awalnya ditentukan dalam karakter). Untuk mempelajari semantik panjang kolom yang ada, permintaan kolom CHAR_USED pada ALL_, USER_, atau DBA_TAB_COLUMNS tampilan kamus data.

Ada informasi tambahan dan batasan dalam dokumentasi di atas. Berikut ini adalah demonstrasi upaya untuk mengurangi ketepatan kolom Angka dan mengurangi panjang Varchar2. Anda dapat mencoba perubahan lain sehingga Anda akan tahu apa yang akan terjadi.

--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));

Pernyataan alter memiliki output sebagai berikut:

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.

Kurangi presisi dengan membuat kolom baru.

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;
Leigh Riffel
sumber
Jadi, kesimpulannya adalah - jika Anda ingin mengurangi ketepatan atau skala kolom dan menyimpan hal-hal seperti indeks, kunci dll. Satu-satunya cara untuk melakukannya adalah menyalin tabel, memotongnya, mengubah jenis, menyalin data kembali ke sana dan menjatuhkan meja sementara. Tidak ada cara yang lebih cepat dan lebih elegan?
mnowotka
1
Nah, Anda bisa membuat kolom baru, menyalin data, membuat ulang indeks, menjatuhkan kolom lama dan mengganti nama yang baru. Anda juga bisa menggunakan DBMS_REDEFINITION, atau Anda bisa membuat tabel baru, menyalin data, menjatuhkan tabel lama dan mengganti nama yang baru. Atau Anda bisa mengekspor tabel, menjatuhkannya, membuat ulang dengan definisi baru dan mereka mengimpor data. Ada banyak cara untuk melakukan ini, tetapi lebih cepat / lebih elegan adalah sesuatu yang harus Anda putuskan.
Leigh Riffel
Mungkin Anda juga dapat membuat kolom baru, menyalin data ke dalamnya, mengatur kolom lama ke nol, memodifikasi panjangnya, menyalin data dari kolom baru kembali ke kolom lama yang diubah dan menjatuhkan kolom baru. Dan semua itu karena oracle tidak memperbolehkan pengurangan kolom numerik meskipun data sesuai. 8- {
Hans-Peter Störr