Создание недетерминированных функций в SQL Server с использованием RAND()

После небольшого поиска и чтения документации ясно, что вы можете писать пользовательские функции в SQL Server, которые помечены как детерминированные или недетерминированные, в зависимости от того, какие встроенные инфузии используются в теле.

RAND() указан под недетерминированными функциями (см. msdn article). Так почему я не могу использовать его в функции?

Ответ 1

Потому что он имеет побочные эффекты.

Конструкции с побочными эффектами в функции не допускаются. Побочным эффектом, который он имеет, является изменение некоторого внутреннего состояния, которое отслеживает последнее значение rand().

Я думаю, вы можете обойти его, включив его в определение вида, а затем выбрав из представления.

Ответ 2

Использование View может сработать для вас.
Из Возврат случайных чисел из оператора select

CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber

Представление необходимо, потому что, как вы уже выяснили, UDF не может использовать функцию rand(), потому что это сделает функцию неопределенной. Вы можете обмануть UDF, чтобы принять случайное число, используя View.

CREATE FUNCTION RandNumber()
RETURNS float
AS
  BEGIN
  RETURN (SELECT RandNumber FROM vRandNumber)
  END

Наконец, вы можете использовать эту функцию в любом SELECT, чтобы теперь вернуть случайное число от 0 до 1 за строку:

SELECT dbo.RandNumber(), *
FROM Northwind..Customers

Ответ 3

Я нашел это решение, которое не создает представление:

В принципе:

Вместо

SET @R = Rand()

Использование

SET @R = ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0

В моем случае мне понадобилось число от 1 до 10:

ROUND(((10 - 1 -1) * ( ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0) + 1), 0))

ROUND(((@max - @lower -1) * ( ABS(CHECKSUM(PWDENCRYPT(N''))) / 2147483647.0) + @lower), 0))

Если вы хотите получить полное объяснение: Использование (или имитация) Rand() В пользовательской функции T-Sql