Статья основана на 17 видео из 30 тем курса SQL c 0 от Аристова Евгения. Ссылки на видео на платформах RUTUBE и VK видео.
В прошлой лекции была разобрана команда INSERT для вставки данных. Помимо добавления новых строк, бывает нужно и обновление старых. Для этого существует команда UPDATE, использование которой составляет ~5% от всех операций в СУБД.
UPDATE
UPDATE [ ONLY ] table_name [ * ] [ [ AS ] alias ]
SET { column_name = { exression | DEFAULT } |
} [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
Внутри операции можно использовать предыдущее значение (например, увеличить его).
Важно не забывать про условие WHERE (редко нужно обновлять все данные без условия). Без WHERE можно потерять все данные, которые потом будет очень сложно или невозможно восстановить.
При обновлении данных занимаемая память увеличивается вдвое, поэтому желательно применять UPDATE к бачам данных.
Создадим таблицу Склад и добавим две записи:
DROP TABLE IF EXISTS warehouse;
CREATE TABLE warehouse (
id serial UNIQUE,
name text NOT NULL DEFAULT '',
kolvo int NOT NULL DEFAULT 0,
price numeric NOT NULL DEFAULT 0.0,
salesTime timestamp with time zone NOT NULL DEFAULT current_timestamp, -- UTC
salesTime2 timestamp NOT NULL DEFAULT current_timestamp
);
INSERT INTO warehouse (name,kolvo,price) VALUES
('apple',10,10.2),
('grape',20,'20.2');

С помощью команды просмотрим строчку с id равным 1:
SELECT *
FROM warehouse
WHERE id = 1;

Обновим эту строчку (условие WHERE) и снова выведем её:
UPDATE warehouse
SET kolvo = kolvo + 30,
price = 30.3
WHERE id = 1;
SELECT *
FROM warehouse
WHERE id = 1;

Мы обновили значение поля kolvo с использованием предыдущего, а полю price присвоили новое значение.
WHERE в UPDATE работает точно так же, как и в SELECT. В UPDATE прописываются только те поля, которые обновляются, остальные остаются неизменны.
Также можно указывать поля через запятую:
UPDATE warehouse
SET (kolvo,price) = (30,30.3)
WHERE id = 1;
SELECT *
FROM warehouse
WHERE id = 1;

Такой формат написания команды не рекомендуется, так как визуально непонятно, в какой столбец какое значение будет записано.
Полю можно присвоить DEFAULT значение:
UPDATE warehouse
SET salesTime = DEFAULT
WHERE id = 1;
SELECT *
FROM warehouse
WHERE id = 1;

Salestime изменился на текущее время.
Как не потерять данные
Рекомендуется в начале написания команды UPDATE ставить невыполнимое условие:
UPDATE warehouse
SET
WHERE 1=0;
Такая запись поможет избежать случайного выполнения команды во время её написания и, как следствие, утери данных.
А после окончательного правильного написания убрать это условие.
Другой способ – писать команды внутри транзакции (подробнее о транзакциях в моей статье):
BEGIN;
UPDATE warehouse
SET ;
ROLLBACK;
Любая операция внутри транзакции будет отменена после применения ROLLBACK.
После проверки корректности работы заменить ROLLBACK на COMMIT.
Конфликты
Для команды INSERT нет конструкции ON CONFLICT, поэтому конфликты можно обрабатывать только с помощью EXEPTION.
Пример запроса с конфликтом:
UPDATE warehouse
SET id = id + 1;

Данная команда пытается присвоить первой строчке id 2, в то время как у второй строчки остается всё ещё не изменённый id 2 (а поле id должно быть уникальным).
RETURNING
После изменения ячейки, можно узнать её новое значение с помощью RETURNING.
[ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]
Выведем количество и цену после их обновления:
UPDATE warehouse
SET kolvo = kolvo + 40,
price = 40.3
WHERE id = 1
RETURNING kolvo, price;

В отличие от INSERT, в UPDATE нельзя получить предыдущее значение через EXCLUDED:
UPDATE warehouse as w
SET (kolvo,price) = (50,50.3)
WHERE id = 1
RETURNING EXCLUDED.kolvo;

В таком варианте вернется уже новое значение:
UPDATE warehouse AS w
SET (kolvo,price) = (kolvo+50,50.3)
WHERE id = 1
RETURNING w.kolvo;
Презентация к статье здесь.
18 из 30 тем будет скоро доступна. Если вы хотите быстрее получить доступ – присоединяйтесь к онлайн группе, ссылка доступна в описании курса.
Добавить комментарий