所以我有两张桌子:
Bookmarks
有几列[id等] Person_Bookmark
有2列[personId,bookmarkId] Bookmarks
代表其他网站的链接。所有有效的书签都有一个id。 Person_Bookmark
表有一堆personIds
及其书签,显示为bookmarkId
。
这是我的伪代码:
> let x = integer list of all bookmarkId's from Person_Bookmark
>
> for each x {
> if ('select * from 'Bookmarks' where 'id' = x returns 0 rows) {
> delete from 'person_bookmark' where 'bookmarkId' = x
> }
> }
请告诉我如何转换为Postgres [edit] SQL脚本。
答案 0 :(得分:5)
@Jan已经提到了外键,但他的建议不完整。
好像你想删除与不存在的书签的所有关联(更多) 以下列形式定义foreign key constraint:
ALTER TABLE person_bookmarks
ADD CONSTRAINT pb_fk FOREIGN KEY (bookmarkid) REFERENCES bookmarks (id)
ON UPDATE CASCADE
ON DELETE CASCADE;
这只允许person_bookmarks.bookmarkid
中存在bookmarks.id
中的值。
ON UPDATE CASCADE
中的条目时, person_bookmarks.bookmarkid
会更改bookmarks.id
中相应的值
当您更改ON DELETE CASCADE
中的条目时,
person_bookmarks.bookmarkid
会在bookmarks.id
中删除相应的行。其他选项可用read the manual.
ON DELETE CASCADE
子句自动 ,您尝试手动修复的内容。在添加fk约束之前,您必须手动修复一次:
DELETE FROM person_bookmarks pb
WHERE NOT EXISTS (SELECT 1 FROM bookmarks b WHERE b.id = pb.bookmarkid);
-- OR NOT EXISTS (SELECT 1 FROM persons p WHERE p.id = pb.personid);
删除所有不存在的bookmarkid
行。取消最后一行以取消死人。
答案 1 :(得分:2)
这适用于SQL Server - 不确定MySQL ...
delete pb
from
person_bookmark pb
where not exists (select 1 from booksmarks b where b.id = pb.bookmarkid)
答案 2 :(得分:0)
@ Derek回复的另一个版本:
DELETE FROM person_bookmark
WHERE bookmarkid NOT IN (SELECT id FROM bookmarks)
需要这样做意味着表之间没有外键索引。我强烈建议你这样做。缺点(或功能)在于,当您例如删除person
时(我猜测您的示例中存在此表),您必须首先删除所有关联数据,否则服务器将抛出错误。
这样的事情:
DELETE FROM person_Bookmark WHERE personid = @personid
DELETE FROM person_SomeOtherTable WHERE personid = @personid
DELETE FROM person WHERE id = @personid
但优点是您的数据库中没有孤立行,并且您不能错误地输入错误数据(为bookmark
存储不存在的person