PostgreSQL-基于另一个表中列的约束

问题描述

我有两张桌子,一张叫选票,一张叫票。选票存储一个字符串列表,这些字符串代表人们可以投票的选项:

CREATE TABLE IF NOT EXISTS Polls (
  id SERIAL PRIMARY KEY,options text[]
);

Votes存储用户做出的投票(其中的投票是一个整数,代表他们投票的选项的索引):

CREATE TABLE IF NOT EXISTS Votes (
  id SERIAL PRIMARY KEY,poll_id integer references Polls(id),value integer NOT NULL,cast_by integer NOT NULL
);

我想确保每当在Votes表中创建一行时,“ value”的值在民意调查中相应行的范围[0,length(options))内(相应地,我的意思是该行poll_id匹配的地方。

是否可以实施任何形式的检查或外键约束?还是我需要某种触发?如果是这样,那触发将是什么样子,并且会存在性能问题?仅使用SELECT语句手动查询相应的民意调查,然后断言“值”在插入投票表中之前是否有效?

解决方法

您不能使用“检查约束”,因为它可以引用同一表的列。

您可以参考官方Manual

因此,这里您应该在BEFORE INSERT表的Votes事件上使用Trigger,或者可以对插入操作使用function / procedure(取决于PostgreSQL的版本)来检查值如果不满足条件,则在插入之前引发异常。

使用触发器:

create or replace function id_exist() returns trigger as
$$
begin
if new.value<0 or new.value>=(select array_length(options,1) from polls where id=new.poll_id) then
raise exception 'value is not in range';
end if;
return new;
end;

$$
language plpgsql

CREATE TRIGGER check_value BEFORE INSERT  ON votes
    FOR EACH ROW EXECUTE PROCEDURE id_exist();

DEMO

,

我建议您修改数据模型以包含一个表PollOptions

CREATE TABLE IF NOT EXISTS PollOptions (
  PollOptionsId SERIAL PRIMARY KEY,-- should use generated always as identity
  PollId INT NOT NULL,REFERENCES Polls(id),OptionNumber int,Option text,UNIQUE (PollId,Option)
);

然后,您的Votes表应该具有对PollOptions的外键引用。您可以使用PollOptionId(PollId,Option)

如果正确设置数据,则无需触发器或特殊功能。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...