Postgresql Postgres:具有两个外键的NOTNULL约束

Postgresql Postgres:具有两个外键的NOTNULL约束,postgresql,Postgresql,我是数据库设计新手,想尝试做一个简单的聊天web应用程序来练习这项技能 我正在尝试制作一个类似Messenger.com的聊天应用程序,用户可以在其中向联系人和群组发送消息 我找到了这个不错的教程,但我的“消息”表有问题: 其思想是,当消息发送给用户时,“接收者组id”为空,当消息发送给组时,“接收者组id”为空。但是,postgres不允许将消息添加到Messages表中,因为外键不能为NULL,也就是说,它违反了Receiver\u user\u id或Receiver\u group\u

我是数据库设计新手,想尝试做一个简单的聊天web应用程序来练习这项技能

我正在尝试制作一个类似Messenger.com的聊天应用程序,用户可以在其中向联系人和群组发送消息

我找到了这个不错的教程,但我的“消息”表有问题:

其思想是,当消息发送给用户时,“接收者组id”为空,当消息发送给组时,“接收者组id”为空。但是,postgres不允许将消息添加到Messages表中,因为外键不能为NULL,也就是说,它违反了Receiver\u user\u id或Receiver\u group\u id的NOT-NULL约束

有什么建议吗

CREATE TABLE users (
  id serial primary key,
  username character varying(32) NOT NULL UNIQUE,
  password character varying(255) NOT NULL,
  name character varying(64) NOT NULL,
  image character varying(255),
  active int NOT NULL DEFAULT 0
);

CREATE TABLE groups (
  id serial primary key,
  name character varying(255) NOT NULL
);

CREATE TABLE group_users (
  id serial primary key,
  user_id serial references users(id),
  group_id serial references groups(id)
);

CREATE TABLE messages (
  id serial primary key,
  user_id serial references users(id),
  reciever_user_id serial references users(id),
  reciever_group_id serial references groups(id),
  body text
);

您需要一个检查约束,以确保这两列中正好有一列包含非null值

CREATE TABLE messages (
  id serial primary key,
  user_id integer,
  receiver_user_id integer,
  receiver_group_id integer,
  body text,
  constraint check_group_user check (
      (receiver_user_id is null and receiver_group_id is not null) 
   or (receiver_user_id is not null and receiver_group_id is null) )
);
另外:不要将FK列定义为
serial
,这将自动生成不同的ID,因为每列使用另一个序列


外键列应使用引用列的基本数据类型定义。因此,
integer
而不是
serial

您需要一个检查约束,以确保这两列中正好有一列包含非空值

CREATE TABLE messages (
  id serial primary key,
  user_id integer,
  receiver_user_id integer,
  receiver_group_id integer,
  body text,
  constraint check_group_user check (
      (receiver_user_id is null and receiver_group_id is not null) 
   or (receiver_user_id is not null and receiver_group_id is null) )
);
另外:不要将FK列定义为
serial
,这将自动生成不同的ID,因为每列使用另一个序列


外键列应使用引用列的基本数据类型定义。因此,
integer
而不是
serial

您还可以使用使用
NUM\u nonnull(…)
的约束

比如:

CREATE TABLE messages (
  id serial primary key,
  user_id integer,
  receiver_user_id integer,
  receiver_group_id integer,
  body text,
  constraint check_group_user check (
    NUM_NONNULLS(receiver_user_id, receiver_group_id) = 1
  )
);

您还可以使用使用
NUM\u nonnull(…)
的约束

比如:

CREATE TABLE messages (
  id serial primary key,
  user_id integer,
  receiver_user_id integer,
  receiver_group_id integer,
  body text,
  constraint check_group_user check (
    NUM_NONNULLS(receiver_user_id, receiver_group_id) = 1
  )
);

谢谢<代码>串行引用是我的问题,
整数引用
有效。谢谢<代码>串行引用是我的问题,
整数引用
有效。