转载:最近整理了sql 2k 与sql 2005 的比较文件,请大家补充!! 关于SQL SERVER 2005 与SQL SERVER 2000比较这个题目太大了,这里只能大体介绍一下,细节方面还需大家共同研究!希望能使大家对SQL SERVER 2005 快速入手,另外sql server 2005 的界面风格有越来越像 .net了,赶快安装一个感受一下吧!进去之后不要再去找查询分析器了,它和企业管理器都被集成在”Microsoft SQL Server Management studio”了,这个工具占内存较大80M多(再加上sql server 的实例进程80M,就160M了),而以前的企业管理器只需20M左右,加上sql server 的实例进程10M多一共才30M多.有得必有失~!hacker at 2006/9/29一、数据库设计方面1、字段类型。SQL Server 2005引入了一系列 新的被称为MAX的数据类型。这是VARCHAR,NVARCHAR和VARBINARY类型的扩展,这几种类型 以前被限制在8000字节以下。MAX可以容纳高达2GB的数据,与TEXT和IMAGE一样。可以使用字符串函数对CLOB类型进行操作。但是这就引发了对varchar和char效率讨论的老问题。到底如何分配varchar的数据,是否会出现大规模的碎片?是否碎片会引发效率问题?这都是需要进一步探讨的东西。数据类型Sql server2000 Sql server2005text 最大2GB varchar(max) 最大2GB(相当于oracle中的CLOB类型)ntext 最大2GB nvarchar(max) 最大2GBimage 最大2GB varbinary(max) 最大2GB(代替image也让SQL Server的字段类型更加简洁统一)无 XML XML 数据被作为二进制大型对象 (BLOB) 存储于内部,可有效地进行重新分析和压缩其它数据类型保持不变。2、外键的级联更能扩展新版本中外键级联加入了SET NULL 和 SET DEFAULT 属性,能够提供能好的级联设置。(有点像oracle了)语法如下(引用sql server 2005 help来说明):CREATE TABLE 和 ALTER TABLE 语句的 REFERENCES 子句支持 ON DELETE 和 ON UPDATE 子句: ? [ ON DELETE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]? [ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]如果没有指定 ON DELETE 或 ON UPDATE,则默认为 NO ACTION。 NO ACTION 指定如果试图删除/修改某一行,而该行的键被其他表的现有行中的外键所引用,则产生错误并回滚 DELETE/UPDATE语句。CASCADE、SET NULL 和 SET DEFAULT 允许通过删除或更新键值来影响指定具有外键关系的表,这些外键关系可追溯到在其中进行修改的表。如果为目标表也定义了级联引用操作,那么指定的级联操作也将应用于删除或更新的那些行。不能为具有 timestamp 列的外键或主键指定 CASCADE。 ON DELETE CASCADE 指定如果试图删除某一行,而该行的键被其他表的现有行中的外键所引用,则也将删除所有包含那些外键的行。 ON UPDATE CASCADE 指定如果试图更新某一行中的键值,而该行的键值被其他表的现有行中的外键所引用,则组成外键的所有值也将更新到为该键指定的新值。 (如果 timestamp 列是外键或被引用键的一部分,则不能指定 CASCADE。 )ON DELETE SET NULL指定如果试图删除某一行,而该行的键被其他表的现有行中的外键所引用,则组成被引用行中的外键的所有值将被设置为 NULL。目标表的所有外键列必须可为空值,此约束才可执行。ON DELETE SET NULL指定如果试图更新某一行,而该行的键被其他表的现有行中的外键所引用,则组成被引用行中的外键的所有值将被设置为 NULL。目标表的所有外键列必须可为空值,此约束才可执行。ON DELETE SET DEFAULT指定如果试图删除某一行,而该行的键被其他表的现有行中的外键所引用,则组成被引用行中的外键的所有值将被设置为它们的默认值。目标表的所有外键列必须具有默认值定义,此约束才可执行。如果某个列可为空值,并且未设置显式的默认值,则会使用 NULL 作为该列的隐式默认值。因 ON DELETE SET DEFAULT 而设置的任何非空值在主表中必须有对应的值,才能维护外键约束的有效性。ON UPDATE SET DEFAULT指定如果试图更新某一行,而该行的键被其他表的现有行中的外键所引用,则组成被引用行中的外键的所有值将被设置为它们的默认值。目标表的所有外键列必须具有默认值定义,此约束才可执行。如果某个列可为空值,并且未设置显式的默认值,则会使用 NULL 作为该列的隐式默认值。因 ON UPDATE SET DEFAULT 而设置的任何非空值在主表中必须有对应的值,才能维护外键约束的有效性。3、索引附加字段即在索引中存储一些常用字段以提高查询速度,这是一个不错的新特性。虽然索引的附加字段没有索引键值效率高,但是相对映射到数据表中效率还是提高了很多。在实验环境中会比映射到表中提高30%左右的效率。例:CREATE INDEX ix_CustomerPostalcode On Sales.Customer(PostalCode) INCLUDE (AddressLine1,AddressLine2,City)索引会提高查询(select)语句的性能,但建有大量索引会影响 INSERT、UPDATE 和 DELETE 语句的性能,因为在表中的数据更改时,所有索引都须进行适当的调整。4、计算字段的持久化原来的计算字段其实和虚拟字段很像。只是管理方面好了而已,性能方面提高不多。但是SQL2005提供了计算字段的持久化,这就提高了查询的性能,但是会加重insert和update的负担。OLTP慎用。OLAP可以大规模使用。 使用 ORDER 排序和虚拟字段 虚拟字段完成的是类似 自增长 ID 的任务 select identity(int,1,1) ID ,hymc into #temp from hybm order by hymc (注: 在ORACLE中,语句: select rownum from USERTABLE order by USERNAME; 得到的rownum还是没有排过序时的ROWNUM,根本不是已经排过序的ROWNUM。也就是说,有没有ORDER BY一个样。)5、分区表分区表是个亮点!从分区表也能看出微软要做大作强SQL Server的信心。资料很多,这里不详细说。但是重点了解的是:现在的SQL Server2005的表,都是默认为分区表的。因为它要支持滑动窗口的这个特性。这种特性对历史数据和实时数据的处理是很有帮助的。但是需要注意的一点,也是我使用过程中发现的一个问题。在建立function->schema->table后,如果在现有的分区表上建立没有显式声明的聚集索引时,分区表会自动变为非分区表。这一点很让我纳闷。如果你觉得我的非分区索引无法对起子分区,你可以提醒我一下呀!没有任何的提醒,直接就变成了非分区表。不知道这算不算一个bug。大家也可以试试。分区表效率问题肯定是大家关心的问题。在我的试验中,如果按照分区字段进行的查询(过滤)效率会高于未分区表的相同语句。但是如果按照非分区字段进行查询,效率会低于未分区表的相同语句。但是随着数据量的增大,这种成本差距会逐渐减小,趋于相等。(500万数量级只相差10%左右)6、CLR类型微软对CLR作了大篇幅的宣传,这是因为数据库产品终于融入.net体系中。最开始我们也是狂喜,感觉对象数据库的一些概念可以实现了。但是作了些试验,发现使用CLR的存储过程或函数在达到一定的阀值的时候,系统性能会呈指数级下滑!这是非常危险的!只使用几个可能没有问题,当一旦大规模使用会造成严重的系统性能问题!其实可以做一下类比,Oracle等数据库产品老早就支持了java编程,而且提供了java池参数作为用户配置接口。但是现在有哪些系统大批使用了java存储过程?!连Oracle自己的应用都不用为什么?!还不是性能有问题!否则面向对象的数据库早就实现了!建议使用CLR的地方一般是和应用的复杂程度或操作系统环境有很高的耦合度的场景。如你想构建复杂的算法,并且用到了大量的指针和高级数据模型。或者是要和操作系统进行Socket通讯的场景。否则建议慎重!7、索引视图索引视图2k就有。但是2005对其效率作了一些改进但是schema.viewname的作用域真是太限制了它的应用面。还有一大堆的环境参数和种种限制都让人对它有点却步。8、语句和事务快照语句级快照和事务级快照终于为SQL Server的并发性能带来了突破。个人感觉语句级快照大家应该应用。事务级快照,如果是高并发系统还要慎用。如果一个用户总是被提示修改不成功要求重试时,会杀人的!9、数据库快照原理很简单,对要求长时间计算某一时间点的报表生成和防用户操作错误很有帮助。但是比起Oracle10g的闪回技术还是细粒度不够。可惜!例子:CREATE DATABASE demo2GOUSE demo2ALTER DATABASE demo2 SET allow_snapshot_isolation ON --启动快照功能CREATE TABLE test( tid INT NOT NULL primary key,tname VARCHAR(50) NOT NULL)INSERT INTO test VALUES(1,'version1')INSERT INTO test VALUES(2,'version2')--连接一USE demo2BEGIN TRANUPDATE test SET tname='version3' WHERE tid=2SELECT * FROM test--连接二USE demo2SET transaction isolation level snapshotSELECT * FROM test10、MirrorMirror可以算是SQL Server的Data guard了。具说它切换速度可以达到秒级,这个功能能否被用户认可还有待时间的考验. 这个操作起来比较简单不在详细介绍。二、开发方面参考页面:http://www.microsoft.com/china/msdn/library/data/sqlserver/05TSQLEnhance.mspx?mfr=true1、Ranking函数集其中最有名的应该是row_number了。这个终于解决了用临时表生成序列号的历史,而且SQL Server2005的row_number比Oracle的更先进。因为它把Order by集成到了一起,不用像Oracle那样还要用子查询进行封装。但是大家注意一点。如下面的例子:USE demoGOCREATE TABLE rankorder(orderid INT,qty INT)GOINSERT 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)GOSELECT 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 rankorderORDER BY qty还有一点要说明:select ROW_NUMBER() OVER (order by aa)from tblorder by bb会先执行aa的排序,然后再进行bb的排序。可能有的朋友会抱怨集成的order by,其实如果使用ranking函数,Order by是少不了的。如果担心Order by会影响效率,可以为order by的字段建立聚集索引,查询计划会忽略order by 操作(因为本来就是排序的嘛)。2、top可以指定一个数字表达式,以返回要通过查询影响的行数或百分比,还可以根据情况使用变量或子查询。可以在DELETE、UPDATE和INSERT查询中使用TOP选项。可以动态传入参数,省却了动态SQL的拼写。例:--声明个变量DECLARE @a INT DECLARE @b INTDECLARE @c INT--赋值SET @a = 10SET @b = 5SELECT @c = @[email protected]--使用计算表达式SELECT TOP(@c) * FROM toptest--使用SELECT语句作为条件SELECT TOP(SELECT COUNT(*) FROM toptest2) * FROM toptest--指出topDELETE TOP(2) toptest where column1>'t6'--更新topUPDATE TOP(2) toptest SET column1 = 'hi' where column1<='t2'3、Apply对递归类的树遍历很有帮助。CROSS APPLY : 得到和FUNCTION 结果相匹配的记录OUTER APPLY: All rows , regardless of matching function results 一个有代表性的例子:USE demoGOCREATE TABLE Arrays(aid INT NOT NULL IDENTITY PRIMARY KEY,array VARCHAR(7999) NOT NULL)GOINSERT INTO Arrays VALUES('')INSERT INTO Arrays VALUES('10')INSERT INTO Arrays VALUES('20,40,30')INSERT INTO Arrays VALUES('-1,-3,-5')GOCREATE FUNCTION function1(@arr AS VARCHAR(7999))RETURNS @t TABLE(pos INT NOT NULL, value INT NOT NULL)ASBEGINDECLARE @end AS INT, @start AS INT, @pos AS INTSELECT @arr = @arr + ',', @pos = 1,@start = 1, @end = CHARINDEX(',', @arr, @start)WHILE @end > 1BEGININSERT INTO @t VALUES(@pos, SUBSTRING(@arr, @start, @end - @start))SELECT @pos = @pos + 1,@start = @end + 1, @end = CHARINDEX(',', @arr, @start)ENDRETURNEND--测试SELECT * FROM function1('200,400,300')GOSELECT A.aid, F.*FROM Arrays AS ACROSS APPLY function1(array) AS FGOSELECT A.aid, F.*FROM Arrays AS AOUTER APPLY function1(array) AS FGO查询结果:4、CTE(Common Table Expression 通用表达式)它是一个可以由定义语句引用的临时表命名的结果集,要用到WITH 关键字。例:WITH SalesCTE(ProductID,SalesOrderID) AS (SELECT ProductID,COUNT(SalesOrderid) FROM Sales.SalesOrderDetail GROUP BY ProductID) SELECT * FROM SalesCTE5、try/catch先说明一下事务相关语法:BEGIN TRAN[SACTION] [transaction_name]COMMIT [TRAN[SACTION]] [transaction_name]ROLLBACK [TRAN[SACTION] [transaction_name]SAVE TRAN[SACTION] [savepoint_name]上面这几很简单不解释了,下面看 SET XACT_ABORT ON/OFF,当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。所以在sql server 2k里使用事务就必须SET XACT_ABORT ON或者设置保存点。有了try/catch sql server2005 就不一样了!! 演示代码如下表。USE demoGO CREATE TABLE student --创建工作表( stuid INT NOT NULL PRIMARY KEY,stuname VARCHAR(50) )CREATE TABLE score ( stuid INT NOT NULL REFERENCES student(stuid),score INT )GOINSERT INTO student VALUES (101,'zhangsan') INSERT INTO student VALUES (102,'wangwu') INSERT INTO student VALUES (103,'lishi') INSERT INTO student VALUES (104,'maliu') 2K事务的打操作 2005 使用TRY...CATCH构造扩充了错误处理能力--调用一个运行时错误SET XACT_ABORT ON(若为OFF 事务不会回滚)BEGIN TRANINSERT INTO score VALUES (101,90)INSERT INTO score VALUES (102,78) INSERT INTO score VALUES (107,76) /*外键错误*/ INSERT INTO score VALUES (103,81) INSERT INTO score VALUES (104,65) COMMIT TRANGOSET XACT_ABORT OFFBEGIN TRYBEGIN TRANINSERT INTO score VALUES (101,90)INSERT INTO score VALUES (102,78) INSERT INTO score VALUES (107,76) /*外键错误*/ INSERT INTO score VALUES (103,81) INSERT INTO score VALUES (104,65) COMMIT TRANPRINT '事务提交'END TRYBEGIN CATCHROLLBACKPRINT '事务回滚'SELECT ERROR_NUMBER() AS ErrorNumber,ERROR_SEVERITY() AS ErrorSeverity,ERROR_STATE() as ErrorState,ERROR_MESSAGE() as ErrorMessage;END CATCHGO6、pivot/unpivot实现行列互转。2K 中这个功能用case实现,不过好像没有case 直观。而且默认的第三字段(还可能更多)作为group by字段很容易造成新手的错误。(有图我就不说了) 7、OUTPUT 关键字在下面的例子中只看蓝色的部分就是正常的insert into … values 语句,通过output 可以将中间值输出 到临时表,也就是不能过触发器也可以实现对中间数据的处理。例:DECLARE @InsertDetails TABLE (ProductID int, Insertedby sysname) INSERT INTO Stock.ProductList OUTPUT inserted.ProductID, suser_name() INTO @InsertDetails VALUES (‘Racing Bike’,412.99)
------------------------------------
sql2005部分新功能 1. TOP 表达式 SQL Server 2000的TOP是个固定值,是不是觉得不爽,现在改进了。 --前n名的订单declare @n int set @n = 10 select TOP(@n) * from Orders2. 分页 不知各位过去用SQL Server 2000是怎么分页的,大多都用到了临时表。SQL Server 2005一句话就支持分页,性能据说也非常不错。--按Freight从小到大排序,求20到30行的结果 select * from( select OrderId, Freight, ROW_NUMBER() OVER(order by Freight) as row from Orders ) a where row between 20 and 303. 排名 select * from( select OrderId, Freight, RANK() OVER(order by Freight) as rank from Orders ) a where rank between 20 and 304. try ... catch SQL Server 2000没有异常,T-SQL必须逐行检查错误代码,对于习惯了try catch程序员,2005是不是更加亲切:SET XACT_ABORT ON -- 打开 try功能 BEGIN TRY begin tran insert into Orders(CustomerId) values(-1) commit tran print 'commited' END TRY BEGIN CATCH rollback print 'rolled back' END CATCH5. 通用表达式CTE 通过表达式可免除你过去创建临时表的麻烦。--例子:结合通用表达式进行分页 WITH OrderFreight AS( select OrderId, Freight, ROW_NUMBER() OVER(order by Freight) as row from Orders ) select OrderId, Freight from OrderFreight where row between 10 and 20特别,通过表达式还支持递归。6. 直接发布Web Service 想要把store procedure变成Web Service就用这个吧,.NET, IIS都不需要,通过Windows 2003的HTTP Protocol Stack直接发布WebService,用这个功能需要Windows 2003 sp1--DataSet CustOrdersOrders(string customerID) CREATE ENDPOINT Orders_Endpoint state=started as http( path='/sql/orders', AUTHENTICATION=(INTEGRATED), ports=(clear) ) for soap( WebMethod 'CustOrdersOrders'( name='Northwind.dbo.CustOrdersOrders' ), wsdl=default, database='Northwind', namespace='http://mysite.org/' )