Après un peu de recherche et de lecture de la documentation, il est clair que vous pouvez écrire des fonctions définies par l'utilisateur dans SQL Server qui sont marquées comme déterministes ou non déterministes selon les fonctions intégrées utilisé dans le corps. RAND() est répertorié sous les fonctions non déterministes (voir msdn article). Alors pourquoi je ne peux pas l'utiliser dans une fonction?Création de fonctions non déterministes dans SQL Server en utilisant RAND()
Répondre
Parce qu'il a des effets secondaires.
Les constructions avec des effets secondaires ne sont pas autorisées dans une fonction. L'effet secondaire est de modifier un état interne qui conserve la dernière valeur rand()
émise.
Je pense que vous pouvez contourner cela en l'incluant dans une définition de vue puis en sélectionnant dans la vue.
L'utilisation d'une vue peut fonctionner pour vous.
De Returning Random Numbers from a select statement
CREATE VIEW vRandNumber
AS
SELECT RAND() as RandNumber
La vue est nécessaire parce que, comme vous avez déjà découvert, une UDF ne peut pas utiliser la fonction rand() car cela rendrait la fonction non-determistic. Vous pouvez tromper l'UDF pour accepter un nombre aléatoire en utilisant une vue.
CREATE FUNCTION RandNumber()
RETURNS float
AS
BEGIN
RETURN (SELECT RandNumber FROM vRandNumber)
END
Enfin, vous pouvez utiliser cette fonction dans tout SELECT pour revenir maintenant un nombre aléatoire entre 0 et 1 par ligne:
SELECT dbo.RandNumber(), *
FROM Northwind..Customers
+1 Pour l'astuce de vue. Je me suis juste souvenu de ça aussi. Ce n'est pas à cause du déterminisme cependant. 'getdate()' est autorisé dans une fonction. De toute évidence, cette fonction ne peut pas être utilisée lorsqu'une fonction déterministe est requise, telle qu'une colonne calculée persistante. C'est à cause des effets secondaires. L'erreur soulevée est "Utilisation invalide d'un opérateur '' rand '' dans une fonction." –
Merci! J'avais entendu parler de faire cela comme un travail autour de la fonction NEWID(), mais je ne savais pas que cela fonctionnerait aussi bien pour RAND(). – BG100
Je trouve cette solution qui ne crée pas une vue:
en gros:
Au lieu de
SET @R = Rand()
Utilisez
SET @R = ABS(CHECKSUM(PWDENCRYPT(N'')))/2147483647.0
Dans mon cas, je voulais un nombre compris entre 1 et 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 vous voulez une explication complète: Using (Or Simulating) Rand() In A T-Sql User-Defined Function
ah, je comprends maintenant! Je n'ai pas pensé au stockage interne du dernier nombre aléatoire. Je peux voir comment cela le distingue des autres fonctions non déterministes. Merci! – BG100
consultez http://sqlfascination.com/tag/randomstring/ Il vous dit exactement comment faire cela. – baash05