查看this SQL Fiddle 和其中的 cmets。您在这里涵盖了很多概念,并且您需要考虑您的设计以及您要完成的工作,但要解决您在问题中提出的目标:
- 您可以使用PRIMARY KEYS 或UNIQUE CONSTRAINTS 来确保不会将重复值插入到您的表中(例如,您不希望
pid 和cid 在汇编表中重复,所以我把它作为主键)。我对你的陈述非常直截了当:
要求是 pid(来自产品)和 uid(来自用户)不应出现在同一行的组装表中。 (强调我的)
您可以使用JOINS 将不同表中的项目相互关联。事实上,您的组装表通常被称为“连接表”。我的示例是使用内部连接(意思是两个表中都必须存在值)。
您可以使用FOREIGN KEYS 来确保您要在另一个表中引用的列存在。
下面是 SQL Fiddle 行为不端的代码。
创建和填充表格:
CREATE TABLE users (
uid serial,
uname text,
CONSTRAINT user_pkey PRIMARY KEY (uid)
);
CREATE TABLE categories (
cid serial,
cname text,
CONSTRAINT cat_pkey PRIMARY KEY (cid)
);
CREATE TABLE products (
pid serial,
pname text,
CONSTRAINT prod_pkey PRIMARY KEY (pid)
);
CREATE TABLE assemble (
join_id serial,
uid bigint,
pid bigint,
cid bigint,
CONSTRAINT assemble_pkey PRIMARY KEY (uid, pid),
CONSTRAINT assemble_user_fkey FOREIGN KEY (uid)
REFERENCES users (uid),
CONSTRAINT assemble_prod_fkey FOREIGN KEY (pid)
REFERENCES products (pid),
CONSTRAINT assemble_cat_fkey FOREIGN KEY (cid)
REFERENCES categories (cid)
);
INSERT INTO users (uname) VALUES ('Akshay');
INSERT INTO users (uname) VALUES ('Mom');
INSERT INTO users (uname) VALUES ('Dad');
INSERT INTO categories (cname) VALUES ('Shoes');
INSERT INTO categories (cname) VALUES ('Hats');
INSERT INTO categories (cname) VALUES ('Coats');
INSERT INTO products (pname) VALUES ('Blue Suede Nikes');
INSERT INTO products (pname) VALUES ('Fedora');
INSERT INTO products (pname) VALUES ('Flying Jacket');
-- Give Akshay a hat
INSERT INTO assemble (uid, cid, pid)
VALUES (
(SELECT uid FROM users WHERE uname='Akshay'),
(SELECT cid FROM categories WHERE cname='Hats'),
(SELECT pid FROM products WHERE pname='Fedora')
);
-- Give Mom a coat
INSERT INTO assemble (uid, cid, pid)
VALUES (
(SELECT uid FROM users WHERE uname='Mom'),
(SELECT cid FROM categories WHERE cname='Coats'),
(SELECT pid FROM products WHERE pname='Flying Jacket')
);
-- Give Dad some shoes
INSERT INTO assemble (uid, cid, pid)
VALUES (
(SELECT uid FROM users WHERE uname='Dad'),
(SELECT cid FROM categories WHERE cname='Shoes'),
(SELECT pid FROM products WHERE pname='Blue Suede Nikes')
);
查询:
-- get the data out of your assemble table, with names from related tables
SELECT u.uname, c.cname, p.pname
FROM users u
INNER JOIN assemble j
ON u.uid = j.uid
INNER JOIN categories c
ON j.cid = c.cid
INNER JOIN products p
ON p.pid = j.pid;
-- Give Mom the same coat... this will fail due to the PRIMARY KEY, even with a different category
INSERT INTO assemble (uid, cid, pid)
VALUES (
(SELECT uid FROM users WHERE uname='Mom'),
(SELECT cid FROM categories WHERE cname='Hats'),
(SELECT pid FROM products WHERE pname='Flying Jacket')
);