正确命名表的id字段

时间:2010-11-21 20:57:37

标签: sql database database-design data-modeling

我目前正在阅读Joe Celko撰写的“SQL Programming Style”一书。

在第一章的“开发标准化后缀”一节中,他列出了id列:

  

“_ id”=标识符。它是独一无二的   模式并引用一个实体   它出现在架构中的任何位置。   永远不要使用“> table_name< _id”

之后几页他说

  

不要使用下划线作为第一个   或姓名中的最后一个字母。它看起来   喜欢这个名字是另一个   成分

他弃用了“id”作为列名。

所以我想知道你们是如何命名id列的?

我知道大多数人可能会想到这个问题的重点,但我正在考虑标准化我的数据模型,尽可能遵循行业标准和ISO标准。

8 个答案:

答案 0 :(得分:3)

我也不赞成使用“Id”作为列名,尽管它已经变得非常普遍。 “EmployeeId”比“Id”长,但它更具描述性。它还允许外键通常具有与其引用的列相同的名称。当对数据库的控制从一个人传递到另一个人时,这非常有用。

上述情况有例外。在同一个表中可以有两个外键,它们都引用相同的键。也可以使用反身外键引用它出现在同一个表的不同行中的键。

让我举一个反身键的例子。您有一个员工表,其中包含关键的EmployeeId。您有另一个名为SupervisorId的列,它记录了主管和多个下级之间的关系。在这种情况下,外键的名称是角色,而不是实体。

作为替代方案,可以使用用户定义的域来记录两列引用相同内容的事实。同样,当数据的基本含义必须传达给新的人时,这是最有用的。

在符号中使用下划线作为内部可视分隔符是一个完全可分的问题。 Camelcasing比下划线更广泛,甚至有一些系统不允许下划线作为符号组成。

最重要的是,保持一致。如果你使用任意的,反复无常的,矛盾的命名惯例,你最终会让自己感到困惑。

答案 1 :(得分:2)

我认为这是一个很好的问题。做什么看起来对你好,并且每次都这样做。那你就没事了。

我使用tablename +'id'模型:UserId,PersonId等。

答案 2 :(得分:1)

对于表ID,我总是使用tablename + ID。

这样做的原因是当它是1对1映射时避免查询中的模糊列名称

有时我会快速编写sql来测试这样的

Select
  * 
FROM table1
Inner join table2 on table1ID = table2ID

如果我没有在ID列中使用tablename,那么这会抛出一个错误(迫使我在表上使用别名)

Select
  * 
FROM table1
Inner join table2 on ID = ID

使用表名的另一个好理由是,在一般测试查询中查看存在哪些数据时使用“*”来选择列。如果你进行连接和选择*,有时候很难理解哪个ID来自哪个表,特别是如果你从2个以上的表中返回大量的列

答案 3 :(得分:1)

我一直倡导全球唯一的TABLENAME_ID。在这方面,我强烈鼓励完全描述其上下文的表名,因此在进行外来引用时,它们的应用程序永远不会有任何歧义。

答案 4 :(得分:1)

我会尝试回答你的问题;而不是分享我对命名标准的看法;)

我认为Celko的观点是学生表中的student_ID是一种代码味道,即设计师的风格可能是总是将ID列(可能是自动增量列)添加到他们创建的每个表中在物理模型中(即使逻辑模型中没有这样的列),打算将这些ID列用于外键。换句话说,Celko不希望你总是使用代理键,而是希望你在适当的时候使用自然键。

如果您继续阅读第1.2.5节(第14-15页)并遵循他的表名规则,您将发现为什么表名+ _ID不太可能发生:

  

如果我找不到行业标准   (姓名),我会找一个集体   或类名...例外:使用a   如果表实际上是奇异名称   其中只有一行。

因此,例如,如果您有一个包含学生数据的表,它可能被称为学生而不是学生,但更有可能是注册(或类似)。并且包含一行且只有一行的表不太可能需要_ID列。

我认为有些名词的复数与单数相同所以也许Sheep_ID是可以接受的(但是当然没有行业标准的羊标识符!)

同时考虑规则1.3.2。 (第19页)避免名称从一个地方变为另一个地方,例如相同的域在Students表中称为ID,在其他表中称为student_ID。在整个模式中不太可能只有一个名为_ID的元素!

答案 5 :(得分:0)

ID作为列名很难维护,在我看来更容易导致连接错误。

假设您总是在每个表中使用ID作为列名。

现在假设您需要加入其中六个表。作为一个典型的人,您复制第一个连接并更改表名。如果你错过了一个,并且你使用id,你将得到一个运行的查询并给出错误的anaswer。如果使用tablenameId,则会出现语法错误。请参阅以下代码以获取示例:

create table #test1 (id int identity, test varchar(10))
create table #test2 (id int identity, test varchar(10))
create table #test3 (id int identity, test varchar(10))

insert #test1
values ('hi')
insert #test1
values ('hello')
insert #test2
values ('hi there')
insert #test3
values ('hello')
insert #test3
values ('hi')
select * 
from #test1 t1
join #test2 t2
    on t1.id = t2.id
join #test3  t3
    on t1.id = t2.id    
select * 
from #test1 t1
join #test2 t2
    on t1.id = t2.id
join #test3  t3
    on t1.id = t3.id        

Drop table #test1
drop table #test2
drop table #test3   
Go

create table #test1 (t1id int identity, test varchar(10))
create table #test2 (t2id int identity, test varchar(10))
create table #test3 (t3id int identity, test varchar(10))   


    insert #test1
    values ('hi')
    insert #test1
    values ('hello')
    insert #test2
    values ('hi there')
    insert #test3
    values ('hello')
    insert #test3
    values ('hi')

select * 
from #test1 t1
join #test2 t2
    on t1.t1id = t2.t2id
join #test3 t3
    on t1.t1id = t3.t3id    

select * 
from #test1 t1
join #test2 t2
    on t1.t1id = t2.t2id
join #test3 t3
    on t1.t1id = t2.t3id    

    Drop table #test1
    drop table #test2
    drop table #test3   

使用tablenameId的另一个问题是,当您想要复杂报表查询中的多个表的实际ID时,您不必创建别名以查看哪个ID来自哪里(并使报表应用程序感到满意)因为他们中的大多数都在报告的唯一字段名中。

答案 6 :(得分:0)

哇,我打算写“我总是使用TablenameID,但世界上其他人都不同意我”。但是,看起来每个人都同意我的意见。

当然,当我在表中使用代理整数ID时。如果有一个自然的主键,我会使用它。

答案 7 :(得分:0)

在我的数据库中:

对于外键ID,我使用外来表名+“Id”的单数形式。我使用大写字母I,因为它是FX警察根深蒂固的标准。

对于自动递增身份,我经常使用“SequenceId”

在我的数据层中:

我使用对象的名称+“Id”,遵循“Id”的最佳实践标准