第一章 T-SQL查询和编程基础 T-SQL语言基础(2)

时间:2023-03-08 21:08:25

T-SQL查询和编程基础 (2)

1.3 创建表和定义数据完整性

注意:表是属于架构,而架构又是属于数据库的

-- Create a database called testdb
IF DB_ID('testdb') IS NULL
CREATE DATABASE testdb;
GO --BD_ID 函数接受一个数据库名称作为输入,返回它的内部数据库ID.如果输入名称指定的数据库不存在,这个函数返回NULL.
--这是检查数据库是否存在的简单方法
--CREATE DATABASE 语句,采用了默认的文件设置(例如:区域和初始大小)

例子中使用的架构是dbo,在每个数据库中都会自动创建这个架构.当用户没有将默认架构显式关联到其他架构时,就会将这个dbo作为默认架构.

1.3.1 创建表

-- Create table Employees
USE testdb; IF OBJECT_ID('dbo.Employees', 'U') IS NOT NULL
DROP TABLE dbo.Employees; CREATE TABLE dbo.Employees
(
empid INT NOT NULL,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
hiredate DATE NOT NULL,
mgrid INT NULL,
ssn VARCHAR(20) NOT NULL,
salary MONEY NOT NULL
);

解释:

a.use语句将当前的数据库上下文切换为testdb.use语句,确保要在正确的数据库中创建对象

b.OBJECT_ID函数用来检查在当前数据库是否存在表,OBJECT_ID函数接受一个对象名称和类型作为它的输入,这里类型"U"代表用户表

c.CREATE TABLE语句负责定义前面提到的关系的主体.在这个语句中先指定表的名称,接着在圆括号中定义它的各个属性(列).显示定义null,或者not null.

1.3.2 定义数据完整性

主键约束(Primary key Constraints)

主键约束实施行的唯一约束,同时不允许约束属性取NULL值.每个表只能定义一个主键.

-- Primary key
ALTER TABLE dbo.Employees
ADD CONSTRAINT PK_Employees
PRIMARY KEY(empid);

**为了实施逻辑主键约束的唯一约束,SQL Server将在幕后创建一个唯一索引(Unique index).唯一索引是SQL Server为了实施唯一约束而采用的一种物理机制.

可以用索引(不一定是唯一索引)来加速查询的处理,避免对整个表进行不必要的扫描.

唯一约束(Unique Constraints)

唯一约束用来保证数据行的一个列(或一组列)数据的唯一,可以在数据库中实现关系模型的替换键(alternate key)的概念.

再同一个表中可以定义多个唯一约束,唯一约束也不限于只定义在NOT NULL列上.

**和主键约束一样,SQL Server也在幕后创建一个唯一索引,作为实施逻辑唯一约束的物理机制

-- Unique
ALTER TABLE dbo.Employees
ADD CONSTRAINT UNQ_Employees_ssn
UNIQUE(ssn);

外键约束(Foreign Key)

外键约束用于实施引用完整性.这种约束在引用表(referencing table)的一组属性上进行定义,并指向被引用表(referenced table)中的一组候选键(主键或唯一约束).

外键的目的是为了将外键列允许的值域限制为被引用列中现有的值.

-- Foreign key
--
--创建表dbo.Orders,并定义主键OrderID
IF OBJECT_ID('dbo.Orders', 'U') IS NOT NULL
DROP TABLE dbo.Orders; CREATE TABLE dbo.Orders
(
orderid INT NOT NULL,
empid INT NOT NULL,
custid VARCHAR(10) NOT NULL,
orderts DATETIME NOT NULL,
qty INT NOT NULL,
CONSTRAINT PK_Orders
PRIMARY KEY(OrderID)
); --表dbo.Orders中的外键约束,指向表dbo.Employees的empid列,主键列
ALTER TABLE dbo.Orders
ADD CONSTRAINT FK_Orders_Employees
FOREIGN KEY(empid)
REFERENCES dbo.Employees(empid); --同一表中的外键,修改表dbo.Employees,定义外键约束mgrid,指向表Employees中的empid列,主键列
ALTER TABLE dbo.Employees
ADD CONSTRAINT FK_Employees_Employees
FOREIGN KEY(mgrid)
REFERENCES Employees(empid);

注:即使被引用的候选键列不存在NULL值,在外键列中也允许NULL值

**外键的引用操作:禁止操作(默认的),级联操作

禁止操作:当试图删除被引用表中的行,或更新被引用的候选键时,如果在引用表中存在相关的行则此操作不能执行,RDBMS将拒绝执行这样的操作,并生成报错的信息.

级联操作:当在引用表中存在相关的数据行时,可以删除被引用表中的数据行货更新被引用候选键属性.可以在外键定义中将ON DELETE和ON UPDATE选项定义为CASCADE,SET DEFAULT和

SET NULL之类的操作.

*CASCADE:操作(删除或更新)将被级联到引用表中相关的行.

例如:ON DELETE CASCADE意味着当从被引用表中删除一行时,RDBMS也将从引用表中删除相关的行.

*SET DEFAULT和SET NULL意味着补偿操作会把相关行的外键属性分别设置为列的默认值或NULL值.注意:不论选择哪种操作,如果遇到了前面提及的NULL值异常,引用表将只有孤立的数据行.

检查约束(Check)

检查约束用于定义在表中输入或修改一行数据之前必须满足的一个谓词.

-- Check
ALTER TABLE dbo.Employees
ADD CONSTRAINT CHK_Employees_salary
CHECK(salary > 0);

注:如上,当谓词计算为false,会拒绝操作;当为true或unknown时,会接受操作.

默认约束(Default)

当插入一行数据时,如果没有为属性显示指定明确的值,就可以用一个表达式作为其默认值.

-- Default
ALTER TABLE dbo.Orders
ADD CONSTRAINT DFT_Orders_orderts
DEFAULT(CURRENT_TIMESTAMP) FOR orderts;

**CURRENT_TIMESTAMP函数,由它返回当前的日期和时间值!

练习

/* 检查数据库是否存在,如果存在,删除此数据库 */
/* select * from sysdatabases where name='bankDB' 检查是否有bankDB的数据库*/ if exists(select * from sysdatabases where name='bankDB')
drop database bankDB
go
/*创建数据库bankDB*/
create database bankDB
on
(
name='bankDB_data',
filename='d:\bank\bankDB.mdf',
size=10,
filegrowth=15%
)
log on
(
name='bankDB_log',
filename='d:\bank\bankDB_log.ldf',
size=5,
filegrowth=15%
) /* 创建表*/ use bankDB
go
create table userInfo --用户信息表
(
customerID int identity(1,1),
customerName char(8) not null,
PID char(18) not null,
telephone char(13) not null,
address varchar(50)
) go create table cardInfo --银行卡信息表
(
cardID char(19) not null,
curType char(5) not null,
savingType char(8) not null,
openDate datetime not null,
openMoney money not null,
balance money not null,
pass char(6) not null,
IsReportLoss bit not null,
customerID int not null
)
go create table transInfo --交易信息表
(
transDate datetime not null,
transType char(4) not null,
cardID char(19) not null,
transMoney money not null,
remark text
)
go /* 为userInfo表添加约束
customerID(顾客编号): 自动编号(标识列),从1开始,主键
PID(身份证号): 只能是18位或15位,身份证号唯一约束
telephone(联系电话): 格式为xxxx-xxxxxxxx或手机号13位
*/ alter table userInfo
add
constraint pk_customerID primary key(customerID),
constraint chk_PID check(len(PID)=18 or len(PID)=15),
constraint uq_PID unique(PID),
constraint chk_telephone check(telephone like '[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
or len(telephone)=13)
go /* cardInfo 表的约束
cardID 卡号 必填,主健,银行的卡号规则和电话号码一样,一般前8位代表特殊含义,
如某总行某支行等。假定该行要求其营业厅的卡号格式为:1010 3576 xxxx xxx开始,每4位号码后有空格,
卡号一般是随机产生。
curType 货币种类 必填,默认为RMB
savingType 存款类型 活期/定活两便/定期
openDate 开户日期 必填,默认为系统当前日期
openMoney 开户金额 必填,不低于1元
balance 余额 必填,不低于1元,否则将销户
pass 密码 必填,6位数字,开户时默认为6个“8”
IsReportLoss 是否挂失 必填,是/否值,默认为”否”
customerID 顾客编号 外键,必填,表示该卡对应的顾客编号,一位顾客允许办理多张卡号
*/ alter table cardInfo
add
constraint pk_cardID primary key(cardID),
constraint ck_cardID check(cardID like '1010 3576 [0-9][0-9][0-9][0-9] [0-9][0-9][0-9][0-9]'),
constraint df_curType default 'RMB' for curType,
constraint ck_savingType check(savingType in ('活期','定活两便','定期')),
constraint df_openDate default getdate() for OpenDate,
constraint ck_openMoney check(openMoney>=1),
constraint ck_balance check(balance>=1),
constraint ck_pass check(pass like '[0-9][0-9][0-9][0-9][0-9][0-9]'),
constraint df_pass default '' for pass,
constraint df_IsReportLoss default 0 for IsReportLoss,
constraint fk_customerID foreign key(customerID) references userInfo(customerID)
go /* transInfo表的约束
transDate 交易日期 必填,默认为系统当前日期
cardID 卡号 必填,外健,可重复索引
transType 交易类型 必填,只能是存入/支取
transMoney 交易金额 必填,大于0
remark 备注 可选输入,其他说明
*/ alter table transInfo
add
constraint df_transDate default getdate() for transDate,
constraint ck_transType check(transType in ('存入','支取')),
constraint fk_cardid foreign key(cardid) references cardInfo(cardID),
constraint ck_transMoney check(transMoney>0)