SQL Server解惑——對象命名的唯一性小結


 

關於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)
)

 

clip_image001

 

 

另外,如果我將這個表對象創建在默認的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

不能出現同名對象

可以出現同名對象


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM