2012-06-21 64 views
0

我有一个问题,有时候由于人为错误relation_id将出现在数据库中,关系并没有真正的ID。MySQL - 选择,没有问题

SELECT relation_id 
FROM relations 
WHERE relation_id NOT 
IN (
    SELECT id 
    FROM relations 
) 

这将返回发生这种情况的字段,我想将relation_id的值切换为NULL。

这里是我到目前为止有:

UPDATE `relations` SET relation_id = NULL WHERE relation_id NOT IN (SELECT id FROM relations) 

这一关当然适用于任何其他表,只有不适合的关系。有人知道解决方法吗?我敢肯定有一种方法

+0

您确定可以使用子查询自行更新表吗? – Sebas

+0

MySQL说: #1093 - 您无法在FROM子句中指定目标表'关系'进行更新 – Pepijn

+0

您是通过表单还是myPhpAdmin手动输入relations_id?通常这些都是自动编号,所以你不应该碰它们 –

回答

3

那么,错误原因实际上是在错误消息本身中详细描述的......您无法指定您更新的表内部的SELECT。但是谁说我们不能更深入?

UPDATE relations 
    SET relation_id = NULL 
WHERE relation_id NOT IN (
     SELECT id FROM (SELECT id FROM relations) AS take_that_sql 
); 

这里是一个SQLFiddle玩。 )

+0

作品!感谢一堆:) – Pepijn

0

试试这个::

SELECT r1.relation_id 
FROM relations r1 
left join relations r2 on (r1.relation_id=r2.id) 
where r2.id is null 
+0

仍然得到MySQL#1093错误 – Pepijn

+0

你可以创建一个临时表,然后加入并做到这一点...... 因为它是一个mysql约束,它不会允许你更新。 –

1

这是我想尝试:

UPDATE relations r 
    LEFT JOIN relations s 
    ON r.relation_id = s.id 
    SET r.relation_id = NULL 
WHERE s.id IS NULL 
    AND r.relation_id IS NOT NULL; 

(我不知道这是否会工作;可能引发异常,因为关系表被引用两次。)

如果多表更新不起作用,我会创建一个工作表,用查询填充工作表(用于标识要更新的行)接着使用工作表运行多表更新。

这个查询标识有一个relation_id不指向行现有id

SELECT r.* 
    FROM relations r 
    LEFT JOIN relations s 
    ON r.relation_id = s.id 
WHERE s.id IS NULL 
    AND r.relation_id IS NOT NULL; 

你并不需要把所有的列,只有主键。 (我在这里假设该主键是单个列id。)

CREATE TABLE work_table (id int PRIMARY KEY); 

INSERT INTO work_table (id) 
SELECT r.id 
    FROM relations r 
    LEFT JOIN relations s 
    ON r.relation_id = s.id 
WHERE s.id IS NULL 
    AND r.relation_id IS NOT NULL; 

UPDATE relations r 
    JOIN work_table s 
    ON r.id = s.id 
    SET r.relation_id = NULL; 

DROP TABLE work_table; 

附录:

如果你正使用InnoDB,你能避免这种类型的数据完整性问题未来通过定义一个外键约束。例如:

ALTER TABLE relations ADD CONSTRAINT relations_FK 
FOREIGN KEY (relation_id) REFERENCES relations(id) 
ON UPDATE CASCADE ON DELETE SET NULL; 

这将禁止变更,这将导致一个relation_id具有比存在于表中的id的值以外的值的表。 (这要求id是PRIMARY KEY,并且relation_id具有相同的数据类型。)