【问题标题】:Converting Pseudocode to SQL Script将伪代码转换为 SQL 脚本
【发布时间】:2012-11-17 04:02:06
【问题描述】:

所以我有两张桌子:

  1. Bookmarks 有几列 [id 等]
  2. 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 [编辑] SQL 脚本。

【问题讨论】:

标签: sql postgresql foreign-keys referential-integrity


【解决方案1】:

@Jan 已经提到了外键,但他的建议并不完整。

您似乎想删除与不存在的书签的所有关联(不再存在)。
以如下形式定义foreign key constraint

ALTER TABLE person_bookmarks
ADD CONSTRAINT pb_fk FOREIGN KEY (bookmarkid) REFERENCES bookmarks (id)
ON UPDATE CASCADE
ON DELETE CASCADE;
  • 这仅允许存在于bookmarks.id 中的person_bookmarks.bookmarkid 中的值。

  • ON UPDATE CASCADE 在您更改bookmarks.id 中的条目时更改person_bookmarks.bookmarkid 中的相应

  • 当您更改 bookmarks.id 中的条目时,ON DELETE CASCADE 会删除 person_bookmarks.bookmarkid 中相应的

其他选项可用,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 的所有行。取消注释最后一行以摆脱死人。

【讨论】:

  • 欧文 - 感谢您的详细解释。从架构的角度来看,是否应该使用外键约束而不是负责进行所需更改的软件是否存在争论?
  • 外键在任何情况下都保持参照完整性,因为它具有故障安全性。它们是 RDBMS 核心的经过验证的解决方案。客户端软件中的任何解决方案迟早都会失败。想想连接中断、绕过客户端软件直接访问数据库的并发(竞争条件)。
【解决方案2】:

这适用于 SQL Server - 不确定 MySQL...

delete pb
from
  person_bookmark pb
where not exists (select 1 from booksmarks b where b.id = pb.bookmarkid)

【讨论】:

  • 这个问题实际上是用 PostgreSQL 标记的。但它是标准 SQL,确实可以在任何 DBMS 中使用。
【解决方案3】:

@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)。

【讨论】:

    猜你喜欢
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 2021-04-06
    相关资源
    最近更新 更多