第3章 SQL Server表

3.1. 表的概念
表是包含数据库中所有数据的数据库对象。表定义是一个列集合。数据在表中的组织方式与在电子表格中相似,都是按行和列的格式组织的。每一行代表一条唯一的记录,每一列代表记录中的一个字段。例如,在包含公司雇员数据的表中,每一行代表一名雇员,各列分别代表该雇员的信息,如雇员编号、姓名、地址、职位以及家庭电话号码等。
表包括下列主要组件:
 列
每一列代表由表建模的对象的某个属性,例如,一个部件表有 ID 列、颜色列和重量列。
 行
每一行代表由表建模的对象的一个单独的实例。例如,公司运送的每个部件在部件表中均占一行。
下图显示了 AdventureWorks 示例数据库中的 HumanResources.Department 表。

3.2. 数据完整性
指定表域的第一步是确定列数据类型。域是列中允许的值的集合。域不仅包括强制数据类型的概念,还包括列中允许的值。例如,Production.Product 表中的 Color 列的域包括 nvarchar 数据类型和大小限制(15 个字符)。该域还可指定列中所允许的字符串,如 Red、Blue、Green、Yellow、Brown、Black、White、Teal、Gray 和 Silver。
空值
列可以接受空值,也可以拒绝空值。在数据库中,NULL 是一个特殊值,表示未知值的概念。NULL 不同于空字符或 0。实际上,空字符是一个有效的字符,0 是一个有效的数字。NULL 只是表示此值未知这一概念。NULL 也不同于零长度字符串。如果列定义中包含 NOT NULL 子句,则不能为该行插入值为 NULL 的行。如果列定义中仅包含 NULL 关键字,则接受 NULL 值。
列中允许 NULL 值可以增加使用该列的所有逻辑比较的复杂程度。SQL-92 标准规定:对 NULL 值的任何比较都不能取值为 TRUE 或 FALSE,而是取值为 UNKNOWN。此规定在比较运算符中引入了三值逻辑,而要正确运用该逻辑很困难。
约束、规则、默认值和触发器
表列中除了具有数据类型和大小属性之外,还有其他属性。其他属性是保证数据库中数据完整性和表的引用完整性的重要部分。
 数据完整性是指列中每个事件都有正确的数据值。数据值的数据类型必须正确,并且数据值必须位于正确的域中。
 引用完整性指示表之间的关系得到正确维护。一个表中的数据只应指向另一个表中的现有行,不应指向不存在的行。
约束
通过约束可以定义 SQL Server 2005 数据库引擎 自动强制实施数据库完整性的方式。约束定义关于列中允许值的规则,是强制实施完整性的标准机制。使用约束优先于使用 DML 触发器、规则和默认值。另外,查询优化器也使用约束定义生成高性能的查询执行计划。
SQL Server 2005 支持下列约束类:
 NOT NULL 指定列不接受 NULL 值。
 CHECK 约束通过限制可放入列中的值来强制实施域完整性。CHECK 约束指定应用于为列输入的所有值的布尔值(计算结果为 TRUE、FALSE 或未知)搜索条件。所有计算结果为 FALSE 的值均被拒绝。可以为每列指定多个 CHECK 约束。
 UNIQUE 约束强制实施列集中值的唯一性。 根据 UNIQUE 约束,表中的任何两行都不能有相同的列值。另外,主键也强制实施唯一性,但主键不允许 NULL 作为一个唯一值。
 PRIMARY KEY 约束标识具有唯一标识表中行的值的列或列集。在一个表中,不能有两行具有相同的主键值。不能为主键中的任何列输入 NULL 值。建议使用一个小的整数列作为主键。每个表都应有一个主键。限定为主键值的列或列组合称为候选键。

3.2.1. PRIMARY KEY约束
表通常具有包含唯一标识表中每一行的值的一列或一组列。这样的一列或多列称为表的主键 (PK),用于强制表的实体完整性。在创建或修改表时,您可以通过定义 PRIMARY KEY 约束来创建主键。
一个表只能有一个 PRIMARY KEY 约束,并且 PRIMARY KEY 约束中的列不能接受空值。由于 PRIMARY KEY 约束可保证数据的唯一性,因此经常对标识列定义这种约束。
如果为表指定了 PRIMARY KEY 约束,则 SQL Server 2005 数据库引擎 将通过为主键列创建唯一索引来强制数据的唯一性。当在查询中使用主键时,此索引还可用来对数据进行快速访问。因此,所选的主键必须遵守创建唯一索引的规则。
如果对多列定义了 PRIMARY KEY 约束,则一列中的值可能会重复,但来自 PRIMARY KEY 约束定义中所有列的任何值组合必须唯一。
可以在创建表时创建单个 PRIMARY KEY 约束作为表定义的一部分。如果表已存在,且没有 PRIMARY KEY 约束,则可以添加 PRIMARY KEY 约束。一个表只能有一个 PRIMARY KEY 约束。
如果已存在 PRIMARY KEY 约束,则可以修改或删除它。例如,可以让表的 PRIMARY KEY 约束引用其他列,更改列的顺序、索引名、聚集选项或 PRIMARY KEY 约束的填充因子。但是,不能更改使用 PRIMARY KEY 约束定义的列长度。

 FOREIGN KEY 约束标识并强制实施表之间的关系。有关详细信息,请参阅 FOREIGN KEY 约束。
一个表的外键指向另一个表的候选键。在下面的示例中,学生选课表SC建立了引用以前定义的学生基本信息表Student的外键。

如果一个外键值没有候选键,则不能向行中插入该值(NULL 除外)。ON DELETE 子句控制尝试删除现有外键指向的行时采取的操作。ON DELETE 子句包含以下几个选项:
 NO ACTION 指定删除失败并提示错误。
 CASCADE 指定还将删除包含指向已删除行的外键的所有行。
 SET NULL 指定将包含指向已删除行的外键的所有行都设置为 NULL。
 SET DEFAULT 指定将包含指向已删除行的外键的所有行都设置为它们的默认值。有关详细信息,请参阅默认值。
ON UPDATE 子句定义尝试更新现有外键指向的候选键值时采取的操作。另外,此子句也支持 NO ACTION、CASCADE、SET NULL 和 SET DEFAULT 选项。
列约束和表约束
约束可以是列约束,也可以是表约束。列约束指定为列定义的一部分,并且只应用于该列。前面的示例中的约束是列约束。表约束的声明与列定义无关,可以应用于表中多个列。当一个约束中必须包含多个列时,必须使用表约束。
例如,如果一个表的主键内有两个或两个以上的列,则必须使用表约束将这些列包含在主键内。假设有一个记录学生成绩的表,其中包括学号(StudentID)、所选课课程编号(CourseID)和该门课程的成绩(Grade),则该表的主键为(学号,课程编号)。可以通过在表的两列主键中同时包含 StudentID 列和 CourseID 列强制实施这一点,如以下示例中所示:

3.3. 创建和修改表
下面的命令创建一个学生基本信息表Student,表中包括的列有:学号、姓名、性别、年龄和班级。
上面的命令创建一个名称为Student的表,它有三个列StudentID、Name、Sex、Age和Class,分别表示学号、姓名、性别、年龄和班级。StudentID的属性有数据类型int和主键约束PRIMARY KEY。
SQL Server联机从书有关于CREATE TABLE命令详细详细说明,但大多数情况下你可以把CREATE TABLE命令看作下面的一种简化形式:
CREATE TABLE 表名 列的定义
其中,列的定义是一个集合,包括每一个列的定义,形式如(列1的定义,列2的定义…,列n的定义),而每个列的定义又包括三部分:列名、数据类型和约束。列定义中的列名和数据类型是在创建表时必须指定的,即每个列都必须有列名和数据类型,而约束是可选项,有些列没有约束,而有约束的列可以在创建表时指定,也可以在创建表后添加。
实际上,SQL中的创建表的命令可以进一步抽象为形式如下的创建对象的命令,
命令 对象 对象的定义
比如创建索引、视图等都符合上面的抽象形式。在学习SQL的命令时,先分析命令的结构有助于加强对命令的理解和易于记忆。
每个表至多可定义 1024 列。表和列的名称必须遵守标识符的规定,在特定表中必须是唯一的,但同一数据库的不同表中可使用相同的列名。必须为每列指定数据类型。
3.4. 查询表
3.5. 自动编号列和标识符列
对于每个表,均可创建一个包含系统生成的序号值的标识符列,该序号值以唯一方式标识表中的每一行。例如,当在表中插入行时,标识符列可自动为应用程序生成唯一的编号。标识符列在其所定义的表中包含的值通常是唯一的。
每个表中均可创建一个全局唯一标识符列,该列中包含在全球联网的所有计算机中不重复的值。当必须合并来自多个数据库系统的相似数据时(例如,在一个客户帐单系统中,其数据位于世界各地的分公司),通常需要保证列包含全局唯一值。当数据被汇集到中心以进行合并和制作报表时,使用全局唯一值可防止不同国家/地区的客户具有相同的帐单号或客户 ID。
3.5.1. IDENTITY 属性
通过使用 IDENTITY 属性可以实现标识符列。这使得开发人员可以为表中所插入的第一行指定一个标识号(Identity Seed 属性),并确定要添加到种子上的增量(Identity Increment 属性)以确定后面的标识号。将值插入到有标识符列的表中之后,SQL Server 2005 数据库引擎会通过向种子添加增量来自动生成下一个标识值。当向现有表中添加标识符列时,还会将标识号添加到现有表行中,并按照最初添加这些行的顺序开始应用种子值和增量值。同时还为所有新添加的行生成标识号。不能修改现有表列来添加 IDENTITY 属性。
在用 IDENTITY 属性定义标识符列时,注意下列几点:
(1) 一个表只能有一个使用 IDENTITY 属性定义的列,且必须通过使用 decimal、int、numeric、smallint、bigint 或 tinyint 数据类型来定义该列。
(2) 可指定种子和增量。二者的默认值均为 1。
(3) 标识符列不能允许为空值,也不能包含 DEFAULT 定义或对象。
(4) 在设置 IDENTITY 属性后,可以使用 $IDENTITY 关键字在选择列表中引用该列。还可以通过名称引用该列。
(5) OBJECTPROPERTY 函数可用于确定一个表是否具有 IDENTITY 列,COLUMNPROPERTY 函数可用于确定 IDENTITY 列的名称。
(6) 通过使值能够显式插入,SET IDENTITY_INSERT 可用于禁用列的 IDENTITY 属性。
语法
以下示例将使用 IDENTITY 属性,为自动递增标识号创建一个新表。
参数
Seed:装载到表中的第一个行使用的值。
increment :与前一个加载的行的标识值相加的增量值。
必须同时指定种子和增量,或者二者都不指定。如果二者都未指定,则取默认值 (1,1)。
备注
如果在经常进行删除操作的表中存在着标识列,那么在标识值之间可能会有间隔。如果这是要考虑的问题,那么请不要使用 IDENTITY 属性。但是,为了确保未产生间隔,或者填补现有的间隔,在用 SET IDENTITY_INSERT ON 显式输入标识值之前,请先对现有的标识值进行计算。
如果要重新使用已删除的标识值,则可使用示例 B 中的示例代码来查找下一个可用的标识值。使用表名称、标识列数据类型和(该数据类型)的最大允许值数值 -1 来替代 tablename、column_type 和 MAX(column_type) - 1。
使用 DBCC CHECKIDENT 检查当前的标识值,并将其与标识列中的最大值进行比较。
如果发布了包含标识列的表进行复制,则必须使用与所用复制方式相应的方式来管理标识列。有关详细信息,请参阅复制标识列。

3.5.2. SET IDENTITY_INSERT
语法
参数
database_name:指定的表所在的数据库的名称。
schema_name :表所属的架构的名称。
table :包含标识列的表的名称。
备注
任何时候,一个会话中只有一个表的 IDENTITY_INSERT 属性可以设置为 ON。如果某个表已将此属性设置为 ON,则对另一个表发出 SET IDENTITY_INSERT ON 语句时,SQL Server 2005 将返回一个错误信息,指出 SET IDENTITY_INSERT 已设置为 ON,并报告已将其属性设置为 ON 的表。
如果插入值大于表的当前标识值,则 SQL Server 自动将新插入值作为当前标识值使用。
SET IDENTITY_INSERT 的设置是在执行或运行时设置的,而不是在分析时设置的。
权限
用户必须是对象的所有者,或者是 sysadmin 固定服务器角色的成员,或者是 db_owner 或 db_ddladmin 固定数据库角色的成员。
以下示例将创建一个包含标识列的表,并显示如何使用 SET IDENTITY_INSERT 设置来填充由 DELETE 语句导致的标识值中的空隙。

3.5.3. 使用常规语法查找标识值之间的间隔
以下示例显示了删除了数据时,用于在标识值中查找间隔的常规语法。

3.5.4. 全局唯一标识符
尽管 IDENTITY 属性在一个表内自动进行行编号,但具有各自标识符列的各个表可以生成相同的值。这是因为 IDENTITY 属性仅在使用它的表上保证是唯一的。如果应用程序必须生成在整个数据库或世界各地所有网络计算机的所有数据库中均为唯一的标识符列,请使用 uniqueidentifier 数据类型和 NEWID (Transact-SQL) 或 NEWSEQUENTIALID() 函数。数据库引擎不会自动为该列生成值。若要插入全局唯一值,请为该列创建 DEFAULT 定义来使用 NEWID 或 NEWSEQUENTIALID 函数生成全局唯一值。
在设置 ROWGUIDCOL 属性后,通过使用 ROWGUID使 IDENTITY 关键字可以引用 IDENTITY 列的方法类似。一个表只能有一个 ROWGUIDCOL 列,且必须通过使用 uniqueidentifier 数据类型定义该列。
OBJECTPROPERTY (Transact-SQL) 函数可用于确定一个表是否具有 ROWGUIDCOL 列,COLUMNPROPERTY (Transact-SQL) 函数可用于确定 ROWGUIDCOL 列的名称。
以下示例创建 uniqueidentifier 列作为主键的表。此示例在 DEFAULT 约束中使用 NEWSEQUENTIALID() 函数为新行提供值。将 ROWGUIDCOL 属性应用到 uniqueidentifier 列,以便可以使用 $ROWGUID 关键字对其进行引用。
3.6. 基本数据定义与查询
实验目的:掌握对数据库表的更新操作,掌握对视图的操作,理解对基本表和视图操作的异同。
内容与要求:使用SQL Server的查询分析器完成下列数据定义和查询(注:不要使用企业管理器对表进行管理,应使用命令创建和修改表)。
按表 2 1和表 2 2提供的内容建立客户表和合同表
表 2 1 客户基本信息表CUSTOMER
编号 字段 数据类型 约束 说明
1 ID CHAR(10) 主码 客户编号
2 NAME VARCHAR(10) 非空 客户姓名
4 DEPARTMENT VARCHAR(32) 非空 客户单位名称
5 PHONE VARCHAR(12) 客户电话
6 MOBILE CHAR(11) 手机
7 EMAIL VARCHAR(32) 电子邮件地址
8 CITY VARCHAR(20) 所在城市
9 ADDRESS VARCHAR(128) 通信地址
10 ZIP CHAR(6) 邮政编码

表 2 2 合同基本信息表CONTRACT
编号 字段 数据类型 约束 说明
1 ID Char(12) 主码 合同编号
2 CUSTOMER_ID CHAR(12) 外码,非空 引用客户表CUSTOMER
3 SIGN_DATE DATETIME 合同签订日期
4 AMOUNT MONEY 非空 合同总额
5 CONTENTS VARCHAR(512) 合同内容
给客户表添加一个表示性别的字段SEX,数据类型为CHAR(1),取值范围为(F,M,f,m)的其中一个(练习表结构的修改和用户定义的完整性约束)
在客户表名称字段上建立的索引(按升序排列)
在客户表中插入相应的不少于5个的记录,在合同表中插入不少于3个的合同记录。
查询客户的姓名、单位、电话、手机和EMAIL地址。查询合同表的信息,输出合同编号、客户单位名称、签订日期和合同总额(注:需要与客户表进行联系查询)
3.7. 复杂查询
实验目的:掌握对的数据库表的更新操作,掌握对视图的操作,理解对基本表和视图操作的异同。
实验内容与要求
在原来的客户与合同信息表的基础上添加一个新的合同应收帐目明细表,如表 2 3所示:
表 2 3 应收帐目信息表COST
编号 字段 数据类型 约束 说明
1 ID CHAR(10) 主码 应收帐目编号
2 CONTRAC_ID CHAR(12) 外码 引用合同编号
3 AMOUNT MONEY 非空 费用金额
4 TYPE INT,值为0或1 非空 费用类别(预付款、尾款)
5 RECEIVE_DATA DATETIME 非空 应到日期
在合同中添或修改相应的记录,每个合同中每个客户有两个以上的合同,然后在应收账目信息表中为每一项合同添加预付款和尾款各一项记录
统计合同总额(所有合同的总额之和)
根据应收账目信息表,输出统计每个单项合同的总额(预付款+尾款,使用分组查询统计),输出内容如下所示:
合同编号 总额
合同编号1 10,000,000.00
合同编号2 12,000,000.00
在客户、合同和合同应收账目三个表的基础上创建一个视图,包括的内容有合同编号、客户单位名称、合同总额、签订日期、应收帐目费用、费用类别和应到日期。
使用该视图修改合同总额。

3.8. 示例数据库
SQL Server 包括 AdventureWorks (OLTP)、AdventureWorksDW(数据仓库)和 AdventureWorksAS (Analysis Services) 等示例数据库。示例数据基于一个虚拟的公司 Adventure Works Cycles,这是一个大型的跨国制造公司,它生产金属和复合材料自行车,产品远销北美、欧洲和亚洲市场。
3.8.1. Adventure Works Cycles 业务方案
Adventure Works Cycles是AdventureWorks 示例数据库所基于的虚构公司,是一家大型跨国生产公司。公司生产金属和复合材料的自行车,产品远销北美、欧洲和亚洲市场。公司总部设在华盛顿州的伯瑟尔市,拥有 299 名雇员,而且拥有多个活跃在世界各地的地区性销售团队。
在 2000 年,Adventure Works Cycles 购买了位于墨西哥的小型生产厂 Importadores Neptuno。Importadores Neptuno 为 Adventure Works Cycles 产品生产多种关键子组件。这些子组件将被运送到伯瑟尔市进行最后的产品装配。2001 年,Importadores Neptuno 转型成为专注于旅行登山车系列产品的制造商和销售商。
实现一个成功的财务年度之后,Adventure Works Cycles 希望通过以下方法扩大市场份额:专注于向高端客户提供产品、通过外部网站扩展其产品的销售渠道、通过降低生产成本来削减其销售成本。

表 2 4 SalesOrderHeader表定义
列 数据类型 非空 说明
SalesOrderID int 非空 主键
RevisionNumber tinyint 非空 随着时间的推移跟踪销售订单更改的递增编号
OrderDate datetime 非空 创建销售订单的日期
DueDate datetime 非空 客户订单到期的日期
ShipDate datetime 非空 订单发送给客户的日期
Status tinyint 非空 订单的当前状态。1=处理中,2=已批准,3=预定,4=已拒绝,5=已发货,6=已取消
OnlineOderFlag Flag(bit) 非空 0=销售人员下的订单,1=客户在线下的订单。
SalesOrderNumber nvarchar(25) 非空 唯一的销售订单标识号。
PurchaseOrderNumber OrderNumber(nvarchar(25)) 非空 客户采购订单号引用
AccountNumber AccountNumber(nvarchar(15)) 非空 财务账号引用
CustomerID int 非空 客户标识号,指向Customer.CustomerID的外键
ContactID int 非空 客户联系人标识号,指向Contact.ContactID的外键
SalesPersonID int 非空 创建销售订单的销售人员,指向SalesPerson.SalesPersonID的外键
TerritoryID int 非空 进行销售的地区,指向SalesTerritory.SalesTerrotoryID的个键
BillToAddressID int 非空 客户开票地址,指向Address.AddressID的外键
ShipToAddressID int 非空 客户收货地址,指向Address.AddressID的外键
ShipMethodID int 非空 发货方法,指向ShipMethod.ShipMethodID的外键
CreditCardID int 非空 信用卡标识号,指向CreditCard.CreditCardID的外键
CreditCardApprovalCode varchar(15) 非空 信用卡公司提供的批准代码
CurrencyRateID int 非空 所使用的外币竞换率,指向CurrencyRate.CurrencyRateID的外键
SubTotal money 非空 销售小计,SalesOrderID的销售小计的计算方式为SUM(SalesOrderDetail.LineTotal)
TaxAmt money 非空 税额
Freight money 非空 运费
TotalDue 非空 客房的应付款总计,计算方式为SubTotal+TaxAmt+Freight
Comment nvarchar(128) 非空 销售代表添加的注释。
Rowguid uniqueidentifier ROWGUIDCOL 非空 唯一标识行的ROWGUIDCOL号,用于支持合并复制。
ModifiedDate datetime 非空 行的上次更新日期和时间。

表 2 5 SalesOrderDetail表的定义
列 数据类型 非空 说明
SalesOrderID int 非空 主键,指向SalesOrderHeader.SalesOrderID的外键
SalesOrderDetailID Tinyint 非空 主键,用于确保数据唯一性的连续编号。
CarrierTrackingNumber Nvarchar(25) 非空 发货人提供的发货跟踪号。
OrderQty Smallint 非空 每个产品的订购数量。
ProductID Int 非空 销售给客户的产品,指向SpecialOfferProduct.ProductID的外键。
SpecialOfferID Int 非空 促销代码,指向SpecialOfferProduct.SpecialOfferID。
UnitPrice money 非空 单件产品的销售价格。
UnitPriceDiscount money 非空 折扣金额。
LineTotal 非空 每件产品的小计,计算方式为OrderQty*UnitPrice
Rowguid uniqueidentifier ROWGUIDCOL 非空 唯一标识行的ROWGUIDCOL号,用于支持合并复制。
ModifiedDate datetime 非空 行的上一次修改的日期和时间。

猜你喜欢

转载自blog.csdn.net/maguanzhan7939/article/details/77924655
今日推荐