Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 正确命名表的id字段_Sql_Database_Database Design_Data Modeling - Fatal编程技术网

Sql 正确命名表的id字段

Sql 正确命名表的id字段,sql,database,database-design,data-modeling,Sql,Database,Database Design,Data Modeling,我目前正在读Joe Celko写的《SQL编程风格》一书 在第一章中,在“开发标准化后缀”一段中,他为id列指出: “_id”=标识符。它在中国是独一无二的 模式和引用一个实体 它出现在模式中的任何位置。 从不使用“>table_name对于表ID,我总是使用tablename+ID 这样做的原因是,当查询是1对1映射时,可以避免查询中出现不明确的列名 有时我会像这样快速编写sql来进行测试 Select * FROM table1 Inner join table2 on table1I

我目前正在读Joe Celko写的《SQL编程风格》一书

在第一章中,在“开发标准化后缀”一段中,他为id列指出:

“_id”=标识符。它在中国是独一无二的 模式和引用一个实体 它出现在模式中的任何位置。
从不使用“>table_name对于表ID,我总是使用tablename+ID

这样做的原因是,当查询是1对1映射时,可以避免查询中出现不明确的列名

有时我会像这样快速编写sql来进行测试

Select
  * 
FROM table1
Inner join table2 on table1ID = table2ID
如果我没有在ID列中使用tablename,那么这将抛出一个错误(强制我在表上使用别名)


使用表名的另一个很好的理由是,在测试查询以查看存在哪些数据时,使用“*“选择列。如果执行联接并选择*,有时很难理解哪个ID来自哪个表,特别是如果从两个以上的表返回大量列,我认为这是一个好问题。做你觉得好的事,每次都要这样做。那你就没事了


我使用tablename+‘id’模型:UserId、PersonId等。

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

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

让我举一个自反键的例子。您有一个包含关键EmployeeId的员工表。您还有另一个列,名为SupervisorId,它记录了一个主管和多个子心系之间的关系。在本例中,外键的名称命名角色,而不是实体

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

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


最重要的是,保持一致。如果您使用任意、反复无常和相互矛盾的命名约定,最终甚至会混淆您自己。

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

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

现在假设您需要连接到其中的六个表。作为一个典型的人,您需要复制第一个联接并更改表名。如果您错过了一个,并且您使用了id,您将得到一个运行的查询,并且给出了错误的答案。如果使用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来自何处(并使报表应用程序满意,因为大多数id都位于报表的唯一字段名上)

我一直提倡全局唯一的TABLENAME\u ID。在这一点上,我强烈建议使用能够充分描述其上下文的表名,这样在进行外部引用时,它们的应用就不会有任何歧义。

哇,我想写“我总是使用TablenameID,但世界上其他人都不同意我”。然而,这里的每个人似乎都同意我的观点


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

在我的数据库中:

对于外键ID,我使用外键表名+ID的单数版本。我使用大写字母I,降低d,因为这是FX cop在我心中根深蒂固的标准

对于自动递增标识,我经常使用“SequenceId”

在我的数据层中:


我使用对象的名称+“Id”,遵循“Id”的最佳实践标准,而不是分享我对命名标准的看法,我将尝试回答您的问题;)

我认为Celko的观点是,学生表中的学生ID是一种代码气味,也就是说,设计师的风格可能是总是在物理模型中创建的每个表中添加一个ID列,可能是一个自动递增列(即使逻辑模型中没有这样的列)目的是将这些ID列用于外键。换句话说,Celko不希望您总是使用代理键,而是希望您在适当的情况下使用自然键

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

如果我找不到行业标准 (姓名),我会寻找一个集体 或类名。。。例外情况:使用 单数名称,如果表实际 有一行,而且只有一行

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

我想有些名词的复数形式与单数形式相同,因此可能可以接受Sheep_ID(当然,只有在没有行业标准的绵羊标识符的情况下!)

也要考虑规则1.3.2。(第19页)避免名称因地而异,例如所引用的同一域名

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