在我正在处理的一个 Web 应用程序中,所有数据库操作都是使用一些在实体框架 ORM 上定义的通用存储库进行抽象的。
但是,为了通用存储库的简单设计,所有涉及的表都必须定义一个唯一的整数(Int32
在 C# 中,int
在 SQL 中)。直到现在,这一直是桌上的PK,也是IDENTITY
.
外键被大量使用,它们引用这些整数列。它们对于一致性和 ORM 生成导航属性都是必需的。
应用层通常会做以下操作:
SELECT * FROM table
UPDATE table SET Col1 = Val1 WHERE Id = IdVal
DELETE FROM table WHERE Id = IdVal
INSERT INTO table (cols) VALUES (...)
不太频繁的操作:
BULK INSERT ... into table
后跟 (*) 所有数据加载(以检索生成的标识符)DELETE FROM table where OtherThanIdCol = SomeValue …
请原谅这里任何定义的松散,但我试图探索一个简单的概念。
一个主键唯一标识一行。表中可能还有其他列具有唯一值,因此它们也可以唯一标识一行(候选键),但主键是为任务指定的。
使主键更有用的属性包括:
由于这些原因,我通常建议主键没有内在价值,因此永远没有理由更改或回收值。也就是说,它应该是没有意义的。
我见过包含某种代码的主键,例如基于名称的客户端代码。明显的问题是 (a) 如果客户端名称更改,那么 PK 也应该更改,以及 (b) 与具有相似名称的客户端发生冲突的风险太大。
半个例外是使用自动递增的数字,它具有序列号的次要含义。但是,它仍然很稳定。
问题是,在什么情况下,如果有的话,最好使用具有其他实际含义的主键?也就是说,PK应该是任意的,并且你通常可以通过序列号获得的建议有什么问题吗?
在创建数据库结构时,我倾向于为每组需要唯一的数据创建唯一的复合键。在它们旁边我通常使用主键(通常是 INT AI id),除非复合键确实足以识别记录。
一方面,好处是我可以避免插入“坏记录”。是否存在这些密钥的使用变得过多或数据库设计不佳的迹象?
我正在为一个应用程序设计一个数据模型,它必须跟踪数据的变化。
第一步,我的应用程序必须支持PostgreSQL,但我想在第二步中添加对其他 RDBMS(尤其是 Oracle 和 MS SQL 服务器)的支持。因此,我想选择使用较少专有功能的便携式数据模型。(表的 DDL 可能因 RDBMS 供应商而异。但应用程序中的 SQL 查询/语句对于所有支持的供应商应尽可能相同。)
例如,假设有users
一张users_versions
桌子。users_versions
在 上有一个外键users
。
表的示例可能如下所示:
users
----------------
id | username
----------------
1 | johndoe
2 | sally
users_versions --> references id of user (userid)
---------------------------------------------------------------------------
id | userid | name | street | place | validfrom | validuntil
---------------------------------------------------------------------------
1 | 1 | John Doe | 2nd Fake St | Faketown | 2018-01-04 | 2018-01-05
2 | 1 …
Run Code Online (Sandbox Code Playgroud)