我是数据库设计的新手,想尝试一个简单的聊天网络应用来练习这项技能。
我正在尝试制作一个像聊天应用程序一样的Messenger.com,用户可以将消息发送给联系人和群组。
我找到了这个很好的教程但是我的“消息”表有问题:http://www.vertabelo.com/blog/technical-articles/database-model-for-a-messaging-system
这个想法是,当向用户发送消息时,“reciever_group_id”为NULL,并且当消息发送到组时,“reciever_user_id”为NULL。但是,postgres不会允许向Messages表添加消息,因为外键不能为NULL,即它违反了reciever_user_id或reciever_group_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
);
答案 0 :(得分:3)
您需要一个检查约束,以确保这两列中只有一列包含非空值。
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
。 serial is not a real data type
答案 1 :(得分:1)
您还可以使用使用NUM_NONNULLS(...)
的约束。
类似的东西:
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
)
);