2015-05-25 2 views
0

У нас есть автореферентные отношения, определенные в нашей базе данных SQLite как таковые ...Как вы можете реализовать оператор If в триггере SQLite?

Create Table Categories{ 
    Id INTEGER PRIMARY KEY, 
    Name TEXT NOT NULL CHECK(length(Text) > 0), 
    ParentId INTEGER References Categories(Id), 
    IsSelected BOOL 
}; 

Мы пытаемся установить триггер на поле IsSelected для автоматического распространения значения вверх по иерархии.

При установке значения True это легко. Мы просто устанавливаем триггер для установки родительского объекта в True, что в свою очередь делает то же самое для его родителя, идя вверх по иерархии, пока не доберется до корня.

Однако, когда мы устанавливаем его в False, эта логика не применяется, потому что может быть другой родной брат измененной записи, которая по-прежнему истинна, поэтому ее родитель по-прежнему прав.

Как я могу сделать следующее в триггере? Заметьте, это, очевидно, бессмысленный гибрид SQL, C# и LINQ, но он иллюстрирует то, что я пытаюсь сделать.

CREATE TRIGGER T_Categories_IsSelectedChanged 
UPDATE OF IsSelected ON Categories 
BEGIN 
    if(new.IsSelected) 
     Update Categories Set IsSelected = True Where Id = old.ParentId; 
    else 
    { 
     void isSiblingSelected = Categories 
      .Where(c => c.ParentId = old.ParentId) 
      .Any(c => c.IsSelected); 

     UPDATE Categories 
     SET IsSelected = isSiblingSelected 
     WHERE Id = old.ParentId; 
    } 
END 

Теперь технически предложение «Else» работает в обоих случаях. Если более короткое замыкание, но, возможно, я мог бы сделать что-то вроде этого ...

Update Categories 
SET IsSelected = (
    SELECT EXISTS(SELECT 1 FROM Categories 
    WHERE IsSelected = True 
    AND ParentId = old.ParentId 
    LIMIT 1)) 
Where ID = old.ParentId; 

... но это только предположение. Я на правильном пути?

ответ

0

СЛУЧАЙ не заявление; вы можете использовать его только внутри выражения.

Однако триггеры имеют WHEN clause, который принимает произвольное выражение SQL:

CREATE TRIGGER T_Categories_IsSelectedChanged_true 
AFTER UPDATE OF IsSelected ON Categories 
FOR EACH ROW 
WHEN new.IsSelected 
BEGIN 
    UPDATE Categories 
    SET IsSelected = 1 
    WHERE Id = old.ParentId; 
END; 

CREATE TRIGGER T_Categories_IsSelectedChanged_false 
AFTER UPDATE OF IsSelected ON Categories 
FOR EACH ROW 
WHEN NOT new.IsSelected 
BEGIN 
    UPDATE Categories 
    SET IsSelected = (SELECT IFNULL(MAX(IsSelected), 0) 
         FROM Categories 
         WHERE ParentId = old.ParentId) 
    WHERE Id = old.ParentId; 
END; 
+0

Отлично. Только то, что я искал. Благодарю. – MarqueIV

0

вы можете обратиться http://www.sqlite.org/lang_expr.html#case.

я не уверен, но код может быть как,

CREATE TRIGGER T_Categories_IsSelectedChanged 
UPDATE OF IsSelected ON Categories 
BEGIN 
case when new.isSelected then 
    Update Categories Set IsSelected = True Where Id = old.ParentId; 
else 
    Update Categories Set IsSelected = Categories 
     .Where(c => c.ParentId = old.ParentId) 
     .Any(c => c.IsSelected); 
END 
+0

Спасибо за указание на заявление случая, но, как я уже говорил, мой код не на самом деле SQL. Это LINQ, чтобы показать логику. Но я проверю заявление Case. Это интересно. – MarqueIV

+0

Вы не можете использовать CASE в SQLite. –