8
votes

Try-attraper dans la fonction définie par l'utilisateur?

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.


2 commentaires

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.


6 Réponses :


2
votes

Pas sûr, mais pourquoi ne pas le retourner autour ... Au premier abord, je la simplifierais comme ceci: xxx

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 ...


3 commentaires

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.



5
votes

Apparemment, vous ne pouvez pas utiliser TRY-CATCH dans un UDF.

Selon ce Reporting de bogue Page pour SQL Server :

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. [...] "

Mais ils donnaient espoir à l'avenir en 2006:

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.


1 commentaires

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.



1
votes

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 xxx

Je suis toujours très intéressé s'il y a une meilleure réponse que celle-ci.


0 commentaires

3
votes

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


3 commentaires

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 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.



1
votes

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


0 commentaires

3
votes

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 ?

À partir de SQL Server 2012, vous pouvez utiliser try_cast / Try_Convert Fonctions:

retourne une valeur de la valeur au type de données spécifié si la distribution réussit; Sinon, retourne null. xxx


0 commentaires