甘草轩

Never surrender to complexity
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

SQLServer2005中的T-SQL增强

Posted on 2006-07-06 18:36  甘草轩  阅读(513)  评论(0编辑  收藏  举报

1、varchar(max)nvarchar(max)varbinary(max)数据型最多可以保存2GB的数据,可以取代textntextimage数据型。

CREATE TABLE myTable
(
    id 
INT
,
    content 
VARCHAR(MAX
)
)

2XML数据
XML
数据型允SQL Server数据中保存XML片段或文档。

错误处 Error Handling

1、新的异常
2、可以捕去会致批止的错误
前提是错误不会接中断(通常是重程度21以上的错误,例如,表或数据完整性可疑、硬件错误等等。)。
3TRY/CATCH 构造

SET XACT_ABORT ON
   
BEGIN TRY
     
<core logic>
   
END TRY
   
BEGIN CATCH TRAN_ABORT
     
<exception handling logic>
   
END TRY

@@error may be quired as first statement in CATCH block

4、演示代

USE demo
  
GO
  
--创建工作表

  
CREATE TABLE student
  ( 
      stuid 
INT NOT NULL PRIMARY KEY,
      stuname 
VARCHAR(50)
  )

  
CREATE TABLE score 
  (
      stuid 
INT NOT NULL REFERENCES student(stuid),
      score 
INT
  )
GO

INSERT INTO student VALUES (101,'zhangsan'
INSERT INTO student VALUES (102,'wangwu'
INSERT INTO student VALUES (103,'lishi'
INSERT INTO student VALUES (104,'maliu'

--调用一个运行时错误
SET XACT_ABORT OFF
  
BEGIN TRAN
     
INSERT INTO score VALUES (101,90)
     
INSERT INTO score VALUES (102,78
     
INSERT INTO score VALUES (10776/* 外键错误 */ 
     
INSERT INTO score VALUES (103,81
     
INSERT INTO score VALUES (104,65
  
COMMIT TRAN
  
GO

  
SELECT * FROM student
  
SELECT * FROM score

--使用TRYCATCH构造,并调用一个运行时错误
SET XACT_ABORT OFF
  
BEGIN TRY
    
BEGIN TRAN
       
INSERT INTO score VALUES (101,90)
       
INSERT INTO score VALUES (102,78
       
INSERT INTO score VALUES (10776/* 外键错误 */ 
       
INSERT INTO score VALUES (103,81
       
INSERT INTO score VALUES (104,65
    
COMMIT TRAN
    
PRINT '事务提交'
  
END TRY
  
BEGIN CATCH
    
ROLLBACK
     
PRINT '事务回滚'
        
SELECT ERROR_NUMBER() AS ErrorNumber,
        ERROR_SEVERITY() 
AS ErrorSeverity,
        ERROR_STATE() 
as ErrorState,
        ERROR_MESSAGE() 
as ErrorMessage;
   
END CATCH
GO

SELECT * FROM score
GO

快照隔离 Snapshot Isolation

1、写入程序不会阻碍取程序
2
Snapshot isolation must be enabled for DB
      ALTER DATABASE
数据
SET allow_snapshot_isolation ON
3
Snapshot isolation must be enabled for connection
      Set transaction isolation level snapshot
4
UPDATE transactions keep old versions of data in a linked list
5
、新的隔离级别提供了以下点:

  1) 提高了只读应用程序的数据可用性
  2) OLTP境中行非阻止取操作
  3) 写入事务进行自制冲突检测
6
、演示代

CREATE DATABASE demo2
GO
USE demo2
   
ALTER DATABASE demo2 SET allow_snapshot_isolation ON
   
CREATE TABLE test
   ( 
     tid 
INT NOT NULL primary key,
     tname 
VARCHAR(50NOT NULL
   )
  
INSERT INTO test VALUES(1,'version1')
  
INSERT INTO test VALUES(2,'version2')

--连接一

USE demo2
BEGIN TRAN
   
UPDATE test SET tname='version3' WHERE tid=2
   
SELECT * FROM test

--连接二
USE demo2
   
SET transaction isolation level snapshot
   
SELECT * FROM test 

TOP 功能

1TOP
可以指定一个数字表达式,以返回要通过查询影响的行数或百分比,可以根据情况使用量或子查询
可以在DELETEUPDATEINSERT查询中使用TOP选项

2、更好地替SET ROWCOUNT选项,使之更有效。

OUTPUT

1SQL Server 2005引入一个新的OUTPUT子句,以使您可以冲修改(INSERTUPDATEDELETE)中将数据返回到表量中。

2、新的OUTPUT子局的

OUTPUT <dml_select_list> INTO @table_variable

可以通引用插入的表或除的表来访问被修改的行的旧/新影象,其方式与访问似。在INSERT句中,只能访问插入的表。DELETE句中,只能访问删除的表。在UPDATE句中,可以访问插入的表除的表。

3、代演示

USE demo
GO
CREATE TABLE tt 
(
  id 
INT IDENTITY
  c1 
VARCHAR(15)
)
GO

INSERT INTO tt VALUES ('r1')
INSERT INTO tt VALUES ('r2')
INSERT INTO tt VALUES ('r5')
INSERT INTO tt VALUES ('r6')
INSERT INTO tt VALUES ('r7')
INSERT INTO tt VALUES ('r8')
INSERT INTO tt VALUES ('r9')
INSERT INTO tt VALUES ('r10')

DECLARE @del AS TABLE (deletedId INT, deletedValue VARCHAR(15))
DELETE tt
OUTPUT DELETED.id, DELETED.c1 
INTO @del
WHERE id < 3
SELECT * FROM @del
GO
-----------------------------------------------
USE demo
GO
CREATE TABLE toptest (column1 VARCHAR(150))
GO
INSERT INTO toptest VALUES('t1')
INSERT INTO toptest VALUES('t2')
INSERT INTO toptest VALUES('t3')
INSERT INTO toptest VALUES('t4')
INSERT INTO toptest VALUES('t5')
INSERT INTO toptest VALUES('t6')
INSERT INTO toptest VALUES('t7')
INSERT INTO toptest VALUES('t8')
SELECT * FROM toptest
GO

CREATE TABLE toptest2 (column2 VARCHAR(150))
GO
INSERT INTO toptest2 VALUES('c1')
INSERT INTO toptest2 VALUES('c2')

--声明3个变量
DECLARE @a INT
DECLARE @b INT
DECLARE @c INT

--赋值
SET @a = 10
SET @b = 5
SELECT @c = @a/@b

--使用计算表达式
SELECT TOP(@c* FROM toptest

--使用SELECT语句作为条件
SELECT TOP(SELECT COUNT(*FROM toptest2) * 
FROM toptest

--指出top
DELETE TOP(2) toptest where column1>'t6'

--更新top
UPDATE TOP(2) toptest SET column1 = 'hi' where column1<='t2'

SELECT * FROM toptest

排序函数 Ranking Functions

1SQL Server引入几个新的排序函数:如ROW_NUMBERRANKDENSE_RANK等。些新函数使您可以有效地分析数据以及向查询果行提供排序

2、排序函数都遵循似的法模式:

()OVER
(
[PARTITION BY]
ORDER BY)

函数只能在查询的两个子句中指定 - SELECT子句或ORDER BY子句中。以下详细讨论不同的函数。 

3ROW_NUMBER
ROW_NUMBER
果集的, 而不是数据纪录存放的原始

USE demo
GO
CREATE TABLE rankorder
(
 orderid 
INT,
 qty 
INT
)
GO
INSERT rankorder VALUES(30001,10)
INSERT rankorder VALUES(10001,10)
INSERT rankorder VALUES(10006,10)
INSERT rankorder VALUES(40005,10)
INSERT rankorder VALUES(30003,15)
INSERT rankorder VALUES(30004,20)
INSERT rankorder VALUES(20002,20)
INSERT rankorder VALUES(20001,20)
INSERT rankorder VALUES(10005,30)
INSERT rankorder VALUES(30007,30)
INSERT rankorder VALUES(40001,40)
GO
SELECT orderid,qty,
  ROW_NUMBER() 
OVER(ORDER BY qty) AS rownumber,
  RANK()       
OVER(ORDER BY qty) AS rank,
  DENSE_RANK() 
OVER(ORDER BY qty) AS denserank 
FROM rankorder
ORDER BY qty

通用表表达式 Common Table Expressions 

通用表表达式(CTE)是一个可以由定义语句引用的临时表命名的果集。在他简单形式中,您可以将CTE视为类似于视图和派生表混合功能的改版本。在查询FROM子句中引用CTE的方式似于引用派生表和视图的方式。CTE一次,即可在查询中多次引用它。在CTE的定中,可以引用在同一批理中定量。但是CTE的真正威力在于它递归功能,即CTE可以包含自身的引用。

视图、派生表和CTE内部的查询的一般形式

1视图

CREATE VIEW <view_name>(<column_aliases>AS <view_query>

2、派生表

SELECT * FROM (<derived_table)query>AS <dericed_table_alias>(<column_aliases>)

3CTE

WITH <cte_alias>(<column_aliases>)
AS
{
 
<cte_query>
)
SELECT * FROM <cte_alias]>

关键WITH之后,CTE提供一个名,并且它的果列提供一个可名列表;CTE的主体;然后从外部查询中引用它。

4、演示代

USE AdventureWorks
GO
WITH SalesCTE(ProductID, SalesOrderID)
AS 
(
 
SELECT ProductID, COUNT(SalesOrderID) 
 
FROM Sales.SalesOrderDetail 
 
GROUP BY ProductID
)
SELECT * FROM SalesCTE

Recursive CTEs 递归的通用表表达式

递归CTE是根据至少两个查询(或者称两个成)构建的,一个是非递归查询,也成固定成,只能用一次,另外一个是递归查询,也成为递归RM),可以反复调用,直到查询不再返回行。查询UNION ALL运算符一个独的CTE

--使用递归的通用表表达式

USE demo
GO
CREATE TABLE CarParts
(
 CarID 
INT NOT NULL,
 Part 
VARCHAR(15),
 SubPart 
VARCHAR(15),
 Qty 
INT
)
GO
INSERT CarParts VALUES (1'Body''Door'4)
INSERT CarParts VALUES (1'Body''Trunk Lid'1)
INSERT CarParts VALUES (1'Body''Car Hood'1)
INSERT CarParts VALUES (1'Door''Handle'1)
INSERT CarParts VALUES (1'Door''Lock'1)
INSERT CarParts VALUES (1'Door''Window'1)
INSERT CarParts VALUES (1'Body''Rivets'1000)
INSERT CarParts VALUES (1'Door''Rivets'100)
INSERT CarParts VALUES (1'Door''Mirror'1)
GO
SELECT * FROM CarParts
GO

WITH CarPartsCTE(SubPart, Qty) 
AS
(
 
-- 固定成员 (AM):
 -- SELECT查询无需参考CarPartsCTE
 SELECT SubPart, Qty
 
FROM CarParts
 
WHERE Part = 'Body'
 
UNION ALL
 
-- 递归成员 (RM):
 -- SELECT查询参考CarPartsCTE
 SELECT CarParts.SubPart, CarPartsCTE.Qty * CarParts.Qty
 
FROM CarPartsCTE 
 
INNER JOIN CarParts ON CarPartsCTE.SubPart = CarParts.Part
 
WHERE CarParts.CarID = 1
)

-- 外部查询

SELECT SubPart, SUM(Qty) AS TotalNUM
FROM CarPartsCTE
GROUP BY SubPart   

新的系运算符 PIVOT/UNPIVOT/APPLY

1PIVOT
PIVOT
运算符将行旋转为列,并且可能同时执行聚合。使用PIVOT运算符要注意的重要一点是,需要它提供一个查询表达式,表达式使用视图、派生表或者是CTE只返回所注的列。

2UNPIVOT
UNPIVOT
运算符行与PIVOT运算符相反的操作;他将列旋转为行了。

3APPLY
APPLY
系运算符允外部表的个行用指定的表函数一次。您可以在查询FROM子句中指定APPLY,其方式与使用JOIN系运算符似。APPLY具有两形式:CROSS APPLYOUTER APPLY

演示:

USE demo
GO

CREATE TABLE orders
(
 Customer 
VARCHAR(10NOT NULL,
 product 
VARCHAR(20NOT NULL,
 quantity 
INT NOT NULL
)
GO
INSERT orders VALUES('Mike''Bike',3)
INSERT orders VALUES('Mike','Chain',2)
INSERT orders VALUES('Mike','Bike',5)
INSERT orders VALUES('Lisa','Bike',3)
INSERT orders VALUES('Lisa','Chain',3)
INSERT orders VALUES('Lisa','Chain',4)
INSERT orders VALUES('Lisa','Bike',2)

SELECT * FROM orders

SELECT * FROM orders
PIVOT (
SUM(quantity) FOR product IN ([Bike],[Chain])) AS a
USE demo
GO
CREATE TABLE SALES1
(
  
[Year] INT,
  Quarter 
CHAR(2),
  Amount 
FLOAT
)
GO
INSERT INTO SALES1 VALUES (2001'Q1'80)
INSERT INTO SALES1 VALUES (2001'Q2'70)
INSERT INTO SALES1 VALUES (2001'Q3'55)
INSERT INTO SALES1 VALUES (2001'Q3'110)
INSERT INTO SALES1 VALUES (2001'Q4'90)
INSERT INTO SALES1 VALUES (2002'Q1'200)
INSERT INTO SALES1 VALUES (2002'Q2'150)
INSERT INTO SALES1 VALUES (2002'Q2'40)
INSERT INTO SALES1 VALUES (2002'Q2'60)
INSERT INTO SALES1 VALUES (2002'Q3'120)
INSERT INTO SALES1 VALUES (2002'Q3'110)
INSERT INTO SALES1 VALUES (2002'Q4'180)
GO

SELECT * FROM SALES1
PIVOT
(
SUM (Amount) --使用SUM聚合数量列
FOR [Quarter] --PIVOT Quarter 列
IN (Q1, Q2, Q3, Q4)) --使用季节
AS P
GO

SELECT * INTO temp1 FROM orders
PIVOT (
sum(quantity) FOR product IN ([Bike],[Chain])) AS a

SELECT * FROM temp1

SELECT customer, product,quantity
FROM temp1
UNPIVOT(quantity 
FOR product IN ([Bike],[Chain])) AS a
----------------------------------------------------
USE demo
GO
CREATE TABLE Arrays
(
  aid 
INT NOT NULL IDENTITY PRIMARY KEY,
  array 
VARCHAR(7999NOT NULL
)
GO
INSERT INTO Arrays VALUES('')
INSERT INTO Arrays VALUES('10')
INSERT INTO Arrays VALUES('20,40,30')
INSERT INTO Arrays VALUES('-1,-3,-5')
GO
CREATE FUNCTION  function1(@arr AS VARCHAR(7999))
  
RETURNS @t TABLE(pos INT NOT NULL, value INT NOT NULL)
AS
BEGIN
  
DECLARE @end AS INT@start AS INT@pos AS INT
  
SELECT @arr = @arr + ','@pos = 1,
    
@start = 1@end = CHARINDEX(','@arr@start)
  
WHILE @end > 1
  
BEGIN
    
INSERT INTO @t VALUES(@posSUBSTRING(@arr@start@end - @start))

    
SELECT @pos = @pos + 1,
      
@start = @end + 1@end = CHARINDEX(','@arr@start)
  
END
  
RETURN
END

--测试
SELECT * FROM function1('200,400,300')
GO

SELECT A.aid, F.*
FROM Arrays AS A
  
CROSS APPLY function1(array) AS F
GO
SELECT A.aid, F.*
FROM Arrays AS A
  
OUTER APPLY function1(array) AS F
GO

DDL DDL Triggers

SQL Server 2005可以就整个服器或数据的某个范围为DDL事件定器。也可为单DDL句(例如:CREAT_TABLEDROP_TABLE等)或者组语句(例如:指定DDL_DATABASE_LEVEL_EVENTS想要触器触数据所有DDL事件)定DDL器。

DDL器内部,可以通过访问eventdata()函数得与激发该器的事件有的数据。eventdata()函数返回有事件的xml数据。DDL器特有用的方案包括DDL更改的完整性检查核方案以及其他方案。

演示:

USE demo
GO
CREATE TRIGGER prevent_drop_table ON DATABASE FOR DROP_TABLE
AS
RAISERROR('没有删除表的权限.'101)
PRINT '尝试在数据库' + DB_NAME() + '中删除表.'
PRINT CONVERT (nvarchar (1000),EventData())
ROLLBACK
GO
-- 测试
CREATE TABLE TestDROP(col1 INT)
GO
INSERT INTO TestDROP VALUES(1)

DROP TABLE testdrop

-- Server
CREATE TRIGGER audit_ddl_logins ON ALL SERVER
  
FOR CREATE_LOGIN, ALTER_LOGIN, DROP_LOGIN
AS
PRINT '发生DDL LOGIN.'
PRINT CONVERT (nvarchar (1000),EventData())
GO

-- 测试
CREATE LOGIN login1 WITH PASSWORD = '123'
ALTER LOGIN login1 WITH PASSWORD = 'xyz'
DROP LOGIN login1

总结

SQL Server 2005中的Transaction-SQL功能提高了用查询时的表达能力,使用可以改善代的性能,并且充了错误处理能力。SQL Server 2005 Transaction-SQL上所做的改反映了其更好地足了ANSI-99 SQL范的要求以及客的需求。Transaction-SQL和托管代选择