如果不存在触发器

时间:2011-05-09 23:36:12

标签: mysql sql triggers

我有两个表concept_access和concept_access_log。我想创建一个触发器,每次从concept_access中删除某些内容时都会有效,检查日志表中是否有类似的记录,如果没有,则在从concept_access中删除之前插入新的。

我修改了触发器,现在它看起来像这样:

DROP TRIGGER IF EXISTS before_delete_concept_access;
DELIMITER //
CREATE TRIGGER before_delete_concept_access
    BEFORE DELETE ON `concept_access` FOR EACH ROW
    BEGIN
        IF (SELECT 1 FROM concept_access_log WHERE map=OLD.map 
                          AND accesstype=OLD.accesstype AND startdate=OLD.startdate AND stopdate=OLD.stopdate) IS NULL THEN
            INSERT INTO concept_access_log (map, accesstype, startdate, stopdate)
            VALUES (OLD.map, OLD.accesstype, OLD.startdate, OLD.stopdate);
        END IF;
    END//
DELIMITER ;

删除前的concept_access中的示例数据:

map accesstype  startdate   stopdate
1   public      NULL        NULL    
1   loggedin    2011-05-11  NULL    
1   friends     NULL        NULL    

日志表已有前2行。它们与concept_access完全相同。当我从concept_access表中删除第一行时,我在日志表中得到了这个:

map accesstype  startdate   stopdate
1   public      NULL        NULL    
1   loggedin    2011-05-11  NULL    
1   friends     NULL        NULL    
1   public      NULL        NULL    

虽然它不应该插入任何东西,因为(1,public,null,null)已经存在。

此表没有主键。我没有创建结构,所以不要问我为什么。改变它将破坏许多已有的功能。我只需要记录从表concept_access中删除的内容并将其存储在日志中而不重复。

如果有人能弄清楚出了什么问题,我真的很感激。

2 个答案:

答案 0 :(得分:14)

DROP TRIGGER IF EXISTS before_delete_concept_access;
DELIMITER //
CREATE TRIGGER before_delete_concept_access
    BEFORE DELETE ON `concept_access` FOR EACH ROW
    BEGIN
        IF (SELECT COUNT(*) FROM concept_access_log WHERE map=OLD.map 
                          AND accesstype=OLD.accesstype AND startdate=OLD.startdate AND stopdate=OLD.stopdate) = 0 THEN
            INSERT INTO concept_access_log (map, accesstype, startdate, stopdate)
            VALUES (OLD.map, OLD.accesstype, OLD.startdate, OLD.stopdate);
        END IF;
    END//
DELIMITER ;

我没有使用不存在,只测试匹配计数是否大于0

你的代码在我的matchine上运行良好,你的mysql版本是什么?

mysql> select version();
+------------+
| version()  |
+------------+
| 5.1.56-log |
+------------+
1 row in set (0.00 sec)

答案 1 :(得分:1)

而不是这个

... WHERE map = OLD.map ...

--  map   OLD.map  bool
--  ---   -------  ----
--  'a'    'a'     TRUE
--  'a'    'b'     FALSE
--  'a'    NULL    FALSE
--  NULL   'b'     FALSE
--  NULL   NULL    FALSE  <-- Undesired! We want this to be TRUE

尝试<=>,这是MySQL's answerIS (NOT) DISTINCT FROM predicate

... WHERE map <=> OLD.map ...
--  TRUE when both have the same non-NULL value or when both are NULL
--  Equivalents:
--    WHERE (map = OLD.map OR (map IS NULL AND OLD.map IS NULL))
--    WHERE (map = OLD.map OR COALESCE(map, OLD.map) IS NULL)