我可以让一个标识字段跨越 SQL Server 中的多个表吗?

2024-03-28

我可以有一个跨多个表的“身份”(唯一的、非重复的)列吗? 例如,假设我有两个表:书籍和作者。

Authors
  AuthorID
  AuthorName
Books
  BookID
  BookTitle

BookID 列和AuthorID 列是标识列。 我希望身份部分跨越两列。 因此,如果存在值为 123 的 AuthorID,则不可能存在值为 123 的 BookID。反之亦然。

我希望这是有道理的。

这可能吗?

Thanks.

我为什么要这样做?我正在编写一个 APS.NET MVC 应用程序。我正在创建一个评论部分。作者可以提出意见。书可以有评论。我希望能够将实体 ID(书籍 ID 或作者 ID)传递给操作,并让该操作提取所有相应的评论。该动作不会关心它是一本书还是一个作者或其他什么。听起来合理吗?


即使您可以将标识序列放在多个表中,您的注释表也无法在单个外键中引用两个列。

根据关系数据库设计理论,最好的方法是创建两个评论表。但显然,您希望避免这种情况,可能是出于代码重用的原因。

最直接的实用方法是在评论表上放置两个外键列,并为每个评论设置一个为空,另一个不为空。

另一种方法(可能是最好的折衷方案)是这样的。您在问题中提到“实体 ID”。所以制作一个实体表!那么作者以及书籍和评论都可以参考that table.

编辑添加:

Philip Kelley、Ray 和(我认为)Artic 都建议修改评论表,添加一个entity_id,它可以指的是book_id or the author_id,以及某种标志(char(1), tinyint, and boolean分别)表明正在引用其中的哪一个。

出于多种原因,无论是实用性(包括数据完整性、报告、效率)还是理论上,这都不是一个好的解决方案。

第一个也是最明显的问题是数据完整性问题。关系数据库系统应该始终负责维护其自身数据的完整性,并且数据库设计有自然且首选的方式来做到这一点。这些机制中最重要的之一是外键系统。如果comment.entity_id列是引用两者book.book_id and author.author_id,则无法为此列创建外键。

当然,您可以在 DML(插入、更新、删除)存储过程中进行检查来验证引用,但这很快就会变得一团糟,因为所有三个表上的所有 DML 操作都会涉及到。

这给我们带来了效率问题。每当查询运行时comment表,它将需要连接到author or book表或两者。查询计划生成系统将没有可用于优化的外键,因此其性能很可能会下降。

那么这个方案在报道中就存在问题。任何报告生成系统都会遇到此类系统的问题。当然,这对于专业程序员来说不是问题,但是任何用户临时报告都必须模拟背后的逻辑,当event_id意味着这个或那个,这可能是一笔非常糟糕的交易。也许您永远不会在该数据库上使用报告生成工具。但话又说回来,没有人知道数据库最终将用在哪里。为什么不与系统合作以允许任何事情发生呢?

这就引出了理论问题。

在关系数据库理论中,每个表(“关系变量”)中的每一行(也称为“元组”)代表关于现实世界的一个命题。设计表格就是决定该命题的形式。让我们看几个例子来说明它是如何工作的。

comment (comment_id int, comment_type char(1), entity_id int, 
         user_id int, comment_text nvarchar(max), comment_date datetime)
/* comment_id identifies a comment (comment_text) that a user (user_id) 
   has made about a book (entity_id if comment_type = 'B') or author 
   (entity_id if comment_type = 'A') at a particular date and 
   time (comment_date).*/

这里很明显,该列(或“属性”)称为entity_id正在履行双重职责。除了引用另一列之外,它实际上并不代表任何内容。这是可行的,但并不令人满意。

comment (comment_id int, book_id int, author_id int, user_id int, 
         comment_text nvarchar(max), comment_date datetime)
/* comment_id identifies a comment (comment_text) that a user (user_id) 
   has made about a book (book_id if not null) or author (author_id if 
   not null) at a particular date and time (comment_date). */

这为我们购买了外键,这是第一个版本中最大的遗漏。但这仍然不是很令人满意,除非一条评论可以同时指一本书和一个作者(这可能是合理的)。可空列是一个警告信号,表明设计存在问题,这里也可能出现这种情况。检查约束可能是必要的,以避免评论根本没有提及任何内容,或者如果不允许的话,则可以同时提及一本书和作者。

从理论角度(以及我的角度:))有一个明显的最佳选择:

book_comment (book_comment_id int, book_id int, user_id int, 
              comment_text nvarchar(max), comment_date datetime)
/* book_comment_id identifies a comment (comment_text) that a 
   user (user_id) has made about a book (book_id) at a particular 
   date and time (comment_date). */

author_comment (author_comment_id int, author_id int, user_id int, 
                comment_text nvarchar(max), comment_date datetime)
/* author_comment_id identifies a comment (comment_text) that a 
   user (user_id) has made about an author (author_id) at a particular 
   date and time (comment_date). */

最后一个选项将提供最佳的效率、数据完整性和报告的简易性。唯一的代价是 DML 存储过程需要将注释放入正确的表中,这不是什么大问题,因为它们必须知道注释所指的内容。

如果您的计划是立即检索一本书或作者的所有评论,那么您可以轻松地在这些表之上创建一个视图来重现其他设计(如果您想要这样做)。

create view comments as 
select 
    book_comment_id as comment_id, 
    book_id as entity_id, 
    comment_text,
    'B' as comment_type
from book_comment
union
select 
    author_comment_id as comment_id, 
    author_id as entity_id, 
    comment_text,
     'A' as comment_type 
from author_comment
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以让一个标识字段跨越 SQL Server 中的多个表吗? 的相关文章

  • 如何使用xampp连接sql服务器和php?

    我正在尝试使用 Xampp 将我的 SQL 服务器与 PHP 连接 我已经在ext文件夹中上传了dll文件 但无法连接它 我的PHP版本是7 2 6 上传的dll文件是 php pdo sqlsrv 72 ts dll php sqlsrv
  • SET IDENTITY_INSERT [表] ON 不起作用

    我想在指定 Id 的位置插入一些记录 以便将数据迁移到我想要保持现有关系完整性的位置 为此 我直接在 SSMS 中的表上运行以下命令 SET IDENTITY INSERT CRMTItem ON 然而 当我从 C 插入一个 Id 为 1
  • 制作 SQL Server 转储并将该转储导入另一个 SQL Server 的最佳(最简单)方法

    我想从一台服务器在 SQL Server 中实现数据库导出 转储 并将该转储导入到另一台 SQL Server 中 并且不一定使用相同的架构名称 例如 如果我准备了一个数据库 其中包含用于为新客户实施新数据库的所有数据集 则该数据库名为 D
  • SQL Server 中 SYSDATETIME 数据类型的准确性

    我已经在 SQL Server 2008 的存储过程中使用 SYSDATETIME 进行了一些测试 我设置了一个包含带有 IDENTITY 字段的 datetime2 7 的表 我了解这种数据类型的精度和准确度之间的差异 但是 在从此示例中
  • 触发器和行版本控制信息

    在什么情况下表触发器会导致在行末尾添加 14 个字节以进行行版本控制 数据行中使用的空间 部分在本页 http msdn microsoft com en us library ms175492 aspx明确指出 每个数据库行可以在行末尾使
  • 如何研究.NET 中的非托管内存泄漏?

    我有一个通过 MSMQ 运行的 WCF 服务 内存随着时间的推移逐渐增加 表明存在某种内存泄漏 我在本地运行该服务并使用 PerfMon 监视一些计数器 CLR 内存托管堆字节总数保持相对恒定 而进程的私有字节随着时间的推移而增加 这让我相
  • 从 Perl 脚本 DBI 关闭 MSSQL 服务器

    我正在写一个 perl 脚本 其中我必须关闭我的 mssql 服务器 做一些操作 然后我必须重新启动它 我知道一种方法是使用 netstat 来停止服务 但我不能使用它 所以我尝试安装 DBI 和 DBD ODBC 模块 我可以通过以下代码
  • SQL 2016 无法创建列主密钥

    I just installed SQL 2016 Standard Edition because I wanted to use the Always Encrypted feature However when I tried to
  • MySQL CREATE TABLE 语句上的外键错误(错误:150)

    我觉得我已经在一对非常简单的创建表语句上尝试了一切可能的方法 类型匹配 我尝试使用 ENGINE InnoDB 等 但很困惑为什么我收到外键错误 我已经离开 SQL 一段时间了 所以这可能是一个简单的问题 mysql gt CREATE T
  • 出错时退出并回滚脚本中的所有内容

    我有一个 TSQL 脚本 它可以进行大量数据库结构调整 但在出现故障时让它继续执行并不真正安全 把事情说清楚 使用 MS SQL 2005 它不是一个存储过程 只是一个脚本文件 sql 我所拥有的按以下顺序排列 BEGIN TRANSACT
  • 使用不存在和联接的 SQL 查询到 LINQ 语法

    我的 SQL 查询如下所示 在 SQL 中运行良好 我需要将其转换为 LINQ 语法 SQL SELECT Key Id FROM LocalizationKeys AS lk WHERE NOT EXISTS SELECT 1 FROM
  • SQL Server 将 SP_EXECUTESQL 识别为对象而不是过程名称

    我在用DBContext Database SqlQuery
  • 触发器以捕获服务器中的架构更改

    是否可以实现类似以下触发器的东西 CREATE TRIGGER tr AU ddl All Server ON DATABASE WITH EXECUTE AS self FOR DDL DATABASE LEVEL EVENTS AS D
  • 如何在 SQL Server 查询中的 FROM 子句中使用变量?

    我正在创建一个查询 该查询将选择表中的所有数据 查询将根据我将传递给存储过程的变量选择表 在我的例子中 如果我执行example sp table1它将选择table1 如果我使用同样的事情example table table2 应该选择
  • 单个 sql 查询可以处理 sql server 中的 null 或值日期范围

    使用 SQL Server 2008 我有一个存储过程 其中开始日期和结束日期作为日期范围的输入参数 寻找一个singlesql 查询 其中在 where 子句中有一个开始日期和结束日期 可以处理日期均为空或都有值的两种情况 我不想使用 I
  • 防止从 SSMS 导出的文件中受影响的行条目

    我怎样才能防止这样的条目 123456 rows affected 在文件末尾导出的文本文件中 似乎没有找到选项 谢谢 你可以使用 SET NOCOUNT ON 不设置计数 https learn microsoft com en us s
  • 如何在 SQL 中的时区中使用“America/New_York”

    我有这段代码在 SQL 中运行良好 但是我想使用不同的时区格式 例如 America New York 代替 US Eastern Standard Time SELECT TODATETIMEOFFSET CAST CURRENT TIM
  • SQL:列出多个连接语句中的重复记录?

    你好 以下查询在连接多个表后返回所有员工 select e from dbo EMP e join dbo HREMP a on a ID e ID join dbo LOGO c on c EMPID e id join dbo LOGO
  • 当我尝试连接到数据库时收到“错误:无法初始化 OLE”? C#

    我正在尝试通过 C 连接到数据库 但这样做时收到一条非常无用的错误消息 08 44 17 错误 无法初始化 OLE 08 44 17 错误 无法初始化 OLE 我尝试寻找解决方案 但没有成功 我也尝试重新启动计算机 但这也没有帮助 我正在运
  • SQL查询多行变成单行

    有什么方法可以将通常返回具有相同值的多行的 SQL 查询更改为单行吗 例如 如果我现有的查询返回以下内容 ColA ColB 1 AA 1 BB 1 CC 2 AA 3 AA 我可以将查询更改为仅返回 3 行 并将 1 的第二个和第三个结果

随机推荐

  • 如何从 JQuery 对象获取 javascript 控件?

    我是 JQuery 的初学者 如何从 JQuery 对象获取作为 javascript 对象的控件 var object this 最常见的var object this 0 如果匹配的元素超过 1 个 this 0 this 1 this
  • 无法将 .war 应用程序部署到 GlassFish 3.1.2

    我有一个 war 应用程序模块 无需任何异常更改和服务器调整即可成功部署 但是 我无法将此应用程序部署到 GF 3 1 2 服务器抛出以下异常 java lang Exception java lang IllegalStateExcept
  • 小数的小数次方?

    net 框架在 Math 类中提供了一种对 double 进行幂运算的方法 但根据精度要求 我需要将小数提高到小数次方 Pow decimal a decimal b 框架有这样的功能吗 有谁知道有这种功能的库吗 为了解决我的问题我找到了一
  • 使用 aws cli 获取 S3 存储桶的 ARN

    是否可以通过AWS命令行获取S3存储桶的ARN 我已经查看了文档aws s3api and aws s3 并且还没有找到一种方法来做到这一点 总是如此arn PARTITION s3 NAME OF YOUR BUCKET 如果您知道存储桶
  • 在方便的初始值设定项中使用 self = 来委托给 JSONDecoder 或 Swift 中的工厂方法,以避免“无法分配给值:'self' 是不可变的”

    有时在 Swift 中 为委托的类编写一个初始化程序可能会很方便JSONDecoder或工厂方法 例如 有人可能想写 final class Test Codable let foo Int init foo Int self foo fo
  • 备份使用git的项目

    在快速重新安装之前 我正在将我的东西刻录到 DVD 上 作为最近的用户 从来没有用 git 这样做过 所以我只是和你们核实一下 如果我理解正确的话 我只需要备份我的项目目录project name 其中有 git在它里面 一起监视隐藏文件
  • 在 Karma 运行所有测试之前执行角度代码?

    是否可以在 karma 中执行某种初始化编码 在执行测试之前 我需要运行这样的代码 angular module module common brand constant BRAND brandname 我的应用程序当前需要这个模块 和这个
  • 批量发送API调用

    我目前正在尝试模拟 50 万个 IoT 设备 以使用 Nodejs 将有效负载推送到 Azure IoT 中心 由于节点本质上是多线程的 因此它的物联网中心充满了数据 并且我收到了网络错误 我还尝试了异步 等待方法 但这需要花费大量时间将数
  • 使用 SciPy 拟合贝塞尔曲线

    我有一组近似二维曲线的点 我想使用 Python 与 numpy 和 scipy 来查找近似拟合点的三次贝塞尔路径 其中我指定两个端点的精确坐标 并返回其他两个控制点的坐标 我最初以为scipy interpolate splprep 可能
  • PHP - 小时差(HH:MM 格式)

    我正在尝试计算在这里工作的人的轮班模式 从结束时间中减去开始时间在很大程度上是可行的 但如果他们通宵工作则不行 例如某人工作于10pm to 6am将显示为 22 00 06 00 我希望它能回来8 hours 但我就是想不出最好的方法 令
  • 谷歌图表趋势线未显示

    我有一个 Google 图表折线图 我想在其上显示趋势线 但它没有显示 数据是从数据库中获取的 而 JavaScript 是由 PHP 生成的 但生成的 JavaScript 如下所示
  • LINQ 查询中的分组依据

    我有一个 DataTable 我想在其中执行 GroupBy 查询 year url type id someurl image 0 2003 date 0 someurl image 1 2009 date 1 我已成功对我的 ID 进行
  • WPF 动画“无法冻结此情节提要时间线树以供跨线程使用”

    我当前有一个列表框 其所选项目绑定到我的 ViewModel 上的属性 每当所选项目不为空时 我想对其执行动画 但是我不断收到以下错误 无法冻结此情节提要时间线树以供跨线程使用 并通过研究了解为什么会发生这种情况 但是我不确定需要采取什么方
  • 如何分组并获取具有 X max 的 Y 列的值? [复制]

    这个问题在这里已经有答案了 我有一个以前从未遇到过的用例 我有以下数据框 并且想要选择 y 的值 其中 x 分别为条件 i 的每个级别实现其最小值和最大值 gt library dplyr gt df lt data frame i c 1
  • 在 ubuntu 20.04 上运行 Tensorflow 时出现“无法加载动态库 'libcudnn.so.8'”

    注意 有很多类似的问题 但是针对不同版本的 ubuntu 和有些不同的特定库 我一直无法弄清楚符号链接 其他环境变量的组合 例如LD LIBRARY PATH会工作 这是我的nvidia配置 nvidia smi Tue Apr 6 11
  • 相当于 dash shell 中的 pipelinefail

    有没有类似的选项dash外壳对应于pipefail in bash 或者如果管道中的命令之一失败 但不退出 则获得非零状态的任何其他方式 set e would 为了更清楚地说明这一点 这是我想要实现的目标的示例 在示例调试 makefil
  • 在 Slack 中合并消息菜单和消息按钮

    我想在我的 Slack 应用程序中结合消息菜单和消息按钮 这是我想要实现的工作流程 1 用户发出斜杠命令来显示菜单 该菜单将有一个下拉菜单和三个按钮 这是我能够实现的 2 我希望用户从下拉列表中选择一个选项 然后按任何操作按钮 然后只应触发
  • Warshall算法思想及改进[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 Warshall Floyd 算法 https en wikipedia org wiki Floyd E2 80 93Warshall a
  • 基于点的线/平面相交

    我在空间中有两个点 L1 和 L2 它们定义了一条线上的两个点 我在空间中有三个点 P1 P2 和 P3 这三个点在平面上 那么给定这些输入 直线在什么点与平面相交 外汇 平面方程 A x B y C z D 0 为 A p1 Y p2 Z
  • 我可以让一个标识字段跨越 SQL Server 中的多个表吗?

    我可以有一个跨多个表的 身份 唯一的 非重复的 列吗 例如 假设我有两个表 书籍和作者 Authors AuthorID AuthorName Books BookID BookTitle BookID 列和AuthorID 列是标识列 我