- SQL Server 2008对T-SQL语言的增强
- 发布时间:2008-11-04 14:57:55 浏览数:5642 发布者:lbsong 设置字体【大 中 小】
Microsoft SQL Server 2008 对 T-SQL 语言进行了进一步增强。为了让开发人员尽快了解这些变化,我们针对 2007 年 6 月 CTP 版本的 SQL Server 2008 中的 T-SQL 语言的新增功能进行了分析和尝试。本文描述自 SQL Server 2008 CTP1 以来这些语言增强和变化。
本文包含如下内容:
· T-SQL 行构造器
· FORCESEEK 表提示
· GROUPING SETS
· 兼容性级别
· 用户自定义表数据类型
· 表值参数
· MERGE 语句
本文适用于:Microsoft)R) SQL Server(TM) 2008 Developer Edition June 2007 CTP
1、T-SQL 行构造器
T-SQL 行构造器(Row Constructors)用来在 INSERT 语句中一次性插入多行数据。例如:
以下为引用的内容:
CREATETABLE#a
(
Column1nvarchar(max),
Column2nvarchar(max)
);
GO
INSERTINTO#a
VALUES(
('1','1'),
('2','2')
);
SELECT*FROM#a;
GO
DROPTABLE#a;
GO
经过增强后的 INSERT 语句的语法结构如下。
以下为引用的内容:
[WITH<common_table_expression>[,...n]]
INSERT
[TOP(expression)[PERCENT]]
[INTO]
{<object>|rowset_function_limited
[WITH(<Table_Hint_Limited>[...n])]
}
{
[(column_list)]
[<OUTPUTClause>]
{VALUES(({DEFAULT|NULL|expression}[,...n])[,...n])
|derived_table
|execute_statement
|<dml_table_source>
|DEFAULTVALUES
}
}
[;]
<object>::=
{
[server_name.database_name.schema_name.
|database_name.[schema_name].
|schema_name.
]
table_or_view_name
}
<dml_table_source>::=
SELECT<select_list>
FROM(<dml_statement_with_output_clause>)
[AS]table_alias[(column_alias[,...n])]
[WHERE<search_condition>]
[OPTION(<query_hint>[,...n])]
#2楼发布者:lbsong时间:2008-11-04 14:58:48
2. FORCESEEK 提示
FORCESEEK 是一个新的表提示(Table Hints),它用来指定 SQL Server 查询优化程序如何更高效的执行查询。该提示指示优化程序对查询引用的表和视图通过索引检索来作为唯一的查询执行访问路径。也就是强制通过索引检索数据。例如:
以下为引用的内容:
USEtempdb;
GO
DROPTABLEt;
GO
CREATETABLEt(iintUNIQUE,jint,vcvarchar(100));
CREATEINDEXt_vcONt(vc);
GO
DECLARE@p1int,@p2int,@p3int,@p4int,@p5int;
SELECT*FROMtWHEREiIN(@p1,@p2,@p3,@p4,@p5);
GO
DECLARE@p1int,@p2int,@p3int,@p4int,@p5int;
SELECT*FROMtWITH(FORCESEEK)WHEREiIN(@p1,@p2,@p3,@p4,@p5);
GO
SELECT*FROMtWHEREvcLIKE'Test%';
GO
SELECT*FROMtWITH(FORCESEEK)WHEREvcLIKE'Test%';
GO
DECLARE@vcvarchar(100);
SELECT*FROMtWHEREvcLIKE@vc;
GO
DECLARE@vcvarchar(100);
SELECT*FROMtWITH(FORCESEEK)wherevclike@vc;
GO
3. GROUPING SETS
新的 T-SQL 对 GROUP BY 子句增加了 GROUPING SETS, ROLLUP 和 CUBE 操作符。还有一个新的函数 GROUPING_ID(),它相比 GROUPING() 函数返回更多分组级别的信息。WITH ROLLUP, WITH CUBE 和 ALL 等非 ISO 标准语法已经不再有效。
4. 兼容性级别
新的 ALTER DATABASE SET COMPATIBILITY_LEVEL 语法替换了 sp_dbcomplevel 存储过程。它用来设置特定数据库的兼容性级别。其语法形式为:
以下为引用的内容:
ALTERDATABASEdatabase_name
SETCOMPATIBILITY_LEVEL={80|90|100}
您可以为 database_name 为名称的数据库设置特定兼容性级别。80、90 和 100 分别代表 SQL Server 2000、SQL Server 2005 和 SQL Server 2008。
#3楼发布者:lbsong时间:2008-11-04 15:00:03
5. 用户自定义表数据类型
现在,SQL Server 提供一种新的用户自定义数据类型——自定义表数据类型(User-defined Table Types)。它可以作为参数提供给语句、存储过程或者函数。您还可以为它创建唯一约束和主键。
请使用 CREATE TYPE 语句创建这种数据类型。如:
以下为引用的内容:
USEAdventureWorks;
GO
/**//*Createauser-definedtabletype*/
CREATETYPELocationTableTypeASTABLE
(LocationNameVARCHAR(50)
,CostRateINT);
GO
对于表类型,有如下约束:
1、用户自定义表类型不能作为表的列或者结构化用户自定义类型的域。
2、基于用户自定义表类型的别名类型。
3、不允许 NOT FOR REPLICATION 选项。
4、CHECK 约束需要一个计算列。
5、在计算列上的主键必须包含 NOT NULL 和 PERSISTED 约束。
6、不能在用户自定义表类型上创建非簇索引。除非索引是创建 PRIMARY KEY 或 UNIQUE 约束的返回值。
7、不能指定 DEFAULT 值。
8、一旦用户自定义表类型被创建,则它就无法更改。
9、如果没有定义用户自定义表类型上的计算列,则用户自定义函数无法调用。
6. 表值参数
数据库引擎现在支持一种新的参数类型来引用用户自定义表类型(参考 5)。表值参数可以发送更多的 SQL Server 数据。
下面的示例展示了如何使用表值参数。
以下为引用的内容:
USEAdventureWorks;
GO
/**//*Createatabletype.*/
CREATETYPELocationTableTypeASTABLE
(LocationNameVARCHAR(50)
,CostRateINT);
GO
/**//*Createaproceduretoreceivedataforthetable-valuedparameter.*/
CREATEPROCEDUREusp_InsertProductionLocation
@TVPLocationTableTypeREADONLY
AS
SETNOCOUNTON
INSERTINTO[AdventureWorks].[Production].[Location]
([Name]
,[CostRate]
,[Availability]
,[ModifiedDate])
SELECT*,0,GETDATE()
FROM @TVP;
GO
/**//*Declareavariablethatreferencesthetype.*/
DECLARE@LocationTVP
ASLocationTableType;
/**//*Adddatatothetablevariable.*/
INSERTINTO@LocationTVP(LocationName,CostRate)
SELECT[Name],0.00
FROM
[AdventureWorks].[Person].[StateProvince];
/**//*Passthetablevariabledatatoastoredprocedure.*/
EXECusp_InsertProductionLocation@LocationTVP;
GO
#4楼发布者:lbsong时间:2008-11-04 15:01:09
7. MERGE 语句
这个新增的 Transaction SQL 语句在一个基于源数据连接结果集的目标表上执行 INSERT、UPDATE 和 DELETE 操作。该语法允许您将一个数据源连接到目标表或视图上。然后在连接后的结果集上执行多种操作。
MERGE 的语法为:
以下为引用的内容:
[WITH<common_table_expression>[,...n]]
MERGE
[TOP(expression)[PERCENT]]
[INTO]target_table[[AS]table_alias]
[WITH(<merge_hint>)]
USING<table_source>
ON<search_condition>
[WHENMATCHED[AND<search_condition>]
THEN<merge_matched>]
[WHEN[TARGET]NOTMATCHED[AND<search_condition>]
THEN<merge_not_matched>]
[WHENSOURCENOTMATCHED[AND<search_condition>]
THEN<merge_matched>]
<output_clause>
[OPTION(<query_hint>[,...n])]
;
<merge_hint>::=
{[<table_hint_limited>[,...n]]
[[,]INDEX(index_val[,...n])]}
<table_source>::=
{
table_or_view_name[[AS]table_alias][<tablesample_clause>]
[WITH(table_hint[[,]...n])]
|rowset_function[[AS]table_alias]
[(bulk_column_alias[,...n])]
|user_defined_function[[AS]table_alias]
|OPENXML<openxml_clause>
|derived_table[AS]table_alias[(column_alias[,...n])]
|<joined_table>
|<pivoted_table>
|<unpivoted_table>
}
<merge_matched>::=
{UPDATESET<set_clause>|DELETE}
<set_clause>::=
{column_name={expression|DEFAULT|NULL}
|{udt_column_name.{{property_name=expression
|field_name=expression}
|method_name(argument[,...n])}}
|column_name{.WRITE(expression,@Offset,@Length)}
|@variable=expression
}[,...n]
<merge_not_matched>::=
INSERT[(<column_list>)]
{VALUES(<values_list>)
|DEFAULTVALUES}
<output_clause>::=
{
[OUTPUT<dml_select_list>INTO{@table_variable|output_table}
[(column_list)]]
[OUTPUT<dml_select_list>]
}
<dml_select_list>::=
{<column_name>|scalar_expression}[[AS]column_alias_identifier]
[,...n]
<column_name>::=
{DELETED|INSERTED|from_table_name}.{*|column_name}
|$ACTION
示例:在一条 SQL 语句中使用 WHERE 在一张表上执行 UPDATE 和 DELETE 操作
以下为引用的内容:
USEAdventureWorks;
GO
MERGEProduction.ProductInventoryASpi
USING(SELECTProductID,SUM(OrderQty)FROMSales.SalesOrderDetailsod
JOINSales.SalesOrderHeadersoh
ONsod.SalesOrderID=soh.SalesOrderID
ANDsoh.OrderDate=GETDATE()
GROUPBYProductID)ASsrc(ProductID,OrderQty)
ON(pi.ProductID=src.ProductID)
WHENMATCHEDANDpi.Quantity-src.OrderQty<>0
THENUPDATESETpi.Quantity=pi.Quantity-src.OrderQty
WHENMATCHEDANDpi.Quantity-src.OrderQty=0
THENDELETE;
这个示例是一个非常典型的销售定货库存问题。这个示例很简单,表达的意思就是:如果某一个产品产生了销售定单数据,则将其对应的产品库存除去该销售定单所产生的数量,如果当前库存数量与该销售定单数量相同,则从库存表中删除该产品的库存纪录。
我们看到,利用 MERGE 语句可以将复杂的 SQL 语句简化。它比起 IF、CASE 等更加灵活和强大。
结论
Microsoft SQL Server 2008 对事务性 SQL 语言做了一些增强,提高了查询效率。使得 SQl Server 成为大中型企业数据库的首先产品。SQL Server 2008 将伴随 Visual Studio 2008 一起发布,开发人员提前了解这些信息有助于在 SQL Server 的新版本发布后快速建立基于该版本的企业级应用程序。