Изменение структуры таблицы. ALTER TABLE
Уже созданные таблицы можно изменять. Для этого используется команда SQL ALTER
. Данная команда относится к группе DDL.
Подготовка данных
Тестировать будем на таблице employees
. Изначально она будет состоять только из одной колонки id
:
create table employees(
id number not null primary key
);
insert into employees(id)
values(1);
insert into employees(id)
values(2);
insert into employees(id)
values(3);
insert into employees(id)
values(4);
create table employees(
id number not null primary key
);
insert into employees(id)
values(1);
insert into employees(id)
values(2);
insert into employees(id)
values(3);
insert into employees(id)
values(4);
Добавление колонки в таблицу
Добавим в таблицу сотрудников колонку для хранения дня рождения:
alter table employees
add (birthday date)
alter table employees
add (birthday date)
По умолчанию все строки таблицы будут иметь null
в новой колонке. Но если при ее добавлении указать значение по-умолчанию, то все строки будут содержать его в новой колонке.
Добавим колонку notify_by_email
, которая будет по-умолчанию содержать в себе "1", если сотруднику нужно отправлять уведомления по почте, и "0", если нет:
alter table employees
add (
notify_by_email number default 0
);
comment on column employees.notify_by_email is
'Уведомлять по почте(1-да, 0-нет)';
alter table employees
add (
notify_by_email number default 0
);
comment on column employees.notify_by_email is
'Уведомлять по почте(1-да, 0-нет)';
Посмотрим, как сейчас выглядят данные в таблице:
Как видно, каждая строка содержит "0" в колонке notify_by_email
.
Нельзя добавить колонку NOT NULL
в таблицу с данными без значения по-умолчанию.
-- Ошибка! Нельзя добавить колонку
-- без default-значения
alter table employees
add(
not_null_col number(1) not null
)
-- Ошибка! Нельзя добавить колонку
-- без default-значения
alter table employees
add(
not_null_col number(1) not null
)
В результате получим ошибку ORA-01758: table must be empty to add mandatory (NOT NULL) column
.
Но если указать значение по-умолчанию, ошибки не будет:
-- Ошибки не будет, каждая строка будет
-- содержать 1 в колонке
alter table employees
add(
not_null_col number(1) default 1 not null
)
-- Ошибки не будет, каждая строка будет
-- содержать 1 в колонке
alter table employees
add(
not_null_col number(1) default 1 not null
)
Колонка добавляется без ошибок:
Добавление нескольких колонок в таблицу
Чтобы добавить несколько колонок в таблицу, нужно просто перечислить их через запятую:
alter table employees
add ( emp_lastname varchar2(100 char),
emp_firstname varchar2(100 char),
dept_id number(2) default 10 not null,
is_out varchar2(1) default 'Y' not null);
comment on column employees.emp_lastname is
'Фамилия';
comment on column employees.emp_firstname is
'Имя';
comment on column employees.dept_id is
'id подразделения';
comment on column employees.is_out is
'Больше не работает?';
alter table employees
add ( emp_lastname varchar2(100 char),
emp_firstname varchar2(100 char),
dept_id number(2) default 10 not null,
is_out varchar2(1) default 'Y' not null);
comment on column employees.emp_lastname is
'Фамилия';
comment on column employees.emp_firstname is
'Имя';
comment on column employees.dept_id is
'id подразделения';
comment on column employees.is_out is
'Больше не работает?';
Удаление колонки из таблицы
Удалим только что добавленную колонку emp_lastname
из таблицы:
alter table employees
drop column emp_lastname
alter table employees
drop column emp_lastname
Следует учитывать, что если на удаляемую колонку ссылаются строки из другой таблицы(посредством внешнего ключа, то удалить колонку не получится.
Убедимся в этом, создав таблицу emp_bonuses
, которая будет ссылаться на колонку id
в таблице employees
:
create table emp_bonuses(
emp_id number not null,
bonus number not null,
constraint emp_bonuses_emp_fk
foreign key(emp_id) references employees(id)
)
create table emp_bonuses(
emp_id number not null,
bonus number not null,
constraint emp_bonuses_emp_fk
foreign key(emp_id) references employees(id)
)
Теперь попробуем удалить колонку id
:
alter table employees
drop column id
alter table employees
drop column id
В результате мы получим ошибку ORA-12992: cannot drop parent key column
, которая говорит о том, что удаляемая колонка является родительской для другой таблицы.
Удаление нескольких колонок в таблице
Удалим колонки emp_firstname
и is_out
из таблицы:
alter table employees
drop (emp_firstname, is_out)
alter table employees
drop (emp_firstname, is_out)
Удалять все колонки из таблицы нельзя, получим ошибку ORA-12983: cannot drop all columns in a table
.
Логическое удаление колонок
Удаление колонок в очень больших таблицах может занять достаточно большое количество времени. В таких случаях можно для начала пометить нужные колонки как неиспользуемые:
alter table employees
set unused (emp_firstname, is_out)
alter table employees
set unused (emp_firstname, is_out)
После выполнения данной команды Oracle удалит эти колонки логически, попросту пометив их как неиспользуемые. При запросе из таблицы они не будут видны, и в таблицу можно даже добавлять колонки с такими же названиями.
Чтобы удалить неиспользуемые колонки физически, используется следующий запрос:
alter table employees
drop unused columns
alter table employees
drop unused columns
Конечно, выполнять его желательно во время наименьшей нагрузки на сервер.
Переименование колонки
Переименуем колонку birthday
в bd
:
alter table employees
rename column birthday to bd
alter table employees
rename column birthday to bd
Изменение типа данных колонки
Изменим тип колонки dept_id
с числового на строковый:
alter table employees
modify(
dept_id varchar2(10)
)
alter table employees
modify(
dept_id varchar2(10)
)
Здесь нужно обратить внимание на то, что при изменении типа мы не добавляли NOT NULL
. В MODIFY
мы должны указать действия, которые действительно что-то изменят. Колонка dept_id
и так была not null
, и при изменении типа это свойство не нужно указывать.
Если попробовать добавить not null
, получим ошибку ORA-01442: column to be modified to NOT NULL is already NOT NULL
:
alter table employees
modify(
dept_id varchar2(10) not null -- получим ошибку
)
alter table employees
modify(
dept_id varchar2(10) not null -- получим ошибку
)
Следует учитывать одну важную деталь при изменении типа данных - изменяемая колонка должна быть пуста.
Рассмотрим более подробно процесс изменения типа колонки, если в ней уже содержатся данные.
Спустя какое-то время мы решили, что не хотим использовать числовое поле для boolean
значений. Вместо этого было решено использовать более понятный строковый тип.
Итак, для начала добавим колонку с нужным нам типом данных. Так как мы не можем назвать ее notify_by_email
(такая уже есть на данный момент), то назовем ее notify_by_email_new
:
alter table employees
add(
notify_by_email_new varchar2(1)
default 'N' not null
)
alter table employees
add(
notify_by_email_new varchar2(1)
default 'N' not null
)
После этого нужно заполнить эту колонку данными. Алгоритм прост - значение "1" в колонке notify_by_email
должно быть перенесено как значение "Y" в колонку notify_by_email_new
, а значение "0" нужно перенести в виде "N". Так как при добавлении колонки мы указали значение по-умолчанию, то в таблице каждая строка содержит значение "N" в этой колонке. Все, что осталось - это изменить значение на "Y", где notify_by_email
равен 1:
update employees e
set e.notify_by_email_new = 'Y'
where e.notify_by_email = 1
update employees e
set e.notify_by_email_new = 'Y'
where e.notify_by_email = 1
Затем удаляем колонку notify_by_email
:
alter table employees
drop column notify_by_email
alter table employees
drop column notify_by_email
Теперь можно переименовать notify_by_email_new
в notify_by_email
:
alter table employees
rename column notify_by_email_new to
notify_by_email
alter table employees
rename column notify_by_email_new to
notify_by_email
Смотрим на результат:
Изменение атрибута NOT NULL в колонке
Сделаем так, чтобы в колонку dept_id
можно было сохранять null
:
alter table employees
modify(dept_id null);
alter table employees
modify(dept_id null);
А теперь снова сделаем ее NOT NULL
:
alter table employees
modify(dept_id not null);
alter table employees
modify(dept_id not null);
Нельзя изменить колонку на NOT NULL, если в ней уже содержатся NULL-значения.
Переименование таблицы
Следующий запрос переименует таблицу employees
в emps
:
rename employees to emps
rename employees to emps
Стоит отметить, что переименование таблицы не приведет к ошибке при наличии ссылок на нее. В нашем примере таблица успешно переименуется, несмотря на дочернюю таблицу emp_bonuses
. Внешний ключ при этом никуда не девается, в таблицу emp_bonuses
по-прежнему нельзя добавить значения, нарушающие условия внешнего ключа.