Что происходит, когда вы изменяете (уменьшаете) длину столбца?


10

Допустим, у меня есть два столбца типа NUMBER(без точности и масштаба) и VARCHAR(300). Я видел, что эти столбцы слишком велики для моих данных, поэтому я хочу изменить их на NUMBER(11)и VARCHAR(10). Так что, если я запускаю этот оператор SQL:

ALTER TABLE FOO
    MODIFY(BAR NUMBER(10));
  • Смогу ли я сделать это на непустом столбце?
  • Если так, то что, если есть одно значение больше чем NUMBER(10), оракул скажет мне об этом?
  • Значения столбца по умолчанию останутся неизменными, если они были определены ранее?
  • Будет ли параметр обнуляемого столбца оставаться неизменным?
  • Первичный, внешний, уникальный ключ в этом столбце останется неизменным?
  • Будут ли ограничения, касающиеся этих столбцов, оставаться неизменными?
  • Будут ли индексы для этих столбцов оставаться неизменными?

Есть ли официальная документация, отвечающая на мои вопросы?

Ответы:


12

Руководство администратора Oracle говорит следующее:

Используйте инструкцию ALTER TABLE ... MODIFY, чтобы изменить существующее определение столбца. Вы можете изменить тип данных столбца, значение по умолчанию, ограничение столбца, выражение столбца (для виртуальных столбцов) и шифрование столбца.

Вы можете увеличить длину существующего столбца или уменьшить ее, если все существующие данные удовлетворяют новой длине. Вы можете изменить столбец с байтовой семантики на семантику CHAR или наоборот. Вы должны установить параметр инициализации BLANK_TRIMMING = TRUE, чтобы уменьшить длину непустого столбца CHAR.

Если вы изменяете таблицу, чтобы увеличить длину столбца типа данных CHAR, следует понимать, что это может быть трудоемкой операцией и может потребовать существенного дополнительного хранения, особенно если таблица содержит много строк. Это связано с тем, что значение CHAR в каждой строке должно быть дополнено пробелами, чтобы соответствовать новой длине столбца.

Oracle SQL Language Reference имеет гораздо больше деталей , в том числе следующие:

Вы можете изменить тип данных любого столбца, если все строки столбца содержат нули. Однако если вы измените тип данных столбца в таблице контейнера материализованного представления, Oracle Database сделает недействительным соответствующее материализованное представление.

Вы всегда можете увеличить размер символа или необработанного столбца или точность числового столбца, независимо от того, содержат ли все строки пустые значения. Вы можете уменьшить размер типа данных столбца, если изменение не требует изменения данных. База данных сканирует существующие данные и возвращает ошибку, если существуют данные, превышающие новый предел длины.

Вы можете изменить столбец DATE на TIMESTAMP или TIMESTAMP WITH LOCAL TIME ZONE. Вы можете изменить любой TIMESTAMP WITH LOCAL TIME ZONE на столбец DATE.

Если таблица пуста, вы можете увеличить или уменьшить начальное поле или дробное второе значение столбца datetime или interval. Если таблица не пуста, то вы можете только увеличить начальное поле или долю секунды в столбце даты / времени или интервала.

Для столбцов CHAR и VARCHAR2 вы можете изменить семантику длины, указав CHAR (чтобы указать семантику символов для столбца, который первоначально был указан в байтах) или BYTE (чтобы указать семантику байтов для столбца, который был первоначально указан в символах). Чтобы узнать семантику длины существующих столбцов, запросите столбец CHAR_USED в представлении словаря данных ALL_, USER_ или DBA_TAB_COLUMNS.

В вышеуказанной документации есть дополнительная информация и ограничения. Вот демонстрация попытки уменьшить точность столбца 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;

Итак, вывод таков: если вы хотите уменьшить точность или масштаб столбца и сохранить такие вещи, как индексы, ключи и т. Д., Единственный способ сделать это - скопировать таблицу, обрезать ее, изменить типы, скопировать данные обратно в нее и удалить временная таблица. Нет более быстрого, более элегантного способа?
mnowotka

1
Ну, вы могли бы создать новый столбец, скопировать данные, пересоздать индекс, удалить старый столбец и переименовать новый. Вы также можете использовать DBMS_REDEFINITION или создать новую таблицу, скопировать данные, удалить старую таблицу и переименовать новую. Или вы можете экспортировать таблицу, удалить ее, заново создать с новым определением и импортировать данные. Есть много способов сделать это, но вам нужно решить, быстрее или элегантнее.
Ли Риффель

Возможно, вы также можете создать новый столбец, скопировать в него данные, установить для старого столбца значение NULL, изменить его длину, скопировать данные из нового столбца обратно в измененный старый столбец и удалить новый столбец. И все это потому, что оракул не позволяет уменьшить числовые столбцы, даже если данные будут соответствовать. 8- {
Hans-Peter Störr
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.