1. 程式人生 > >到T-SQL DML 三級的階梯:在SQL server中實現關系模型

到T-SQL DML 三級的階梯:在SQL server中實現關系模型

有一個 records 建數據庫 外鍵約束 ast base 成功 還需要 lin

作者: Gregory Larsen, 2017/08/02 (第一次出版: 2011/11/09)

翻譯:謝雪妮,許雅莉,賴慧芳,劉瓊濱

譯文:

系列

該文章是階梯系列的一部分:T-SQL DML的階梯。

這個階梯將為您提供一個基本的理解,即如何使用SQL Server的翻譯 SQL(T- SQL)的方言和對SQL Server表格中的數據進行處理。DML是數據操縱語言,是處理數據的語言的方面。它包括語句選擇、插入、更新和刪除。這個階梯也將提供一些SQL語言的歷史和一些關於集合理論的一般概念。每一層都將建立在先前的水平之上,因此當您完成時,您將很好地了解如何從SQL Server中選擇和修改數據。

在上一級的樓梯上,我提供了關於基本選擇語句和SQL歷史的信息,這些級別為理解如何檢索數據以及SQL環境是如何演變的提供了基礎,因為技術和技術解決方案已經改變了超時工作。在這個級別,我將探索如何實現基於關系模型的簡單SQL Server數據庫。在開始創建數據庫之前,首先讓我介紹一下關系模型的創建者的一些歷史。

關系數據建模之父

關系數據庫設計的概念首先由Edgar F提出。. 在1970年,Codd發表論文的標題為“大型共享數據銀行的數據關系模型”。 Codd在IBM工作時開發了這種建模理論。BM在Codd的數據建模概念上跳得不夠快,因此並不是第一個供應關系數據庫引擎的供應商,它利用了Codd的新關系數據建模理論。Codd的關系建模概念現在是用來在SQL Server和其他關系數據庫引擎中創建關系數據庫的框架。Codd出生於英格蘭的波特蘭島,在加入皇家空軍之前學習了數學和化學,成為了第二次世界大戰的飛行員1948年,他搬到紐約,開始在IBM工作,在那裏他是一名數學程序員。他漂流了好幾年,最終搬到加州,在IBM聖何塞研究實驗室工作。直到20世紀90年代,當他的健康狀況不佳迫使他退休時,Codd繼續努力完善並證明了關系數據模型的合理性。2003年4月18日,Codd去世,享年79歲。

在SQL Server中實現關系模型

這個階梯不是用來教你關系數據建模,或數據庫設計,而是教你如何從一個關系模型創建一個SQL Server數據庫。但是在我為創建SQL Server數據庫提供代碼塊之前,我們首先需要探索一個將被實現的關系數據模型。我的簡單模型將包含一些實體(數據表),其中有主鍵定義和不同實體之間的一些關系(外鍵約束)。

我的簡單的關系模型將是一個簡單的酒店預訂系統。這個預訂系統需要跟蹤客戶預訂信息。圖1說明了這個簡單的關系模型,我將使用t - sql實現它:

技術分享

通過回顧這個模型,您可以看到它包含許多實體(由方框表示)來跟蹤預訂相關信息。每個實體都由一些屬性(列)組成,其中一個或多個屬性被標識為主鍵(粗體和下劃線的名稱)。也表示實體之間的一些關系(以箭頭表示),以顯示不同的實體之間是如何相互關聯的。我將使用實體、屬性、主鍵和關系的模型,然後開發一個物理SQL Server數據庫,它表示此關系模型的設計。要從這個模型構建物理數據庫,我們需要在SQL Server中識別基於此模型定義的不同對象。對於圖1中的每個實體或框,我將在SQL Server中創建一個表。對於每個實體的每個屬性,我將在關聯的表中創建一個列。對於每個主鍵,我將創建一個唯一的集群索引(註意,使用唯一的非聚集索引也可以創建主鍵)。有關索引的更多信息,請參見http://www .sqlservercentral.com/stairway/72399/).。最後,對於每個關系,我將創建一個外鍵約束。要開始構建我的數據庫,我首先需要創建一個SQL Server數據庫來保存我計劃創建的所有新數據庫對象。我的數據庫將被稱為房間預訂。我將使用以下的t - sql代碼創建我的數據庫

CREATE DATABASE RoomReservation;


要從我的模型中開始構建我的房間預訂數據庫對象,我將創建表對象。要在sql server中創建一個表,我需要使用創建表語句。通過創建表語句,我將能夠定義每個表中的每個表和所有列。下面是創建SQL Server表的簡單語法

CREATE TABLE <table_name> (
<column_definition> [,…N]);

Where:

<table_name> = Name of table
<column_definition> = column_name data_type,[NULL | NOT NULL]

For complete syntax of the CREATE TABLE statement refer to SQL Server Books Online.

The first table I create will be the Customer table, created using the code in Listing 1.

USE RoomReservation;
GO
CREATE TABLE dbo.Customer (
	CustomerId INT NOT NULL,
	FirstName NVARCHAR(50) NOT NULL, 
	LastName NVARCHAR(50) NOT NULL,
	Address1 NVARCHAR(100) NOT NULL, 
	Address2 NVARCHAR(100) NULL,
	PhoneNumber NVARCHAR(22) NOT NULL, 
	EmailAddress VARCHAR(100) NULL, 
	City VARCHAR(100) NOT NULL,
	StateProvince NVARCHAR(100) NOT NULL,
	PostalCode NVARCHAR(100) NOT NULL);

清單1:創建Customer表

在這段代碼中,當我創建我的Customer表時,我創建了我需要的所有列,但我還指定了在插入或更新記錄時,該列是否需要一個值。我通過在某些列上指定非空值來實現這一點,而其他列則指定為空值。

如果一個列被定義為不為空,那意味著你不能創建一個記錄,除非你用一個實際值填充這個列。而使用空值規範定義一個列意味著您可以創建一行,而不必為這個列指定一個值,或者另一種方法是,該列允許空值。我在創建表的語句上面我允許列地址2和郵箱地址支持空值,而所有其他的柱子需要值將提供創建一個行時。

這個創建表語句並沒有完全定義我的客戶表,因為它是在我上面的關系數據庫模型中表示的。我還需要創建一個主鍵約束的列ID。這個主鍵約束將確保該表中沒有兩個記錄具有相同的客戶編號碼的值。這個主鍵約束將確保該表中沒有兩個記錄具有相同的客戶編號碼的值。創建主鍵的代碼如清單2所示

USE RoomReservation;
GO
CREATE TABLE dbo.Customer (
	CustomerId INT NOT NULL CONSTRAINT PK_Customer PRIMARY KEY,
	FirstName NVARCHAR(50) NOT NULL, 
	LastName NVARCHAR(50) NOT NULL,
	Address1 NVARCHAR(100) NOT NULL, 
	Address2 NVARCHAR(100) NULL,
	PhoneNumber NVARCHAR(22) NOT NULL, 
	EmailAddress NVARCHAR(100) NULL, 
	City VARCHAR(100) NOT NULL,
	StateProvince NVARCHAR(100) NOT NULL,
	PostalCode NVARCHAR(100) NOT NULL);

清單2:向客戶表添加主鍵約束
此表語句向客戶表添加了主鍵約束。該主鍵將在聚集索引命名pk_customer窗體的創建。在翻譯SQL語言中,通常有不止一種方法來做同樣的事情。另外,我可以通過運行清單3中的創建表語句一次性創建我的客戶表和主鍵。

USE RoomReservation;
GO
CREATE TABLE dbo.Customer (
	CustomerId INT NOT NULL CONSTRAINT PK_Customer PRIMARY KEY,
	FirstName NVARCHAR(50) NOT NULL, 
	LastName NVARCHAR(50) NOT NULL,
	Address1 NVARCHAR(100) NOT NULL, 
	Address2 NVARCHAR(100) NULL,
	PhoneNumber NVARCHAR(22) NOT NULL, 
	EmailAddress NVARCHAR(100) NULL, 
	City VARCHAR(100) NOT NULL,
	StateProvince NVARCHAR(100) NOT NULL,
	PostalCode NVARCHAR(100) NOT NULL);
清單3:用主鍵創建客戶表的另一種方法
在這一點上,我已經向您展示了如何創建具有定義主鍵的表。唯一要展示給您的是如何創建外鍵約束。但在此之前,讓我先向您提供創建上述關系數據庫模型中其余表和主鍵的腳本。您可以在清單4中找到它。
USE RoomReservation;
GO

CREATE TABLE dbo.Reservation (
	ReservationId INT NOT NULL, 
	ArrivalDate DATETIME NOT NULL,
	DepartureDate DATETIME NOT NULL,
	DailyRate SMALLMONEY NOT NULL,
	ReservationStatusID INT NOT NULL,
	CustomerId INT NOT NULL, 
	RoomTypeID INT NOT NULL);
	
ALTER TABLE dbo.Reservation ADD CONSTRAINT
    PK_Reservation PRIMARY KEY CLUSTERED (ReservationId);
	
CREATE TABLE dbo.RoomType (
	RoomTypeId INT NOT NULL,
	RoomDesc NVARCHAR(1000) NOT NULL); 
	
ALTER TABLE dbo.RoomType ADD CONSTRAINT
    PK_RoomType PRIMARY KEY CLUSTERED (RoomTypeId);

CREATE TABLE dbo.ReservationStatus (
	ReservationStatusId INT NOT NULL, 
	ReservationStatusDesc NVARCHAR(50) NOT NULL);

ALTER TABLE dbo.ReservationStatus ADD CONSTRAINT
    PK_ReservationStatus PRIMARY KEY CLUSTERED (ReservationStatusId);
	
CREATE TABLE dbo.PaymentType (
	PaymentTypeId INT NOT NULL, 
	PaymentTypeDesc NVARCHAR(50) NOT NULL); 

ALTER TABLE dbo.PaymentType ADD CONSTRAINT
    PK_PaymentType PRIMARY KEY CLUSTERED (PaymentTypeId);

CREATE TABLE dbo.CustomerPaymentType (
	PaymentTypeId INT NOT NULL, 
	CustomerId INT NOT NULL, 
	PaymentNotes NVARCHAR(2000) NULL);

ALTER TABLE dbo.CustomerPaymentType ADD CONSTRAINT
    PK_CustomerPaymentType PRIMARY KEY CLUSTERED (PaymentTypeId, CustomerId);

清單4:創建額外的表和主鍵約束

一個外鍵約束在兩個相互關聯的表之間強制引用完整性。外鍵約束定義的表是“引用表”,需要在另一個表中有相關的記錄,稱為“引用”表,任何時候在表中插入或更新一行。在圖1的關系模型中,這些外鍵關系由箭頭表示。外鍵約束只在關系中的一個表上定義。在我的圖表中,外鍵約束將定義在具有箭頭尾部(無尖端)的那些表上。

為了在關系模型中定義這些外鍵約束,我需要修改每個引用表來添加約束。清單5是我可以用來在保留表上創建外鍵約束的t - sql代碼。這個約束確保記錄不會被插入或更新到預訂表中,除非在顧客表中基於客戶編號找到匹配的記錄。

USE RoomReservation;
GO
ALTER TABLE dbo.Reservation
ADD CONSTRAINT FK_Reservation_CustomerPaymentType FOREIGN KEY (CustomerId)
    REFERENCES dbo.Customer (CustomerID);


清單5:在引用客戶表的預訂表上創建一個外鍵約束
為了完成我的設計,我需要實現其他所有外鍵約束的圖1在我的模型識別。清單6包含了在我的數據模型中創建額外外鍵約束的變更表語句。

USE RoomReservation;
GO
ALTER TABLE dbo.Reservation
ADD CONSTRAINT FK_Reservation_CustomerPaymentType FOREIGN KEY (CustomerId)
    REFERENCES dbo.Customer (CustomerID);
清單6:創建額外的外鍵限制

驗證數據庫的設計

一旦我完成了從數據模型構建數據庫的工作,我應該驗證所實現的設計,以確保它是正確的。這個驗證過程是確保我在物理數據庫中構建的所有數據完整性規則都正確地實現了。在我的設計中,我需要驗證這些規則。

所有插入或更新的行必須對定義為非空值的列有一個特定的值。

主鍵的列不允許重復的值。

具有外鍵約束因素的列不允許在引用表中沒有匹配記錄的數據。

驗證數據完整性規則之前,我首先需要用一些有效數據填充引用的表。我將使用清單7中的代碼來填充那些有一些有效數據的表:

SET NOCOUNT ON;
-- Create PaymentType records
INSERT INTO PaymentType VALUES(1,‘Visa‘);
INSERT INTO PaymentType VALUES(2,‘MasterCard‘);
INSERT INTO PaymentType VALUES(3,‘American Express‘);
-- Create Customer 
INSERT INTO Customer VALUES 
    (1,‘Greg‘,‘Larsen‘,‘123 Some Place‘
      ,NULL,‘123-456-7890‘,Null,‘MyCity‘,‘MA‘,‘12345‘);
-- Create Reservation Status
INSERT INTO ReservationStatus VALUES (1,‘Booked‘);
INSERT INTO ReservationStatus VALUES (2,‘Cancelled‘);
-- Create Room Type
INSERT INTO RoomType VALUES (1,‘Kingsize‘);
INSERT INTO RoomType VALUES (2,‘Queen‘);
INSERT INTO RoomType VALUES
清單7:插入初始數據

為了驗證我在數據庫中構建的數據完整性規則,我將運行清單8中的INSERT語句。

USE RoomReservation;
GO
-- Violates NOT NULL constraint
INSERT INTO Reservation VALUES(1,‘2011-8-1 5:00 PM‘
                                ,‘2011-8-2 9:00 AM‘ 
                                , 150.99,1,1,1);                                                                                                                                                          
-- Violates Primary Key Constraint
INSERT INTO RoomType VALUES (4,‘Suite‘);  
-- Violates Foreign Key Constraint
INSERT INTO CustomerPaymentType VALUES (1,1,‘Will need an internet connection‘);
清單8:用INSERT語句測試各種約束

這些INSERT語句中的每一個都應該失敗,因為它們違反了構建在訂房數據庫中的數據完整性規則。第一個INSERT語句違反了預訂規則列的非空驗證檢查。

第二個INSERT語句違反了放在房間類型表上的主鍵約束。這個INSERT語句試圖為房間類型編號的列插入3的值。問題是在房間類型值為3的房間類型表中已經有了記錄。

最後一個INSERT語句違反了顧客繳費方式表的外鍵約束。在這個特殊的INSERT語句中,顧客表中沒有客戶編號值為2的值。

要正確地插入這些記錄,插入的數據值需要清理。一旦數據被清理幹凈,我就可以將這些新數據插入到合適的表中。清單9包含清除所有數據完整性檢查並成功插入到房間預訂數據庫中的適當表的清理INSERT語句:

USE RoomReservation;
GO
-- Violates NOT NULL constraint
INSERT INTO Reservation VALUES(1,‘2011-8-1 5:00 PM‘
                                ,‘2011-8-2 9:00 AM‘ 
                                , 150.99,1,1,1);                                                                                                                                                          
-- Violates Primary Key Constraint
INSERT INTO RoomType VALUES (4,‘Suite‘);  
-- Violates Foreign Key Constraint
INSERT INTO CustomerPaymentType 


清單9:附加約束測試
 

關系數據庫設計

我的預訂示例演示了如何使用關系模型並使用它來實現SQL Server數據庫。通過使用非空值、主鍵和外鍵完整性約束,我將數據完整性規則構建到數據庫設計中。這允許我在底層數據庫定義中執行這些規則,而不必在業務處理層中編寫代碼來驗證這些數據規則。通過這樣做,我允許SQL Server數據庫引擎為我執行這些數據完整性檢查。

通過了解並在關系數據庫模型周圍創建數據庫設計,您將構建一個健壯且高效的數據庫實現,您可以在數據庫中構建數據完整性檢查。

到T-SQL DML 三級的階梯:在SQL server中實現關系模型