/*

 2006年10月01日

 SQL Server 数据库的高级操作
(1) 批处理
(2) 变量
(3) 逻辑控制
(4) 视图
(5) 函数
(6) 高级查询 */ (1)批处理
将多条SQL语句作为一个整体去编译,生成一个执行计划,然后,执行!
理解批处理的关键在于"编译",对于由多条语句组成的一个批处理,
如果在编译时,其中,有一条出现语法错误,将会导致编译失败! create table t
(
a int,
b int
) -- 注释
-- 如果多行注释中包含了批处理的标识符go
-- 在编译的过程中代码将会被go分割成多个部分来分批编译
-- 多行注释的标记将会被分隔而导致编译出错
-- 以下几条语句是三个非常经典的批处理
-- 你猜一下会添加几条记录!
/*
insert into t values (1,1)
go
*/
insert into t values (2,2)
go
/*
insert into t values (3,3)
*/
go -- 查询看添加了几条记录
select * from t truncate table t (2)变量 -- 全局变量
SQL Server中全局变量由系统定义、系统维护,用户一般仅可对其进行读取! -- 查看SQL Server版本
print @@version -- 服务器名称
print @@servername -- 系统错误编号
insert into t values ('a','a')
print @@error insert into t values ('a','a')
if @@error = 245
print 'Error' -- SQL Server 版本的语言信息
print @@LANGUAGE -- 一周的第一天从星期几算起
print @@datefirst -- CPU 执行命令所耗费时间的累加
print @@cpu_busy -- 获取最近添加的标识列的值
create table tt
(
a int identity(3, 10),
b int
)
insert into tt (b) values (1)
print @@identity
select * from tt -- 局部变量
局部变量由用户定义,仅可在同一个批处理中调用和访问 declare @intAge tinyint
set @intAge = 12
print @intAge declare @strName varchar(12)
select @strName = 'state'
print @strName
select au_lname, @strName from authors (3)逻辑控制 -- IF条件判断
declare @i int
set @i = 12
if (@i > 10)
begin -- {
print 'Dadadada!'
print 'Dadadada!'
end -- }
else
begin
print 'XiaoXiao!'
print 'XiaoXiao!'
end -- While循环控制
declare @i int;
set @i = 12;
print @i
--return;
while (@i < 18)
begin
print @i;
set @i = @i + 1;
if @i < 17
continue;
if @i > 15
break;
end;
print @i -- CASE 分支判断
select au_lname, state, '犹他州' from authors where state = 'UT'
select au_lname, state, '密西西比州' from authors where state = 'MI'
select au_lname, state, '肯塔基州' from authors where state = 'KS' select au_lname, state,
case state
when 'UT' then '犹他州'
when 'MI' then '密西西比州'
when 'KS' then '肯塔基州'
when 'CA' then '加利福利亚'
else state
end
from authors (3)视图
-- Northwind 数据库中Employees表
-- 创建视图显示每个员工的编号(EmployeeID)、姓(FirstName)、名(LastName)以及上级(ReportsTo)的姓
use northwind
go -- 注意:字段ReportsTo指代了每个员工的上级的编号
select EmployeeID, FirstName, LastName, ReportsTo
from employees
go -- 寻找每个员工的上级
-- 子查询
select emp.EmployeeID, emp.FirstName, emp.LastName,
(select mag.FirstName from employees as mag where emp.ReportsTo = mag.EmployeeID ) as ManagerFirstName
from employees as emp
go (4.1)系统函数 -- 获取指定字符串中左起第一个字符的ASC码
print ascii('ABCDEF')
-- 根据给定的ASC码获取相应的字符
print char(65)
-- 获取给定字符串的长度
print len('abcdef')
-- 大小写转换
print lower('ABCDEF')
print upper('abcdef')
-- 去空格
print ltrim(' abcd dfd df ')
print rtrim(' abcd dfd df ')
-- 求绝对值
print abs(-12)
-- 幂
-- 3 的 2 次方
print power(3,2)
print power(3,3)
-- 随机数
-- 0 - 1000 之间的随机数
print rand() * 1000
-- 获取圆周率
print pi() -- 获取系统时间
print getdate() -- 获取3天前的时间
print dateadd(day, -3 , getdate())
-- 获取3天后的时间
print dateadd(day, 3 , getdate())
-- 获取3年前的时间
print dateadd(year, -3 , getdate())
-- 获取3年后的时间
print dateadd(year, 3 , getdate()) -- 获取3月后的时间
print dateadd(month, 3 , getdate())
-- 获取9小时后的时间
print dateadd(hour, 9 , getdate())
-- 获取9分钟后的时间
print dateadd(minute, 9 , getdate()) -- 获取指定时间之间相隔多少年
print datediff(year, '2005-01-01', '2008-01-01')
-- 获取指定时间之间相隔多少月
print datediff(month, '2005-01-01', '2008-01-01')
-- 获取指定时间之间相隔多少天
print datediff(day, '2005-01-01', '2008-01-01') -- 字符串合并
print 'abc' + 'def' print 'abcder' print 'abc' + ''
print 'abc' + 456 -- 类型转换
print 'abc' + convert(varchar(10), 456) select title_id, type, price from titles
-- 字符串连接必须保证类型一致(以下语句执行将会出错)
-- 类型转换
select title_id + type + price from titles
-- 正确
select title_id + type + convert(varchar(10), price) from titles print '' + convert(varchar(3), 123)
print '' + '' print convert(varchar(12), '2005-09-01',110) -- 获取指定时间的特定部分
print year(getdate())
print month(getdate())
print day(getdate()) -- 获取指定时间的特定部分
print datepart(year, getdate())
print datepart(month, getdate())
print datepart(day, getdate())
print datepart(hh, getdate())
print datepart(mi, getdate())
print datepart(ss, getdate())
print datepart(ms, getdate()) -- 获取指定时间的间隔部分
-- 返回跨两个指定日期的日期和时间边界数
print datediff(year, '2001-01-01', '2008-08-08')
print datediff(month, '2001-01-01', '2008-08-08')
print datediff(day, '2001-01-01', '2008-08-08')
print datediff(hour, '2001-01-01', '2008-08-08')
print datediff(mi, '2001-01-01', '2008-08-08')
print datediff(ss, '2001-01-01', '2008-08-08') -- 在向指定日期加上一段时间的基础上,返回新的 datetime 值
print dateadd(year, 5, getdate())
print dateadd(month, 5, getdate())
print dateadd(day, 5, getdate())
print dateadd(hour, 5, getdate())
print dateadd(mi, 5, getdate())
print dateadd(ss, 5, getdate()) -- 其他
print host_id()
print host_name()
print db_id('pubs')
print db_name(5) -- 利用系统函数作为默认值约束
drop table ttt create table ttt
(
stu_name varchar(12),
stu_birthday datetime default (getdate())
) alter table ttt
add constraint df_ttt_stu_birthday default (getdate()) for stu_birthday insert into ttt values ('ANiu', '2005-04-01')
insert into ttt values ('ANiu', getdate()) insert into ttt values ('AZhu', default) sp_help ttt select * from ttt (4.2)自定义函数 select title_id
from titles
where type = 'business' select stuff(title_id,1,3,'ABB'), type
from titles
where type = 'business' select count(title_id) from titles where type = 'business'
select title_id from titles where type = 'business' select *,count(dbo.titleauthor.title_id)
FROM dbo.authors INNER JOIN
dbo.titleauthor ON dbo.authors.au_id = dbo.titleauthor.au_id select au_id, count(title_id)
from titleauthor
group by au_id SELECT dbo.authors.au_id, COUNT(dbo.titleauthor.title_id) AS '作品数量'
FROM dbo.authors left outer JOIN
dbo.titleauthor ON dbo.authors.au_id = dbo.titleauthor.au_id
GROUP BY dbo.authors.au_id
order by '作品数量' -- 自定义函数的引子(通过这个子查询来引入函数的作用) -- 子查询
-- 统计每个作者的作品数
-- 将父查询中的作者编号传入子查询
-- 作为查询条件利用聚合函数count统计其作品数量
select au_lname,
(select count(title_id)
from titleauthor as ta
where ta.au_id = a.au_id
) as TitleCount
from authors as a
order by TitleCount -- 是否可以定义一个函数
-- 将作者编号作为参数统计其作品数量并将其返回
select au_id, au_lname, dbo.GetTitleCountByAuID(au_id) as TitleCount
from authors
order by TitleCount -- 根据给定的作者编号获取其相应的作品数量
create function GetTitleCountByAuID(@au_id varchar(12))
returns int
begin
return (select count(title_id)
from titleauthor
where au_id = @au_id)
end -- 利用函数来显示每个作者的作品数量
create proc pro_CalTitleCount
as
select au_id, au_lname, dbo.GetTitleCountByAuID(au_id) as TitleCount
from authors
order by TitleCount
go -- 执行存储过程
execute pro_CalTitleCount -- vb中函数定义格式
function GetTitleCountByAuID(au_id as string) as integer ....... GetTitleCountByAuID = ?
end function -- SALES 作品销售信息
select * from sales -- 根据书籍编号查询其销售记录(其中,qty 表示销量)
select * from sales where title_id = 'BU1032' -- 根据书籍编号统计其总销售量(其中,qty 表示销量)
select sum(qty) from sales where title_id = 'BU1032' -- 利用分组语句(group by),根据书籍编号统计每本书总销售量(其中,qty 表示销量)
select title_id, sum(qty) from sales group by title_id -- 是否可以考虑定义一个函数根据书籍编号来计算其总销售量
-- 然后,将其应用到任何一条包含了书籍编号的查询语句中
select title_id, title, dbo.GetTotalSaleByTitleID(title_id) as TotalSales
from titles
order by TotalSales -- 定义一个函数根据书籍编号来计算其总销售量
create function GetTotalSaleByTitleID(@tid varchar(24))
returns int
begin
return(select sum(qty) from sales where title_id = @tid)
end select count(title_id) + 1
from titles
where dbo.GetTotalSaleByTitleID(title_id) > dbo.GetTotalSaleByTitleID('pc1035') -- 删除函数
drop function GetRankByTitleId -- 根据书籍编号计算其销量排名
create function GetRankByTitleId(@tid varchar(24))
returns int
begin
return (select count(title_id) + 1
from titles
where dbo.GetTotalSaleByTitleID(title_id) > dbo.GetTotalSaleByTitleID(@tid))
end -- 统计书籍销量的前10位
-- 其中,可以利用函数计算结果的别名作为排序子句的参照列
select top 10 title_id, title, dbo.GetTotalSaleByTitleID(title_id) as TotalSales
from titles
order by TotalSales desc -- 书籍销量排名视图
create view viewToalSales
as
select title_id, title, dbo.GetTotalSaleByTitleID(title_id) as TotalSales
from titles
go select * from viewToalSales; -- 根据书籍编号计算其销量排名
create function GetTheRankOfTitle(@id varchar(20))
returns int
begin
return(select count(TotalSales) + 1
from viewToalSales
where TotalSales > dbo.GetTotalSaleByTitleID(@id))
end -- 根据书籍编号计算其销量排名
select dbo.GetTheRankOfTitle('pc1035') from titles -- 在查询语句中利用函数统计每本书的总销量和总排名
select title_id, title,
dbo.GetTotalSaleByTitleID(title_id) as TotalSales,
dbo.GetRankByTitleId(title_id) as TotalRank
from titles
order by TotalSales desc -- 查看表结构
sp_help titles
-- 查看存储过程的定义内容
sp_helptext GetRankByTitleId
sp_helptext sp_helptext
sp_helptext xp_cmdshell -- [ORDER DETAILS] 订单详细信息
select * from [order details]
select * from [order details] where productid = 23
-- 根据产品编号在订单详细信息表中统计总销售量
select sum(quantity) from [order details] where productid = 23 -- 构造一个函数根据产品编号在订单详细信息表中统计总销售量
create function GetTotalSaleByPID(@Pid varchar(12))
returns int
begin
return(select sum(quantity) from [order details] where productid = @Pid)
end select * from products
-- 在产品表中查询,统计每一样产品的总销量
select productid, productname, dbo.GetTotalSaleByPID(productid) from products --
CREATE FUNCTION LargeOrderShippers ( @FreightParm money )
RETURNS @OrderShipperTab TABLE
(
ShipperID int,
ShipperName nvarchar(80),
OrderID int,
ShippedDate datetime,
Freight money
)
AS
BEGIN
INSERT @OrderShipperTab
SELECT S.ShipperID, S.CompanyName,
O.OrderID, O.ShippedDate, O.Freight
FROM Shippers AS S INNER JOIN Orders AS O
ON S.ShipperID = O.ShipVia
WHERE O.Freight > @FreightParm
RETURN
END SELECT * FROM LargeOrderShippers( $500 ) -- 根据作者编号计算其所得版权费
create function fun_RoyalTyper ( @au_id id)
returns int
as
begin
declare @rt int
select @rt = sum(royaltyper) from titleauthor where au_id = @au_id
return (@rt)
end
go select top 1 au_lname, au_fname, dbo.fun_RoyalTyper(au_id) as '版权费'
from authors
order by dbo.fun_RoyalTyper(au_id) desc
go create function fun_MaxRoyalTyper_Au_id ()
returns id
as
begin
declare @au_id id
select @au_id = au_id
from authors
order by dbo.fun_RoyalTyper(au_id)
return(@au_id)
end
go select dbo.fun_MaxRoyalTyper_Au_id()
go select au_lname, au_fname, dbo.fun_RoyalTyper(au_id) as '版权税'
from authors
where au_id = dbo.fun_MaxRoyalTyper_Au_id()
go (5)高级查询 select title_id, price from titles -- 查找最高价格
select max(price) from titles -- 查找最贵书籍的价格(排序),如果存在多本价格最贵的书,此方法将会遗漏
select top 1 title_id, price
from titles
order by price desc -- 查找最贵书籍的价格(子查询)
select title_id, price
from titles
where price = (select max(price) from titles) -- 查询指定出版社出版的书(连接)
select p.pub_name as '出版社', t.title as '书籍名称'
from publishers as p join titles as t on p.pub_id = t.pub_id
where pub_name = 'New Moon Books' -- 查询指定出版社出版的书(子查询)
select title
from titles
where pub_id = (select pub_id
from publishers
where pub_name = 'New Moon Books') -- 查询指定出版社出版的书(分开查询)
select title from titles where pub_id = '' select pub_id
from publishers
where pub_name = 'New Moon Books' -- 重点
-- 理解相关子查询的基础
--
select * from titles where type = 'business'
select * from titles where type = 'business123' select * from titles where 1 = 1 -- 在订单表中寻找满足以下条件的订单编号以及相应的客户编号
-- 在详细订单表中存在对应的订单编号并且其中包含产品编号为23的产品
-- 然后将产品编号为23的产品订购量返回判断是否大于20
USE northwind SELECT orderid, customerid
FROM orders AS or1
WHERE 20 < (SELECT quantity FROM [order details] AS od
WHERE or1.orderid = od.orderid
AND od.productid = 23)
GO SELECT au_lname, au_fname
FROM authors
WHERE 100 IN
(
SELECT royaltyper FROM titleauthor
WHERE titleauthor.au_ID = authors.au_id
) select authors.au_lname,authors.au_fname
from authors join titleauthor on titleauthor.au_ID=authors.au_id
where titleauthor.royaltyper =100 USE pubs SELECT au_lname, au_fname
FROM authors
WHERE au_id IN
(SELECT au_id
FROM titleauthor
WHERE title_id IN
(SELECT title_id
FROM titles
WHERE type = 'popular_comp')) select distinct t.type, a.au_lname, a.au_fname
from authors as a join titleauthor as ta on a.au_id = ta.au_id
join titles as t on ta.title_id = t.title_id
where t.type = 'business' -- 查找类型为'business'或是'trad_cook'类型的书籍
select * from titles where type = 'business'
select * from titles where type = 'trad_cook' -- 查找类型为'business'或是'trad_cook'类型的书籍(Or)
select * from titles
where type = 'business' or type = 'trad_cook' -- 查找类型为'business'或是'trad_cook'类型的书籍(In)
select * from titles
where type in ('business', 'trad_cook') -- 查找来自'KS'或是'UT'的作者
select au_lname, state from authors
where state = 'KS'
select au_lname, state from authors
where state = 'UT' -- 查找来自'KS'或是'UT'的作者(Or)
select au_lname, state from authors
where state = 'UT' or state = 'KS' -- 查找来自'KS'或是'UT'的作者(In)
select au_lname, state from authors
where state in ('UT', 'KS') select au_lname, state from authors
where state not in ('UT', 'KS') -- 查找出版了类型为'business'类型的书籍的出版社
SELECT pub_id FROM titles WHERE type = 'business' SELECT pub_id,pub_name
FROM publishers
WHERE pub_id IN ('', '') -- 查找出版了类型为'business'类型的书籍的出版社(In和子查询)
SELECT pub_id,pub_name
FROM publishers
WHERE pub_id IN
(SELECT pub_id
FROM titles
WHERE type = 'business') SELECT title, advance
FROM titles
WHERE advance >
(
SELECT MAX(advance)
FROM publishers INNER JOIN titles ON
titles.pub_id = publishers.pub_id
WHERE pub_name = 'Algodata Infosystems'
) SELECT title, advance
FROM titles
WHERE advance > all
(
SELECT advance
FROM publishers INNER JOIN titles ON
titles.pub_id = publishers.pub_id
WHERE pub_name = 'Algodata Infosystems'
and advance is not null
) declare @i int
set @i = 12
if @i < null
print 'DDDDD'
else
print 'XXXXX' SELECT advance
FROM publishers INNER JOIN titles ON
titles.pub_id = publishers.pub_id
WHERE pub_name = 'Algodata Infosystems' select title_id, price from titles
where price > all
(
select price from titles where type = 'business'
) select title_id, price from titles
where price >
(
select max(price) from titles where type = 'business'
) select title_id, price from titles
where price > any
(
select price from titles where type = 'business'
) select title_id, price from titles
where price >
(
select min(price) from titles where type = 'business'
) select price from titles where type = 'business' if exists(select * from titles where type = '')
print 'ZZZZZ'
else
print 'BBBBB' if exists(select * from authors
where city = 'Berkeley' and state ='UT')
print 'Welcome'
else
print 'Bye-Bye' -- 筛选出'business'以及'trad_cook'类型的书籍(联合查询)
select title_id, type from titles where type = 'business'
union
select title_id, type from titles where type = 'trad_cook' -- 统计'business'类型的书籍的总价(联合查询)
select title, price from titles where type = 'business'
union
select '合计:', sum(price) from titles where type = 'business' -- 统计所有书籍的类型剔除重复(Distinct)
select distinct type from titles -- 作者记录的复制(Select Into)
select * into au from authors select * from au -- 查看数据表结构(Select Into并没有对数据表的约束进行复制)
sp_help authors
sp_help au -- 分页(子查询的经典应用之一) -- Jobs 职务信息表(pubs 数据库)
-- 在实际项目中,显示职务信息时,而职务信息量非常庞大,可能需要将其分为若干个页面来显示
-- 比如:每页显示4条记录,那么,第一页将显示1,2,3,4,第二页将显示5,6,7,8。。。。。 -- 显示所有信息
SELECT * FROM jobs
-- 显示前 4 信息
select top 4 * from jobs
-- 显示前 8 信息
select top 8 * from jobs
-- 显示前 12 信息
select top 12 * from jobs -- 寻找规律,每一页的信息源于前(页面大小 * 页码)条信息的反序结果的前 页面大小 条记录
-- 比如:第二页就是前 8 条记录的反序结果的前 4 条
select top 4 *
from (select top 8 * from jobs) as tt
order by job_id desc -- 当然,对于期望按升序显示查询结果的要求可以对查询结果进行再次排序
select * from
(select top 4 *
from (select top 8 * from jobs) as tt
order by job_id desc) as stt
order by job_id -- SQL 命令中不支持在 select 的查询列表中直接使用局部变量
-- 比如:select top @PageSize * from jobs
-- 那么,可以考虑对sql命令进行拼装,然后,利用系统存储过程 sp_executesql 来执行
exec sp_executesql N'Select * from jobs' -- 存储过程的实现
-- 其中,@CurrentPageSize用于确定最后一页的页面大小
create proc proGetJobsByPage
@CurrentPageSize int,
@PageSize int,
@CurrentPage int
as
Declare @strSql nvarchar(400)
set @strSql = 'select * from
(select top ' + convert(nvarchar(4), @CurrentPageSize) + ' *
from (select top ' + convert(nvarchar(4),(@PageSize * @CurrentPage)) + ' * from jobs) as tt
order by job_id desc) as stt
order by job_id'
exec sp_executesql @strSql
go -- 测试
exec proGetJobsByPage 2, 4, 4 (6)存储过程 -- 扩展存储过程 -- 查询系统目录下文件信息
xp_cmdshell 'dir *.*' -- 启动Windows系统服务
xp_cmdshell 'net start iisadmin' (7)游标 -- 游标的五个基本操作步骤: -- 声明
declare cur_titles cursor
for
select title, price from titles -- 打开
open cur_titles -- 提取
fetch cur_titles fetch next from cur_titles -- 关闭
close cur_titles -- 释放
deallocate cur_titles -- 利用游标遍历所有书籍信息,通过冒泡排序法进行比较,找出最高价格的书
-- 这一段为批处理版
-- 与批处理版相比,存储过程版更方便调试以及代码的重用 -- 声明
declare cur_titles cursor
for select title, price from titles -- 打开
open cur_titles declare @title varchar(80)
declare @price numeric(9,4) declare @title_temp varchar(80)
declare @price_temp numeric(9,4) -- 提取
fetch cur_titles into @title, @price fetch cur_titles into @title_temp, @price_temp while @@fetch_status = 0
begin
if @price < @price_temp
begin
set @price = @price_temp
set @title = @title_temp
end
fetch cur_titles into @title_temp, @price_temp
end -- 关闭
close cur_titles -- 释放
deallocate cur_titles -- 显示处理结果
print '最贵的书是: ' + @title + ' ' + '价格是: ' + convert(varchar(12),@price)
go -- 定义一个存储过程
-- 利用游标遍历所有书籍信息,通过冒泡排序法进行比较,找出最高价格的书(游标具体应用的经典)
-- 这段存储过程的实现代码相对下面的实现方式略有不同
-- 代码重复,但是思路更清晰
create procedure pro_GetMaxTitle
as
-- 声明
declare cur_titles cursor
for select title, price from titles -- 打开
open cur_titles -- 存储最贵的书籍信息
declare @title varchar(80)
declare @price numeric(9,4)
-- 存储从游标中提取出来的书籍的信息
declare @title_temp varchar(80)
declare @price_temp numeric(9,4) -- 提取
fetch cur_titles into @title, @price
-- 判断是否存在书籍信息
if @@fetch_status <> 0
begin
print '没有书籍信息!'
-- 关闭
close cur_titles
-- 释放
deallocate cur_titles
-- 结束存储过程
return
end fetch cur_titles into @title_temp, @price_temp -- 判断是否只存在一本书
if @@fetch_status <> 0
begin
-- 显示处理结果
print '最贵的书是: ' + @title + ' ' + '价格是: ' + convert(varchar(12),@price)
-- 关闭
close cur_titles
-- 释放
deallocate cur_titles
-- 结束存储过程
return
end while @@fetch_status = 0
begin
if @price < @price_temp
begin
set @price = @price_temp
set @title = @title_temp
end
fetch cur_titles into @title_temp, @price_temp
end -- 显示处理结果
print '最贵的书是: ' + @title + ' ' + '价格是: ' + convert(varchar(12),@price) -- 关闭
close cur_titles -- 释放
deallocate cur_titles go -- 定义一个存储过程
-- 利用游标遍历所有书籍信息,通过冒泡排序法进行比较,找出最高价格的书
-- 相对上面的实现方式,以下实现方式更简洁
create procedure pro_GetMaxTitle
as
-- 声明
declare cur_titles cursor
for select title, price from titles -- 打开
open cur_titles -- 存储最贵的书籍信息
declare @title varchar(80)
declare @price numeric(9,4)
-- 存储从游标中提取出来的书籍的信息
declare @title_temp varchar(80)
declare @price_temp numeric(9,4) -- 提取
fetch cur_titles into @title, @price
-- 判断是否存在书籍信息
if @@fetch_status = 0
begin
print '没有书籍信息!'
goto errNoTitles
end fetch cur_titles into @title_temp, @price_temp
-- 判断是否只存在一本书
if @@fetch_status = 0
begin
goto errOnlyOne
end while @@fetch_status = 0
begin
if @price < @price_temp
begin
set @price = @price_temp
set @title = @title_temp
end
fetch cur_titles into @title_temp, @price_temp
end errOnlyOne:
-- 显示处理结果
print '最贵的书是: ' + @title + ' ' + '价格是: ' + convert(varchar(12),@price) errNoTitles:
-- 关闭
close cur_titles -- 释放
deallocate cur_titles go -- 根据作者编号查看其相应的作品年销售量
-- 低于5000,提示: 销售量太低
-- 高于5000,提示: 销售量太高
create procedure pro_sales_avg (@au_id id)
as
if exists(select au_id from authors where au_id = @au_id)
begin
declare TempSales cursor
for
select title, ytd_sales
from titleauthor ta join titles t
on ta.title_id = t.title_id
where au_id = @au_id open TempSales declare @t varchar(80)
declare @y int fetch TempSales
into @t, @y while @@fetch_status = 0
begin
if 5000 > @y
print @t + ' ' + convert(varchar(5),@y) + ' 销售量太低'
else
print @t + ' ' + convert(varchar(5),@y) + ' 销售量太高'
fetch TempSales
into @t, @y
end close TempSales
deallocate TempSales
end
else
print '作者编号无效!'
go exec pro_sales_avg '213-46-8915' /*
示例
A. 使用简单游标和语法
打开该游标时所生成的结果集包括 pubs 数据库的 authors 表中的所有行和列。可以更新该游标,对该游标所做的所有更新和删除均在提取中表现出来。因为没指定 SCROLL 选项,FETCH NEXT 是唯一可用的提取选项。
*/ DECLARE authors_cursor CURSOR
FOR
SELECT * FROM authors OPEN authors_cursor FETCH NEXT FROM authors_cursor /*
B. 使用嵌套游标生成报表输出
下例显示如何嵌套游标以生成复杂的报表。为每个作者声明内部游标。
*/ SET NOCOUNT ON DECLARE @au_id varchar(11), @au_fname varchar(20), @au_lname varchar(40),
@message varchar(80), @title varchar(80) PRINT "-------- Utah Authors report --------" DECLARE authors_cursor CURSOR
FOR
SELECT au_id, au_fname, au_lname
FROM authors
WHERE state = "UT"
ORDER BY au_id OPEN authors_cursor FETCH NEXT FROM authors_cursor
INTO @au_id, @au_fname, @au_lname WHILE @@FETCH_STATUS = 0
BEGIN
PRINT " "
SELECT @message = "----- Books by Author: " +
@au_fname + " " + @au_lname PRINT @message -- Declare an inner cursor based
-- on au_id from the outer cursor. DECLARE titles_cursor CURSOR FOR
SELECT t.title
FROM titleauthor ta, titles t
WHERE ta.title_id = t.title_id AND
ta.au_id = @au_id -- Variable value from the outer cursor OPEN titles_cursor
FETCH NEXT FROM titles_cursor INTO @title IF @@FETCH_STATUS <> 0
PRINT " <<No Books>>" WHILE @@FETCH_STATUS = 0
BEGIN SELECT @message = " " + @title
PRINT @message
FETCH NEXT FROM titles_cursor INTO @title END CLOSE titles_cursor
DEALLOCATE titles_cursor -- Get the next author.
FETCH NEXT FROM authors_cursor
INTO @au_id, @au_fname, @au_lname
END CLOSE authors_cursor
DEALLOCATE authors_cursor
GO -------- Utah Authors report -------- ----- Books by Author: Anne Ringer
The Gourmet Microwave
Is Anger the Enemy? ----- Books by Author: Albert Ringer
Is Anger the Enemy?
Life Without Fear (8)触发器 -- 设定数据库的递归触发器
alter database pubs
set recursive_triggers on
go -- 创建数据表,并设定主键、外键以及缺省约束
create table emp_mgr
(
Emp char(30) primary key,
Mgr char(30) null foreign key references emp_mgr(Emp),
NoOfReports int default 0
)
go -- 创建插入触发器
create trigger emp_marins
on emp_mgr
for insert
as
declare @e char(30),@m char(30)
declare cur_mgr cursor for
select emp_mgr.emp
from emp_mgr,inserted
where emp_mgr.emp = inserted.mgr open cur_mgr fetch next from cur_mgr into @e while @@fetch_status = 0
begin
update emp_mgr
set emp_mgr.NoOfReports = emp_mgr.NoOfReports + 1
where emp_mgr.emp = @e fetch next from cur_mgr into @e
end close cur_mgr deallocate cur_mgr go -- 查看数据表相关触发器
sp_helptrigger emp_mgr
go create trigger emp_mgrupd
on emp_mgr
for update
as
if update (mgr)
begin
update emp_mgr
set emp_mgr.NoOfReports = emp_mgr.NoofReports + 1
from inserted
where emp_mgr.emp = inserted.mgr update emp_mgr
set emp_mgr.NoOfReports = emp_mgr.NoOfReports -1
from deleted
where emp_mgr.emp = deleted.mgr end go insert emp_mgr(emp,mgr) values ('Harry',null)
insert emp_mgr(emp,mgr) values ('Alice','Harry')
insert emp_mgr(emp,mgr) values ('Paul','Alice')
insert emp_mgr(emp,mgr) values ('Joe','Alice')
insert emp_mgr(emp,mgr) values ('Dave','Joe')
go select * from emp_mgr
go update emp_mgr
set mgr = 'Harry'
where emp = 'Dave'
go select * from emp_mgr
go -- “进销存”系统(触发器的经典应用之一) 某“进销存”系统需要记录进货的信息以及出货的信息,并且当用户记录这些信息的同时,库存信息也需要进行相应的调整,
比如:记录进货信息时,如果该货品是新货,在库存表中还不存在任何信息时,则需要添加一条库存信息(Insert),
否则,只需要对相应的库存记录进行更新(Update);然而,在记录出货信息时,如果该货品在库存表中的库存量小于出货量时,
则需抛出一个用户自定义的“应用错误”(raise_appliction_error),否则,只需要对相应的库存记录进行更新(Update)。
那么,我们如何来作到数据库系统的自动完成。 create table 进货
(
货号 char(1) not null,
数量 int not null,
时间 smalldatetime
) create table 库存
(
货号 char(1) not null,
数量 int not null
) create table 出货
(
货号 char(1) not null,
数量 int not null,
时间 smalldatetime
) drop table 库存
drop table 进货
drop table 出货 select * from 进货
select * from 库存
select * from 出货 create proc pro进货
(
@h char(1),
@s int,
@j smalldatetime
)
as
insert into 进货 values (@h, @s, @j) if exists(select * from 库存 where 货号 = @h)
update 库存 set 数量 = 数量 + @s where 货号 = @h
else
insert into 库存 values (@h, @s)
go execute pro进货 'A', 120, '2005-12-28'
execute pro进货 'A', 180, '2005-12-29' create proc pro出货
(
@h char(1),
@s int,
@j smalldatetime
)
as
if exists(select * from 库存 where 货号 = @h)
begin
if exists(select 数量 from 库存 where 货号 = @h and 数量 >= @s)
begin
update 库存 set 数量 = 数量 - @s where 货号 = @h
insert into 出货 values (@h, @s, @j)
end
else
print 'No,you need too more!'
end
else
print 'No, no you need Dongxi!'
go execute pro出货 'D', 120, '2005-12-28'
execute pro出货 'A', 680, '2005-12-29'
execute pro出货 'A', 80, '2005-12-29' create proc pro进货
(
@h char(1),
@s int,
@j smalldatetime
)
as
insert into 进货 values (@h, @s, @j)
go create trigger tri进货
on 进货
after insert
as
declare @h char(1)
declare @s int
select @h = 货号, @s = 数量 from inserted if exists(select * from 库存 where 货号 = @h)
update 库存 set 数量 = 数量 + @s where 货号 = @h
else
insert into 库存 values (@h, @s)
go create proc pro销售
(
@h char(1),
@s int,
@j smalldatetime
)
as
if exists(select * from 库存 where 货号 = @h)
insert into 销售 values (@h, @s, @j)
go create trigger tri销售
on 销售
after insert
as
if (select 数量 from inserted) > (select 数量 from 库存 where 货号 = (select 货号 from inserted))
begin
print 'Nononono!'
rollback
end
else
update 库存 set 数量 = 数量 - (select 数量 from inserted) where 货号 in (select 货号 from inserted)
go -- 部门管理(触发器的递归实现的经典应用之一)
use pubs
go drop table departments
go -- 定义数据表
create table Departments
(
dep_id int not null identity(1,1) primary key,
dep_name varchar(18) not null unique,
dep_parent int not null,
dep_description varchar(42) null
)
go -- 添加基本数据
insert into departments
(dep_name, dep_parent, dep_description)
values
('上海', 0, '省级代理')
go insert into departments
(dep_name, dep_parent, dep_description)
values
('北京', 0, '省级代理')
go insert into departments
(dep_name, dep_parent, dep_description)
values
('湖南', 0, '省级代理')
go insert into departments
(dep_name, dep_parent, dep_description)
values
('长沙', 3, '市级代理')
go insert into departments
(dep_name, dep_parent, dep_description)
values
('株洲', 3, '市级代理')
go insert into departments
(dep_name, dep_parent,dep_description)
values
('湘潭', 3, '市级代理')
go insert into departments
(dep_name, dep_parent, dep_description)
values
('石峰', 5, '区级代理')
go insert into departments
(dep_name, dep_parent, dep_description)
values
('天元', 5, '区级代理')
go insert into departments
(dep_name, dep_parent,dep_description)
values
('芦淞', 5, '区级代理')
go select * from departments
go -- 定义添加部门的存储过程
create procedure proc_InsertDepartment
@dep_parent_id int,
@dep_name varchar(20),
@dep_id int output
as
insert into departments (dep_name, dep_parent,dep_description) values (@dep_name, @dep_parent_id, '代理')
select @dep_id = @@IDENTITY
go -- 定义修改指定部门的名称的存储过程
create procedure proc_UpdateDepartment
@dep_id int,
@dep_name varchar(20)
as
update departments set dep_name = @dep_name where dep_id = @dep_id
go -- 定义删除指定部门以及相应子部门的存储过程
create procedure proc_DeleteDepartment
@dep_id int
as
delete from departments where dep_id = @dep_id
go -- 定义删除触发器(递归)
create trigger tri_del_dep
on departments
for delete
as
-- 获取被删除部门的编号
-- 检查是否存在子部门
if exists(select * from departments where dep_parent in (select dep_id from deleted ))
begin
-- 如果返回值为真,删除相应子部门,激活子部门的删除触发器,进行递归调用
delete from departments where dep_parent in (select dep_id from deleted )
end
go -- 启动直接递归触发器
exec sp_dboption 'pubs','recursive triggers','true' -- 启动间接递归触发器
exec sp_configure 'nested triggers','' (9)链接服务
-- 在SQL Server上创建一个链接服务:与其他数据库建立连接,将其数据表或是视图作为本地信息源访问
-- 比如:将Access数据库Northwind作为一个链接服务源
EXEC sp_addlinkedserver
@server = 'SEATTLE Mktg',
@provider = 'Microsoft.Jet.OLEDB.4.0',
@srvproduct = 'OLE DB Provider for Jet',
@datasrc = 'C:\Program Files\Microsoft Office\OFFICE11\SAMPLES\Northwind.mdb' SELECT *
into #au4
FROM OPENQUERY([SEATTLE Mktg], 'SELECT * FROM 产品')
GO select *
from #au4

SQL基础用法(实例二)的更多相关文章

  1. SQL基础用法(实例一)

    /* 2006年10月01日 SQL Server 数据库的基本操作 (1) 数据库的创建 (2) 数据表的创建以及相关约束的指定(含临时表) (3) 数据的添/删/改 (4) 数据的查询 */ () ...

  2. SQL基础--查询之二--连接查询

    SQL基础--查询之二--连接查询

  3. SQL 基础笔记(二):进阶查询

    本笔记整理自<SQL 基础教程>.<MySQL 必知必会>和网上资料.个人笔记不保证正确. 一.复杂查询 视图 将 SELECT 查询包装成一个虚拟表,该虚拟表就被称为视图.( ...

  4. 高效IO之File文件操作类的基础用法(二)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 前言 众所周知Java提供File类,让我们对文件进行操作,下面就来简单整理了一 ...

  5. SQL基础语法(二)

    SQL SELECT 语句 本章讲解 SELECT 和 SELECT * 语句. SQL SELECT 语句 SELECT 语句用于从表中选取数据. 结果被存储在一个结果表中(称为结果集). SQL ...

  6. Mongodb命令 --- MongoDB基础用法(二)

    Mongodb命令 数据库操作 创建数据库 MongoDB 创建数据库的语法格式如下: use DATABASE_NAME 如果数据库不存在,则创建数据库,否则切换到指定数据库. 删除数据库 Mong ...

  7. jqery基础知识实例(二)

    无缝滚动 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  8. 二十、oracle pl/sql基础

    一.pl/sql developer开发工具pl/sql developer是用于开发pl/sql块的集成开发环境(ide),它是一个独立的产品,而不是oracle的一个附带品. 二.pl/sql介绍 ...

  9. oracle pl/sql 基础

    一.pl/sql developer开发工具pl/sql developer是用于开发pl/sql块的集成开发环境(ide),它是一个独立的产品,而不是oracle的一个附带品. 二.pl/sql介绍 ...

随机推荐

  1. 01: shell基本使用

    目录: 1.1 编写登录欢迎脚本 1.2 重定向与管道操作 1.3 使用shell变量 1.4 特殊的shell变量 1.5 read与echo使用比较 1.1 编写登录欢迎脚本返回顶部 (1)新建脚 ...

  2. 20165310 Java实验四 《Android程序设计》

    20165310 实验四 <Android程序设计> 第24章:初识Android 任务一:改写res目录中的内容,Hello World后要显示自己的学号,自己学号前后一名同学的学号 首 ...

  3. linux下精确替换某个字符串

    1.linux下精确替换某个字符串 sed -i 's/\<old\>/new/g' filename.txt 2.举例: 2.1有个文件名为filename.txt,内容如下: newd ...

  4. ZedGraph如何动态的加载曲线

    ZedGraph的在线文档 http://zedgraph.sourceforge.net/documentation/default.html 官网的源代码 http://sourceforge.n ...

  5. UVa 1614 奇怪的股市

    https://vjudge.net/problem/UVA-1614 题意:输入一个长度为n的序列a,满足1<=ai<=i,要求确定每个数的正负号,使得所有数的总和为0. 思路:贪心部分 ...

  6. Codeforces Beta Round #94 div 1 D Numbers map+思路

    D. Numbers time limit per test 2 seconds memory limit per test 256 megabytes input standard input ou ...

  7. Selenium 对元素element的操作举例

    前三个用的比较多,模拟用户操作最多的就是点击,输入文本,其他的UI自动化测试中涉及的不多,对判断元素是否存在,断言元素是否被选中,元素被选中后CSS属性是否更改等,还是很有必要的.

  8. 【转】总结C++中取成员函数地址的几种方法

    转自:“http://www.cnblogs.com/nbsofer/p/get_member_function_address_cpp.html” 这里, 我整理了4种C++中取成员函数地址的方法, ...

  9. 关于python中的 “ FileNotFoundError: [Errno 2] No such file or directory: '……'问题 ”

    今天在学python时,在模仿一个为图片加上图标并移动到指定文件夹的程序时遇到“FileNotFoundError: [Errno 2] No such file or directory: '152 ...

  10. Java内存管理知识你需要吗?

    0.Java 对内存的划分: Java虚拟机规范将物理内存(主内存和CPU中的缓存.寄存器)划分为程序计数器.Java 虚拟机栈.本地方法栈.Java 堆.方法区五个区域,但并没有规定这些区域的具体实 ...