J'essaie d'écrire un UDF pour traduire une chaîne d'un GUID ou d'un code de projet associé à ce guide dans le GUID:
Msg 443, Level 16, State 14, Procedure fn_user_GetProjectID, Line 16 Invalid use of side-effecting or time-dependent operator in 'BEGIN TRY' within a function.
6 Réponses :
Pas sûr, mais pourquoi ne pas le retourner autour ... Au premier abord, je la simplifierais comme ceci: Si cela ne fournit pas assez de manutention d'erreur, je suis sûr que Il existe une meilleure façon de vérifier que la distribution peut fonctionner sans utiliser d'essayer / attraper ... p> p>
Il ne résout pas le problème de la distribution erronée si @Project n'est pas vraiment un code, mais pas un caractère unique non plus. Et, il met le chariot lent avant le cheval rapide. Beaucoup plus rapide à vérifier si c'est un caractère unique en premier, que d'essayer d'aller chercher dans la table.
Comme je l'ai dit, je suis sûr qu'il y a un meilleur moyen de valider que la distribution fonctionnera. Il doit être tout numérique, non? En outre, la requête est-elle vraiment si lente? ...
Oui, j'ai plusieurs endroits où je fais cela, l'un est avec plusieurs millions de rangées. Le projet que l'on n'aura probablement que quelques centaines.
Apparemment, vous ne pouvez pas utiliser TRY-CATCH dans un UDF. P>
Selon ce Reporting de bogue Page pour SQL Server : P>
Livres en ligne Documents de ce comportement, en sujet "Créer une fonction (Transact-sql) ":" Ce qui suit Les déclarations sont valables dans une fonction: [...] Contrôle de contrôle des flux Sauf essayer ... Déclarations de capture. [...] " p> blockQuote>
Mais ils donnaient espoir à l'avenir en 2006: P>
Cependant, c'est une grave limitation qui devrait être enlevé dans un avenir Libération. Vous devriez poster une suggestion à cet égard et je vais votez de tout coeur pour cela. P> blockQuote>
Eh bien, oui, je sais que je ne peux pas utiliser l'essai attrayant, c'est ce que je demandais des alternatives. La méthode FOSCOS fonctionnera également, mais je ne veux pas l'erreur si la distribution échoue.
Ma méthode de force brute consistait à créer ma propre fonction toguid () qui la vérifie peut être convertie en un guid d'abord, sinon, elle renvoie Null. Cela peut ne pas être très rapide, mais cela fait le travail, et il est probablement plus rapide de convertir le GUID s'il s'agit d'essayer de le regarder dans la table. EDIT: Je voulais donner crédit à ce blog, où j'ai eu la base de mon code pour cette fonction: http://jesschadwick.blogspot.com/2007/11/safe-handling-of-uniqueIdentifier-in.html Je suis toujours très intéressé s'il y a une meilleure réponse que celle-ci. P> p>
de MSDN :
une colonne ou une variable locale de Le type de données unique peut être initialisé à une valeur dans la Voies suivantes: P>
à l'aide de la fonction NewID. P>
en convertissant d'une constante de chaîne sous la forme xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx, dans lequel chaque x est un chiffre hexadécimal dans la plage 0-9 ou A-F. p>
Par exemple, 6f9619FF-8B86-D011-B42D-00C04FC964FF est une valeur unique identifiant valide. P> BlockQuote>
Vous pouvez utiliser le motif correspondant à la vérification de la chaîne. Notez que cela ne fonctionnera pas pour un codage spécifique qui réduit la taille du GUID: P>
declare @Project nvarchar(50) declare @ProjectID uniqueidentifier declare @HexPattern nvarchar(268) set @HexPattern = '[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]' + '[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]' + '[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]' + '[A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9][A-F0-9]' /* Take into account GUID can have curly-brackets or be missing dashes */ /* Note: this will not work for GUIDs that have been specially encoded */ set @Project = '{' + CAST(NEWID() AS VARCHAR(36)) + '}' select @Project set @Project = REPLACE(REPLACE(REPLACE(@Project,'{',''),'}',''),'-','') /* Cast as uniqueid if pattern matches, otherwise return null */ if @Project LIKE @HexPattern select @ProjectID = CAST( SUBSTRING(@Project,1,8) + '-' + SUBSTRING(@Project,9,4) + '-' + SUBSTRING(@Project,13,4) + '-' + SUBSTRING(@Project,17,4) + '-' + SUBSTRING(@Project,21,LEN(@Project)-20) AS uniqueidentifier) select @ProjectID
Cela ne tient pas compte que des informations créatifs peuvent également être entourés de {}, et ils n'ont même pas encore de tirets. C'est un peu plus compact que ma version mais elle échoue dans certaines situations. Je sortirais les tirets de votre @HexPattern, puis avant que je fasse le test, sortez les tirets et les accessoires bouclés.
Droite ... Je ne pensais pas en dehors de SQL Server.
Vous n'avez réellement pas besoin de mettre les tirets dos i> avant de faire le casting non plus, mais vous avez une nouvelle approche avec le modèle. C'est beaucoup plus propre que ma boucle. Je vais vous donner celui-ci.
Vérifiez si @Project est un numéro à l'aide de la fonction ISnumeric.
Votre code doit ressembler à celui: P>
declare @ProjectID uniqueidentifier set @ProjectID = null IF ISNUMERIC(@Project) > 0 BEGIN set @ProjectID = cast(@Project as uniqueidentifier) END if(@ProjectID is null) BEGIN select @ProjectID = ProjectID from Project where projectcode = @Project END return @ProjectID
Je sais que je ne peux pas utiliser l'essai attrayez dans une fonction, je suppose que des questions simplifiées seraient,
y a-t-il un moyen de faire une distribution qui vient de retourner null si la distribution échoue, si la distribution échoue. d'une erreur forte>? em> p> À partir de SQL Server 2012, vous pouvez utiliser try_cast / Try_Convert Fonctions: P>
retourne une valeur de la valeur au type de données spécifié si la distribution réussit; Sinon, retourne null. p> blockQuote>
xxx pré> blockQuote>
Utilise SQLCLR une option? Si tel est le cas, écrire votre propre fonction SQLCLR fonctionnerait.
SQLCLR n'est définitivement pas une option. Serait tellement plus facile, oui. J'ai fini par utiliser une combinaison de ma solution et de 8 Ko.