标签: referential-integrity

DELETE 语句与 REFERENCE 约束冲突

我的情况是这样的:

表 STOCK_ARTICLES:

ID *[PK]*
OTHER_DB_ID
ITEM_NAME
Run Code Online (Sandbox Code Playgroud)

表位置:

ID *[PK]*
LOCATION_NAME
Run Code Online (Sandbox Code Playgroud)

表 WORK_PLACE:

ID *[PK]*
WORKPLACE_NAME
Run Code Online (Sandbox Code Playgroud)

表 INVENTORY_ITEMS:

ID *[PK]*
ITEM_NAME
STOCK_ARTICLE *[FK]*
LOCATION *[FK]*
WORK_PLACE *[FK]*
Run Code Online (Sandbox Code Playgroud)

显然,INVENTORY_ITEMS 中的 3 个 FK 引用了相应其他表中的“ID”列。

这里的相关表是 STOCK_ARTICLE 和 INVENTORY_ITEMS。

现在有一个由几个步骤(SQL 脚本)组成的 SQL 作业,用于将上述数据库与另一个数据库(OTHER_DB)“同步” 。这项工作的步骤之一是“清理”。它从 STOCK_ITEMS 中删除其他数据库中没有具有相同 ID 的相应记录的所有记录。它看起来像这样:

DELETE FROM STOCK_ARTICLES
 WHERE
    NOT EXISTS
     (SELECT OTHER_DB_ID FROM
     [OTHER_DB].[dbo].[OtherTable] AS other
               WHERE other.ObjectID = STOCK_ARTICLES.OTHER_DB_ID)
Run Code Online (Sandbox Code Playgroud)

但是这一步总是失败:

DELETE 语句与 REFERENCE 约束“FK_INVENTORY_ITEMS_STOCK_ARTICLES”相冲突。冲突发生在数据库“FIRST_DB”、表“dbo.INVENTORY_ITEMS”、“STOCK_ARTICLES”列中。[SQLSTATE 23000](错误 547)该语句已终止。[SQLSTATE 01000](错误 3621)。步骤失败。

所以问题是当它们被INVENTORY_ITEMS引用时,它不能从STOCK_ARTICLES中删除记录。但是这种清理需要起作用。这意味着我可能必须扩展清理脚本,以便它首先识别应该从 STOCK_ITEMS 中删除的记录,但不能因为相应的 ID 是从 INVENTORY_ITEMS 内部引用的。那么应该先删除INVENTORY_ITEMS里面的记录,然后再删除STOCK_ARTICLES里面的记录。我对吗?那么 …

sql-server delete referential-integrity

10
推荐指数
2
解决办法
6万
查看次数

如果外键/级联删除不好,为什么要使用具有该功能的数据库服务器?

我注意到 wordpress/rails 等不使用外键约束或从数据库中级联删除功能。相反,他们在 PHP/Ruby/脚本级别处理这个!

我已经阅读了这个这个。大多数反对外键约束的论点都涉及性能、多线程、锁定、可伸缩性等。

假设反对外键的论点是有效的,我的问题是:

  1. 如果外键不好,为什么 WordPress/Rails/etc 使用支持外键的 sql-server?他们会从 MySQL 转向 NoSQL 类型的服务器吗?
  2. 另一方面,应用程序能否以某种方式编码以利用外键功能而不会遇到问题?
  3. 如果我们仅将数据库用于应用程序/脚本层的存储和管理“关系”,那么 noSQL/redis 会更好吗?

mysql nosql foreign-key referential-integrity

8
推荐指数
1
解决办法
9292
查看次数

在单独的数据库之间建立关系是不好的做法吗?

我正在与具有多个数据库的客户合作。有几个master级别数据库与instance级别数据库(特定于应用程序的 DB)有关系。从instanceto的关系master是整数值,表示master. 中的视图和存储过程instances设置为master通过这些存储的键加载数据。

显然,没有真正的参照完整性,但这是不好的做法还是数据应该驻留在instance数据库的只读表中?

sql-server best-practices referential-integrity multi-tenant

8
推荐指数
1
解决办法
1052
查看次数

如何识别具有指向 Sybase 中特定表的外键的表?

我正在寻找(最好)一个 SQL 语句,该语句为任何带有外键的表选择表/和列名到 Sybase 中的给定表。我认为sys...表格应该以某种方式可能,但对 sybase 来说是全新的,我无法理解它。因此,任何朝着正确方向发展的帮助都受到高度赞赏。

编辑:为了完整起见:SELECT @@VERSION返回

'Adaptive Server Enterprise/15.0.3/EBF 17156 ESD#3/P/Sun_svr4/OS 5.8/ase1503/2726/64-bit/FBO/Fri Feb 5 05:26:23 2010'

编辑 2 非常
感谢您的建议,尤其是Andrew Bickerton 的评论。这使我能够构建一个基本的 SQL 选择语句,作为更进一步的起点。

如果其他人对它感兴趣,这里是:

select 
  fko.name    "Foreign key name",
  par.name    "Referenced table name",
  fk1.name || ' -> ' || pk1.name "Reference 1",
  fk2.name || ' -> ' || pk2.name "Reference 2",
  fk3.name || ' -> ' || pk3.name "Reference 3",
  fk4.name || ' -> ' || pk4.name "Reference 4"
from …
Run Code Online (Sandbox Code Playgroud)

sybase referential-integrity

7
推荐指数
1
解决办法
2万
查看次数

“合并” Postgres 表中的两行,带有外键

我使用 PostgreSQL 中的以下两个表来保存我读过的书籍的数据库:

CREATE TABLE authors (
    id SERIAL PRIMARY KEY,
    name text
);

CREATE TABLE books (
    id SERIAL PRIMARY KEY,
    title text,
    author_id integer REFERENCES authors(id) ON UPDATE CASCADE ON DELETE CASCADE,
    UNIQUE(title, author_id)
);
Run Code Online (Sandbox Code Playgroud)

现在,在浏览我的作者列表时,我发现了以下两个条目:

id | name
----------
 1 | Mark Twain
 2 | Samuel Clemens
Run Code Online (Sandbox Code Playgroud)

我想要做的是删除“马克吐温”条目,并有效地更新所有引用“马克吐温”的书籍以引用“塞缪尔克莱门斯”。我知道我可以手动执行此操作,但我想要一个有效的解决方案,无论哪些表正在引用authors(id)

我想过这样做(在交易中):

  1. 将 Mark Twain 更改id为 2,让我们UPDATE CASCADE负责更改引用。
  2. 删除马克吐温条目

但这会遇到一些问题,主要是:

  1. 第一步创建一个重复的主键
  2. 一旦它们都具有相同的 ID,我不确定如何引用要删除的正确行!
  3. DELETE CASCADE让我担心的第二个步骤

还有一个更微妙的问题,可以用我(精心策划的)books表格的一部分来说明:

id | title              | …
Run Code Online (Sandbox Code Playgroud)

postgresql foreign-key referential-integrity postgresql-9.4

7
推荐指数
1
解决办法
4247
查看次数

任何基于图形/感知的数据库是否具有维护引用完整性的良好机制?

任何基于图形/图形感知的数据库(Neo4j、ArangoDB、OrientDB 或其他)是否具有与关系数据库提供的机制相同的维护引用完整性的机制?

我正在探索各种基于文档的数据库,以找到合适的引擎用于向某个项目添加辅助数据存储。

我发现了基于图的/多模型数据库,它们似乎是一个好主意,但我惊讶地发现它们似乎没有提供与现代关系数据库相同级别的关系/链接/边缘保护。

特别是,我正在讨论将实体/顶点的删除与链接/边的删除相链接。在关系数据库中,我可以有一个外键约束,它将一个表中的记录与另一个表中的记录链接起来,并且可以

  1. 如果表 A 中的记录被表 B 中的记录引用,则防止删除该记录(“删除时不执行任何操作”),或者

  2. 如果删除表 A 中的引用记录,则删除表 B 中的引用记录。

我希望在图形感知数据库中找到类似的机制。例如,如果“评论”顶点链接到“帖子”顶点(形成多对一关系),则需要解决以下问题/挑战:

  1. 当该帖子的评论存在边缘时,防止删除该帖子。这样,评论就永远不会有指向帖子的悬空链接/边缘。解决方案是:根据链接/边缘属性,

    1. 阻止删除帖子,直到删除该帖子的评论的所有边缘,或者

    2. 删除帖子时删除链接到该帖子的所有评论。

  2. 防止删除评论到帖子的边缘而不删除评论本身,以防止评论根本没有到帖子的链接/边缘。

  3. 仅当创建边缘以同时将此评论链接到帖子时才允许创建评论。

基于图形的数据库中确实缺乏这样的机制,还是我只是找不到它们?

我知道OrientDB有“链接”数据类型,可能解决了第二个问题和第三个问题(如果链接类型属性被声明为强制且非空,那么在不指定链接目的地的情况下不可能创建记录,稍后不可能通过取消设置属性来中断链接)。

然而,据我记得,可以删除链接类型属性指向的记录,从而产生悬空链接(因此第一个问题没有解决)。

我还知道,在某些数据库中,我可以使用嵌套文档作为多个链接文档的替代方案。然而,这种方法不能很好地扩展(对于链接记录数量可以无限增长的情况)。此外,它也非常有限(当需要多个链接时,例如,指向帖子和用户的链接,它不能用作替代方案;还有其他重要的限制)。

referential-integrity graph neo4j

7
推荐指数
1
解决办法
315
查看次数

通过转发表到多个表的外键

问题陈述

\n

我有一个表,其中有一列的值为外键,但外键的目标表因行而异。相关表可以仅根据键值来确定,并且存在一小组固定的此类表。

\n

我想在此处添加外键约束,以便我的 DBMS 可以确保引用完整性。当然,我不能直接执行此操作,但我有一个建议的解决方案,其中涉及带有传入和传出外键约束的中间“转发表”。我正在寻找评论:

\n
    \n
  • 这个解决方案是否确实解决了问题,或者我是否错过了\n边缘情况;
  • \n
  • 面对数据模型的变化,该解决方案的表现如何(例如,新的参考表);
  • \n
  • GENERATED ALWAYS AS ... STOREDPostgres列的这种使用是否合理或可疑;
  • \n
  • 该解决方案是否可能引入并发问题。
  • \n
\n

建议的解决方案

\n

为了说明该解决方案,请考虑一个存储“用户”和“组”的简单数据库。用户和组均由整数 ID 作为键控,\n并且 ID 的某些位被保留以告知其 ID 类型:

\n
-- User and group IDs are both integers, but are in disjoint subsets of the key\n-- space, distinguished by the low 8 bits.\nCREATE DOMAIN userid AS int8 CHECK ((VALUE & 255) = 1);\nCREATE DOMAIN groupid AS int8 CHECK ((VALUE & 255) = 2);\n\nCREATE TABLE users(\n    user_id userid …
Run Code Online (Sandbox Code Playgroud)

postgresql database-design referential-integrity

7
推荐指数
1
解决办法
1292
查看次数

一个可以引用多种类型对象的对象应该如何在关系模式中建模?

为这个晦涩的问题道歉,用一个具体的例子可能更有意义:

在我的应用程序中,我可能会创建一个包含一组项目的投资组合。但是,我也可以添加一个嵌套在投资组合(然后可能包含项目)中的“子投资组合”。目前,我通过以下方式绘制了我的架构:

+------------+    +-----------------------+    +------------+
| Portfolios |    | Portfolio_project_map |    | Projects   |
+------------+    +-----------------------+    +------------+
|   port_id  |    |   parent_id           |    |   proj_id  |
+------------+    +-----------------------+    +------------+
|            |    |   child_id            |    |            |
                  +-----------------------+
                  |   child_is_portfolio  |
                  +-----------------------+
Run Code Online (Sandbox Code Playgroud)

这看起来非常难看。在关系数据库中建模这种关系的正确方法是什么?还是真的没有,这样的细节应该在业务逻辑中严格执行?它甚至有可能对指定的外键约束Portfolio_project_map,使得child_id引用要么port_id还是proj_id

另外,这样的问题到底叫什么?我发现在几个地方引用了“一对一”,但我有一种不完全正确的感觉?

mysql database-design referential-integrity

6
推荐指数
1
解决办法
294
查看次数

一对多关系的查找表

我有一个ticketsid,我需要将它关联到一个查找表,其中该数据的对应项是另一个id受外部源控制的表。

tickets
- id
- sutff

lookup
- outside_data_id
- ticket_id
Run Code Online (Sandbox Code Playgroud)

我只需要知道关联是否存在(因此是lookup表)并且具有一对多的关系。我知道没有别的有关outside_data_id除了id本身和相关ticket_id

此外,我不想更改tickets表格,因为这只会影响少量的ticket_id's。

例子

outside_data_id = 1234
Run Code Online (Sandbox Code Playgroud)

可能与:

ticket_id = 321
ticket_id = 322
ticket_id = 900
Run Code Online (Sandbox Code Playgroud)

下面的查找表结构会起作用还是有更好的方法?

CREATE TABLE lookup
(
   outside_data_id integer, 
   ticket_id integer
)
Run Code Online (Sandbox Code Playgroud)

postgresql database-design clustered-index referential-integrity index-tuning

6
推荐指数
2
解决办法
5119
查看次数

更新引用时删除行

假设我有一个person带有 id 和其他一些列的表。其他表person使用ON UPDATE CASCADE. 例如:

CREATE TABLE person (id int PRIMARY KEY);
CREATE TABLE sale (id int PRIMARY KEY,
    person_id int REFERENCES person(id) ON UPDATE CASCADE);
Run Code Online (Sandbox Code Playgroud)

现在,我想要做的是:从 person 表中删除重复的条目,修复referencessale引用。例如,使用此数据:

INSERT INTO person values (1), (2), (3);
INSERT INTO sale VALUES (11, 1), (12, 2), (13, 3);
Run Code Online (Sandbox Code Playgroud)

Person12实际上是一样的,所以他们应该被“合并”。通过合并我的意思是不包括人2在更新的人引用1sale表。

由于ON UPDATE CASCADE表上有一个引用person,我想知道是否有某种方法可以在不必手动更新sale表的情况下,在删除人的同时导致级联更新2

我在这里试图实现的是避免使用专用程序来更新引用,因为引用表的数量很可能会增加,需要在此过程中进行维护(并且已经相当大了)。

postgresql delete dynamic-sql referential-integrity update

6
推荐指数
1
解决办法
3807
查看次数