1. 程式人生 > 其它 >SQL Server表值函式

SQL Server表值函式

GPS平臺、網站建設、軟體開發、系統運維,找森大網路科技!
https://cnsendnet.taobao.com
來自森大科技官方部落格
http://www.cnsendblog.com/index.php/?p=1966

表值函式

表值函式提供強大的結果集生成能力。它可以在查詢內部表或檢視允許的任何地方使用。表值函式在使用上比返回一個結果集的儲存過程更靈活,因為函式的結果集可以聯接到查詢中的其他表。

SQL Server中有兩種表值函式。內聯表值函式在概念上與帶引數的檢視類似。多語句表值函式允許多條語句在表變數中建立結果集來返回。

1. 內聯表值函式

建立內聯表值函式很簡單。內聯表值函式的內容是一條帶引數的SELECT語句。返回資料型別永遠是表,不過返回表的結構由SELECT語句的結構來定義。下面是內聯表值函式的一個例子,檢索給定CustomerID的商品銷售總量。

  1. USE AdventureWorks2008;
  2. GO
  3. CREATE FUNCTION Sales.ufnSalesByCustomer (@CustomerID int)
  4. RETURNS TABLE
  5. AS
  6. RETURN
  7. (
  8. SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS Total
  9. FROM Production.ProductAS P

10.JOIN Sales.SalesOrderDetailAS SD

  1. ON SD.ProductID = P.ProductID

12.JOIN Sales.SalesOrderHeaderAS SH

13.ON SH.SalesOrderID = SD.SalesOrderID

14.WHERE SH.CustomerID = @CustomerID

15.GROUP BY P.ProductID, P.Name

16.);

17.GO

注意,函式體由一條RETURN語句組成。使用這個函式的一個例子如下所示:

  1. SELECT * FROM Sales.ufnSalesByCustomer(30052);

內聯表值函式功能強大,在要求引數化查詢的情況下值得考慮。它們在結果集如何使用上提供更多的靈活性。

2. 多語句表值函式

多語句表值函式允許多條語句來建立表的內容。多語句表值函式可以用來替換使用多個步驟來構建結果集的儲存過程。

多語句表值函式允許開發人員使用多個步驟動態地填充表,這一點與儲存過程類似,不過它們可以在SELECT語句中像表那樣被引用。

使用多語句表值函式時,表的結構必須在函式頭定義。要為表使用一個變數名,並且所有修改資料的操作只能引用表變數。

下面的例子是一個函式,類似上一節中建立的ufnSalesByCustomer。首先建立表變數,然後使用剛才建立的標量函式來更新表變數,讓它包含總的存貨清單。建立函式的語句如下所示:

  1. USE AdventureWorks2008;
  2. GO
  3. CREATE FUNCTION Sales.ufnSalesByCustomerMS (@CustomerID int)
  4. RETURNS @table TABLE
  5. ( ProductID int PRIMARY KEY NOT NULL,
  6. ProductName nvarchar(50) NOT NULL,
  7. TotalSales numeric(38,6) NOT NULL,
  8. TotalInventory int NOT NULL )
  9. AS

10.BEGIN

11. INSERT INTO @table

12. SELECT P.ProductID, P.Name, SUM(SD.LineTotal) AS Total, 0

13.FROM Production.ProductAS P

14.JOIN Sales.SalesOrderDetailSD ON SD.ProductID = P.ProductID

15.JOIN Sales.SalesOrderHeader SH ON SH.SalesOrderID = SD.SalesOrderID

16.WHERE SH.CustomerID = @CustomerID

17.GROUP BY P.ProductID, P.Name;

18.

19.UPDATE @table

20.SET TotalInventory = dbo.ufnGetTotalInventoryStock(ProductID);

21.

22.RETURN;

23.END;

執行這個函式與執行前面的行內函數一樣:

  1. SELECT * FROM Sales. ufnSalesByCustomerMS (30052);

-------------------------------------------------------------------------------------

表值函式和標量值函式的不同是 表值函式是返回一個Table型別 Table型別相當與一張儲存在記憶體中的一張虛擬表.

表值函式的語法:

CREATE FUNCTION [ schema_name. ] function_name
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] }
[ ,...n ]
]
)
RETURNS TABLE
[ WITH <function_option> [ ,...n ] ]
[ AS ]
RETURN [ ( ] select_stmt [ ) ]
[ ; ]

現在來寫一個比較實用的表值函式..

寫一個切割字串的表值函式

view plaincopy to clipboardprint?
--------------------------這個函式用來切割字串的-----------------
--函式的引數 第一個是要切割的字串 第二個是要以什麼字串切割
CREATE FUNCTION Split(@Text NVARCHAR(4000),@Sign NVARCHAR(4000))
RETURNS @tempTable TABLE(id INT IDENTITY(1,1) PRIMARY KEY,[VALUE] NVARCHAR(4000))
AS
BEGIN
DECLARE @StartIndex INT --開始查詢的位置
DECLARE @FindIndex INT --找到的位置
DECLARE @Content VARCHAR(4000) --找到的值
--初始化一些變數
SET @StartIndex = 1 --T-SQL中字串的查詢位置是從1開始的
SET @FindIndex=0

--開始迴圈查詢字串逗號
WHILE(@StartIndex <= LEN(@Text))
BEGIN
--查詢字串函式 CHARINDEX 第一個引數是要找的字串
-- 第二個引數是在哪裡查詢這個字串
-- 第三個引數是開始查詢的位置
--返回值是找到字串的位置
SELECT @FindIndex = CHARINDEX(@Sign,@Text,@StartIndex)
--判斷有沒找到 沒找到返回0
IF(@FindIndex =0 OR @FindIndex IS NULL)
BEGIN
--如果沒有找到者表示找完了
SET @FindIndex = LEN(@Text)+1
END
--擷取字串函式 SUBSTRING 第一個引數是要擷取的字串
-- 第二個引數是開始的位置
-- 第三個引數是擷取的長度
--@FindIndex-@StartIndex 表示找的的位置-開始找的位置=要擷取的長度
--LTRIM 和 RTRIM 是去除字串左邊和右邊的空格函式
SET @Content = LTRIM(RTRIM(SUBSTRING(@Text,@StartIndex,@FindIndex-@StartIndex)))
--初始化下次查詢的位置
SET @StartIndex = @FindIndex+1
--把找的的值插入到要返回的Table型別中
INSERT INTO @tempTable ([VALUE]) VALUES (@Content)
END
RETURN
END
--------------------------這個函式用來切割字串的-----------------
--函式的引數 第一個是要切割的字串 第二個是要以什麼字串切割
CREATE FUNCTION Split(@Text NVARCHAR(4000),@Sign NVARCHAR(4000))
RETURNS @tempTable TABLE(id INT IDENTITY(1,1) PRIMARY KEY,[VALUE] NVARCHAR(4000))
AS
BEGIN
DECLARE @StartIndex INT --開始查詢的位置
DECLARE @FindIndex INT --找到的位置
DECLARE @Content VARCHAR(4000) --找到的值
--初始化一些變數
SET @StartIndex = 1 --T-SQL中字串的查詢位置是從1開始的
SET @FindIndex=0

--開始迴圈查詢字串逗號
WHILE(@StartIndex <= LEN(@Text))
BEGIN
--查詢字串函式 CHARINDEX 第一個引數是要找的字串
-- 第二個引數是在哪裡查詢這個字串
-- 第三個引數是開始查詢的位置
--返回值是找到字串的位置
SELECT @FindIndex = CHARINDEX(@Sign,@Text,@StartIndex)
--判斷有沒找到 沒找到返回0
IF(@FindIndex =0 OR @FindIndex IS NULL)
BEGIN
--如果沒有找到者表示找完了
SET @FindIndex = LEN(@Text)+1
END
--擷取字串函式 SUBSTRING 第一個引數是要擷取的字串
-- 第二個引數是開始的位置
-- 第三個引數是擷取的長度
--@FindIndex-@StartIndex 表示找的的位置-開始找的位置=要擷取的長度
--LTRIM 和 RTRIM 是去除字串左邊和右邊的空格函式
SET @Content = LTRIM(RTRIM(SUBSTRING(@Text,@StartIndex,@FindIndex-@StartIndex)))
--初始化下次查詢的位置
SET @StartIndex = @FindIndex+1
--把找的的值插入到要返回的Table型別中
INSERT INTO @tempTable ([VALUE]) VALUES (@Content)
END
RETURN
END

這個函式的作用就是類似.Net中的string類的Split方法

現在來測試這個函式

這個函式返回的是Table型別 所以可以用下面的語法來呼叫

view plaincopy to clipboardprint?
SELECT * FROM dbo.Split('a,b,c,d,e,f,g',',')
SELECT * FROM dbo.Split('a,b,c,d,e,f,g',',')

得到的結果

GPS平臺、網站建設、軟體開發、系統運維,找森大網路科技!
https://cnsendnet.taobao.com
來自森大科技官方部落格
http://www.cnsendblog.com/index.php/?p=1966