Transact-SQL及其程序设计基础

5.2 Transact-SQL基础
5.2.2 数据查询
1.查询表中所有的列
例如,要查询表book中的所有书籍的信息,可在SQL查询分析器中输入如下命令:
SELECT * FROM book
2.查询表中指定的列
例如,要查询所有书籍的名称和价格,可输入下面的SQL语句:
SELECT book_name,price FROM book
可以重新排列列的次序,在SELECT后的列名的顺序决定了显示结果中的列序。如果想把价格放在前面,则上面的SQL语句应该写成:
SELECT price,book_name FROM book
3.使用单引号加入字符串
例如,要查询所有书籍的名称和价格,并在价格前面显示字符串“价格为:”,可输入下面的SQL语句:
SELECT book_name,'价格为:',price FROM book
4.使用别名
例如,查询所有书籍的名称和价格,并在标题栏种显示“书名”和“价格”字样,而不是显示book_name和price。可输入下面的SQL语句:
SELECT book_name AS 书名,price AS 价格 FROM book
或者:SELECT book_name 书名,price 价格 FROM book
或者:SELECT '书名'=book_name,'价格'=price FROM book
5.查询特定的记录
例如,要查询《Windows 2000 网络管理》一书的信息,则可以输入以下SQL语句:
SELECT * FROM book WHERE book_name='Windows 2000 网络管理'
6.对查询结果进行排序
例如,依照价格高低来显示所有书籍的信息,输入以下SQL语句:
SELECT * FROM book ORDER BY price DESC
7. 多表查询
输入下面的SQL语句:
SELECT book.book_name,authors.author_name
FROM book,authors
WHERE book.author_id=authors.author_id
8.消除重复的行
例如,查询所有书籍所属的出版社。输入SQL语句如下:
SELECT DISTINCT publisher FROM book
5.2.3 数据插入和删除
在表authors中插入一笔记录,即新增一个作者。输入SQL语句如下:
INSERT authors(author_id,author_name) VALUES(3,'张英魁')
表示加入了一笔记录。使用SELECT语句查询authors表,可看到新增加的记录。输入如下SQL语句:
SELECT * FROM authors
例如,删除book表中《“Windows 2000 Professional 看图速成》一书的记录,可以输入以下SQL语句:
DELETE book
WHERE book_name='Windows 2000 Professional 看图速成'
下面的例子即为删除authors表中的所有数据:
TRUNCATE TABLE authors
5.2.4 数据修改
例如,将authors表中作者为“王小明”全部改为“王晓明”,SQL语句如下:
UPDATE authors SET author_name='王晓明'
WHERE author_name='王小明'
5.2.5 使用函数
例如,在orderform表中,提交一笔订单,在插入数据时,即可使用GETDATE()函数来获取当前的日期。为了保持数据完整性,首先在clients表中插入一个客户,然后再在orderform表中提交一笔订单。输入下面的SQL语句:
INSERT clients VALUES(1,'刘明耀','北京市海淀区')
INSERT orderform VALUES(1,2,50,GETDATE(),1)
按F5键,然后使用SELECT语句可查看执行结果:
SELECT * FROM orderform
5.2.6 使用公式
例如,要查询所有订单中的书名、数量和总额。此时,就可以使用公式来计算总额。输入的SQL语句如下:
SELECT book.book_name,orderform.book_number,
'总额为:',(book.price*orderform.book_number)
FROM orderform,book
WHERE orderform.book_id=book.book_id
5.2.7 数据库的操作语句
5.2.7.1 创建数据库
例如,建立一个名为test的数据库,可以输入如下的SQL语句:
CREATE DATABASE test
例如,要创建一个销售数据库,并设定数据文件为d:/销售.LDF,大小为5MB,最大为20MB,每次增长5MB。事务日志文件为d:/ 销售.LDF,大小为5MB,最大为10MB,每次增长为1MB。则创建的SQL语句为:
CREATE DATABASE 销售数据库
ON (
NAME = 销售数据,
FILENAME = 'd:/Program Files/Microsoft SQL Server/MSSQL/data/销售数据.MDF',
SIZE = 10MB,
MAXSIZE = 50MB,
FILEGROWTH = 10MB
)
LOG ON(
NAME = 销售数据日志,
FILENAME = 'd:/Program Files/Microsoft SQL Server/MSSQL/data/销售数据日志.LDF',
SIZE = 10MB,
MAXSIZE = 20MB,
FILEGROWTH = 5MB
)
5.2.7.2 修改数据库
例如,为销售数据库新增一个逻辑名为“销售数据2”的数据文件,其大小及其最大值分别为10MB和50MB。输入的SQL语句为:
ALTER DATABASE 销售数据库
ADD FILE (
NAME = 销售数据2,
FILENAME = 'd:/Program Files/Microsoft SQL Server/MSSQL/data/销售数据2.MDF',
SIZE = 10MB,
MAXSIZE = 50MB,
FILEGROWTH = 5MB
)
5.2.7.3 使用和删除数据库
例如,可以使用如下SQL语句来删除销售数据库:
DROP DATABASE 销售数据库
5.2.8 表的操作语句
5.2.8.1 表的创建
1.基本用法
在test数据库中创建一个clients表,SQL语句如下:
USE test
CREATE TABLE clients (
client_id int,
client_name char(8),
address char(50)
)
2.段属性参数
下面的SQL语句是在test数据库中建立一个book表,并指定book_id为主键,而book_name为非空:
CREATE TABLE book (
book_id int NOT NULL PRIMARY KEY,
book_name char(8) NOT NULL,
author_id char(50)
)
3.与其他表建立关联
例如,可以将book表中的author_id字段关联到authors表的author_id字段。在企业管理器中将上面创建的book表删除,然后执行下面的语句:
CREATE TABLE authors(
author_id int NOT NULL PRIMARY KEY,
author_name char(8) NOT NULL,
address char(50) NULL
)
CREATE TABLE book (
book_id int NOT NULL PRIMARY KEY,
book_name char(8) NOT NULL,
author_id int FOREIGN KEY REFERENCES authors (author_id)
)
5.2.8.2 修改表
例如,在test数据库中给book表增加一个“简介”字段:
ALTER TABLE book ADD 简介 text
5.2.8.3 删除关联和表
例如,要删除表book,可执行下述SQL语句:
DROP TABLE book
5.3 Transact-SQL程序设计基础
5.3.1 标识符
5.3.1.1 常规标识符
例如:
SELECT * FROM TableX WHERE KeyCol = 124
5.3.1.2 分隔标识符
例如,打开和关闭该选项的SET语句如下:
SET QUOTED_IDENTIFIER ON
SET QUOTED_IDENTIFIER OFF
5.3.1.3 使用标识符
例如,一个用户名为bookadm的用户登录到MyServer服务器上,并使用book数据库。使用下述语句创建了一个MyTable表:
CREATE TABLE MyTable
(
column1 int,
column2 char(20)
)
5.3.2 数据类型
5.3.2.1 系统数据类型
1.整数型
例如,下面的语句创建了一个表Int_table,其中的4个字段分别使用这4种整数类型:
USE test
CREATE TABLE Int_table
(
c1 tinyint,
c2 smallint,
c3 int,
c4 bigint,
)
INSERT Int_table VALUES (50,5000,50000,500000)
SELECT * FROM Int_table
2.小数数据类型
例如,在下面的表Decimal_table中,字段c1就是一个decimal数据类型:
CREATE TABLE Decimal_table
(
c1 decimal(3,2)
)
INSERT Decimal_table VALUES (4.5678)
SELECT * FROM Decimal_table
在为小数数值型数据赋值时,应保证所赋数据整数部分的位于小于或者等于定义的长度,否则会出现溢出错误。例如,给Decimal_table插入一笔记录,在SQL查询分析器中执行下面语句:
INSERT Decimal_table VALUES (45.678)
3.近似数值型
4.字符型数据类型
例如,下面的SQL语句将局部变量MyCharVar声明为char类型,长度为25:
DECLARE @MyCharVar CHAR(25)
SET @MyCharVar = 'This is a string'
下面则是使用两个单引号来表示嵌入单引号:
SET @MyCharVar = 'This is a ''string'''
CHAR函数可以把一个整数转换为ASCII字符。当确定控制字符时(比如回车或换行),这是很有用的。在字符串中用CHAR(13)和CHAR(10)产生一个回车并生成一个新行。例如:
PRINT 'First line.' + CHAR(13) + CHAR(10) + 'Second line.'
5.逻辑数据类型
例如,下面是使用bit数据类型的例子:
CREATE TABLE Bit_table
(
c1 bit,
c2 bit,
c3 bit
)
INSERT Bit_table VALUES(12,1,0)
SELECT * FROM Bit_table
6.货币型
下面是使用货币数据类型的例子:
CREATE TABLE Money_table
(
c1 money,
c2 smallmoney
)
INSERT Money_table VALUES ($12345678,$1234)
SELECT * FROM Money_table
7.二进制数据类型
下面是使用二进制数据类型的例子:
CREATE TABLE Binary_table
(
c1 binary(10),
c2 varbinary(20),
c3 image
)
INSERT Binary_table VALUES (0x123,0xfffff,0x14fffff)
SELECT * FROM Binary_table
8.日期时间类型
下面是一个使用smalldatetime数据类型的例子:
SELECT CAST('2000-05-08 12:35:29.998' AS smalldatetime)
以下是使用日期时间数据类型的例子:
CREATE TABLE Datetime_table
(
c1 datetime,
c2 smalldatetime,
)
INSERT Datetime_table VALUES ('2001-05-15 00:04:39.257','04/15/1996 14:30:20 PM')
SELECT * FROM Datetime_table
9.Unicode字符型
使用Unicode字符时,应该在前面加一个标识符N,但是存储时并不存储该标识符。例如:
DECLARE @MyUnicodeVar NCHAR(25)
SET @MyUnicodeVar = N'This is a Unicode string.'
PRINT @MyUnicodeVar
10.其他数据类型
下面的示例使用NEWID对声明为uniqueidentifier数据类型的变量赋值,并将其打印出来:
DECLARE @MyID uniqueidentifier
SET @MyID = NEWID()
PRINT 'Value of @MyID is: '+ CONVERT(varchar(255), @MyID)
5.3.2.2 用户定义数据类型
2.使用存储过程
下面的示例为国内及国际电话和传真号码另外创建两个用户定义的数据类型telephone和fax:
EXEC sp_addtype telephone, 'varchar(24)', 'NOT NULL'
EXEC sp_addtype fax, 'varchar(24)', 'NULL'
5.3.3 运算符
2.赋值运算符
例如,下面的SQL语句先声明一个变量,然后将一个取模运算的结果赋给该变量,最后是打印该变量的值:
DECLARE @MyCounter INT
SET @MyCounter = 17%3
PRINT CONVERT(varchar(255), @MyCounter)
也可以使用赋值运算符在列标题和为列定义值的表达式之间建立关系。例如,下面的SQL语句是将bookdb数据库中的book表的book_id均以“书籍”显示:
USE bookdb
SELECT book_id = '书籍',book_name,price FROM book
3.按位运算符
例如,下面的SQL语句对两个变量进行按位运算:
DECLARE @a INT,@b INT
SET @a = 5
SET @b = 10
SELECT @a&@b,@a|@b,@a^@b
4.比较运算符
下面的SQL语句查询book表中价格大于35.0的书籍信息:
USE bookdb
SELECT * FROM book WHERE price > 35.0
5.逻辑运算符
例如,下面的SQL语句在book表中查询书名包含“网络管理”,而且价格在20到50之间的书籍的信息:
SELECT * FROM book
WHERE (book_name LIKE '%网络管理%') AND (price BETWEEN 20 AND 50)
6.字符串连接运算符
例如,下面的SQL语句将两个字符串连接在一起:
SELECT ('abc' + 'def')
7.一元运算符
例如,下面的SQL语句,首先声明一个变量,并对变量赋值,然后对变量取负:
DECLARE @Num1 int
SET @Num1 = 5
SELECT -@Num1
8.运算符优先级
例如,在下面的示例中,在SET语句中使用的表达式中,在加号运算符之前先对减号运算符进行求值:
DECLARE @MyNumber int
SET @MyNumber = 6 - 5 + 7
SELECT @MyNumber
例如:
DECLARE @MyNumber int
SET @MyNumber = 3 * (5 + (7 - 3) )
SELECT @MyNumber
5.1.4 变量
1.局部变量
在SQL Server中,一次可以定义多个变量。例如:
DECLARE @maxprice float,@pub char(12)
例如,下面首先定义了两个变量,并分别使用SET和SELECT为其赋值,然后使用这两个变量查询价格小于50,且出版社为“明耀工作室”的书籍信息:
DECLARE @maxprice float,@pub char(12)
SET @maxprice =50
SELECT @pub='明耀工作室'
SELECT * FROM book WHERE price < @maxprice AND publisher = @pub
5.3.5 批处理
下面的SQL语句创建一个视图。因为CREATE VIEW必须是批处理中的唯一语句,所以需要GO命令将CREATE VIEW语句与其周围的USE和SELECT语句隔离:
USE bookdb
GO

CREATE VIEW auth_titles AS SELECT * FROM authors
GO

SELECT * FROM auth_titles
GO
5.3.6 注释
下面就是使用注释的例子:
USE bookdb
GO
--这是双连字符注释
SELECT * FROM book --从表book中查询书籍信息
GO
/*这是正斜杠-星号对
注释*/
SELECT * FROM authors /*查询作者信息*/
GO
5.3.7 控制流语句
5.3.7.1 BEGIN...END语句
BEGIN...END语句可以嵌套使用。例如:
BEGIN
DECLARE @MyVar float
SET @MyVar = 456.256
BEGIN
PRINT '变量@MyVar的值为:'
PRINT CAST(@MyVar AS varchar(12))
END
END
5.3.7.2 IF...ELSE语句
IF...ELSE语句地执行方式是:如果布尔表达式的值为True,则执行IF后面的语句块;否则执行ELSE后面的语句块。
例如:
USE bookdb
IF (SELECT price FROM book WHERE book_name LIKE '%网络管理%')>50
BEGIN
PRINT '这本书太贵了!'
PRINT '我承受不起!'
END
ELSE
BEGIN
PRINT '这本书还可以!'
PRINT '我要买一本!'
END
5.3.7.3 CASE语句
1.简单CASE格式
例如:
USE pubs
GO
SELECT au_fname, au_lname,
CASE state
WHEN 'CA' THEN 'California'
WHEN 'KS' THEN 'Kansas'
WHEN 'TN' THEN 'Tennessee'
WHEN 'OR' THEN 'Oregon'
WHEN 'MI' THEN 'Michigan'
WHEN 'IN' THEN 'Indiana'
WHEN 'MD' THEN 'Maryland'
WHEN 'UT' THEN 'Utah'
END AS StateName
FROM pubs.dbo.authors WHERE au_fname LIKE 'M%'
2.搜索CASE格式
例如:
USE bookdb
GO
SELECT book_name,
CASE
WHEN price>=50 THEN '太贵了!'
WHEN price>=40 THEN '还可以,考虑考虑!'
ELSE '挺便宜的,买一本'
END AS 价格
FROM book
GO
5.3.7.4 WHILE语句
例如,下面的SQL语句是计算从1加到100的值:
DECLARE @MyResult int,@MyVar int
SET @MyVar = 0
SET @MyResult = 0
WHILE @MyVar<=100
BEGIN
SET @MyResult = @MyResult+@MyVar
SET @MyVar=@MyVar+1
END
PRINT CAST(@MyResult AS char(25))
5.3.7.5 GOTO语句
例如,使用下面的语句重新计算从1加到100的值:
DECLARE @MyResult int,@MyVar int
SET @MyVar = 0
SET @MyResult = 0
my_loop: --定义标号
SET @MyResult = @MyResult+@MyVar
SET @MyVar=@MyVar+1
IF @MyVar<=100
GOTO my_loop --如果小于100,跳转到my_loop标号处
PRINT CAST(@MyResult AS char(25))
5.3.7.6 RETURN语句
例如,首先执行下面的SQL语句创建一个存储过程:
USE bookdb
GO
CREATE PROC MyPro @bookname char(50) --创建存储过程MyPro
AS
IF (SELECT price FROM book WHERE book_name LIKE @bookname)>=50
RETURN 1
ELSE
RETURN 2
然后执行下面的SQL语句:
DECLARE @Return_value int
EXEC @Return_value=MyPro '%网络管理%'
IF @Return_value=1
PRINT '这本书太贵了!'
ELSE
PRINT '这本书还可以,值得考虑购买!'
GO
5.3.7.7 WAITFOR语句
例如,下面的SQL语句指定在1点58时执行一个语句:
BEGIN
WAITFOR TIME '1:58:00'
PRINT '现在是1:58:00'
END
5.3.8 函 数
5.3.8.1 内置函数
例如,下面是一个使用内置函数的例子:
PRINT '现在日期和时间是:' + CAST(GETDATE() AS char(50))
5.3.8.2 用户定义函数
例如:下面的SQL语句在test数据库中定义了一个CubicVolume用户定义函数,然后使用该函数计算一个长方体的体积:
USE test
GO
CREATE FUNCTION CubicVolume
--输入参数
(@CubeLength decimal(4,1), @CubeWidth decimal(4,1),
@CubeHeight decimal(4,1) )
RETURNS decimal(12,3) -- 返回立方体的体积
AS
BEGIN
RETURN ( @CubeLength * @CubeWidth * @CubeHeight )
END
GO
PRINT CAST(dbo.CubicVolume(20,5, 10) AS char(255))
GO
例如:
USE bookdb
GO
CREATE FUNCTION SearchBook ( @BookPrice float )
RETURNS @BookInfo TABLE
(
book_name char(50),
author_name char(8),
book_price float,
publisher char(50)
)
AS
BEGIN
INSERT @BookInfo
SELECT book.book_name,authors.author_name,book.price,book.publisher
FROM book,authors
WHERE book.author_id = authors.author_id AND book.price > @BookPrice
RETURN
END
GO
下面的SQL语句即使使用该函数查询价格大于35的书籍信息:
SELECT * FROM SearchBook(35)
5.4 小 结
参考答案:
2.这是一个带条件的多表查询。可以使用下面的语句:
USE bookdb
GO
SELECT book_name AS 书名,author_name AS 作者,price AS 价格,
publisher AS 出版社
FROM book,authors
WHERE price > 35
3.可以使用下面的SQL语句:
USE bookdb
GO
SELECT book_name AS 书名,(price*0.9) AS 打折后的价格
FROM book

 

第7章 SQL高级使用
7.1 SELECT高级查询
7.1.1 数据汇总
7.1.1.1 聚合函数
例如,下面的SQL语句用来查询authors表中有几个作者的地址存在:
USE bookdb
GO
SELECT COUNT(address) FROM authors
GO
执行结果:
2
而下面的SQL语句则是查询book表中书籍的价格的最大值:
USE bookdb
GO
SELECT MAX(price) FROM book
GO
执行结果为:
45.0
7.1.1.2 GROUP BY子句
例如,下面的SQL语句首先在表clients、表book、表orderform中插入几笔记录,然后使用GROUP BY子句汇总各个客户所定购的书籍总数:
USE bookdb
GO
--在clients表中插入两个客户
INSERT clients VALUES(2,'科技书店','北京市朝阳区')
INSERT clients VALUES(3,'明天书屋','北京市西城区')
--GO
--在book表中插入4本书的记录
INSERT book VALUES(5,'AutoCAD 2000 中文版使用指南',2,25.0,'21世纪出版社')
INSERT book VALUES(6,'Office 2000 中文版使用指南',2,28.0,'明天出版社')
INSERT book VALUES(7,'Windows 2000 Professional 中文版使用指南',1,30.0,'东东出版社')
INSERT book VALUES(8,'Linux 使用指南',3,32.0,'唐唐出版社')
GO
--在orderform表中插入6笔记录
INSERT orderform VALUES(2,6,10,GETDATE(),2)
INSERT orderform VALUES(3,5,10,GETDATE(),3)
INSERT orderform VALUES(4,3,25,GETDATE(),1)
INSERT orderform VALUES(5,8,15,GETDATE(),1)
INSERT orderform VALUES(6,4,30,GETDATE(),3)
INSERT orderform VALUES(7,7,40,GETDATE(),2)
GO
SELECT clients.client_name,SUM(orderform.book_number) AS 书籍总数
FROM clients,orderform
WHERE clients.client_id=orderform.client_id
GROUP BY clients.client_name
GO
CUBE参数会对检索的字段中各类型的数据做汇总运算。例如,下面的SQL语句就是使用CUBE进行汇总的例子:
SELECT clients.client_name,book.book_name,
SUM(orderform.book_number) AS 书籍总数
FROM clients,orderform,book
WHERE clients.client_id=orderform.client_id AND book.book_id=orderform.book_id
GROUP BY clients.client_name,book.book_name WITH CUBE
ROLLUP参数会依据GROUP BY后面所列第一个字段做汇总运算。如果要检索不同客户定购的各种书的总量和所有书的总量,可执行下述SQL语句:
FROM clients,orderform,book
WHERE clients.client_id=orderform.client_id AND book.book_id=orderform.book_id
GROUP BY clients.client_name,book.book_name WITH ROLLUP
7.1.1.3 HAVING子句
例如,下面的SQL语句用于查询定购书量大于等于40本的客户名称和书名:
SELECT clients.client_name,book.book_name,
SUM(orderform.book_number) AS 书籍总数
FROM clients,orderform,book
WHERE clients.client_id=orderform.client_id AND book.book_id=orderform.book_id
GROUP BY clients.client_name,book.book_name
HAVING SUM(orderform.book_number)>=40
7.1.1.4 COMPUTE和COMPUTE BY子句
例如,下面就是使用COMPUTE子句的例子:
SELECT clients.client_name,book.book_name,orderform.book_number
FROM clients,orderform,book
WHERE clients.client_id=orderform.client_id AND book.book_id=orderform.book_id
COMPUTE SUM(orderform.book_number)
如果需要各个客户的定购数量,而不是总的定购数量,则可执行下面的SQL语句:
FROM clients,orderform,book
WHERE clients.client_id=orderform.client_id AND book.book_id=orderform.book_id
ORDER BY clients.client_name
COMPUTE SUM(orderform.book_number) BY clients.client_name
7.1.2 联接查询
例如,下面使用联接查询书名称及其作者:
USE bookdb
GO
SELECT book_name,author_name FROM book JOIN authors
ON (book.author_id=authors.author_id)
GO
无法在ntext、text或image列上直接联接表。不过,可以用SUBSTRING在ntext、text或image列上间接联接表。例如:
SELECT * FROM t1 JOIN t2 ON SUBSTRING(t1.textcolumn, 1, 20)
= SUBSTRING(t2.textcolumn, 1, 20)
在表t1和t2中的每个文本列前20个字符上进行两表内联接。此外,另一种比较两个表中的ntext或text列的方法是用WHERE子句比较列的长度。例如:
WHERE DATALENGTH(p1.pr_info) = DATALENGTH(p2.pr_info)
7.1.2.1 内联接
内联接使用INNER JOIN关键词,上面查询书名称及其作者的例子就是一个内联接的例子,也可以按下面方式查询:
USE bookdb
GO
SELECT book_name,author_name FROM book INNER JOIN authors
ON (book.author_id=authors.author_id)
GO
7.1.2.2 外联接
1.左向外联接
例如,下面的SQL语句首先删除order_id为7的订单(定购的书籍为《Windows 2000 Professional 中文版使用指南》),然后查询那本书没有被定购:
USE bookdb
GO
DELETE orderform WHERE order_id=7
GO
SELECT orderform.order_date,book.book_name, orderform.book_number
FROM book LEFT OUTER JOIN orderform ON (book.book_id=orderform.book_id)
GO
2.右向外联接
实际上,右向外联接和左向外联接的的功能是一样的,例如,将上面的示例中,将FROM子句中book表和orderform表交换一下位置,然后使用RIGHT OUTER JOIN:
USE bookdb
GO
SELECT orderform.order_date,book.book_name, orderform.book_number
FROM orderform RIGHT OUTER JOIN book ON (book.book_id=orderform.book_id)
GO
7.1.2.3 交叉联接
例如,下面的SQL语句使用交叉联接产生客户和作者可能的组合:
USE bookdb
GO
SELECT clients.client_name,authors.author_name
FROM clients CROSS JOIN authors
GO
7.1.3 子查询
例如,下面的SQL语句使用子查询来查询《Windows 2000 网络管理》一书的作者:
USE bookdb
GO
SELECT author_name FROM authors
WHERE author_id =
(SELECT author_id
FROM book
WHERE book_name='Windows 2000 网络管理')
GO
使用下面的联接方式也能完成此功能:
USE bookdb
GO
SELECT author_name
FROM authors JOIN book ON(book.author_id=authors.author_id)
WHERE book_name='Windows 2000 网络管理'
GO
7.1.3.2 子查询类型
1.使用IN或NOT IN
例如,下面的SQL语句查询已经被定购的书的名称和出版社:
USE bookdb
GO
SELECT book_name,publisher
FROM book
WHERE book_id IN(
SELECT book_id
FROM orderform)
GO
如果要查询没有被定购的书籍,则可以使用NOT IN:
USE bookdb
GO
SELECT book_name,publisher
FROM book
WHERE book_id NOT IN(
SELECT book_id
FROM orderform)
GO
2.UPDATE、DELETE和INSERT语句中的子查询
子查询可以嵌套在UPDATE、DELETE和INSERT语句以及SELECT语句中。例如,删除没有被定购的书籍信息:
USE bookdb
GO
DELETE book
WHERE book_id NOT IN(
SELECT book_id
FROM orderform)
GO
SELECT * FROM book
GO
3.比较运算符的子查询
例如,下面查找大于平均价格的书籍:
USE bookdb
GO
SELECT DISTINCT book.book_name
FROM book
WHERE price >
(SELECT AVG(price)
FROM book)
GO
例如,下面返回价格最高的一本书的书名:
USE bookdb
GO
SELECT book.book_name
FROM book
WHERE price >=ALL
(SELECT price
FROM book)
GO
4.存在性检查
例如,要查询所有被定购的书籍名称及其相应的出版社,可使用下面的SQL语句:
USE bookdb
GO
SELECT book_name,publisher
FROM book
WHERE EXISTS(
SELECT *
FROM orderform)
GO
7.1.3.3 多层嵌套
例如,下面使用多层嵌套子查询来查询客户“科技书店”所定购的书籍名称:
USE bookdb
GO
SELECT book_name
FROM book
WHERE book_id IN(
SELECT book_id
FROM orderform
WHERE client_id=(
SELECT client_id
FROM clients
WHERE client_name='科技书店')
)
GO
7.1.3.4 相关子查询
例如,下面使用相关子查询查询名为“刘耀儒”的作者所著的书目:
USE bookdb
GO
SELECT book_name
FROM book
WHERE '刘耀儒' IN
(SELECT author_name
FROM authors
WHERE authors.author_id = book.author_id)
GO
7.1.4 使用UNION运算符组合多个结果
例如,要查询所有作者和客户的号码和名称,可使用下面的SQL语句:
USE bookdb
GO
SELECT author_id,author_name FROM authors
UNION
SELECT client_id,client_name FROM clients
GO
7.1.5 在查询的基础上创建新表
例如,下面的SQL语句将查询得到的书名和作者插入到新建的表author_book中:
USE bookdb
GO
SELECT book.book_name,authors.author_name
INTO author_book
FROM authors,book
WHERE authors.author_id=book.author_id
GO
执行结果可通过下面的SELECT语句来查看:
SELECT * FROM author_book
7.2 错误处理
7.2.1 使用@@ERROR全局变量处理错误
例如,下述语句就是一个使用@@ERROR的例子:
USE bookdb
GO
SELECT * FROM book
GO
IF @@ERROR=0
PRINT '执行成功!'
GO
7.2.2 使用RAISERROR
例如,下面的例子在返回给应用程序的消息中替换了DB_ID和DB_NAME函数的值:
DECLARE @DBID INT
SET @DBID = DB_ID()

DECLARE @DBNAME NVARCHAR(128)
SET @DBNAME = DB_NAME()

RAISERROR
('The current database ID is:%d, the database name is: %s.',
16, 1, @DBID, @DBNAME)
而以下例子使用由用户定义的消息完成了同样的处理:
EXEC sp_addmessage 50005, 16,
'The current database ID is:%d, the database name is: %s.','us_english'
GO
DECLARE @DBID INT
SET @DBID = DB_ID()

DECLARE @DBNAME NVARCHAR(128)
SET @DBNAME = DB_NAME()

RAISERROR (50005, 16, 1, @DBID, @DBNAME)
GO
7.3 管理ntext、text和image数据
例如,下面的SQL语句在test数据库中创建一个text1表,其中c2字段的数据类型为text,并插入一笔记录:
USE test
GO
CREATE TABLE text1 (c1 int, c2 text)
EXEC sp_tableoption 'text1', 'text in row', 'on'
INSERT text1 VALUES ('1', 'This is a text.')
GO
然后执行下面的SQL语句:
SELECT * FROM text1
7.3.1 检索ntext、text或image值
1.在SELECT语句中引用该列
例如,可使用下面的语句将TEXTSIZE改为64512:
SET TEXTSIZE 64512
如果要改为默认值,则可以使用下面的SQL语句:
SET TEXTSIZE 0
2.使用TEXTPTR函数可获得传递给READTEXT语句的文本指针
例如,下面读取text1表的c2字段的第1到第7个字符:
--在对text数据类型的对象使用指针前,应将text in row选项关闭
EXEC sp_tableoption 'text1', 'text in row', 'off'
DECLARE @ptrval varbinary(16)
SELECT @ptrval = TEXTPTR(c2)
FROM text1
READTEXT text1.c2 @ptrval 0 7
3.使用SUBSTRING函数可检索从列开头特定偏移位置开始的数据块
例如,可以使用下面的SQL语句来检索text1表的c2字段的第1到第7个字符:
SELECT SUBSTRING(c2, 1, 7) AS c2
FROM text1
3.使用PATINDEX函数可检索一些特定字节组合的偏移量
例如,下面的SQL语句检索字符a位于c2字段的第几个:
USE test
GO
SELECT PATINDEX('%a%',c2) AS 起始位置
FROM text1
GO
7.3.2 修改ntext、text或image值
2.使用WRITETEXT语句重写该列的整个数据值
例如,下面的SQL语句修改test数据库中的text1表的字符串值:
USE test
GO
DECLARE @ptrval varbinary(16)
SELECT @ptrval = TEXTPTR(c2) FROM text1
WRITETEXT text1.c2 @ptrval 'This is a modified text.'
GO
SELECT * FROM text1
GO
3.使用UPDATETEXT语句更新ntext、text或image列的特定数据块
例如,下面的SQL语句在text1表的c2字段的末尾加入字符串This is an inserted text.:
USE test
GO
DECLARE @ptrval varbinary(16)
SELECT @ptrval = TEXTPTR(c2)
FROM text1
UPDATETEXT text1.c2 @ptrval NULL 0 'This is an inserted text.'
GO
SELECT * FROM text1
GO
7.4 事务处理
7.3.2 显式事务
4.在事务内设置保存点
例如:
USE bookdb
GO
BEGIN TRAN MyTran --启动事务
INSERT INTO book
VALUES(9,'Windows 2000 Professional 看图速成',1,35,'21世纪出版社') --插入一笔记录

SAVE TRAN MySave --保存点

DELETE book WHERE book_id=9 --删除记录

ROLLBACK TRAN MySave --回滚事务
COMMIT TRAN
GO
SELECT * FROM book --查询book表的记录
GO
7.3.3 自动提交事务
在下面的例子中,由于编译错误,第三个批处理中的任何INSERT语句都没有执行(没有返回显示结果)。但看上去好像是前两个INSERT语句没有执行便进行了回滚:
USE test
GO
CREATE TABLE TestBatch (Cola INT PRIMARY KEY, Colb CHAR(3))
GO
INSERT INTO TestBatch VALUES (1, 'aaa')
INSERT INTO TestBatch VALUES (2, 'bbb')
INSERT INTO TestBatch VALUSE (3, 'ccc') /*符号错误*/
GO
SELECT * FROM TestBatch /*不会返回任何结果*/
GO
7.3.4 隐式事务
下的SQL语句演示了在将IMPLICIT_TRANSACTIONS设置为ON时显式或隐式启动事务。它使用@@TRANCOUNT函数演示打开的事务和关闭的事务:
USE test
GO

SET NOCOUNT ON --不显示受影响的行数
CREATE table t1 (a int)
GO
INSERT INTO t1 VALUES (1)
GO

PRINT '使用显示事务'
BEGIN TRAN
INSERT INTO t1 VALUES (2)
PRINT '事务内的事务数目: '+ CAST(@@TRANCOUNT AS char(5))
COMMIT TRAN
PRINT '事务外的事务数目: '+ CAST(@@TRANCOUNT AS char(5))
GO

PRINT '设置IMPLICIT_TRANSACTIONS为ON'
GO
SET IMPLICIT_TRANSACTIONS ON
GO

PRINT '使用隐式事务'
GO
--这里不需要BEGIN TRAN语句来定义事务的启动
INSERT INTO t1 VALUES (4)
PRINT '事务内的事务数目: '+ CAST(@@TRANCOUNT AS char(5))
COMMIT TRAN
PRINT '事务外的事务数目: '+ CAST(@@TRANCOUNT AS char(5))
GO
7.5 数据的锁定
7.5.4 自定义锁
2.自定义锁超时
若要查看当前LOCK_TIMEOUT的值,可以使用@@LOCK_TIMEOUT全局变量。例如,下面的SQL语句设置LOCK_TIMEOUT的值为1800毫秒,并使用@@LOCK_TIMEOUT来显示该值:
SET LOCK_TIMEOUT 1800
GO
DECLARE @Timeout int
SELECT @Timeout = @@lock_timeout
PRINT @Timeout
GO
3.自定义事务隔离级别
例如,若要设置事务隔离级别为可串行读,以确保并发事务不能在book表中插入幻像行,则可执行下述SQL语句:
USE bookdb
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
SELECT * FROM book
GO
若要确定当前设置的事务隔离级别,可以使用DBCC USEROPTIONS语句,例如:
USE bookdb
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
DBCC USEROPTIONS
GO
4.锁定提示
例如,如果将事务隔离级别设置为SERIALIZABLE,并且在SELECT语句中使用表级锁定提示NOLOCK,则可执行下面的SQL语句:
USE bookdb
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
SELECT book_name FROM book WITH (NOLOCK)
GO
可以使用sp_lock存储过程来查看锁定:
EXEC sp_lock
GO
可以使用object_name函数来返回此锁定的数据库对象(表):
SELECT object_name(1029578706)
GO
7.6 使用游标
7.6.1 游标的概念
7.6.2 使用游标
3.从打开的游标中提取行
例如:
USE bookdb
GO
SET NOCOUNT ON
UPDATE book SET book_name = 'LINUX教程'
WHERE book_id = 20
IF @@ROWCOUNT = 0
print '没有行被更新!'
GO
6.游标示例
下面是一个简单的游标使用的例子:
/*声明游标*/
DECLARE book_cursor CURSOR
FOR SELECT * FROM book
/*打开游标*/
OPEN book_cursor
/*提取第一行数据*/
FETCH NEXT FROM book_cursor
/*关闭和释放游标*/
CLOSE book_cursor
DEALLOCATE book_cursor
下面使用游标打印一个简单的书籍信息的表格:
USE bookdb
GO
SET NOCOUNT ON
/*打印表标题*/
PRINT ' *********书籍信息表***********'
PRINT ' '
PRINT '-----------------------------------------------------------------'
PRINT '| 书 名 | 作 者 |价格|'
PRINT '-----------------------------------------------------------------'
/*声明变量*/
DECLARE @bookname varchar(100), @authorname varchar(20),
@bookprice varchar(40),@pubname varchar(80)

/*声明游标*/
DECLARE book_cursor CURSOR
FOR SELECT book_name,author_name,price FROM book,authors
WHERE book.author_id=authors.author_id
/*打开游标*/
OPEN book_cursor
/*提取第一行数据*/
FETCH NEXT FROM book_cursor
INTO @bookname, @authorname, @bookprice

WHILE @@FETCH_STATUS = 0
BEGIN
/*打印数据*/
PRINT '|'+@bookname+'|'+@authorname+'|'+CAST(@bookprice AS char(5))+'|'
PRINT '-----------------------------------------------------------------'
/*提取下一行数据*/
FETCH NEXT FROM book_cursor
INTO @bookname, @authorname, @bookprice
END

/*关闭和释放游标*/
CLOSE book_cursor
DEALLOCATE book_cursor
GO
7.7 小结
参考答案:
1.可以使用下面的SQL语句:
USE bookdb
GO
SELECT clients.client_name,SUM(orderform.book_number*book.price) AS 总金额
FROM clients,orderform,book
WHERE clients.client_id=orderform.client_id AND orderform.book_id = book.book_id
GROUP BY clients.client_name
2.可以使用下面的SQL语句:
USE bookdb
GO
SELECT * FROM book
WHERE book_id NOT IN(
SELECT book_id
FROM orderform)
3.使用UNION组合两个结果。

第8章 视 图
8.2 创建视图
8.2.3 使用SQL语句创建视图
例如,下面的SQL语句创建book_total视图,其中包括了书名、价格、定购的数量和总额:
USE bookdb
GO
CREATE VIEW dbo.book_total
AS
SELECT dbo.book.book_name AS 书名, dbo.book.price AS 价格,
dbo.orderform.book_number AS 数量,
dbo.book.price*dbo.orderform.book_number AS 总额
FROM dbo.orderform INNER JOIN
dbo.book ON dbo.orderform.book_id = dbo.book.book_id
GO
8.3 使用视图
8.3.1 使用视图进行数据检索
使用视图来检索数据,可以像对表一样来对视图进行操作。例如,使用上面创建的book_total视图来查询所有定购书籍的书名及其总金额:
SELECT 书名,总额 FROM book_total
8.3.2 通过视图修改数据
例如,下面的SQL语句在test数据库中创建一个表和基于该表的视图,并利用视图插入了一笔记录:
USE test
GO
/*如果表Table1存在,则删除*/
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Table1')
DROP TABLE Table1
GO
/*如果视图View1存在,则删除*/
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_NAME = 'View1')
DROP VIEW View1
GO
/*创建表Table1*/
CREATE TABLE Table1 ( column_1 int, column_2 varchar(30))
GO
/*创建视图View1*/
CREATE VIEW View1 AS SELECT column_2, column_1
FROM Table1
GO
/*通过视图View1插入一笔记录*/
INSERT INTO View1 VALUES ('Row 1',1)
/*查看插入的记录*/
SELECT * FROM Table1
GO
8.4 视图的修改
8.4.2 重命名视图
例如,下面的SQL语句将视图book_info重命名为“书籍信息”:
USE bookdb
GO
EXEC sp_rename 'book_info','书籍信息'
GO
执行下面的语句也可以完成相同的功能:
USE bookdb
GO
EXEC sp_rename 'book_info','书籍信息', 'OBJECT'
GO
8.5 视图信息的查询
8.5.2 使用sp_helptext存储过程
例如,可以使用下面的SQL语句来查看视图“书籍信息”的定义:
EXEC sp_helptext '书籍信息'
8.6 视图的删除
8.6.2 使用Transact-SQL
例如,下面的语句检查test数据库中是否有View1视图,若有,则删除:
USE test
GO
/*如果视图View1存在,则删除*/
IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_NAME = 'View1')
DROP VIEW View1
GO
8.7 小 结
答案:
3.参考SQL语句如下:
CREATE VIEW dbo.订单
AS
SELECT dbo.orderform.order_date AS 定购日期, dbo.book.book_name AS 书名,
dbo.book.price AS 单价, dbo.orderform.book_number AS 数量,
dbo.clients.client_name AS 客户名,
dbo.orderform.book_number * dbo.book.price AS 总额
FROM dbo.book INNER JOIN
dbo.orderform ON dbo.book.book_id = dbo.orderform.book_id INNER JOIN
dbo.clients ON dbo.orderform.client_id = dbo.clients.client_id

第9章 数据库完整性
9.1 约 束
9.1.1 PRIMARY KEY约束
例如,下面的SQL语句创建一个名为student的表,其中指定student_number为主键:
USE test
GO
CREATE TABLE student
(sutdent_number int PRIMARY KEY,
student_name char(30))
GO
9.1.2 FOREIGN KEY约束
例如,下面就是一个使用FOREIGN KEY约束的例子:
CREATE TABLE product
(product_number int,
student_number int
FOREIGN KEY REFERENCES student(student_number)
ON DELETE NO ACTION)
GO
9.1.3 UNIQUE约束
例如,下面的SQL语句创建了一个test2表,其中指定了c1字段不能包含重复的值:
USE test
GO
CREATE TABLE test2
(c1 int UNIQUE,
c2 int)
GO
INSERT test2 VALUES(1,100)
GO
如果再插入一行:
INSERT test2 VALUES(1,200)
9.1.4 CHECK约束
例如,下面的SQL语句创建一个成绩(score)表,其中使用CHECK约束来限定成绩只能在0~100分之间:
CREATE TABLE score
(sutdent_number int,
score int NOT NULL CHECK(score>=0 AND score <=100)
)
9.2 默认值
9.2.1 在创建表时指定默认值
例如,下面在test数据库中创建一个datetest表,其中c2指定默认值未当前日期:
USE test
GO
CREATE TABLE datetest(
c1 int,
c2 datetime DEFAULT (getdate())
)
然后插入一行数据:
INSERT datetest(c1) VALUES(1)
SELECT * FROM datetest
同样,可以给bookdb数据库中的orderform表中的order_date字段加上默认值:
USE bookdb
GO
ALTER TABLE orderform
ADD
CONSTRAINT DateDflt
DEFAULT getdate() FOR order_date
9.2.2 使用默认对象
9.2.2.1 创建默认对象
2.使用CREATE DEFAULT语句
例如,使用下面的SQL语句也可以创建address_default默认对象:
USE bookdb
GO
CREATE DEFAULT address_default AS '无'
GO
9.2.2.2 绑定默认对象
2.使用sp_bindefault存储过程
例如,上面将address_default默认对象绑定到authors表的address列上的操作过程可以使用下面的SQL语句来完成:
USE bookdb
EXEC sp_bindefault 'address_default', 'authors.address'
9.2.2.4 解除默认对象的绑定
例如,下面的SQL语句解除authors表address列上的默认值绑定:
USE bookdb
EXEC sp_unbindefault 'authors.address'
9.2.2.5 删除默认对象
例如,下面的SQL语句判断是否存在address_default默认对象,如果存在则删除该默认对象:
USE bookdb
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'address_default'
AND type = 'D')
DROP DEFAULT address_default
GO
9.3 规 则
9.3.1 创建规则
例如,下面的SQL语句创建一个名为score_rule的规则,限定输入的值必须在0到100之间:
USE test
GO
CREATE RULE score_rule AS @score BETWEEN 0 and 100
而下面创建的规则将输入到该规则所绑定的列中的实际值限制为只能是该规则中列出的值:
USE test
GO
CREATE RULE list_rule AS @list IN ('1997', '1997', '1996')
也可以使用LIKE来创建一个模式规则,即遵循某种格式的规则。例如,要使得该规则指定任意两个字符的后面跟一个连字符和任意多个字符(或没有字符),并以1到6之间的整数结尾,则可以使用下面的SQL语句:
USE test
GO
CREATE RULE pattern_rule
AS
@value LIKE '__-%[1-6]'
9.3.2 绑定规则
例如,下面的SQL语句可以将score_rule规则绑定到score表的score列上:
USE test
EXEC sp_bindrule 'score_rule', 'score.score'
9.3.3 删除规则
例如,要解除绑定到score表的score列上的规则,可以使用下面SQL语句:
USE test
EXEC sp_unbindrule 'score.score'
例如,要删除规则score_rule,可以使用下面的SQL语句:
DROP RULE score_rule
9.4 存储过程
9.4.1 创建存储过程
9.4.1.1 使用CREATE PROCEDURE语句创建
例如,下面创建一个简单的存储过程bookinfopro,用于检索书籍的名称、价格和出版社:
USE bookdb
--判断bookinfopro存储过程是否存在,若存在,则删除
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'bookinfopro' AND type = 'P')
DROP PROCEDURE bookinfopro
GO
USE bookdb
GO
--创建存储过程bookinfopro
CREATE PROCEDURE bookinfopro
AS
SELECT book_name,price,publisher
FROM book
GO
通过下述SQL语句执行该存储过程:
EXECUTE bookinfopro
9.4.2 执行存储过程
例如,下面就是执行简单存储过程的例子:
EXECUTE bookinfopro
9.4.3 存储过程的参数
9.4.3.1 使用参数
例如,下面的SQL语句创建了一个用于向orderform表中插入记录的存储过程Add_Order:
USE bookdb
GO
CREATE PROC Add_Order
(
@order_id int,
@book_id int,
@book_number int,
@order_date datetime,
@client_id int
)
AS
INSERT INTO orderform
VALUES(@order_id,@book_id,@book_number,@order_date,@client_id)
则可以使用下面的SQL语句调用该存储过程:
EXEC Add_Order 7,2,10,'99-05-06',2
另外一种传递参数的方法是采用“@order_id=7”的形式,此时,各个参数的顺序可以任意排列。例如,上面的例子可以这样执行:
EXEC Add_Order @order_id=7, @book_id=2, @book_number=10,
@order_date ='99-05-06', @client_id =2
9.4.3.2 使用默认参数
例如,下面的存储过程就指定了默认值:
USE bookdb
GO
CREATE PROC Add_Author
(
@author_id int,
@author_name char(8),
@address char(50)='无', --默认值为'无'
@telphone char(15)='无' --默认值为'无'
)
AS
INSERT INTO authors
VALUES(@author_id,@author_name,@address,@telphone)
在上面创建的存储过程中,包含4各参数,其中@address和@telphone具有默认值“无”。如果调用该存储过程:
EXEC Add_Author 4,'张三'
GO
SELECT * FROM authors
GO
9.4.3.3 使用返回参数
例如,下面的存储过程Query_book返回两个参数@book_name和@price,分别代表了书名和价格:
CREATE PROC Query_book
(
@book_id int,
@book_name char(50) OUTPUT,
@price float OUTPUT
)
AS
SELECT @price=price,@book_name=book_name
FROM book
WHERE book_id=@book_id
执行该存储过程,来查询book_id为2的书籍的名称和价格:
DECLARE @price float
DECLARE @book_name char(50)
EXEC Query_book 2,@book_name OUTPUT,@price OUTPUT
SELECT '书名'=@book_name,'价格'=@price
GO
9.4.3.4 存储过程的返回值
例如,下面的存储过程根据输入的参数来判断返回值:
USE test
GO
CREATE PROC test_ret
(
@input_int int =0
)
AS
IF @input_int=0
RETURN 0 --如果输入的参数等于0,则返回0
IF @input_int>0
RETURN 1000 --如果输入的参数大于0,则返回1000
IF @input_int<0
RETURN -1000 --如果输入的参数等于0,则返回-1000
执行该存储过程:
DECLARE @Ret_int int
EXEC @Ret_int=test_ret -50
SELECT '返回值'=@Ret_int
9.4.4 存储过程的查看、修改和删除
可以使用sp_helptext存储过程来查看存储过程的定义信息,例如,要查看test_ret存储过程的定义信息,可以执行下面的SQL语句:
EXEC sp_helptext test_ret
例如,要删除test_ret存储过程,可执行下面的SQL语句:
DROP PROCEDURE test_ret
9.5 触发器
9.5.1 创建触发器
9.5.1.1 使用Transact-SQL语句创建
例如,下面是创建一个触发器,在插入记录时,自动显示表中的内容:
USE test
GO
/*如果表T1存在,则删除*/
IF EXISTS(SELECT name FROM sysobjects WHERE name ='T1')
DROP TABLE T1
GO
/*创建表T1 */
CREATE TABLE T1(
student_number int,
student_name char(30)
)
GO
/*如果触发器Query_T1存在,则删除*/
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'Query_T1' AND type = 'TR')
DROP TRIGGER Query_T1
GO
/*创建触发器Query_T1 */
CREATE TRIGGER Query_T1
ON T1
FOR INSERT, UPDATE, DELETE
AS
SELECT * FROM T1
GO
则在执行下面的语句时:
INSERT T1 VALUES(985240,'llyyrr')
9.5.2 inserted表和deleted表
例如,下面的例子说明了inserted表和deleted表的作用:
/*如果触发器Query_T1存在,则删除*/
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'Query_T1' AND type = 'TR')
DROP TRIGGER Query_T1
GO
/*创建触发器Query_T1 */
CREATE TRIGGER Query_T1
ON T1
FOR INSERT, UPDATE, DELETE
AS
SELECT * FROM inserted
SELECT * FROM deleted
GO
如果此时执行下面的UPDATE语句:
UPDATE T1 SET student_name='lyr'
WHERE student_number=985240
9.5.3 使用触发器
9.5.3.1 INSERT和UPDATE触发器
例如,下面创建的check_score触发器可用来检查插入的成绩是否在0到100之间:
USE test
GO
/*检查是否存在score表,若存在,则删除*/
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'score')
DROP TABLE score
GO
/*创建score表*/
CREATE TABLE score
(
student_no int,
score int
)
/*检查是否存在check_score触发器,若存在,则删除*/
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'check_score' AND type = 'TR')
DROP TRIGGER check_score
GO
/*在score表上创建check_score触发器*/
CREATE TRIGGER check_score
ON score
FOR INSERT, UPDATE
AS
DECLARE @score int
SELECT @score=score FROM inserted
IF @score<0 OR @score>100
BEGIN
ROLLBACK
RAISERROR('成绩必须在0到100之间!',16,1)
END
GO
如果此时插入一笔记录:
INSERT score VALUES(985240,150)
9.5.3.2 DELETE触发器
例如,score表种包含了学生的学号和成绩,如果还存在一个T1表(在9.5.1.1一节种创建的T1表),其中包含了学生的学号和姓名,它们之间以学号相关联。
如果要删除T1表中的记录,则与该记录的学号对应的学生成绩也应该删除:
/*向表score中插入一笔记录*/
INSERT score VALUES(985240,85)
GO
/*创建触发器delete_trigger*/
CREATE TRIGGER delete_trigger
ON T1
FOR DELETE
AS
DELETE score WHERE score.student_no=deleted.student_number
GO
此时,要删除T1表中的记录:
DELETE T1 WHERE student_number=985240
则score表中对应的记录也被删除。如果使用SELECT语句来查询score表,将看到该记录已经被删除。
9.5.5 删除触发器
例如,要删除Query_T1触发器,则可以执行下面的SQL语句:
DROP TRIGGER Query_T1

第10章 数据的备份恢复和传输
10.1 备份数据
10.1.2 备份设备
10.1.2.2 使用sp_addumpdevice存储过程
例如,下面创建一个逻辑名为test_backup的备份设备:
USE test
EXEC sp_addumpdevice 'disk', 'test_backup', 'D:/test_backup.bak'
10.1.3 备份数据库
10.1.3.2 使用BACKUP语句
例如,使用下面的SQL语句可以完成上面相同的功能:
BACKUP DATABASE bookdb TO Book_Backup
10.2 数据的恢复
10.2.2 恢复用户数据库
10.2.2.2 使用RESTORE语句
例如,下面的SQL语句用于恢复bookdb数据库:
RESTORE DATABASE bookdb FROM Book_Backup

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值