Cosa succede quando modifichi (riduci) la lunghezza di una colonna?


10

Diciamo che ho due colonne di tipo NUMBER(senza precisione e scala) e VARCHAR(300). Ho visto che queste colonne sono troppo grandi per i miei dati, quindi voglio modificarle in NUMBER(11)e VARCHAR(10). Quindi, se eseguo questa istruzione SQL:

ALTER TABLE FOO
    MODIFY(BAR NUMBER(10));
  • Potrò farlo sulla colonna non vuota?
  • In tal caso, cosa succede se esiste un valore maggiore di NUMBER(10), l'oracolo me lo dirà?
  • I valori predefiniti delle colonne rimarranno invariati se definiti in precedenza?
  • L'opzione nullable della colonna rimarrà invariata?
  • La chiave primaria, esterna e unica su quella colonna rimarrà invariata?
  • I vincoli che coinvolgono tali colonne rimarranno invariati?
  • Gli indici su quelle colonne rimarranno invariati?

C'è qualche documentazione ufficiale che risponde alle mie domande?

Risposte:


12

La Guida per amministratori Oracle dice quanto segue:

Utilizzare l'istruzione ALTER TABLE ... MODIFY per modificare una definizione di colonna esistente. È possibile modificare il tipo di dati della colonna, il valore predefinito, il vincolo della colonna, l'espressione della colonna (per le colonne virtuali) e la crittografia della colonna.

È possibile aumentare la lunghezza di una colonna esistente o ridurla, se tutti i dati esistenti soddisfano la nuova lunghezza. È possibile modificare una colonna dalla semantica dei byte alla semantica CHAR o viceversa. È necessario impostare il parametro di inizializzazione BLANK_TRIMMING = TRUE per ridurre la lunghezza di una colonna CHAR non vuota.

Se si sta modificando una tabella per aumentare la lunghezza di una colonna del tipo di dati CHAR, tenere presente che può essere un'operazione che richiede tempo e può richiedere notevole spazio di archiviazione aggiuntivo, soprattutto se la tabella contiene molte righe. Questo perché il valore CHAR in ogni riga deve essere vuoto per soddisfare la nuova lunghezza della colonna.

L'Oracle SQL Guida di riferimento ha molto più in dettaglio tra cui le seguenti:

È possibile modificare il tipo di dati di qualsiasi colonna se tutte le righe della colonna contengono valori null. Tuttavia, se si modifica il tipo di dati di una colonna in una tabella del contenitore della vista materializzata, il database Oracle invalida la vista materializzata corrispondente.

Puoi sempre aumentare le dimensioni di un carattere o una colonna non elaborata o la precisione di una colonna numerica, indipendentemente dal fatto che tutte le righe contengano valori nulli. È possibile ridurre la dimensione di un tipo di dati di una colonna purché la modifica non richieda la modifica dei dati. Il database esegue la scansione dei dati esistenti e restituisce un errore se esistono dati che superano il nuovo limite di lunghezza.

È possibile modificare una colonna DATA in TIMESTAMP o TIMESTAMP CON FUSO ORARIO LOCALE. È possibile modificare qualsiasi TIMESTAMP CON FUSO ORARIO LOCALE in una colonna DATA.

Se la tabella è vuota, è possibile aumentare o diminuire il campo iniziale o il secondo valore frazionario di una colonna datetime o intervallo. Se la tabella non è vuota, è possibile aumentare solo il campo iniziale o il secondo frazionario di una colonna datetime o intervallo.

Per le colonne CHAR e VARCHAR2, è possibile modificare la semantica della lunghezza specificando CHAR (per indicare la semantica dei caratteri per una colonna originariamente specificata in byte) o BYTE (per indicare la semantica dei byte per una colonna originariamente specificata in caratteri). Per conoscere la semantica della lunghezza delle colonne esistenti, eseguire una query sulla colonna CHAR_USED della vista del dizionario dei dati ALL_, USER_ o DBA_TAB_COLUMNS.

Ci sono ulteriori informazioni e restrizioni nella documentazione sopra. Ecco una dimostrazione del tentativo di ridurre la precisione di una colonna numerica e di ridurre la lunghezza di un Varchar2. Puoi provare altre modifiche in modo da sapere cosa accadrà.

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

Le istruzioni alter hanno il seguente output:

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.

Riduci la precisione creando una nuova colonna.

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;

Quindi, la conclusione è: se vuoi ridurre la precisione o la scala della colonna e mantenere cose come indici, chiavi ecc., L'unico modo per farlo è copiare la tabella, troncarla, cambiarne i tipi, copiare i dati su di essa e rilasciarla la tabella temporanea. Non esiste un modo più veloce, più elegante?
mnowotka,

1
Bene, potresti creare una nuova colonna, copiare i dati, ricreare l'indice, eliminare la vecchia colonna e rinominare quella nuova. È inoltre possibile utilizzare DBMS_REDEFINITION oppure creare una nuova tabella, copiare i dati, eliminare la vecchia tabella e rinominare quella nuova. Oppure puoi esportare la tabella, rilasciarla, ricrearla con la nuova definizione e importare i dati. Ci sono molti modi per farlo, ma più veloce / più elegante è qualcosa che dovrai decidere.
Leigh Riffel,

Probabilmente puoi anche creare una nuova colonna, copiare i dati su di essa, impostare la colonna vecchia su null, modificarne la lunghezza, copiare i dati dalla nuova colonna sulla vecchia colonna modificata e rilasciare la nuova colonna. E tutto ciò perché l'oracolo non consente di ridurre le colonne numeriche anche se i dati si adatterebbero. 8- {
Hans-Peter Störr,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.