Que se passe-t-il lorsque vous modifiez (réduisez) la longueur d'une colonne?

10

Disons que j'ai deux colonnes de type NUMBER(sans précision et échelle) et VARCHAR(300). J'ai vu que ces colonnes sont beaucoup trop grandes pour mes données, je souhaite donc les modifier en NUMBER(11)et VARCHAR(10). Donc, si je lance cette instruction SQL:

ALTER TABLE FOO
    MODIFY(BAR NUMBER(10));
  • Pourrai-je le faire sur une colonne non vide?
  • Si oui, que se passe-t-il s'il y a une valeur supérieure à NUMBER(10), Oracle m'en parlera-t-il?
  • Les valeurs par défaut des colonnes resteront-elles inchangées si elles ont été définies précédemment?
  • L'option nullable de colonne restera-t-elle inchangée?
  • La clé primaire, étrangère et unique de cette colonne restera-t-elle inchangée?
  • Les contraintes impliquant ces colonnes resteront-elles inchangées?
  • Les index de ces colonnes resteront-ils inchangés?

Existe-t-il des documents officiels répondant à mes questions?

mnowotka
la source

Réponses:

12

Le Guide des administrateurs Oracle dit ce qui suit:

Utilisez l'instruction ALTER TABLE ... MODIFY pour modifier une définition de colonne existante. Vous pouvez modifier le type de données de colonne, la valeur par défaut, la contrainte de colonne, l'expression de colonne (pour les colonnes virtuelles) et le chiffrement des colonnes.

Vous pouvez augmenter ou diminuer la longueur d'une colonne existante si toutes les données existantes satisfont la nouvelle longueur. Vous pouvez changer une colonne de la sémantique d'octet en sémantique CHAR ou vice versa. Vous devez définir le paramètre d'initialisation BLANK_TRIMMING = TRUE pour diminuer la longueur d'une colonne CHAR non vide.

Si vous modifiez une table pour augmenter la longueur d'une colonne de type de données CHAR, sachez que cela peut prendre du temps et peut nécessiter un stockage supplémentaire substantiel, en particulier si la table contient de nombreuses lignes. Cela est dû au fait que la valeur CHAR dans chaque ligne doit être remplie de blanc pour satisfaire la nouvelle longueur de colonne.

La référence du langage Oracle SQL contient beaucoup plus de détails, notamment:

Vous pouvez modifier le type de données de n'importe quelle colonne si toutes les lignes de la colonne contiennent des valeurs NULL. Cependant, si vous modifiez le type de données d'une colonne dans une table de conteneur de vues matérialisées, Oracle Database invalide la vue matérialisée correspondante.

Vous pouvez toujours augmenter la taille d'un caractère ou d'une colonne brute ou la précision d'une colonne numérique, que toutes les lignes contiennent ou non des valeurs nulles. Vous pouvez réduire la taille d'un type de données d'une colonne tant que la modification ne nécessite pas de modification des données. La base de données analyse les données existantes et renvoie une erreur s'il existe des données dépassant la nouvelle limite de longueur.

Vous pouvez modifier une colonne DATE en TIMESTAMP ou TIMESTAMP WITH LOCAL TIME ZONE. Vous pouvez modifier n'importe quel TIMESTAMP AVEC LOCAL TIME ZONE en une colonne DATE.

Si la table est vide, vous pouvez augmenter ou diminuer le champ de tête ou la seconde fraction de valeur d'une colonne datetime ou intervalle. Si la table n'est pas vide, vous pouvez uniquement augmenter le champ de tête ou la fraction de seconde d'une colonne datetime ou intervalle.

Pour les colonnes CHAR et VARCHAR2, vous pouvez modifier la sémantique de longueur en spécifiant CHAR (pour indiquer la sémantique des caractères pour une colonne qui a été initialement spécifiée en octets) ou BYTE (pour indiquer la sémantique des octets pour une colonne qui a été initialement spécifiée en caractères). Pour connaître la sémantique de longueur des colonnes existantes, interrogez la colonne CHAR_USED de la vue du dictionnaire de données ALL_, USER_ ou DBA_TAB_COLUMNS.

Il existe des informations supplémentaires et des restrictions dans la documentation ci-dessus. Voici une démonstration de la tentative de réduire la précision d'une colonne numérique et de réduire la longueur d'un Varchar2. Vous pouvez essayer d'autres modifications pour savoir ce qui se passera.

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

Les instructions alter ont la sortie suivante:

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.

Réduisez la précision en créant une nouvelle colonne.

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
la source
Donc, la conclusion est - si vous voulez diminuer la précision ou l'échelle de la colonne et garder des choses comme les index, les clés, etc. la seule façon de le faire est de copier la table, de la tronquer, de changer les types, de recopier les données et de la supprimer la table temporaire. Il n'y a pas de moyen plus rapide et plus élégant?
mnowotka
1
Eh bien, vous pouvez créer une nouvelle colonne, copier les données, recréer l'index, supprimer l'ancienne colonne et renommer la nouvelle. Vous pouvez également utiliser DBMS_REDEFINITION ou créer une nouvelle table, copier les données, supprimer l'ancienne table et renommer la nouvelle. Ou vous pouvez exporter la table, la déposer, la recréer avec la nouvelle définition et les importer les données. Il existe de nombreuses façons de le faire, mais vous devrez décider plus rapidement / plus élégamment.
Leigh Riffel
Vous pouvez également créer une nouvelle colonne, y copier les données, définir l'ancienne colonne sur null, modifier sa longueur, copier les données de la nouvelle colonne vers l'ancienne colonne modifiée et supprimer la nouvelle colonne. Et tout cela parce que Oracle ne permet pas de réduire les colonnes numériques même si les données conviennent. 8- {
Hans-Peter Störr