加密系統資料表中儲存的 CREATE FUNCTION 文字,防止函數作為複寫一部分被發佈。
將函數繫結至其參考的資料庫物件。啟用後:
ALTER)或移除(DROP)被參考的物件。SCHEMABINDING 時執行 ALTER FUNCTION。啟用條件(全部滿足):
schema.object)。REFERENCES 權限。RETURNS 指定標量型別 → 標量值函數,可使用多重 T-SQL 陳述式定義。RETURNS TABLE → 資料表值函數:
@return_variable TABLE (...))→ 多重陳述式函數。確定性函數:相同輸入永遠傳回相同結果。
非確定性函數:相同輸入可能傳回不同結果,會產生副作用(修改全域狀態、檔案、網路等)。
@@CONNECTIONS @@TOTAL_ERRORS @@CPU_BUSY @@TOTAL_READ
@@IDLE @@TOTAL_WRITE @@IO_BUSY GETDATE
@@MAX_CONNECTIONS GETUTCDATE @@PACK_RECEIVED NEWID
@@PACK_SENT RAND @@PACKET_ERRORS TEXTPTR
@@TIMETICKS
[database.]owner.function_name(args...)[database.][owner.]function_name(args...):: 前綴,如 SELECT * FROM ::fn_helpcollations()在預存程序中導致陳述式終止的錯誤,會繼續執行下一陳述式;但在 函數中會導致函數停止執行,進而使呼叫該函數的陳述式停止。
CREATE FUNCTION 權限(預設授予 sysadmin, db_owner, db_ddladmin)。EXECUTE 權限;其他使用者需明確授予。CONSTRAINT, DEFAULT, 計算資料行中參考 UDF 時,需該函數的 REFERENCES 權限。CREATE FUNCTION ISOweek (@DATE datetime)
RETURNS int
AS BEGIN
DECLARE @ISOweek int
SET @ISOweek = DATEPART(wk, @DATE) + 1
- DATEPART(wk, CAST(DATEPART(yy, @DATE) AS CHAR(4)) + '0104')
IF (@ISOweek = 0)
SET @ISOweek = dbo.ISOweek(CAST(DATEPART(yy, @DATE) - 1 AS CHAR(4)) + '12'
+ CAST(24 + DATEPART(DAY, @DATE) AS CHAR(2))) + 1
IF (DATEPART(mm, @DATE) = 12 AND (DATEPART(dd, @DATE) - DATEPART(dw, @DATE)) >= 28)
SET @ISOweek = 1
RETURN @ISOweek
END
GO
SET DATEFIRST 1
SELECT master.dbo.ISOweek('12/26/1999') AS 'ISO Week' -- 回傳 52
USE pubs
GO
CREATE FUNCTION SalesByStore (@storeid varchar(30))
RETURNS TABLE
AS RETURN (
SELECT title, qty
FROM sales s, titles t
WHERE s.stor_id = @storeid AND t.title_id = s.title_id
)
CREATE TABLE employees (
empid nchar(5) PRIMARY KEY,
empname nvarchar(50),
mgrid nchar(5) REFERENCES employees(empid),
title nvarchar(30)
)
CREATE FUNCTION fn_FindReports (@InEmpId nchar(5))
RETURNS @retFindReports TABLE (
empid nchar(5) PRIMARY KEY,
empname nvarchar(50) NOT NULL,
mgrid nchar(5),
title nvarchar(30)
)
AS BEGIN
DECLARE @RowsAdded int
DECLARE @reports TABLE (
empid nchar(5) PRIMARY KEY,
empname nvarchar(50) NOT NULL,
mgrid nchar(5),
title nvarchar(30),
processed tinyint DEFAULT 0
)
INSERT @reports SELECT empid, empname, mgrid, title, 0
FROM employees WHERE empid = @InEmpId
SET @RowsAdded = @@ROWCOUNT
WHILE @RowsAdded > 0 BEGIN
UPDATE @reports SET processed = 1 WHERE processed = 0
INSERT @reports
SELECT e.empid, e.empname, e.mgrid, e.title, 0
FROM employees e, @reports r
WHERE e.mgrid = r.empid AND e.mgrid <> e.empid AND r.processed = 1
SET @RowsAdded = @@ROWCOUNT
UPDATE @reports SET processed = 2 WHERE processed = 1
END
INSERT @retFindReports SELECT empid, empname, mgrid, title FROM @reports
RETURN
END
GO
SELECT * FROM fn_FindReports('11234')