-
#1
Не создаётся триггер (MySQL 5.0.51a-3ubuntu5.1)
Код:
CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = OLD.id;
END;
CREATE TRIGGER `artists_litera_autoinsert` after insert ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = NEW.id;
END;
Текст ошибки:
#1064 — You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near » at line 3
Подскажите, пожалуйста, что я делаю не так? Или хотя бы объясните о какой ошибке говорит MySQL сервер? Ответ просто до безобразия избыточен
UPD: забыл сказать, что в интернетах вычитал, что для создания триггеров в MySQL < 5.1.6 необходимо быть супер-пользователем. На локальному компе стоит 5.0.45, из под рута пробовал создавать эти триггеры, результат тот же (та же ошибка в ответе).
Dl
Новичок
-
#2
А если разделитель сменить?
-
#3
Уже пытался.
Запрос:
Код:
DELIMITER |
CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = OLD.id;
END;
|
Ответ:
#1064 — You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘DELIMITER |
CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_’ at line 1
Dl
Новичок
-
#4
То есть в командной строке ругается на DELIMITER |
?
Dl
Новичок
-
#6
Ну не знаю, как через phpmyadmin, но такие варианты работают:
PHP:
$query = 'CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = OLD.id;
END;';
$mysqli->query($query);
$query = 'CREATE TRIGGER `artists_litera_autoinsert` after insert ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = NEW.id;
END;';
$mysqli->query($query);
$query = 'CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = OLD.id;
END;
CREATE TRIGGER `artists_litera_autoinsert` after insert ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = NEW.id;
END;';
$mysqli->multi_query($query);
-
#7
через phpMyAdmin вряд ли такое получится… он не любит все эти процедуры, триггеры и т.д…
-
#8
Окей, исполнил запросы через консоль.
Вопрос — как можно триггеры создавать без рутовских полномочий?
-
#9
для mysql-5.0 никак похоже. как-то даже пришлось отказаться от триггеров
-
#10
так правильней
[sql]
CREATE TRIGGER `artists_litera_autoupdate` BEFORE update ON `cms_artists` or BEFORE INSERT ON `cms_artists`
FOR EACH ROW
SET NEW.`litera` = substring(NEW.name, 0, 1);
[/sql]
-
#11
Ребята, большое спасибо за дискуссию!
-~{}~ 04.06.09 21:01:
ан нет, не прошёл предложенный prolis’ом запрос
Код:
mysql> CREATE TRIGGER `artists_litera_autoupdate` BEFORE UPDATE ON `cms_artists` OR BEFORE INSERT ON `cms_artists`
-> FOR EACH
-> ROW
-> SET NEW.`litera` = substring(NEW.name, 0, 1 ) ;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near
'OR BEFORE INSERT ON `cms_artists`
FOR EACH
ROW
SET NEW.`litera` = substring(NEW.' at line 1
что не так?
-~{}~ 04.06.09 21:07:
Блин, даже если два триггера создавать то запрос проходит как бы успешно, но на самом деле ничего не меняет в `information_schema`.`TRIGGERS` пустота
Код:
mysql> DELIMITER $$
mysql> CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_artists`
-> FOR EACH ROW BEGIN
-> UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = OLD.id;
-> END;
->
-> CREATE TRIGGER `artists_litera_autoinsert` after insert ON `cms_artists`
-> FOR EACH ROW BEGIN
-> UPDATE `cms_artists` SET `litera` = substring(NEW.name, 0, 1) WHERE `id` = NEW.id;
-> END;
-> $$
Query OK, 0 rows affected (0.06 sec)
Query OK, 0 rows affected (0.06 sec)
-~{}~ 04.06.09 21:11:
Хотя если потом исполнить для одного триггера отдельно (artists_litera_autoupdate) то MySQL отвечает:
ERROR 1235 (42000): This version of MySQL doesn’t yet support ‘multiple triggers with the same action time and event for one table’
т.е. триггер таки есть, но он не отрабатывает нужным образом и отсутствует в information_schema!
-~{}~ 04.06.09 21:17:
Так это ещё и не всё!
Код:
INSERT INTO `klipz`.`cms_artists` (`name`) VALUES ('yabidabidudududu')
Ответ MySQL:
#1442 — Can’t update table ‘cms_artists’ in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
-~{}~ 04.06.09 22:47:
Удалил триггеры, добавил только для обновления. Чето нифига не изменяется содержимое поля litera после обновления
-~{}~ 04.06.09 22:50:
Всё равно не понимаю. Триггер вроде бы успешно создался, при show triggers он показывается а в information_schema его нет. А вроде как должен быть. Ведь так?
[q]mysql> CREATE TRIGGER `artists_litera_autoupdate` AFTER UPDATE ON `cms_artists`
-> FOR EACH ROW BEGIN
-> UPDATE `cms_artists` SET `litera` = substring(NEW.`name`, 0, 1) WHERE `id` = NEW.`id`;
-> END;
-> $$
Query OK, 0 rows affected (0.01 sec)
mysql> show triggers$$
+—————+———+————-+———————+———+———+———-+—————-+
| Trigger | Event | Table | Statement | Timing |Created| sql_mode | Definer |
+—————+———+————-+———————+———+———+———-+—————-+
| artists_litera_autoupdate | UPDATE | cms_artists | BEGIN
UPDATE `cms_artists` SET `litera` = substring(NEW.`name`, 0, 1) WHERE `id` = NEW.`id`;
END | AFTER | NULL | | [email protected] |
+—————+———+————-+———————+———+———+———-+—————-+
1 row in set (0.00 sec)
[/q]
Код:
SELECT *
FROM `TRIGGERS`
LIMIT 0 , 30
[q]MySQL returned an empty result set (i.e. zero rows). ( Query took 0.0185 sec )[/q]
Dl
Новичок
-
#12
не прошёл предложенный prolis’ом запрос
И не должен
даже если два триггера создавать то запрос проходит как бы успешно
Это похоже больше на шаманство, чем на осмысленные действия. Почему между END; и CREATE нету $$ ?
#1442 — Can’t update table ‘cms_artists’ in stored function/trigger because it is already used by statement which invoked this stored function/trigger
http://dev.mysql.com/doc/refman/5.0/en/stored-program-restrictions.html
Within a stored function or trigger, it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger
-
#13
Клааааааааасссс!
Я целый день впустую потратил. Г..споди, какой кошмар дурак блин, мануалы читать надо было сначала.
Итак, тогда переформулирую вопрос: мне необходимо каким-то образом иметь в базе данных актуальную информацию в виде поле `litera` типа char, которое будет содержать первый символ поля `name`, типа varchar. Решил что триггеры идеально подойдут для моего случая.
Есть ли какой-нибудь другой способ реализовать задуманное мной средствами MySQL?
Dl
Новичок
-
#14
Ну если принципиально триггером, то вот так:
set new.`litera`=substring(new.`name`, 1, 1)
-
#15
так ничего не изменилось-то, так же не даёт ничего сделать. черт, целый день зря потратил. сеня с утра в скрипты заложил етот функционал..
Dl
Новичок
-
#16
так ничего не изменилось-то, так же не даёт ничего сделать
Информативно
-
#17
Создавал такой триггер:
Код:
CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_artists`
FOR EACH ROW BEGIN
UPDATE `cms_artists` set new.`litera`=substring(new.`name`, 1, 1) WHERE `id` = NEW.`id`;
END;
и затем, при апдейте вываливалось таже самая ошибка:
#1442 — Can’t update table ‘cms_artists’ in stored function/trigger because it is already used by statement which invoked this stored function/trigger
Если я правильно понял цитату с mysql.com выше, то получается, что в моём случае, триггеры использовать невомзожно.
Dl
Новичок
-
#18
set new.`litera`=substring(new.`name`, 1, 1)
Я про update не упомянул ни слова, это все содержимое begin … end
-
#19
Уже смешно, честно
Код:
mysql> delimiter $$
mysql> CREATE TRIGGER `artists_litera_autoupdate` after update ON `cms_artists`
-> FOR EACH ROW BEGIN
-> set new.`litera`=substring(new.`name`, 1, 1);
-> END;
-> $$
ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
Dl
Новичок
Введение
Триггер — это откомпилированная SQL-процедура, исполнение которой обусловлено наступлением определенных событий внутри реляционной базы данных.
События к которым можно привязывать триггеры в MySQL: INSERT, UPDATE, DELETE.
Время, в которое будет исполнен триггер может быть: BEFORE (до наступления заданного события) или AFTER (после него).
Ограничения (не все)
Во-первых, триггеры появились в MySQL 5.0.2.
Во-вторых, триггеры в MySQL могут создаваться только пользователем с привилегией SUPER, т.е. если Ваше приложение использует триггеры, то ни на одном, даже платном, хостинге оно работать не будет.
Во-третьих, нельзя редактировать таблицу уже открытую для чтения или записи условием инициализации триггера. В этом случае просто используйте оператор SET для нужных полей.
CREATE TRIGGER `artists_litera_autoupdate` AFTER UPDATE ON `cms_artists` FOR EACH ROW BEGIN UPDATE `cms_artists` SET `litera` = UPPER(SUBSTRING(NEW.`name`, 1, 1)) WHERE `id` = OLD.`id`; END;
В противном случае Вы получите такую ошибку:
#1442 — Can’t update table ‘tablename’ in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
Кроме того в показанном выше запросе есть ещё одна ошибка, которая после исправления предидущей обязательно появится:
ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
В-четвёртых, значения надо менять до обновления.
В конечном счёте правильный вариант:
CREATE TRIGGER `artists_litera_autoupdate` BEFORE UPDATE ON `cms_artists` FOR EACH ROW BEGIN SET NEW.`litera`= UPPER(SUBSTRING(NEW.`name`, 1, 1)); END;
В-пятых, при очищении таблицы (TRUNCATE) триггер, повешенный на событие DELETE, исполняться не будет.
Синтаксис
CREATE TRIGGER — даём понять MySQL’ю что мы от него хотим.
`artists_litera_autoupdate` — имя создаваемого триггера.
BEFORE — время его исполнения.
UPDATE — событие, по наступлению которого, в указанное время, исполняется триггер.
ON `cms_artists` — таблица, к которой привязывается триггер.
FOR EACH ROW BEGIN — определяет выражения (до END;), которые будут применены к каждому ряду затронутому событием, к которому привязан триггер. Т.е. при запросе:
UPDATE `news` SET `views` = `views` + 1 WHERE `id` IN (1,2,3)
Триггер, повешенный на обновление этой таблицы будет выполнен три раза, если количество записей, удовлетворяющих WHERE равно трём. Тоже самое верно и для множественных вставок:
INSERT INTO `posts` (`date`, `title`) VALUES (NOW(), 'Проверка раз'), (NOW(), 'Проверка два')
В этом случае триггер, повешенный на INSERT для таблицы `posts` будет выполнен два раза.
Пример из жизни
Задача: чтобы максимально упростить SELECT запросы при выводе информации о записях из базы необходимо значение среднего рейтинга и количества голосов хранить в этой же таблице. При этом, как Вы сами прекрасно понимаете, за этими полями надо как-то следить, поддерживать информацию в них в актуальном состоянии.
Как это делается обычно?
Усложенение SELECT’а путём постоянного пересчёта количества голосов из таблицы `cms_videos_ratings` с помощью COUNT(), JOIN и GROUP BY.
Но есть и другой путь — после INSERT’а в таблицу с рейтингом делают дополнительный запрос для получения нового значения среднего рейтинга. Затем поле `rating` в таблицу`videos` обновляют на новое значение, а поле `votes` = `votes` + 1. А ведь есть ещё и удаление рейтинга и его обновление, что добавит не одну лишнюю строчку кода в Ваше приложение.
В этом случае происходит усложнение бизнес-логики приложения а так же создаётся лишняя нагрузка. Кто-то, конечно же, скажет, что это экономия на спичках, и опровергнуть я это не смогу, т.к. у меня нет никаких статистических данных а получать и анализировать мне просто некогда.
Давайте просто вернёмся к началу статьи, к определению триггеров. Поскольку это комплириуемая SQL-процедура, то она будет исполняться быстрее интерпретируемого SQL-запроса, который до исполнения ещё пройдёт через Вашу обёртку для работы с базами данных (если таковая имеется), а затем через обёртку для работы с MySQL из php (например).
Зачем вообще об этом задумываться, если это можно поручить MySQL?
DELIMITER $$ CREATE TRIGGER `videos_rating_autoupdate` AFTER INSERT ON `cms_videos_ratings` FOR EACH ROW BEGIN SET @new_vid = NEW.`video_id`; SET @total_votes = (SELECT COUNT(`id`) FROM `cms_videos_ratings` WHERE `video_id` = @new_vid); SET @current_rating = (SELECT SUM(`rating`) / @total_votes FROM `cms_videos_ratings` WHERE `video_id` = @new_vid); UPDATE `cms_videos` SET `votes` = @total_votes, `rating` = @current_rating WHERE `id` = @new_vid; END; $$
Аналогичное применение триггерам можно найти и для подсчета количества материалов, добавленных пользователем на ресурс и для подсчёта количества его комментариев, элементов в избранном и многих-многих других вещей.
При использовании метода в лоб Ваше приложение покроется десятками лишних строк и здесь уже плевать на производительность — значительно усложняется восприятие Вашего кода.
Важно знать
Как получить список всех триггеров существующих в текущей базе данных?
SHOW TRIGGERS;
Как удалить триггер из текущей базы данных?
DROP TRIGGER `name`;
После удаления таблицы, к которой привязан триггер, не стоит пытаться удалить его (триггер) — MySQL сделает это автоматически.
У меня не создаётся триггер, я использую phpMyAdmin
Сам столкнулся с такой проблемой. Искать причину её появления не было времени, поэтому рекомендую создавать через консоль:
root@Ubuntu-804:~# mysql -uПОЛЬЗОВАТЕЛЬ -pПАРОЛЬ ИМЯ_БАЗЫ_ДАННЫХ mysql> DELIMITER $$ mysql> CREATE TRIGGER ..... -> ..... -> $$
MySQL.com
- синтаксис
- ограничения
Первый пост здесь. Кросспост из моего блога.
Error: 1350 SQLSTATE: HY000
(ER_VIEW_SELECT_CLAUSE)
Message: View’s SELECT contains a ‘%s’ clause
Error: 1351 SQLSTATE: HY000
(ER_VIEW_SELECT_VARIABLE)
Message: View’s SELECT contains a variable or parameter
Error: 1352 SQLSTATE: HY000
(ER_VIEW_SELECT_TMPTABLE)
Message: View’s SELECT refers to a temporary table ‘%s’
Error: 1353 SQLSTATE: HY000
(ER_VIEW_WRONG_LIST)
Message: View’s SELECT and view’s field list have different column
counts
Error: 1354 SQLSTATE: HY000
(ER_WARN_VIEW_MERGE)
Message: View merge algorithm can’t be used here for now (assumed
undefined algorithm)
Error: 1355 SQLSTATE: HY000
(ER_WARN_VIEW_WITHOUT_KEY)
Message: View being updated does not have complete key of
underlying table in it
Error: 1356 SQLSTATE: HY000
(ER_VIEW_INVALID)
Message: View ‘%s.%s’ references invalid table(s) or column(s) or
function(s) or definer/invoker of view lack rights to use them
Error: 1357 SQLSTATE: HY000
(ER_SP_NO_DROP_SP)
Message: Can’t drop or alter a %s from within another stored
routine
Error: 1358 SQLSTATE: HY000
(ER_SP_GOTO_IN_HNDLR)
Message: GOTO is not allowed in a stored procedure handler
Error: 1359 SQLSTATE: HY000
(ER_TRG_ALREADY_EXISTS)
Message: Trigger already exists
Error: 1360 SQLSTATE: HY000
(ER_TRG_DOES_NOT_EXIST)
Message: Trigger does not exist
Error: 1361 SQLSTATE: HY000
(ER_TRG_ON_VIEW_OR_TEMP_TABLE)
Message: Trigger’s ‘%s’ is view or temporary table
Error: 1362 SQLSTATE: HY000
(ER_TRG_CANT_CHANGE_ROW)
Message: Updating of %s row is not allowed in %strigger
Error: 1363 SQLSTATE: HY000
(ER_TRG_NO_SUCH_ROW_IN_TRG)
Message: There is no %s row in %s trigger
Error: 1364 SQLSTATE: HY000
(ER_NO_DEFAULT_FOR_FIELD)
Message: Field ‘%s’ doesn’t have a default value
Error: 1365 SQLSTATE: 22012
(ER_DIVISION_BY_ZERO)
Message: Division by 0
Error: 1366 SQLSTATE: HY000
(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD)
Message: Incorrect %s value: ‘%s’ for column ‘%s’ at row %ld
Error: 1367 SQLSTATE: 22007
(ER_ILLEGAL_VALUE_FOR_TYPE)
Message: Illegal %s ‘%s’ value found during parsing
Error: 1368 SQLSTATE: HY000
(ER_VIEW_NONUPD_CHECK)
Message: CHECK OPTION on non-updatable view ‘%s.%s’
Error: 1369 SQLSTATE: HY000
(ER_VIEW_CHECK_FAILED)
Message: CHECK OPTION failed ‘%s.%s’
Error: 1370 SQLSTATE: 42000
(ER_PROCACCESS_DENIED_ERROR)
Message: %s command denied to user ‘%s’@’%s’ for routine ‘%s’
Error: 1371 SQLSTATE: HY000
(ER_RELAY_LOG_FAIL)
Message: Failed purging old relay logs: %s
Error: 1372 SQLSTATE: HY000
(ER_PASSWD_LENGTH)
Message: Password hash should be a %d-digit hexadecimal number
Error: 1373 SQLSTATE: HY000
(ER_UNKNOWN_TARGET_BINLOG)
Message: Target log not found in binlog index
Error: 1374 SQLSTATE: HY000
(ER_IO_ERR_LOG_INDEX_READ)
Message: I/O error reading log index file
Error: 1375 SQLSTATE: HY000
(ER_BINLOG_PURGE_PROHIBITED)
Message: Server configuration does not permit binlog purge
Error: 1376 SQLSTATE: HY000
(ER_FSEEK_FAIL)
Message: Failed on fseek()
Error: 1377 SQLSTATE: HY000
(ER_BINLOG_PURGE_FATAL_ERR)
Message: Fatal error during log purge
Error: 1378 SQLSTATE: HY000
(ER_LOG_IN_USE)
Message: A purgeable log is in use, will not purge
Error: 1379 SQLSTATE: HY000
(ER_LOG_PURGE_UNKNOWN_ERR)
Message: Unknown error during log purge
Error: 1380 SQLSTATE: HY000
(ER_RELAY_LOG_INIT)
Message: Failed initializing relay log position: %s
Error: 1381 SQLSTATE: HY000
(ER_NO_BINARY_LOGGING)
Message: You are not using binary logging
Error: 1382 SQLSTATE: HY000
(ER_RESERVED_SYNTAX)
Message: The ‘%s’ syntax is reserved for purposes internal to the
MySQL server
Error: 1383 SQLSTATE: HY000
(ER_WSAS_FAILED)
Message: WSAStartup Failed
Error: 1384 SQLSTATE: HY000
(ER_DIFF_GROUPS_PROC)
Message: Can’t handle procedures with different groups yet
Error: 1385 SQLSTATE: HY000
(ER_NO_GROUP_FOR_PROC)
Message: Select must have a group with this procedure
Error: 1386 SQLSTATE: HY000
(ER_ORDER_WITH_PROC)
Message: Can’t use ORDER clause with this procedure
Error: 1387 SQLSTATE: HY000
(ER_LOGGING_PROHIBIT_CHANGING_OF)
Message: Binary logging and replication forbid changing the global
server %s
Error: 1388 SQLSTATE: HY000
(ER_NO_FILE_MAPPING)
Message: Can’t map file: %s, errno: %d
Error: 1389 SQLSTATE: HY000
(ER_WRONG_MAGIC)
Message: Wrong magic in %s
Error: 1390 SQLSTATE: HY000
(ER_PS_MANY_PARAM)
Message: Prepared statement contains too many placeholders
Error: 1391 SQLSTATE: HY000
(ER_KEY_PART_0)
Message: Key part ‘%s’ length cannot be 0
Error: 1392 SQLSTATE: HY000
(ER_VIEW_CHECKSUM)
Message: View text checksum failed
Error: 1393 SQLSTATE: HY000
(ER_VIEW_MULTIUPDATE)
Message: Can not modify more than one base table through a join
view ‘%s.%s’
Error: 1394 SQLSTATE: HY000
(ER_VIEW_NO_INSERT_FIELD_LIST)
Message: Can not insert into join view ‘%s.%s’ without fields list
Error: 1395 SQLSTATE: HY000
(ER_VIEW_DELETE_MERGE_VIEW)
Message: Can not delete from join view ‘%s.%s’
Error: 1396 SQLSTATE: HY000 (ER_CANNOT_USER) Message: Operation %s failed for %s
How does the MySQL error message look like?
ERROR 1396 (HY000): Operation CREATE USER failed for 'dummy'@'%'
What does the MySQL error message mean?
MySQL had a problem creating or dropping this user.
When does this MySQL error message happen?
Most probably the user exists already (during creation) or does not exist any more (during deletion).
mysql> create user 'dummy'@'%' identified by 'Abcdrs!12'; Query OK, 0 rows affected (0.00 sec) mysql> -- minutes later mysql> CREATE USER 'dummy'@'%' identified by 'Abcdrs!12'; ERROR 1396 (HY000): Operation CREATE USER failed for 'dummy'@'%' mysql> DROP USER dummy; ERROR 1396 (HY000): Operation DROP USER failed for 'dummy'@'%'
How to fix this MySQL error?
Drop the user before creating it or omit creation. Create user before dropping it or omit dropping.
Error: 1397 SQLSTATE: XAE04
(ER_XAER_NOTA)
Message: XAER_NOTA: Unknown XID
Error: 1398 SQLSTATE: XAE05
(ER_XAER_INVAL)
Message: XAER_INVAL: Invalid arguments (or unsupported command)
Error: 1399 SQLSTATE: XAE07
(ER_XAER_RMFAIL)
Message: XAER_RMFAIL: The command cannot be executed when global
transaction is in the %s state