我使用PDO(PHP数据对象)进行PHP的数据库交互。这个问题涉及三个数据库表:两个只是带主键的标准表,另一个是描述其他两个表之间关系的表。因此它没有主键,但有2个外键列(table_1_id和table_2_id)。两者都不是唯一的,因为其他两个表中的记录之间存在多对多的关系。
要确定是否应该添加关系,我只需要在关系表中没有与table_1_id和table_2_id匹配的行时插入记录。
理想情况下,我的插页看起来像这样:
INSERT INTO table_3 (table_1_id, table_2_id) VALUES (:id1, :id2)
WHERE NOT EXISTS (
SELECT 1 FROM table_3 WHERE table_1_id = :id1 AND table_2_id = :id2
)
但是,我知道这不是有效的SQL。 我已经环顾四周,无法确定最佳方法。
感谢您的帮助
答案 0 :(得分:0)
尝试添加组合主键
ALTER TABLE table_3 ADD PRIMARY KEY(`table_1_id`,`table_2_id`);
答案 1 :(得分:0)
你所谈论的关系被称为“多对多”。
MySql允许您指定多个列作为唯一索引,即列组合唯一索引。
<强> Please see this question in SO that has detailed information about the subject 强>
这可以防止您创建重复的角色,这是您想要完成的。
对于PHP代码,PDO在sql语句失败时抛出错误,因此可以使用try / catch
答案 2 :(得分:0)
首先,您最好在(table_1_id, table_2_id)
中明确定义复合PK table_3
CREATE TABLE table3
(
table_1_id INT NOT NULL,
table_2_id INT NOT NULL,
PRIMARY KEY (table_1_id, table_2_id),
FOREIGN KEY table_1_id REFERENCES table_1 (table_1_id),
FOREIGN KEY table_2_id REFERENCES table_2 (table_2_id)
)
其次然后您可以使用IGNORE
子句而不是子查询
INSERT IGNORE INTO table_3 (table_1_id, table_2_id) VALUES (:id1, :id2)
这是 SQLFiddle 演示
如果您出于某种原因想要坚持使用子查询版本,那么您的INSERT语句应该看起来像这样
INSERT IGNORE INTO table_3 (table_1_id, table_2_id)
SELECT ?, ?
FROM dual
WHERE NOT EXISTS
(
SELECT *
FROM table_3
WHERE table_1_id = ?
AND table_2_id = ?
);
这是 SQLFiddle 演示
答案 3 :(得分:0)
一种选择是在两列的组合上定义唯一约束(或主键)。这是规范模式。但是这不允许多行具有相同的值组合。
因此,假设您确实希望允许“重复”行,但只是这一个INSERT语句您不想插入重复行,那么使用SELECT
代替VALUES
关键字。基本上,编写一个有条件地返回值的SELECT语句。
这样的事可能适合你:
INSERT INTO table_3 (table_1_id, table_2_id)
SELECT v.id1, v.id2
FROM ( SELECT :id1 AS table_1_id, :id2 AS table_2_id ) v
LEFT
JOIN table_3 d
ON d.table_1_id = v.table_1_id
AND d.table_2_id = v.table_2_id
WHERE d.table_1_id IS NULL