提问人:nickf 提问时间:10/14/2008 最后编辑:chills42nickf 更新时间:4/11/2020 访问量:150472
外键命名方案
Foreign Key naming scheme
问:
我刚刚开始第一次使用外键,我想知道是否有标准的命名方案可用于它们?
给定这些表格:
task (id, userid, title)
note (id, taskid, userid, note);
user (id, name)
其中,任务具有注释,任务归用户所有,用户创作注释。
在这种情况下,如何命名这三个外键?或者,这到底重要吗?
更新:这个问题是关于外键名称,而不是字段名称!
答:
怎么样 ?FK_TABLENAME_COLUMNNAME
Keep It S 尽可能实现 Stupid。
评论
FK_Animals_OwnerID
我通常只留下我的 PK 名称 id,然后在命名其他表中的 FK 时连接我的表名和键列名。我从不为驼峰大小写而烦恼,因为有些数据库会丢弃区分大小写,无论如何都只返回所有大写或小写名称。无论如何,这是我的表格版本的样子:
task (id, userid, title);
note (id, taskid, userid, note);
user (id, name);
请注意,我还用单数来命名我的表,因为一行表示我正在保留的对象之一。其中许多约定是个人喜好。我建议选择一个约定并始终使用它比采用别人的约定更重要。
评论
SQL Server 中的标准约定是:
FK_ForeignKeyTable_PrimaryKeyTable
因此,例如,笔记和任务之间的键是:
FK_note_task
任务和用户之间的关键是:
FK_task_user
这使您可以“一目了然”地查看密钥中涉及哪些表,因此可以轻松查看特定表(第一个命名的表)依赖于哪些表(第二个表已命名)。在此方案中,完整的密钥集为:
FK_task_user
FK_note_task
FK_note_user
因此,您可以看到任务依赖于用户,而注释依赖于任务和用户。
评论
message
from_user_id
to_user_id
fk_message_user
fk_tablename_columnname
我使用两个下划线字符作为分隔符,即
fk__ForeignKeyTable__PrimaryKeyTable
这是因为表名本身偶尔会包含下划线字符。这通常遵循约束的命名约定,因为数据元素的名称通常包含下划线字符,例如
CREATE TABLE NaturalPersons (
...
person_death_date DATETIME,
person_death_reason VARCHAR(30)
CONSTRAINT person_death_reason__not_zero_length
CHECK (DATALENGTH(person_death_reason) > 0),
CONSTRAINT person_death_date__person_death_reason__interaction
CHECK ((person_death_date IS NULL AND person_death_reason IS NULL)
OR (person_death_date IS NOT NULL AND person_death_reason IS NOT NULL))
...
评论
根据此处的答案和注释,包含 FK 表、FK 字段和 PK 表 (FK_FKTbl_FKCol_PKTbl) 的命名约定应避免 FK 约束名称冲突。
因此,对于此处给定的表:
fk_task_userid_user
fk_note_userid_user
因此,如果您添加一列来跟踪上次修改任务或注释的人......
fk_task_modifiedby_user
fk_note_modifiedby_user
Microsoft 关于 SQL Server 的说明:
外键约束不必只链接到 PRIMARY 另一个表中的 KEY 约束;它也可以定义为引用 另一个表中 UNIQUE 约束的列。
因此,我将使用描述依赖关系的术语,而不是传统的主要/外国关系术语。
当通过依赖(子)表中类似名称的列引用独立(父)表的 PRIMARY KEY 时,我省略了列名:
FK_ChildTable_ParentTable
引用其他列时,或者列名在两个表之间有所不同,或者只是为了显式:
FK_ChildTable_childColumn_ParentTable_parentColumn
评论
如果您不经常引用 FK 并使用 MySQL(和 InnoDB),那么您可以让 MySQL 为您命名 FK。
稍后,可以通过运行查询来查找所需的 FK 名称。
评论
我通常的做法是
FK_ColumnNameOfForeignKey_TableNameOfReference_ColumnNameOfReference
或者换句话说
FK_ChildColumnName_ParentTableName_ParentColumnName
这样,我就可以命名两个引用同一表的外键,例如 with from 表history_info table
column actionBy and actionTo
users_info
它会像
FK_actionBy_usersInfo_name - For actionBy
FK_actionTo_usersInfo_name - For actionTo
请注意:
我没有包含子表名称,因为这对我来说似乎是常识,我在子表中,所以我可以很容易地假设子表的名称。它的总字符数为 26 个字符,非常符合 Charles Burns 在此处的评论中所说的 oracle 的 30 个字符限制
读者须知:下面列出的许多最佳实践都不起作用 在 Oracle 中,因为它的名称限制为 30 个字符。表名或 列名可能已经接近 30 个字符,因此约定 将两者合并为一个名称需要截断标准或 其他技巧。——查尔斯·伯恩斯
评论
这可能有点矫枉过正,但它对我有用。当我处理VLDB时,它对我有很大帮助。我使用以下内容:
CONSTRAINT [FK_ChildTableName_ChildColName_ParentTableName_PrimaryKeyColName]
当然,如果由于某种原因您没有引用主键,则必须引用唯一约束中包含的列,在本例中:
CONSTRAINT [FK_ChildTableName_ChildColumnName_ParentTableName_ColumnInUniqueConstaintName]
可以很长吗,是的。它是否有助于保持报告信息清晰,或者让我快速了解潜在问题是在生产警报期间 100% 很想知道人们对这种命名约定的想法。
评论
FK_ChildTableName_ChildColumnName_ParentTableName_ColumnInUniqueConstaintName
尝试使用大写的版本 4 UUID,第一个八位字节替换为 FK 和“_”(下划线)而不是“-”(破折号)。
例如
FK_4VPO_K4S2_A6M1_RQLEYLT1VQYV
FK_1786_45A6_A17C_F158C0FB343E
FK_45A5_4CFA_84B0_E18906927B53
理由如下
- 严格的生成算法 => 个统一的名称;
- 密钥长度小于 30 个字符,这是 Oracle 中的命名长度限制(12c 之前);
- 如果您的实体名称发生了变化,则不需要像基于实体名称的方法那样重命名 FK(如果 DB 支持表重命名运算符);
- 人们很少使用外键约束的名称。例如,.DB 工具通常显示约束适用的内容。不用害怕神秘的外观,因为你可以避免用它来“解密”。
评论
sourcetable_targettable_uid
上一个:我应该对密码施加最大长度吗?
下一个:在字段名称周围使用反引号
评论