我有 4 个这样相关的表(这是一个例子):
Company:
ID
Name
CNPJ
Department:
ID
Name
Code
ID_Company
Classification:
ID
Name
Code
ID_Company
Workers:
Id
Name
Code
ID_Classification
ID_Department
Run Code Online (Sandbox Code Playgroud)
假设我有一个classificationwith id = 20, id_company = 1。并且department有id_company = 2(代表另一家公司)。
这将允许创建来自两个公司的工人,因为分类和部门分别链接到公司。我不希望这种情况发生,所以我认为我的人际关系有问题,我不知道如何解决。
表之间的外键是否应该链接到自然键或代理键是否有最佳实践?我真正找到的唯一讨论(除非我的 google-fu 缺失)是Jack Douglas 在这个问题中的回答,他的推理对我来说似乎是合理的。我知道除了规则改变之外的讨论,但这在任何情况下都需要考虑。
提出这个问题的主要原因是我有一个遗留应用程序,它使用带有自然键的 FK,但是开发人员强烈推动转向 OR/M(在我们的例子中是 NHibernate),并且一个 fork 已经产生了一些破坏性更改,因此我希望使用自然键将它们推回正轨,或者移动旧应用程序以使用 FK 的代理键。我的直觉告诉我要恢复原始的 FK,但老实说,我不确定这是否真的是正确的道路。
我们的大多数表都已经定义了代理键和自然键(尽管是唯一约束和 PK),因此在这种情况下,必须添加额外的列对我们来说不是问题。我们使用的是 SQL Server 2008,但我希望这对于任何数据库都足够通用。
我有几个表,其中的记录可以用几个广泛的业务领域唯一标识。过去,我将这些字段用作 PK,并考虑到以下好处:
但是,我听说过一个创建合成IDENTITY INTPK的案例,而是使用单独的UNIQUE约束来强制执行业务密钥。优点是狭窄的 PK 使得二级索引小得多。
如果一个表有没有比PK其他指标,我看不出有任何理由赞成第二种方法,虽然在一个大表它可能是最好的假设,指数可能在未来是必要的,因此,有利于在狭窄合成PK . 我是否缺少任何考虑?
顺便说一下,我并不是反对在数据仓库中使用合成键,我只是对何时使用单一的宽泛 PK 以及何时使用窄 PK 加上宽泛的 UK 感兴趣。
看看下面的sqlfiddle:http ://sqlfiddle.com/#!2/dacb5/1
CREATE TABLE contacts
(
id int auto_increment primary key,
name varchar(20),
network_id int,
network_contact_id int
);
INSERT INTO contacts
(name, network_id, network_contact_id)
VALUES
('John', 4, 10),
('Alex', 4, 11),
('Bob', 4, 12),
('Jeff', 4, 45),
('Bill', 7, 11),
('Walter', 7, 45),
('Jessie', 7, 360) ;
Run Code Online (Sandbox Code Playgroud)
我有一个基本的联系人表。该network_id和network_contact_id字段包含链接到其他表的ID号码。
我希望能够运行INSERT IGNORE查询,此表,但我想用的组合network_id,并network_contact_id作为唯一键来匹配。
因此,举例来说,如果我试图插入一个接触的是有network_id = 4和network_contact_id = 12中,INSERT IGNORE查询将看到该条目已经存在,而忽略被抛出任何错误。
所以基本上,network_id不是唯一的。network_contact_id不是唯一的。但两者的结合是独一无二的。我该如何设置?我是否必须有一个其他字段作为其他两个字段的串联值?或者有没有办法为此表设置密钥,以便它可以满足我的需要?
我有一个“评论”表,可以模拟某个主题的对话,如下所示:
id serial
topic_id integer
parent_comment_id integer
body text
Run Code Online (Sandbox Code Playgroud)
因此,每条评论都有对其主题的引用,并最终引用其父评论(如果它不是该主题的第一条评论)。
我想添加一个约束,以防止添加主题/父项不匹配的行(例如,通过引用没有所需评论的主题,或者相反地引用错误主题的评论)。
这可能吗?是否需要触发器?
(为了记录,我试过
ALTER TABLE comments ADD FOREIGN KEY (parent_comment_id, topic_id)
REFERENCES comments (id, topic_id)
Run Code Online (Sandbox Code Playgroud)
但它抱怨there is no unique constraint matching given keys for referenced table "comments")
可能的重复:
每个表都应该有一个单字段代理/人工主键吗?
我无法想象每个表都不使用唯一 ID,这就是我问这个问题的原因。您不应该为表中的每一行分配一个唯一的 ID 吗?
这个交流网站的新手,所以我希望我的问题不是不合适的。
创建一个有点标准化的数据库 我有一个设计问题,我不确定如何有效地处理。
一张表与另外两张表具有一对多关系。这两个表然后在它们之间具有多对多关系。我不应该以某种方式确保(除了在编程插入中)链接在一起的项目属于同一个父表。
让我们把它放在一个场景中(这是一个虚构的场景):
部门表,其中每一行是公司中的一个部门。它与 Employee 表具有一对多关系。因此,每个员工都属于一个且仅一个部门。
Division 表还与记录了特定项目的 Project 表具有一对多关系。该项目还必须注册员工在此特定项目中记录的小时数。我会使用 Employee 和 Project 之间的多对多表和一个小时列来做到这一点。
这应该一切正常(我认为至少),除了理论上数据库中没有任何内容可以确保 Employee 和 Project 属于同一个部门,即使它们应该并且实际上都属于该表中的一个实体。
有什么好方法可以确保这种模式的意图和数据的完整性由一些抽象的关系数据库处理。您会以任何其他方式构建数据库还是会对多对多关系施加一些限制?
我不确定是否有人问过这个问题。至少我找不到。
我对数据搜索和检索效率方面的主键感到好奇。
这是一个假设的例子......我有一个独特的学生列表StudentID(比如 10 位数字,因为学校永远不会有那么多学生)和StudentName(这也是独一无二的)。
将其用StudentID作主键或为主键创建一个新字段(可能是 6 - 8 位数字或字符和数字的组合。即 ATC1002)会更好吗?
如果我用StudentName作主键,我会看到任何检索性能下降吗?如果有,一般大概多少钱?是否还有其他因素会影响主要领域的选择?
我将向一个相当大的表添加一个聚集索引:
有一Id列可能用于索引键,但它是nvarchar(18)和not unique(尽管那里没有重复值)。
但是我不愿意使用它,因为它的数据类型(性能影响)并且一直在考虑添加一int identity(1,1)列并将其用作聚集索引键。
您更愿意推荐哪种解决方案?TIA
我正在使用 MS SQL Server,但在一般数据库设计中,我想知道当数据库中的每一行都有其自动生成的代理键值时会出现什么问题。
我知道一些优点,比如主键不需要标识没有NULL的唯一列,不需要管理复合主键,范式更容易管理,唯一性有保证。
我想知道,是否有任何关于性能或索引结构等的充分理由应该使我们使用真实世界的事实键而不是代理键?
谢谢。
primary-key ×3
constraint ×2
foreign-key ×2
index ×1
index-tuning ×1
insert ×1
mysql ×1
natural-key ×1
postgresql ×1
rdbms ×1
sql-server ×1