0

默认情况下PostgresTRIGGER的事务性是否像 MySQL 中的(我已经读过)?

我创建了一个TRIGGER过程,该过程使用一个简单的方法IF来限制一个列的值,如果超出限制,则TABLE使用另一个值来限制列的值。UPDATE

我希望它放在一个单曲中,但是如果我用...TRANSACTION包装IF... ,它会给出错误THEN UPDATEBEGINCOMMIT

SQL error:

ERROR:  syntax error at or near ";"
LINE 2:         BEGIN;
                     ^

默认情况下是TRIGGERs吗?TRANSACTION如果没有,怎么能做一个TRIGGERTRANSACTION

代码

ON INSERT OR UPDATEarticles

BEGIN
    BEGIN; /* this first TRANSACTION line causes error */
    IF (NEW.votes_used > (SELECT votes_available FROM vote_totals 
     WHERE vote_totals.user_id = NEW.user_id)) THEN
        UPDATE articles SET votes_used = (SELECT votes_available FROM vote_totals 
         WHERE vote_totals.userID = NEW.user_id) WHERE user_id = NEW.user_id;
    END IF;
    COMMIT; /*last TRANSACTION line */
    RETURN NULL;
END;

我宁愿在数据进入之前做 aCHECKFOREIGN将其扼杀在萌芽状态,但我不知道如何使用 a 来做到这一点FOREIGN,而且我读过CHECKs 不能使用子查询。我想我读到这是要走的路,但我必须透露我是 db noob。

4

2 回答 2

1

您不需要UPDATE在触发器内部。您可以将值分配给NEW.votes_used

使用类似的东西:

BEGIN
    IF (NEW.votes_used > (SELECT votes_available FROM vote_totals 
     WHERE vote_totals.user_id = NEW.user_id)) THEN
        NEW.votes_used := (SELECT votes_available FROM vote_totals 
         WHERE vote_totals.userID = NEW.user_id);
    END IF;
    RETURN NEW;
END;

或者

BEGIN
    NEW.votes_used := LEAST(NEW.votes_used, (SELECT votes_available 
                                             FROM vote_totals 
                                             WHERE vote_totals.userID = NEW.user_id));
    RETURN NEW;
END;

这必须是BEFORE UPDATE工作的触发器。(并且作为所有BEFORE UPDATE触发器它必须RETURN NEW)。

如果您想使用触发器模拟检查约束 - 请尝试以下操作:

BEGIN
    IF (NEW.votes_used > (SELECT votes_available  
                          FROM vote_totals 
                          WHERE vote_totals.user_id = NEW.user_id)) 
    THEN RAISE EXCEPTION 'Not enough votes';
    END IF;
    RETURN NEW;
END;
于 2013-10-08T15:19:12.620 回答
0

触发器是事务性的,因为它们的操作可以回滚。你不需要做任何事情来让它们像那样工作。

语法错误就是这样。没有看到代码很难告诉你更多。

于 2013-10-08T15:02:51.083 回答