在写入之前,使用另一个表中的值限制字段的值

时间:2013-10-08 14:57:23

标签: postgresql triggers transactions postgresql-9.1

默认情况下Postgres TRIGGER的事务是否像(我读过的)在MySQL中?

我创建了TRIGGER procedure,使用简单的IF来限制列的值,使用其他TABLE的值,如果违反了限制,则使用后续UPDATE

我希望将其放在一个TRANSACTION中,但如果我将IF ... THEN UPDATEBEGIN包裹在一起...... {{1} },它给出了错误

COMMIT

默认情况下SQL error: ERROR: syntax error at or near ";" LINE 2: BEGIN; ^ TRIGGER al?如果没有,TRANSACTION如何TRIGGER al?

这是TRANSACTION的{​​{1}}:

ON INSERT OR UPDATE

我很想做一个articlesBEGIN 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; 在数据进入之前将其扼杀在萌芽状态,但我不知道如何使用{{1}我已经读过CHECK s不能使用子查询。我想我读到这是要走的路,但我必须透露我是db noob。

2 个答案:

答案 0 :(得分: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;

答案 1 :(得分:0)

触发器是事务性的,因为它们的操作可以回滚。你没有必要做任何让它们像那样工作的东西。

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