外文转译:通过楼梯到T-SQL DML等级3:在SQL Server中实现关系模型

从楼梯到T-SQL DML等级3SQL Server中实现关系模型

作者:Gregory Larsen 2017/08/02(第一次发布:2011/11/09

使用SQL Server的Transact-SQL(T-SQL)方言,此楼梯将为您提供如何使用SQL Server表中的数据的基本了解。DML是数据操作语言,是处理数据的语言的一个方面。它包括SELECT,INSERT,UPDATE和DELETE语句。这个楼梯还将提供SQL语言的一些历史和关于集合理论的一些一般概念。每个级别都将建立在先前的级别上,所以在完成之后,您将很好地了解如何从SQL Server中选择和修改数据。

在此楼梯的以前级别中,我向您提供了有关基本SELECT语句和SQL历史的信息。这些级别为您提供了理解如何检索数据的基础,以及随着技术和技术解决方案已经超时而改变了SQL环境的发展。在这个级别中,我将探索如何实现基于关系模型的简单SQL Server数据库。在创建数据库之前,首先让我分享关于关系模型创建者的一些历史。

关系数据建模之父

关系数据库设计的概念由Edgar F. Codd于1970年首次引入,题为“大型共享数据库数据的关系模型”。Codd在IBM工作时开发了这种建模理论。IBM对Codd的数据建模概念没有足够快的速度,因此不是首先提供利用Codd新关系数据建模理论的关系数据库引擎的供应商。Codd的关系建模概念现在是用于在SQL Server和其他关系数据库引擎中创建关系数据库的框架。

Codd出生于英国的波特兰岛,并在加入皇家空军之前先后读数学和化学,成为二战的飞行员。他在1948年搬到纽约,开始为IBM工作,在那里他是一名数学程序员。他浮出了若干年,最后搬到了加利福尼亚州的IBM San Jose研究实验室工作。Codd继续努力改进和证明关系数据模型的正当性,直到20世纪90年代,他的失败的健康迫使他退休。埃德加·科德德于2003年4月18日死于79岁。

SQL Server中实现关系模型

这个楼梯不是教你关系数据建模或数据库设计,而只是向你展示如何从关系模型创建一个SQL Server数据库。但是,在我可以为您提供创建SQL Server数据库的代码块之前,我们首先需要探索将要实现的关系数据模型。我的简单模型将包含一些具有主键定义的实体(数据表)和不同实体之间的一些关系(外键约束)。

我简单的关系模式将是一个简单的酒店预订系统。该预订系统将需要跟踪客户预约信息。图1说明了我将使用T-SQL实现的简单关系模型:

1:一个简单的关系数据库模型,由6个表组成

通过查看此模型,您可以看到它包含一些实体(由框表示)来跟踪预留相关信息。每个实体由一些属性(列)组成,其中一个或多个属性被标识为主键(粗体和带下划线的名称)。还表示了实体(由箭头表示)之间的一些关系,其示出了不同实体如何彼此相关。我将使用这种模型的实体,属性,主键和关系,然后开发一个表示该关系模型设计的物理SQL Server数据库。

要从此模型构建物理数据库,我们需要根据此模型识别SQL Server中将要定义的不同对象。对于图1中的每个实体或框,我将在SQL Server中创建一个表。对于每个实体的每个属性,我将在关联的表中创建一个列。对于每个主键,我将创建一个唯一的聚簇索引(注意,主键也可以使用唯一的非聚集索引创建。有关索引的更多信息,请参阅索引楼梯http://www.sqlservercentral.com /楼梯/ 72399 /)。最后,对于每个关系,我将创建一个外键约束。

要开始构建数据库,我首先需要创建一个SQL Server数据库来保存我计划创建的所有新的数据库对象。我的数据库将被称为RoomReservation。我将使用以下T-SQL代码创建我的数据库:

创建数据库RoomReservation ;

要从我的模型开始构建我的RoomReservation数据库对象,我将创建表对象。要在SQL Server中创建表,我需要使用CREATE TABLE语句。使用CREATE TABLE语句,我将能够定义每个表和每个表中的所有列。以下是创建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

在这段代码中,当我创建了我的客户表时,我创建了我需要的所有列,但是我也指定了当这个表中插入或更新记录时,列是否需要一个值。我通过在某些列上指定NOT NULL来实现,而其他列我指定了NULL

如果列被定义为NOT NULL,这意味着您无法创建记录,除非您使用实际值填充此列。而使用NULL规范定义列表意味着您可以创建一行而不指定此列的值,或者另一种方法是列允许NULL值。在我上面的CREATE TABLE语句中,我允许列Address2EmailAddress支持NULL,而其余所有列需要在创建行时提供一个值。

此CREATE TABLE语句没有完全定义我的Customer表,因为它在上面的关系数据库模型中表示。我仍然需要在CustomerID列上创建一个主键约束此主键约束将确保此表中没有两个记录具有相同的CustomerID值。创建该主键的代码在清单2中。

USE RoomReservation;

GO

ALTER TABLE dbo.Customer ADD CONSTRAINT

     PK_Customer PRIMARY KEY CLUSTERED (CustomerId);

清单2:将一个PRIMARY KEY约束添加到Customer

此ALTER TABLE语句向我的C ustome r表添加了一个主键约束。该主键将以名为PK_Customer的聚簇索引的形式创建

在Transact-SQL语言中,通常有多种方法来做同样的事情。或者,我可以通过运行清单3中的CREATE TABLE语句一次创建我的Customer表和主键。

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:使用PRIMARY KEY 创建Customer表的另一种方法

在这一点上,我已经向您展示了如何使用定义的PRIMARY KEY创建表。唯一可以告诉你的是如何创建FOREIGN KEY约束。但在我可以这样做之前,让我首先提供您在上面的关系数据库模型中创建其余表和PRIMARY KEYS的脚本。你可以在清单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:创建附加表和PRIMARY KEY约束

FOREIGN KEY约束强制相互相关的两个表之间的引用完整性。定义外键约束的表是“引用表”,并且需要在另一个表中具有相关记录,称为“引用”表,任何时候在表中插入或更新行。。在图1的关系模型中,这些外键关系用箭头表示。FOREIGN KEY约束仅在关系中的一个表上定义。在我的图中,FOREIGN KEY约束将被定义在附加了箭头尾端(非尖端)的那些表上。

要在我的关系模型中定义这些FOREIGN KEY约束条件,我将需要更改每个引用表来添加约束。清单5是可用于在“ 预留表上创建FOREIGN KEY约束的T-SQL代码。此约束确保在“ 预留表中不会插入或更新记录,除非在Customer表中基于CustomerId找到匹配的记录。

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

 

   

清单5:在 引用Customer表的Reservation表上创建FOREIGN KEY约束

为了完成我的设计,我需要实现在图1中我的模型中识别的所有其他外键constings。清单6包含在我的数据模型中创建附加外键约束的ALTER TABLE语句。

USE RoomReservation;
GO
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 (3,'Double');

 

      

清单6:创建附加的FOREIGN KEY约束

验证数据库设计

一旦我完成了从数据模型构建数据库,我应该验证实现的设计,以确保它是正确的。此验证过程是确保我内置到我的物理数据库中的所有数据完整性规则正确实施。在我的设计中,我需要验证的规则

  • 插入或更新的所有行必须为定义为NOT NULL的任何列定义特定的值。
  • PRIMARY KEY的 列不允许重复的值
  • 具有外键常量的列不允许在引用的表中没有匹配记录的数据

在我可以验证数据完整性规则之前,我首先需要使用一些有效的数据填充引用的表。我将使用清单7中的代码来填充这些表与一些有效的数据:

USE RoomReservation;
GO
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 (3,'Double');

                             

清单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,NULL,1,1);                                                                                                                                                          
-- Violates Primary Key Constraint
INSERT INTO RoomType VALUES (3,'Suite');  
-- Violates Foreign Key Constraint
INSERT INTO CustomerPaymentType VALUES (1,2,'Will need an internet connection');

 

清单8:使用INSERT语句测试各种约束

这些INSERT语句中的每一个都应该失败,因为它们违反了在RoomReservation数据库中内置的数据完整性规则。第一个INSERT 语句违反了Reservat io nStatusID列的NOT NULL验证检查。

第二个INSERT 语句违反了放置在RoomType表上的PRIMARY KEY约束。此INSERT语句正在尝试为RoomTypeID列插入3的值。这个问题已经存在了创纪录的RoomTyp使用电子表格RoomTypeID值为3。

最后一个INSERT 语句违反了CustomerPaymentType表的FOREIGN KEY约束。在这个特定的INSERT语句没有客户ID与值2客户表。

要正确插入这些记录,插入的数据值将需要清理。一旦数据清理完毕,我将能够将这些新数据插入相应的表格。清单9包含清理的INSERT语句,它将传递所有数据完整性检查,并成功插入到RoomReservation数据库中的相应表中:

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');

清单9:附加约束测试

关系数据库设计

我的预订示例演示了如何使用关系模型并使用它来实现SQL Server数据库。通过使用NOT NULL,PRIMARY KEY和FOREIGN KEY constaints,我将数据完整性规则直接构建到我的数据库设计中。这允许我在底层数据库定义中强制执行这些规则,而不必在我的业务处理层中编写代码来验证这些数据规则。通过这样做,我允许SQL Server数据库引擎为我执行这些数据完整性检查。

通过围绕关系数据库模型了解和创建数据库设计,您将构建一个强大而高效的数据库实现,您可以在其中构建数据库中的数据完整性检查。

 

本文是 T-SQL DML楼梯楼梯的一部分

本文转译于Gregory Larsen的楼梯系列中的“从楼梯到T-SQL DML等级3SQL Server中实现关系模型”

原文链接:http://www.sqlservercentral.com/articles/Stairway+Series/75775/

 

posted on 2017-10-17 17:02  fenglianchen  阅读(155)  评论(0编辑  收藏  举报

导航