by Admin
19. марта 2009 16:53
Данная тема вроде бы ни раз уже поднималась, но натолкнувшись в форуме вновь на данный вопрос, решил описать обходной путь у себя в БЛОГе. И так, если верить BOL (SQL Server Books Online) в UDF(в пользовательских функциях) нельзя использовать недетерминированные функции. Недетерминированными считаются функции, которые возвращают различные результаты от вызова к вызову, даже если они вызываются с одинаковыми параметрами. К недетерминированным функциям относятся:
@@CONNECTIONS |
@@TOTAL_READ |
@@CPU_BUSY |
@@TOTAL_WRITE |
@@DBTS |
CURRENT_TIMESTAMP |
@@IDLE |
GETDATE |
@@IO_BUSY |
GETUTCDATE |
@@MAX_CONNECTIONS |
GET_TRANSMISSION_STATUS |
@@PACK_RECEIVED |
MIN_ACTIVE_ROWVERSION |
@@PACK_SENT |
NEWID |
@@PACKET_ERRORS |
NEWSEQUENTIALID |
@@TIMETICKS |
RAND |
@@TOTAL_ERRORS |
TEXTPTR |
К нашему счастью, начиная с SQL Server 2005 список недетерминированных функций, которые нельзя использовать в UDF резко сократился до NEWID, NEWSEQUENTIALID, RAND, TEXTPTR. При попытке создать функцию допустим с NEWID:
CREATE FUNCTION dbo.TestFunc()
RETURNS REAL AS
BEGIN
RETURN (SELECT RAND())
END
Получаем ошибку:
Msg 443, Level 16, State 1, Procedure TestFunc, Line 5 Invalid use of a side-effecting operator ‘rand’ within a function.
Итак, как обойти это ограничение: необходимо наши недетерминированные функции обернуть в VIEW (представление), а затем уже его использовать в наших пользовательских функциях:
--Создаём наше представление
CREATE VIEW NondeterministicFunctions
AS
SELECT RAND() as MyRAND, NEWID() as MyNEWID, GETDATE() as MyGETDATE
--и т.д.
GO
--Ну, а дальше, используя наше представление,
--получаем из UDF доступ к недетерминированным функциям
CREATE FUNCTION dbo.TestFunc()
RETURNS REAL
AS
BEGIN
RETURN (SELECT MyRAND FROM NondeterministicFunctions )
END
GO
Удачи!
cba21dbf-407b-488d-a9dc-7a5cefc06350|3|5.0|27604f05-86ad-47ef-9e05-950bb762570c
Tags: SQL Server
SQL Server