[英]Prevent insert if condition is met
我有一个这样的表格Content
:
id | text | date | idUser → User | contentType
另一个表Answer
:
idAnswer → Content | idQuestion → Content | isAccepted
我想确保Answer
的日期大于Question
的日期。 一个问题是一个Content
与contentType
=“问题”。
我尝试使用以下触发器解决此问题,但是当我尝试插入Answer
出现错误:
ERROR: record "new" has no field "idanswer" CONTEXT: SQL statement "SELECT (SELECT "Content".date FROM "Content" WHERE "Content".id = NEW.idAnswer) < (SELECT "Content".date FROM "Content" WHERE "Content".id = NEW.idQuestion)" PL/pgSQL function "check_valid_date_answer" line 2 at IF
扳机:
CREATE TRIGGER check_valid_answer
AFTER INSERT ON "Answer"
FOR EACH ROW EXECUTE PROCEDURE check_valid_date_answer();
触发功能:
CREATE FUNCTION check_valid_date_answer() RETURNS trigger
LANGUAGE plpgsql
AS $$BEGIN
IF (SELECT "Content".date FROM "Content"
WHERE "Content".id = NEW.idAnswer)
< (SELECT "Content".date FROM "Content"
WHERE "Content".id = NEW.idQuestion)
THEN
RAISE NOTICE 'This Answer is an invalid date';
END IF;
RETURN NEW;
END;$$;
所以,我的问题是:我真的需要为此创建触发器吗? 我看到我不能在Answer
使用CHECK
,因为我需要与另一个表的属性进行比较。 有没有其他(更简单/更好)的方法来做到这一点? 如果没有,为什么会出现错误,我该如何解决?
你的基本方法是合理的。 触发器是一个有效的解决方案。 除了3 个问题之外,它应该可以工作:
我们需要查看您的确切表定义才能确定,但证据就在那里。 错误消息说: has no field
"idanswer"
- 小写。 不说"idAnswer"
- 骆驼案例。 如果您在 Postgres 中创建了 CaMeL 案例标识符,那么您将在他们的余生中到处双引号。
要么引发EXCEPTION
而不是友好的NOTICE
来实际中止整个事务。
或者RETURN NULL
而不是RETURN NEW
以静默方式中止插入的行而不引发异常并且不回滚任何内容。
我会做第一个。 这可能会修复手头的错误并起作用:
CREATE FUNCTION trg_answer_insbef_check()
RETURNS trigger AS
$func$
BEGIN
IF (SELECT c.date FROM "Content" c WHERE c.id = NEW."idAnswer")
< (SELECT c.date FROM "Content" c WHERE c.id = NEW."idQuestion") THEN
RAISE EXCEPTION 'This Answer is an invalid date';
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
正确的解决方案是只使用合法的小写名称并完全避免此类问题。 这包括您不幸的表名以及列名date
,它是标准 SQL 中的保留字,不应用作标识符 - 即使 Postgres 允许。
BEFORE
触发器CREATE TRIGGER insbef_check
BEFORE INSERT ON "Answer"
FOR EACH ROW EXECUTE PROCEDURE trg_answer_insbef_check();
您想在执行任何其他操作之前中止无效插入。
当然,您必须确保时间戳表Content
不能更改,或者您需要更多触发器来确保满足您的条件。
Answer
的 fk 列也是如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.