Создание условного триггера SQL в SQLite - PullRequest
10 голосов
/ 30 июня 2009

Я пытаюсь написать триггер для sqlite и просто сталкиваюсь со всеми видами проблем. По правде говоря, моя настоящая проблема в том, что я плохо знаком с языком SQL. Во всяком случае здесь идет ...

У меня есть две таблицы Table1 и Table2. В Table1 есть столбец с именем time (который представляет собой 64-битное целое время). Мне нужен триггер, который следит за новой строкой, вставляемой в Table1. Если в Таблице 1 есть 3 или более строк, которые имеют время больше X (жестко заданное значение в приведенном ниже примере 120 секунд), мне нужно вставить новую строку в Таблицу 2.

Вот что у меня есть (обратите внимание, это не работает)

CREATE TRIGGER testtrigger AFTER  
INSERT ON Table1 WHEN 
( 
   SELECT COUNT() AS tCount FROM
   ( 
     SELECT * FROM Table1 WHERE  
       time > (NEW.time - 120)  
   ) WHERE tCount > 3
) 
BEGIN 
   INSERT INTO Table2 (time, data) VALUES 
   (NEW.time, 'data1');  
END

Какие-нибудь добрые души, которые лучше в SQL, чем я?

Ответы [ 3 ]

9 голосов
/ 30 июня 2009

Это работает, потому что для условия WHEN требуется выражение :

sqlite> .schema Table1
CREATE TABLE Table1 (time int);
CREATE TRIGGER testtrigger AFTER INSERT ON Table1
WHEN 3<(SELECT Count() FROM Table1 WHERE time>(NEW.time-120))
BEGIN
INSERT INTO Table2 (time, data) VALUES (NEW.time,'data1');
END;

Вы смотрели на эту справочную страницу ? Из того, что я могу сказать, это «неправильное использование агрегата», которое, вероятно, связано с утверждением в разделе When. У вас было это:

sqlite> .tables
Table1  Table2
sqlite> .schema Table1
CREATE TABLE Table1 (time int);
CREATE TRIGGER testtrigger AFTER
INSERT ON Table1 WHEN 
( 
   SELECT COUNT() AS tCount FROM
   ( 
     SELECT * FROM Table1 WHERE  
       time > (NEW.time - 120)  
   ) WHERE tCount > 3
) 
BEGIN 
   INSERT INTO Table2 (time, data) VALUES 
   (NEW.time, 'data1');  
END;
sqlite> .schema Table2
CREATE TABLE Table2 (time int,data string);
sqlite> insert into Table1 VALUES (5);
SQL error: misuse of aggregate: 
sqlite> 

Я попытался удалить "WHERE tCount", чтобы превратить его в выражение , но затем у оператора возникла синтаксическая ошибка.

Так что вместо этого я переключился на решение выше.

1 голос
/ 30 июня 2009

Ваше предложение WHEN в триггере должно быть выражением сравнения, которое возвращает true или false вместо возврата числа. Попробуйте идею Дламблина.

0 голосов
/ 30 июня 2009

Может быть, другой синтаксический подход?

CREATE TRIGGER testtrigger ON Table1

FOR INSERT 
AS
BEGIN

  DECLARE @timeNum int

  SET @timeNum = SELECT count(*) FROM Table1 WHERE time > (New.time - 120)

  IF @timeNum > 3

    BEGIN
        INSERT INTO Table2 (time, data) VALUES 
            (NEW.time, 'data1');
    END

END

Но также попробуйте некоторые отладочные операторы. Когда я отлаживал свой последний триггер для веб-сервиса, я помещал некоторые операторы INSERT в таблицу отладки, которую я настраивал. Таким образом, вы можете выводить @timeNum каждый раз, когда вызывается триггер, а затем помещать в цикл другой отладочный INSERT, чтобы проверить, действительно ли вы попали в логику INSERT таблицы 2.

UPDATE: Сожалею! Похоже, SqlLite вроде отстой, я не знал, что ему не хватает этого синтаксиса. Тем не менее, если вы не получаете никаких ответов, рассмотрите некоторые операторы отладки, чтобы убедиться, что пути вашего кода вызываются в правильных условиях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...