MySQL триггер для обновления поля до значения id
Вопрос
Я хотел бы иметь триггер для выполнения следующей операции для вставленных записей:
# pseudocode
if new.group_id is null
set new.group_id = new.id
else
# don't touch it
end
Более четко: скажем, у меня есть одна таблица с тремя столбцами: id
первичный ключ, group_id
int, value
varchar.
Когда я вставляю с group_id
вот так:
INSERT INTO table(value, group_id) VALUES ('a', 10)
Я бы хотел иметь:
id | group_id | value
---+----------+------
1 | 10 | a
но когда я опускаю group_id
:
INSERT INTO table(value) VALUES ('b')
он должен быть автоматически установлен на id
этой записи:
id | group_id | value
---+----------+------
2 | 2 | b
Возможно ли это с помощью триггера? (Я знаю, что могу обновить запись после вставки, но наличие триггера было бы лучше.)
Решение
Я не знаю ни одного способа сделать это одним оператором, даже используя триггер.
Триггерное решение, предложенное @Lucky, будет выглядеть в MySQL следующим образом:
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
SET NEW.group_id = COALESCE(NEW.group_id, NEW.id);
END
Однако есть проблема. На этапе BEFORE INSERT
автоматически сгенерированное значение id
еще не было сгенерировано. Так что если group_id
равен нулю, по умолчанию используется NEW.id
, который всегда равен 0.
Но если вы измените этот триггер на срабатывание во время фазы AFTER INSERT
, чтобы у вас был доступ к сгенерированному значению NEW.id
, вы не сможете изменить столбец значения. р>
MySQL не поддерживает выражения для DEFAULT
столбца, поэтому вы не можете также объявить это поведение в определении таблицы.
Единственное решение - выполнить INSERT
, а затем сразу же выполнить UPDATE
, чтобы изменить group_id
, если он не установлен. р>
INSERT INTO MyTable (group_id, value) VALUES (NULL, 'a');
UPDATE MyTable SET group_id = COALESCE(group_id, id) WHERE id = LAST_INSERT_ID();
Другие советы
Я отвечаю здесь, как и в принятом ответе Билл Карвин утверждает:
<Ч>На этапе BEFORE INSERT автоматически сгенерированное значение id не было генерируется еще. Так что если group_id равен нулю, по умолчанию используется NEW.id, который всегда 0.
У меня есть ответ на этот вопрос - для OP (и для посетителей), вот несколько моментов: Вы не можете обновить таблицу, из которой вызывается триггер, для этого вы получите Ошибка 1442 :
Error Code: 1442
Can't update table 'MyTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
1. Обновить новую строку
Используйте триггер BEFORE INSERT ON
, чтобы вы могли обновить все поля для новой строки, которые могут быть доступны через оператор NEW, т.е.
set NEW.group_id = NEW.id
2. Получите значение auto_increment перед вставкой :
SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='MyTable'
Подводя итог - триггер SQL для d будет выглядеть следующим образом:
DELIMITER //
DROP TRIGGER IF EXISTS MyTrigger//
CREATE TRIGGER MyTrigger BEFORE INSERT ON MyTable
FOR EACH ROW BEGIN
IF new.group_id IS NULL
set @auto_id := (SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='MyTable' AND TABLE_SCHEMA=DATABASE() );
set NEW.group_id = @auto_id;
ENF IF;
END;
//
DELIMITER ;
Это работает для меня
DELIMITER $
CREATE TRIGGER `myTriggerNameHere`
BEFORE INSERT ON `table` FOR EACH ROW
BEGIN
SET NEW.group_id = IF(NEW.group_id IS NULL, LAST_INSERT_ID()+1, NEW.group_id);
END;
$
DELIMITER ;
Я считаю, что это будет работать для вас
У меня есть две таблицы
test_b: a_id, value
test_c: a_id, value
А вот триггер на вставке теста б. Он проверяет, имеет ли значение a_id значение NULL и вставляет ли он 0
CREATE TRIGGER test_b AFTER INSERT ON test_b
FOR EACH ROW
INSERT INTO test_c (a_id, value) VALUES (IFNULL(NEW.a_id, 0),NEW.value)
Этот триггер должен делать то, что вы просили.
CREATE TRIGGER mytrigger BEFORE INSERT ON mytable
IF new.group_id IS NULL
SET new.group_id = new.id
END IF
END;
Он скопирован из очень похожего примера в документации MYSQL. страница.
В этой ситуации триггер кажется излишним. Просто примените значение по умолчанию.
CREATE TABLE `test` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`value` varchar(100) NOT NULL,
`group_id` TINYINT(3) UNSIGNED NOT NULL DEFAULT '2'
)