Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Есть таблица 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)
Неактивен
Проблема хранения метаданных в виде данных всегда решается только одним
способом — с помощью подготовленных выражений.
Что-то подобное обсуждалось вот тут:
http://sqlinfo.ru/forum/viewtopic.php?id=1968
Неактивен
Почитала ту тему и никак не поняла как это к данной ситуации применить (( Там хоть запрос можно собрать из переменных, а у меня запроса никакого нет, надо обратиться к NEW. Может я туплю, но никак не пойму
Неактивен
А Вам обязательно это на SQL реализовывать? На клиенте нельзя?
(на SQL это можно, но очень геморно и довольно медленно будет работать; для таких вещей это самый неудобный язык, и стоит писать на нём, только если больше никаких возможностей нет).
Неактивен
Оксана написал:
Почитала ту тему и никак не поняла как это к данной ситуации применить (( Там хоть запрос можно собрать из переменных, а у меня запроса никакого нет, надо обратиться к NEW. Может я туплю, но никак не пойму
SET @col = NEW.имя_колонки; и есть запрос, который вам нужно выполнить. Так как имя поля хранится в переменной, то запрос вам придется выполнить через подготовленные выражения.
Неактивен
LazY написал:
А Вам обязательно это на SQL реализовывать? На клиенте нельзя?
(на SQL это можно, но очень геморно и довольно медленно будет работать; для таких вещей это самый неудобный язык, и стоит писать на нём, только если больше никаких возможностей нет).
Данные в базу пишет контроллер , собирающий температуру и давление с датчиков, он может только их собрать и записать в базу. Аварийные значения надо отлавливать сразу при добавлении, а поскольку в добавлении участвует только контроллер и MySQL сервер, я подумала что самым правильным будет отловить это с помощью триггера. Я первый раз пытаюсь писать просто на SQL, документацию читаю - и ничего лучшего не нашла чем то что написала ( Может в SQL Как-то можно использовать массивы? Это бы значительно упростило дело, тогда я бы считала все данные из таблицы perems в массив(благо там ограниченное число записей, <100) и за один заход проверила все переменные из NEW
конечно на PHP или perl это можно сделать быстро, а вот как
то сделать на SQL??
Отредактированно Оксана (16.02.2010 13:12:41)
Неактивен
Понятно.
варийные значения надо отлавливать сразу при добавлении, а поскольку в добавлении участвует только контроллер и MySQL сервер, я подумала что самым правильным будет отловить это с помощью триггера.
С помощью триггера лучше не делать, т.к. он не может корректно отменить запись в таблицу (максимум, что можно сделать - специально вызвать ошибку, но так лучше не делать).
Может в SQL Как-то можно использовать массивы?
Массивов в SQL нет
Вместо них приходится использовать временные таблицы (кстати, из-за этого может медленно работать; поэтому, возможно, Вам придется сначала копить данные, а потом периодически их перезаливать в основную таблицу с проверкой).
В общем, Вам тут без процедуры не обойтись.
А поскольку у Вас имена столбцов, то никак не обойтись без 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
Неактивен
LazY написал:
С помощью триггера лучше не делать, т.к. он не может корректно отменить запись в таблицу (максимум, что можно сделать - специально вызвать ошибку, но так лучше не делать).
К счастью мне не надо отменять запись в таблицу, задача отловить аварийные значения и записать их в другую таблицу(аварийный журнал), а в основную пишется всё.
Спасибо за ссылки, попробую разобраться
Неактивен
Что-то я не понимаю...
Написала процедуру
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)
Неактивен
Вкладывать процедуру в триггер не поможет — ограничения триггеров остаются.
Иначе зачем было бы вообще делать ограничения
По поводу датчиков и MySQL — я не верю, что железка контроллером общается
непосредственно с MySQL. Наверняка есть какое-то ПО, которое читает железку
и пишет в базу. Соответственно, это ПО можно модернизировать.
Ну и, разумеется, всё это можно сделать простыми триггерами, только нужно не
делать «общий супервариант», а сделать копипастом (благо, поля всего четыре):
IF NEW.fieldname1 > 7 THEN
INSET INTO events1 VALUES (NEW.fieldname1)
END IF;
С реально существующим именем поля, разумеется. И так четыре раза — для разных
полей. Так Вы не будете влезать в жесткий кодинг для этого не предназначенный, и
решите свою проблему максимально простым способом.
Неактивен
Ну полей там 39 вообще говоря, я сначала хотела так и сделать, потом подумала что это будет некрасиво. Но раз красиво не получается, сделаю так )) Всё равно всем спасибо
Отредактированно Оксана (16.02.2010 17:17:52)
Неактивен
У Вас 39 полей, для которых Вы хотите проверить одно и то же условие?
Попробуйте использовать, например, GREATEST(field1, ... field39) < value
Неактивен
paulus +1
Вообще покопайтесь во встроенных функциях MySQL
(в частности, математических)
http://dev.mysql.com/doc/refman/5.0/en/ … tions.html
Среди них есть довольно неожиданные (которых в других языках нет, например, в PHP), так что просмотрите на всякий случай - возможно, там есть то, что Вам требуется.
Неактивен
Страниц: 1