2010-08-20 31 views
9

Después de buscar y leer la documentación, está claro que puede escribir funciones definidas por el usuario en SQL Server que estén marcadas como deterministas o no deterministas, dependiendo de las infunciones incorporadas. usado dentro del cuerpoCreación de funciones no deterministas en SQL Server utilizando RAND()

RAND() se enumera bajo las funciones no deterministas (ver msdn article). Entonces, ¿por qué no puedo usarlo en una función?

Respuesta

13

Porque tiene efectos secundarios.

Las construcciones con efectos secundarios no están permitidas en una función. El efecto secundario que tiene es cambiar algún estado interno que realiza un seguimiento del último valor rand() emitido.

Creo que puede evitarlo incluyéndolo en una definición de vista y luego seleccionando desde la vista.

+0

ah, entiendo ahora! No pensé en el almacenamiento interno del último número aleatorio. Puedo ver cómo esto lo diferencia de otras funciones no deterministas. ¡Gracias! – BG100

+0

echa un vistazo a http://sqlfascination.com/tag/randomstring/ Le dice exactamente cómo hacer esto. – baash05

19

Usar una vista podría funcionar para usted.
De Returning Random Numbers from a select statement

CREATE VIEW vRandNumber 
AS 
SELECT RAND() as RandNumber 

La vista es necesario porque, como ya se enteraron, una UDF no puede utilizar la función rand() porque eso haría que la función no determistic. Puede engañar al UDF para que acepte un número aleatorio usando una Vista.

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

Por último, puede utilizar esta función en cualquier momento SELECT para devolver un número aleatorio entre 0 y 1 por fila:

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

+1 Para el truco de la vista. Yo también me acordé de eso también. Sin embargo, no es por el determinismo. 'getdate()' está permitido en una función. Obviamente, esa función no se puede usar cuando se requiere una función determinista, como una columna calculada persistente. Es a causa de los efectos secundarios. El error planteado es "Uso no válido de un operador de efecto secundario 'rand' dentro de una función". –

+0

¡Gracias! Había escuchado acerca de hacer esto como un trabajo para la función NEWID(), pero no me di cuenta de que también funcionaría para RAND(). – BG100

3

yo encontramos este solution que no crea un punto de vista:

Básicamente:

En lugar de

SET @R = Rand() 

Uso

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

En mi caso, yo quería un número entre 1 y 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)) 

Si quieres una explicación completa: Using (Or Simulating) Rand() In A T-Sql User-Defined Function

Cuestiones relacionadas