欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SQL Server解惑——对象命名的唯一性小结

程序员文章站 2022-04-16 09:24:39
关于SQL Server数据库中的对象命名的唯一性问题。例如表、索引、约束等数据库对象,有时候DBA在做数据库维护时,经常要创建对象或重命名对象,此时就会遇到一个问题,对象命名的唯一性问题。虽然是一个小小的问题,估计不少人搞不清,在看文章前,你可以先回答几个问题 1: 表名在数据库是不是唯一? 不同... ......

 

关于sql server数据库中的对象命名的唯一性问题。例如表、索引、约束等数据库对象,有时候dba在做数据库维护时,经常要创建对象或重命名对象,此时就会遇到一个问题,对象命名的唯一性问题。虽然是一个小小的问题,估计不少人搞不清,在看文章前,你可以先回答几个问题

 

1: 表名在数据库是不是唯一? 不同的schema下,是否可以存在同名的表?

 

2: 索引名在数据库是不是唯一? 不同的schema下,是否可以存在同名的表?

 

3: 其它数据库对象呢? 例如约束、触发器。

 

 

那么我们接下来看看实验例子吧,如下所示,adventureworks2014数据库中存在命名为production.product的表

 

use adventureworks2014;
go
select * from sys.objects where object_id =object_id('production.product')

 

 

此时创建同名的表,就与遇到there is already an object named 'product' in the database.这个错误。如下所示:

 

create table production.product
(
    name  nvarchar(32)
)

 

 

 

另外,如果我将这个表对象创建在默认的scheme(dbo)下面,那么这个是没有什么问题的。如下所示:

 

create table dbo.product
(
    name  nvarchar(32)
)

 

 

 

结论总结:表名在数据库是唯一,在同一个schema下,不允许存在相同的表名,但是不同的schema下,是可以存在同名的表。这个很好理解,现实生活中很多这样的例子,例如,大学寝室, 11栋宿舍楼有201命名的寝室, 13栋宿舍楼也有201命名的寝室。

 

下面我们生成'production.product'的脚本,然后修改一下表名为product_2020,执行脚本时就会遇到约束已经存在的错误提示(注意,不会一次性显示所有约束已经存在的错误提示)。

 

 

set ansi_nulls on
go
 
set quoted_identifier on
go
 
create table [production].[product_2020](
    [productid] [int] identity(1,1) not null,
    [name] [dbo].[name] not null,
    [productnumber] [nvarchar](25) not null,
    [makeflag] [dbo].[flag] not null constraint [df_product_makeflag]  default ((1)),
    [finishedgoodsflag] [dbo].[flag] not null constraint [df_product_finishedgoodsflag]  default ((1)),
    [color] [nvarchar](15) null,
    [safetystocklevel] [smallint] not null,
    [reorderpoint] [smallint] not null,
    [standardcost] [money] not null,
    [listprice] [money] not null,
    [size] [nvarchar](5) null,
    [sizeunitmeasurecode] [nchar](3) null,
    [weightunitmeasurecode] [nchar](3) null,
    [weight] [decimal](8, 2) null,
    [daystomanufacture] [int] not null,
    [productline] [nchar](2) null,
    [class] [nchar](2) null,
    [style] [nchar](2) null,
    [productsubcategoryid] [int] null,
    [productmodelid] [int] null,
    [sellstartdate] [datetime] not null,
    [sellenddate] [datetime] null,
    [discontinueddate] [datetime] null,
    [rowguid] [uniqueidentifier] rowguidcol  not null constraint [df_product_rowguid]  default (newid()),
    [modifieddate] [datetime] not null constraint [df_product_modifieddate]  default (getdate()),
 constraint [pk_product_productid] primary key clustered 
(
    [productid] asc
)with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on [primary]
) on [primary]
 
go

 

 

msg 2714, level 16, state 5, line 11

there is already an object named 'pk_product_productid' in the database.

msg 1750, level 16, state 0, line 11

could not create constraint or index. see previous errors.

 

 

如上所示,约束也是唯一的,它跟表名一样。而且也是跟schema有关系,如下所示,下面sql是ok的。

 

set ansi_nulls on
go
 
set quoted_identifier on
go
 
create table [dbo].[product_2020](
    [productid] [int] identity(1,1) not null,
    [name] [dbo].[name] not null,
    [productnumber] [nvarchar](25) not null,
    [makeflag] [dbo].[flag] not null constraint [df_product_makeflag]  default ((1)),
    [finishedgoodsflag] [dbo].[flag] not null constraint [df_product_finishedgoodsflag]  default ((1)),
    [color] [nvarchar](15) null,
    [safetystocklevel] [smallint] not null,
    [reorderpoint] [smallint] not null,
    [standardcost] [money] not null,
    [listprice] [money] not null,
    [size] [nvarchar](5) null,
    [sizeunitmeasurecode] [nchar](3) null,
    [weightunitmeasurecode] [nchar](3) null,
    [weight] [decimal](8, 2) null,
    [daystomanufacture] [int] not null,
    [productline] [nchar](2) null,
    [class] [nchar](2) null,
    [style] [nchar](2) null,
    [productsubcategoryid] [int] null,
    [productmodelid] [int] null,
    [sellstartdate] [datetime] not null,
    [sellenddate] [datetime] null,
    [discontinueddate] [datetime] null,
    [rowguid] [uniqueidentifier] rowguidcol  not null constraint [df_product_rowguid]  default (newid()),
    [modifieddate] [datetime] not null constraint [df_product_modifieddate]  default (getdate()),
 constraint [pk_product_productid] primary key clustered 
(
    [productid] asc
)with (pad_index = off, statistics_norecompute = off, ignore_dup_key = off, allow_row_locks = on, allow_page_locks = on) on [primary]
) on [primary]
 
go

 

 

结论:对于任何约束(主键约束、外键约束、默认约束等),在数据库中同一个schema下是唯一的,不允许存在相同的约束名称,但是不同的schema下,是可以存在同名的约束。

 

 

索引呢,你简单测试一下,就会有所发现情况有点不同。

 

 

 

use [adventureworks2014]
go
 
 
create unique nonclustered index [ak_product_rowguid] on [production].[product_2020]
(
    [rowguid] asc
)with (pad_index = off, statistics_norecompute = off, sort_in_tempdb = off, ignore_dup_key = off, drop_existing = off, online = off, allow_row_locks = on, allow_page_locks = on)
go

 

 

为什么索引对象的唯一性是跟前面表对象有所不同呢,这个说实话,实在没有看到详细介绍,只能怀疑是跟sql server官方的设定、限制有关系。

 

 

sql server中可以存在同名的索引吗? 如果是同一个表呢?

 

答案:不同的表,可以存在同名的索引,但是同一个表,不能存在同名的索引

 

 

对于触发器而言,它跟表名、约束一样的规则。 这里限于篇幅,就不展开了,有兴趣的自行测试一下。

 

 

下面将前面的知识用表格总结一下:

 

 

相同schema

不同schema

table

不能出现同名对象

可以出现同名对象

constraint

不能出现同名对象

可以出现同名对象

index

可以出现同名对象,但是同一个表,不能存在同名的索引

可以出现同名对象

trigger

不能出现同名对象

可以出现同名对象