- 工信部備案號 滇ICP備05000110號-1
- 滇公安備案 滇53010302000111
- 增值電信業務經營許可證 B1.B2-20181647、滇B1.B2-20190004
- 云南互聯網協會理事單位
- 安全聯盟認證網站身份V標記
- 域名注冊服務機構許可:滇D3-20230001
- 代理域名注冊服務機構:新網數碼
SQL Server 2008對T-SQL語言的增強
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 語句中一次性插入多行數據。例如:
CREATE TABLE #a
(
Column1 nvarchar(max),
Column2 nvarchar(max)
);
GO
INSERT INTO #a
VALUES (
('1', '1'),
('2', '2')
);
select * from #a;
GO
drop TABLE #a;
GO
經過增強后的 INSERT 語句的語法結構如下。
[ WITH <common_table_expression> [ ,...n ] ]
INSERT
[ TOP ( expression ) [ PERCENT ] ]
[ INTO ]
{ <object> | rowset_function_limited
[ WITH ( <Table_Hint_Limited> [ ...n ] ) ]
}
{
[ ( column_list ) ]
[ <OUTPUT Clause> ]
{ VALUES ( ( { DEFAULT | NULL | expression } [ ,...n ] ) [ ,...n ] )
| derived_table
| execute_statement
| <dml_table_source>
| DEFAULT VALUES
}
}
[; ]
<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. FORCESEEK 提示
FORCESEEK 是一個新的表提示(Table Hints),它用來指定 SQL Server 查詢優化程序如何更高效的執行查詢。該提示指示優化程序對查詢引用的表和視圖通過索引檢索來作為唯一的查詢執行訪問路徑。也就是強制通過索引檢索數據。例如:
USE tempdb;
GO
drop TABLE t;
GO
CREATE TABLE t(i int UNIQUE, j int, vc varchar(100));
CREATE INDEX t_vc ON t(vc);
GO
DECLARE @p1 int, @p2 int, @p3 int, @p4 int, @p5 int;
select * from t where i IN (@p1, @p2, @p3, @p4, @p5);
GO
DECLARE @p1 int, @p2 int, @p3 int, @p4 int, @p5 int;
select * from t WITH (FORCESEEK) where i IN (@p1, @p2, @p3, @p4, @p5);
GO
select * from t where vc LIKE 'Test%';
GO
select * from t WITH (FORCESEEK) where vc LIKE 'Test%';
GO
DECLARE @vc varchar(100);
select * from t where vc LIKE @vc;
GO
DECLARE @vc varchar(100);
select * from t WITH (FORCESEEK) where vc like @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 存儲過程。它用來設置特定數據庫的兼容性級別。其語法形式為:
ALTER DATABASE database_name
SET COMPATIBILITY_LEVEL = { 80 | 90 | 100 }
您可以為 database_name 為名稱的數據庫設置特定兼容性級別。80、90 和 100 分別代表 SQL Server 2000、SQL Server 2005 和 SQL Server 2008。
5. 用戶自定義表數據類型
現在,SQL Server 提供一種新的用戶自定義數據類型――自定義表數據類型(User-defined Table Types)。它可以作為參數提供給語句、存儲過程或者函數。您還可以為它創建唯一約束和主鍵。
請使用 CREATE TYPE 語句創建這種數據類型。如:
USE AdventureWorks;
GO
/* Create a user-defined table type */
CREATE TYPE LocationTableType AS TABLE
( LocationName VARchar(50)
, CostRate INT );
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 數據。
下面的示例展示了如何使用表值參數。
USE AdventureWorks;
GO
/* Create a table type. */
CREATE TYPE LocationTableType AS TABLE
( LocationName VARchar(50)
, CostRate INT );
GO
/* Create a procedure to receive data for the table-valued parameter. */
CREATE PROCEDURE usp_InsertProductionLocation
@TVP LocationTableType READONLY
AS
SET NOCOUNT ON
INSERT INTO [AdventureWorks].[Production].[Location]
([Name]
,[CostRate]
,[Availability]
,[ModifiedDate])
select *, 0, GETDATE()
from @TVP;
GO
/* Declare a variable that references the type. */
DECLARE @LocationTVP
AS LocationTableType;
/* Add data to the table variable. */
INSERT INTO @LocationTVP (LocationName, CostRate)
select [Name], 0.00
from
[AdventureWorks].[Person].[StateProvince];
/* Pass the table variable data to a stored procedure. */
EXEC usp_InsertProductionLocation @LocationTVP;
GO
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>
[ WHEN MATCHED [ AND <search_condition> ]
THEN <merge_matched> ]
[ WHEN [TARGET] NOT MATCHED [ AND <search_condition> ]
THEN <merge_not_matched> ]
[ WHEN SOURCE NOT MATCHED [ 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>::=
{ update SET <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> )
| DEFAULT VALUES }
<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 操作
USE AdventureWorks;
GO
MERGE Production.ProductInventory AS pi
USING (select ProductID, SUM(OrderQty) from Sales.SalesOrderDetail sod
JOIN Sales.SalesOrderHeader soh
ON sod.SalesOrderID = soh.SalesOrderID
AND soh.OrderDate = GETDATE()
GROUP BY ProductID) AS src (ProductID, OrderQty)
ON (pi.ProductID = src.ProductID)
WHEN MATCHED AND pi.Quantity - src.OrderQty <> 0
THEN update SET pi.Quantity = pi.Quantity - src.OrderQty
WHEN MATCHED AND pi.Quantity - src.OrderQty = 0
THEN DELETE;
這個示例是一個非常典型的銷售定貨庫存問題。這個示例很簡單,表達的意思就是:如果某一個產品產生了銷售定單數據,則將其對應的產品庫存除去該銷售定單所產生的數量,如果當前庫存數量與該銷售定單數量相同,則從庫存表中刪除該產品的庫存紀錄。
我們看到,利用 MERGE 語句可以將復雜的 SQL 語句簡化。它比起 IF、CASE 等更加靈活和強大。
結論
Microsoft SQL Server 2008 對事務性 SQL 語言做了一些增強,提高了查詢效率。使得 SQl Server 成為大中型企業數據庫的首先產品。SQL Server 2008 將伴隨 Visual Studio 2008 一起發布,開發人員提前了解這些信息有助于在 SQL Server 的新版本發布后快速建立基于該版本的企業級應用程序。
售前咨詢
售后咨詢
備案咨詢
二維碼
TOP