SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 15.02.2010 17:51:56

Оксана
Участник
Зарегистрирован: 15.02.2010
Сообщений: 7

Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Есть таблица lectus с некими названиями полей, и таблица perems, в которой для этих полей введены ограничения p1-p4

Я из таблицы perems читаю названия и ограничения и хочу потом проверить вставляемую строку lectus и если значения выходят за рамки записать это в журнал (таблица `list_events`)

Т.е делаю запрос по некому индексу

SELECT `ID`,`p_name`,`p1`,`p2`,`p3`,`p4` INTO @id_p,@p_name,@p1,@p2,@p3,@p4 FROM `perems` WHERE `ID`=@ind;
Потом хочу проверить поле вставляемой строки

SET @col = NEW.@p_name;

Естественно тут идёт ругань
#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 '@p_name; IF @col<@p1 OR @col>@p4 THEN INSERT INTO `list_events` SET `id_p`=@' at line 6



Вопрос: Как мне корректно вытащить этот столбец из NEW????

Ниже нужный триггер

delimiter ;;
CREATE TRIGGER `lectus_insert` BEFORE INSERT ON `lectus`
FOR EACH ROW BEGIN
SELECT val INTO @ind FROM `test` WHERE `id`=1;
WHILE @ind<39 DO
SELECT `ID`,`p_name`,`p1`,`p2`,`p3`,`p4` INTO @id_p,@p_name,@p1,@p2,@p3,@p4 FROM `perems` WHERE `ID`=@ind;
SET @col = NEW.@p_name;
IF @col<@p1 OR @col>@p4 THEN
INSERT INTO `list_events` SET `id_p`=@id_p, `p1`=@p1, `p2`=@p2, `p3`=@p3, `p4`=@p4, `val_p`=@col;
END IF;
SET @ind = @ind + 1;
END WHILE;
END
;;
delimiter ;

Отредактированно Оксана (15.02.2010 17:54:00)

Неактивен

 

#2 15.02.2010 21:37:02

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Проблема хранения метаданных в виде данных всегда решается только одним
способом — с помощью подготовленных выражений.

Что-то подобное обсуждалось вот тут:
http://sqlinfo.ru/forum/viewtopic.php?id=1968

Неактивен

 

#3 16.02.2010 02:05:57

Оксана
Участник
Зарегистрирован: 15.02.2010
Сообщений: 7

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Почитала ту тему и никак не поняла как это к данной ситуации применить (( Там хоть запрос можно собрать из переменных, а у меня запроса никакого нет, надо обратиться к NEW. Может я туплю, но никак не пойму

Неактивен

 

#4 16.02.2010 02:25:38

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

А Вам обязательно это на SQL реализовывать? На клиенте нельзя?
(на SQL это можно, но очень геморно и довольно медленно будет работать; для таких вещей это самый неудобный язык, и стоит писать на нём, только если больше никаких возможностей нет).

Неактивен

 

#5 16.02.2010 02:37:50

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Оксана написал:

Почитала ту тему и никак не поняла как это к данной ситуации применить (( Там хоть запрос можно собрать из переменных, а у меня запроса никакого нет, надо обратиться к NEW. Может я туплю, но никак не пойму

SET @col = NEW.имя_колонки; и есть запрос, который вам нужно выполнить. Так как имя поля хранится в переменной, то запрос вам придется выполнить через подготовленные выражения.

Неактивен

 

#6 16.02.2010 13:08:58

Оксана
Участник
Зарегистрирован: 15.02.2010
Сообщений: 7

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

LazY написал:

А Вам обязательно это на SQL реализовывать? На клиенте нельзя?
(на SQL это можно, но очень геморно и довольно медленно будет работать; для таких вещей это самый неудобный язык, и стоит писать на нём, только если больше никаких возможностей нет).

Данные в базу пишет контроллер , собирающий температуру и давление с датчиков, он может только их собрать и записать в базу. Аварийные значения надо отлавливать сразу при добавлении, а поскольку в добавлении участвует только контроллер и MySQL сервер,  я подумала что самым правильным будет отловить это с помощью триггера. Я первый раз пытаюсь писать просто на SQL, документацию читаю - и ничего лучшего не нашла чем то что написала ( Может в SQL Как-то можно использовать массивы? Это бы значительно упростило дело, тогда я бы считала все данные из таблицы perems в массив(благо там ограниченное число записей, <100) и за один заход проверила все переменные из NEW

конечно на PHP или perl это можно сделать быстро, а вот как
то сделать на SQL??

Отредактированно Оксана (16.02.2010 13:12:41)

Неактивен

 

#7 16.02.2010 13:45:01

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Понятно.

варийные значения надо отлавливать сразу при добавлении, а поскольку в добавлении участвует только контроллер и MySQL сервер,  я подумала что самым правильным будет отловить это с помощью триггера.

С помощью триггера лучше не делать, т.к. он не может корректно отменить запись в таблицу (максимум, что можно сделать - специально вызвать ошибку, но так лучше не делать).

Может в SQL Как-то можно использовать массивы?

Массивов в SQL нет sad
Вместо них приходится использовать временные таблицы (кстати, из-за этого может медленно работать; поэтому, возможно, Вам придется сначала копить данные, а потом периодически их перезаливать в основную таблицу с проверкой).

В общем, Вам тут без процедуры не обойтись.
А поскольку у Вас имена столбцов, то никак не обойтись без PREPARE STATEMENT.

Вот, посмотрите
http://sqlinfo.ru/forum/viewtopic.php?id=363
http://sqlinfo.ru/forum/viewtopic.php?id=1235
http://webew.ru/articles/2080.webew#mysql

Неактивен

 

#8 16.02.2010 13:49:22

Оксана
Участник
Зарегистрирован: 15.02.2010
Сообщений: 7

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

LazY написал:

С помощью триггера лучше не делать, т.к. он не может корректно отменить запись в таблицу (максимум, что можно сделать - специально вызвать ошибку, но так лучше не делать).

К счастью мне не надо отменять запись в таблицу, задача отловить аварийные значения и записать их в другую таблицу(аварийный журнал), а в основную пишется всё.
Спасибо за ссылки, попробую разобраться

Неактивен

 

#9 16.02.2010 15:03:15

Оксана
Участник
Зарегистрирован: 15.02.2010
Сообщений: 7

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Что-то я не понимаю...
Написала процедуру

CREATE DEFINER=`root`@`localhost` PROCEDURE `get_col_value`(IN table_name CHAR(64), column_name CHAR(64),id_v INT(10),OUT call_val FLOAT)
BEGIN
SET @var = CONCAT('SELECT ', column_name, ' INTO ',call_val,' FROM ', table_name, ' WHERE ID=',id_v);
PREPARE zxc FROM @var;
EXECUTE zxc;
END

далее триггер
delimiter ;;
CREATE TRIGGER `lectus_insert` AFTER INSERT ON `lectus`
FOR EACH ROW BEGIN
SELECT val INTO @ind FROM `test` WHERE `id`=1;
WHILE @ind<39 DO
SET @ind_n = NEW.ID;
SELECT `ID`,`p_name`,`p1`,`p2`,`p3`,`p4` INTO @id_p,@p_name,@p1,@p2,@p3,@p4 FROM `perems` WHERE `ID`=@ind;
CALL get_col_value(`lectus`,@p_name,@ind_n,@call);
IF @call<@p1 OR (@call >=@p1 AND @call< @p2) OR (@call >@p3 AND @call<=@p4) OR @call>@p4 THEN
INSERT INTO `list_events` SET `id_p`=@id_p, `p1`=@p1, `p2`=@p2, `p3`=@p3, `p4`=@p4, `val_p`=@call;
END IF;
SET @ind = @ind + 1;
END WHILE;
END
;;

и получаю в процедуре
#1312 - PROCEDURE sdu.get_col_value can't return a result set in the given context

Что я сделала не так?

Отредактированно Оксана (16.02.2010 15:25:39)

Неактивен

 

#10 16.02.2010 16:56:30

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Вкладывать процедуру в триггер не поможет — ограничения триггеров остаются.
Иначе зачем было бы вообще делать ограничения smile

По поводу датчиков и MySQL — я не верю, что железка контроллером общается
непосредственно с MySQL. Наверняка есть какое-то ПО, которое читает железку
и пишет в базу. Соответственно, это ПО можно модернизировать.

Ну и,  разумеется, всё это можно сделать простыми триггерами, только нужно не
делать «общий супервариант», а сделать копипастом (благо, поля всего четыре):
IF NEW.fieldname1 > 7 THEN
   INSET INTO events1 VALUES (NEW.fieldname1)
END IF;

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

Неактивен

 

#11 16.02.2010 17:17:35

Оксана
Участник
Зарегистрирован: 15.02.2010
Сообщений: 7

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

Ну полей там 39 вообще говоря, я сначала хотела так и сделать, потом подумала что это будет некрасиво. Но раз красиво не получается, сделаю так )) Всё равно всем спасибо

Отредактированно Оксана (16.02.2010 17:17:52)

Неактивен

 

#12 16.02.2010 18:02:50

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

У Вас 39 полей, для которых Вы хотите проверить одно и то же условие?
Попробуйте использовать, например, GREATEST(field1, ... field39) < value

Неактивен

 

#13 16.02.2010 18:24:53

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Помогите запихать в триггер в оператор NEW.callname callname в виде переменной

paulus +1
Вообще покопайтесь во встроенных функциях MySQL
(в частности, математических)
http://dev.mysql.com/doc/refman/5.0/en/ … tions.html

Среди них есть довольно неожиданные (которых в других языках нет, например, в PHP), так что просмотрите на всякий случай - возможно, там есть то, что Вам требуется.

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson