数据库TransactSQL程序设计.docx
《数据库TransactSQL程序设计.docx》由会员分享,可在线阅读,更多相关《数据库TransactSQL程序设计.docx(17页珍藏版)》请在冰豆网上搜索。
数据库TransactSQL程序设计
第9章Transact-SQL程序设计
EXECsp_addtypetest_add,'Varchar(10)','NOTNULL'
DECLARE@int_varint
SELECT@int_var=12/*给@int_var赋值*/
SELECT@int_var/*将@int_var的值输出到屏幕上*/
在一条语句中可以同时对几个变量进行赋值,例如,
DECLARE@LastNamechar(8),@Firstnamechar(8),@BirthDatedatetime
SELECT@LastName='Smith',@Firstname='David',@BirthDate='1985-2-20'
SELECT@LastName,@Firstname,@BirthDate
【例9-1】使用SELECT语句从customer表中检索出顾客编号为C0002的行,再将顾客的名字赋给变量@customer。
DECLARE@customervarchar(40),@curdatedatetime
SELECT@customer=customer_name,@curdate=getdate()
FROMcustomer
WHEREcustomer_id='C0002'
【例9-2】将sell_order表中的transporter_id列值为“T001”、goods_id列值为“G00003”的order_num列的值赋给局部变量@order_num。
DECLARE@order_numfloat
UPDATEsell_order
SET@order_num=order_num*2
/*@order_num为局部变量,order_num为sell_order表中的列名称*/
WHEREtransporter_id='T001'ANDgoods_id='G00003'
【例9-3】计算employee表的记录数并赋值给局部变量@rows。
DECLARE@rowsint
SET@rows=(SELECTCOUNT(*)FROMemployee)
SELECT@rows
【例9-4】使服务器产生服务,并显示错误号。
raiserror('miscellaneouserrormessage',16,1)/*产生一个错误*/
if@@error<>0
SELECT@@erroras'lasterror'
【例9-5】捕捉例9-4中服务器产生的错误号,并显示出来。
DECLARE@my_errorint
RAISERROR('miscellaneouserrormessage',16,1)
SELECT@my_error=@@error
IF@my_error<>0
SELECT@my_erroras'lasterror'
【例9-6】使用@@spid返回当前用户进程的ID。
SELECT@@spidas'ID',SYSTEM_USERAS'LoginName',USERAS'UserName'
【例9-7】在Sales数据库中创建jobs表,并在表中插入带有identity列的行,并且使用@@identity来显示新行中所用的identity值。
CREATETABLEjobs(
[job_id][smallint]IDENTITY(1,1)NOTNULL,
[job_desc][varchar](50)COLLATEChinese_PRC_CI_ASNOTNULL,
[min_lvl][tinyint]NOTNULL,
[max_lvl][tinyint]NOTNULL
)ON[PRIMARY]
INSERTINTOjobs(job_desc,min_lvl,max_lvl)
VALUES('Accountant',12,125)
SELECT@@IDENTITYAS'Identity'
【例9-8】创建两个过程:
innerproc和outerproc。
outerproc过程用来调用innerproc过程,innerproc过程用来显示@@nestlevel的设置。
①定义innerproc为内嵌过程。
CREATEPROCEDUREinnerprocas
SELECT@@nestlevelAS'InnerLevel'
GO
②定义outerproc为外层过程。
CREATEPROCEDUREouterprocas
SELECT@@nestlevelAS'OuterLevel'
EXECinnerproc
GO
③执行outerproc。
EXECUTEouterproc
GO
【例9-9】使用“+”将goods表中高于9000元的商品价格增加15元。
SELECTgoods_name,unit_price,(unit_price+15)ASnowprice
FROMgoods
WHEREunit_price>9000
【例9-10】从表department中读取manager列的各记录的实际长度。
SELECTDatalength(rtrim(manager))AS'DATALENGTH',
Len(rtrim(manager))AS'LEN'
FROMdepartment
SELECTsoundex('1'),soundex('a'),soundex('计算机'),soundex('abc'),
soundex('abcd'),soundex('a12c'),soundex('a数字')
SELECTdifference('red','read'),difference(soundex('ac'),soundex('zc')),
difference(soundex('abc'),soundex('abcd'))
SELECTcharindex(',','red,white,blue')
SELECTpatindex('%abc%','abc123'),patindex('123','abc123')
【例9-11】在同一表达式中使用sin、atan、rand、pi、sign函数。
SELECTsin(23.45),atan(1.234),rand(),pi(),sign(-2.34)
【例9-12】用ceiling和floor函数返回大于或等于指定值的最小整数值和小于或等于指定值的最大整数值。
SELECTceiling(123),floor(321),ceiling(12.3),ceiling(-32.1),floor(-32.1)
【例9-13】round函数的使用。
SELECTround(12.34512,3),round(12.34567,3),round(12.345,-2),round(154.321,-2)
SELECTgetdate()
【例9-14】使用datediff函数来确定货物是否按时送给客户。
SELECTgoods_id,datediff(dd,send_date,arrival_date)
FROMpurchase_order
【例9-15】使用datename函数返回员工的出生日期的月份(mm)名称。
SELECTemployee_name,(datename(mm,birth_date)
FROMemployee
SELECTsuser_sname(0x01)
【例9-16】使用object_name函数返回已知ID号的对象名。
SELECTobject_name(469576711)
【例9-17】利用object_id函数,根据表名返回该表的ID号。
SELECTnameFROMsysindexes
WHEREid=object_id('customer')
【例9-18】创建一个用户定义函数DatetoQuarter,将输入的日期数据转换为该日期对应的季度值。
如输入'2006-8-5',返回'3Q2006',表示2006年3季度。
CREATEFUNCTIONDatetoQuarter(@dqdatedatetime)
RETURNSchar(6)
AS
BEGIN
RETURN(datename(q,@dqdate)+'Q'+datename(yyyy,@dqdate))
END
【例9-19】创建用户定义函数goodsq,返回输入商品编号的商品名称和库存量。
CREATEFUNCTIONgoodsq(@goods_idvarchar(30))
RETURNSTABLE
AS
RETURN(SELECTgoods_name,stock_quantity
FROMgoods
WHEREgoods_id=@goods_id)
【例9-20】根据输入的订单编号,返回该订单对应商品的编号、名称、类别编号、类别名称。
CREATEFUNCTIONgood_info(@in_o_idvarchar(10))
RETURNS@goodinfoTABLE
(o_idchar(6),
g_idchar(6),
g_namevarchar(50),
c_idchar(6),
c_namevarchar(20))
AS
BEGIN
DECLARE@g_idvarchar(10),@g_namevarchar(30)
DECLARE@c_idvarchar(10),@c_namevarchar(30)
SELECT@g_id=goods_idFROMsell_order
WHEREorder_id1=@in_o_id
SELECT@g_name=goods_name,@c_id=classification_id
FROMgoodsWHEREgoods_id=@g_id
SELECT@c_name=classification_name
FROMgoods_classificationWHERE@c_id=classification_id
INSERT@goodinfo
VALUES(@in_o_id,@g_id,@g_name,@c_id,@c_name)
RETURN
END
SELECTdbo.DatetoQuarter('2006-8-5')
SELECT*FROMdbo.goodsq('G00002')
SELECT*FROMdbo.good_info('S00002')
DROPFUNCTONDatetoQuarter
【例9-21】显示Sales数据库中customer表的编号为C0001的联系人姓名。
USESales
GO
DECLARE@linkman_namechar(8)
BEGIN
SELECT@linkman_name=(SELECTlinkman_nameFROMcustomer
WHEREcustomer_idLIKE'C0001')
SELECT@linkman_name
END
【例9-22】语句块嵌套举例。
DECLARE@errorcodeint,@nowdatedatetime
BEGIN
SET@nowdate=getdate()
INSERTsell_order(order_date,send_date,arriver_date,custom_id)
VALUES(@nowdate,@nowdate+5,@nowdate+10,'C0002')
SELECT@errorcode=@@error
IF@errorcode>0
BEGIN
RAISERROR('当表sell_order插入数据时发生错误!
',16,1)
RETURN
END
END
--Thisisacomment.Wholelinewillbeignored.
SELECTemployee_name,address--查询所有姓钱的员工
FROMemployee
WHEREemployee_nameLIKE'钱%'
/*
Thisisacommnet.
Alltheselineswillbeignored.
*/
/*Listallemployees.*/
SELECT*FROMemployee
/*
--Listallemployees.
SELECT*FROMemployee
*/
【例9-23】判断表goods中supplier_id为S001的商品的平均单价是否大于9799。
IF(SELECTavg(unit_price)FROMgoods
WHEREsupplier_id='S001')>$9799.0
SELECT'supplier_id为S001的商品的平均单价比9799大'
ELSE
SELECT'supplier_id为S001的商品的平均单价比9799小'
【例9-24】用EXISTS确定表department中是否存在“陈晓兵”。
DECLARE@lnamevarchar(40),@msgvarchar(255)
SELECT@lname='陈晓兵'
IFEXISTS(SELECT*FROMdepartmentWHEREmanager=@lname)
BEGIN
SELECT@msg='有人名为'+@lname
SELECT@msg
END
ELSE
BEGIN
SELECT@msg='没有人名为'+@lname
SELECT@msg
END
【例9-25】嵌套IF…ELSE语句的使用。
IF(SELECTSUM(order_num)FROMsell_order)>50
PRINT'他们是最佳的客户'
ELSE
IF(SELECTSUM(order_num)FROMsell_order)>30
PRINT'必须与他们保持联络'
ELSE
PRINT'再想想办法吧!
!
'
【例9-26】使用简单CASE函数将goods表中的商品分类重命名,以使之更易理解。
SELECT
CASEclassification_id
WHEN'P001'THEN'笔记本计算机'
WHEN'P002'THEN'激光打印机'
WHEN'P003'THEN'喷墨打印机'
WHEN'P004'THEN'交换机'
ELSE'没有这种品牌'
ENDASClassification,
goods_nameAS'GoodsName',unit_priceASPrice
FROMgoods
WHEREunit_priceISNOTNULL
【例9-27】根据goods表中库存货物数量与订货量之差,使用CASE搜索函数判断该商品是否进货。
SELECTgoods_nameAS商品名称,
CASE
WHENstock_quantity-order_quantity<=3THEN'紧急进货'
WHENstock_quantity-order_quantity>3
andstock_quantity-order_quantity<=10THEN'暂缓进货'
WHENstock_quantity-order_quantity>10THEN'货物充足'
ENDAS进货判断
FROMgoods
【例9-28】使用GOTO语句改变程序流程。
DECLARE@xint
SELECT@x=1
label_1:
SELECT@x
SELECT@x=@x+1
WHILE@x<6
GOTOlabel_1
【例9-29】RETURN语句应用示例。
DECLARE@xint,@yint
SELECT@x=1,@y=2
IF@x>@y
RETURN
ELSE
RETURN
WAITFORDELAY'00:
01:
00'
SELECT*FROMgrade
WAITFORTIME'23:
00'
BACKUPDATABASEstudentsdbTOstudentsdb_bkp
【例9-30】将goods表中库存数最大的商品每次订购两件,计算如此需要多少次订购才能使库存数不够一次订购。
DECLARE@countint,@maxstockidchar(6),@maxstockfloat
SET@count=0
SET@maxstock=(SELECTmax(stock_quantity)FROMgoods)
SET@maxstockid=(SELECTgoods_idFROMgoods
WHEREstock_quantity=@maxstock)
SELECT@maxstockid,@maxstock
WHILE(@maxstock>
(SELECTorder_quantityFROMgoodsWHEREgoods_id=@maxstockid))
BEGIN
UPDATEgoods
SETorder_quantity=order_quantity+2
WHEREgoods_id=@maxstockid
SET@count=@count+1
END
SELECT@count
【例9-31】对于goods表,如果平均库存少于12,WHILE循环就将各记录库存增加5%,再判断最高库存是否少于或等于25,是则WHILE循环重新启动并再次将各记录库存增加5%。
当循环不断地将库存增加直到最高库存超过25时,然后退出WHILE循环。
在WHILE中使用BREAK或CONTINUE控制循环体的执行。
/*执行循环,直到库存平均值超过12*/
WHILE(SELECTavg(stock_quantity)FROMgoods)<12
BEGIN
UPDATEgoods
SETstock_quantity=stock_quantity*1.05
SELECTmax(stock_quantity)FROMgoods
/*如果最大库存值超过25,则用BREAK退出WHILE循环,否则继续循环*/
IF(SELECTmax(stock_quantity)FROMgoods)>25
BEGIN
PRINT'库存太多了'
BREAK
END
ELSE
CONTINUE
END
【例9-32】计算s=1!
+2!
+…+10!
。
DECLARE@sint,@nint,@tint,@cint
/*@s存储阶乘和,@n为外层循环控制变量,@c为内层循环控制变量,@t为@n的阶乘值*/
SET@S=0
SET@n=1
WHILE@n<=10
BEGIN
SET@c=1
SET@t=1
WHILE@c<=@n
BEGIN
SET@t=@t*@c
SET@c=@c+1
END
SET@s=@s+@t
SET@n=@n+1
END
SELECT@s,@n
executesp_executesqlN'SELECT*fromSales.dbo.employee'
【例9-33】创建一个视图,使用GO命令将CREATEVIEW语句与批处理中的其他语句(如USE、SELECT语句等)隔离。
USESales
GO
--批处理结束标志
CREATEVIEWemployee_info
AS
SELECT*FROMemployee
GO
--CREATEVIEW语句与其他语句隔离
SELECT*FROMemployee_info
GO
【例9-34】使用SQL-92标准的游标声明语句声明一个游标,用于访问Sales数据库中的goods表的信息。
USESales
GO
DECLAREGoods_cursorCURSOR
FOR
SELECT*FROMGoods
FORREADONLY
【例9-35】为customer表定义一个全局滚动动态游标,用于访问顾客的编号、姓名、地址、电话信息。
DECLAREcur_customerCURSOR
GLOBALSCROLLDYNAMIC
FOR
SELECTcustomer_id,customer_name,address,telephone
FROMcustomer
【例9-36】打开例9-35中声明的游标,读取游标中的数据。
OPENcur_customer
FETCHNEXTFROMcur_customer/*取第一个数据行*/
WHILE@@fetch_status=0/*检查@@fetch_status是否还有数据可取*/
BEGIN
FETCHNEXTFROMcur_customer
END
CLOSEcur_customer
DEALLOCATEcur_customer
【例9-37】定义游标cur_customer,通过cur_customer更新customer表中的customer_name和linkman_name列。
DECLAREcur_customerCURSOR
FOR
SELECT*FROMcustomer
FORUPDATEOFcustomer_name,linkman_name/*该两列可更新*/
OPENcur_customer/*打开cur_customer游标*/
FETCHNEXTFROMcur_customer/*将第一行数据放入缓冲区,以便更新操作*/
UPDATEcustomer
SETcustomer_name='南方体育用品公司',linkman_name='李强'
WHERECURRENTOFcur_customer
CLOSEcur_customer/*关闭cur_customer游标*/
DELETEFROMcustomer
WHERECURRENTOFcur_customer
DECLARE@cur_varCURSOR/*定义游标变量*/
DECLAREcur_customerCURSOR
FORSELECT*FROMcustomer/*定义游标*/
SET@cur_var=cur_customer/*设置游标与游标变量的关联*/
DECLARE@cur_varCURSOR/*定义游标变量*/
SET@cur_var=CURSORSCROLLKEYSETFOR
SELECT*FROMcustomer/*创建游标并与游标变量的关联*/