web-dev-qa-db-fra.com

Comment vérifier si une chaîne est un identifiant unique?

Existe-t-il un équivalent de IsDate ou IsNumeric pour uniqueidentifier (SQL Server)? Ou existe-t-il un équivalent de (C #) TryParse?

Sinon, je devrais écrire ma propre fonction, mais je veux m'assurer de ne pas réinventer la roue.

Le scénario que j'essaie de couvrir est le suivant:

SELECT something FROM table WHERE IsUniqueidentifier(column) = 1
48
Benoittr

SQL Server 2012 rend tout cela beaucoup plus facile avec TRY_CONVERT(UNIQUEIDENTIFIER, expression)

SELECT something
FROM   your_table
WHERE  TRY_CONVERT(UNIQUEIDENTIFIER, your_column) IS NOT NULL;

Pour les versions précédentes de SQL Server, les réponses existantes ne tiennent pas compte de quelques points, ce qui signifie qu'elles risquent de ne pas correspondre aux chaînes que SQL Server transtypera en réalité en UNIQUEIDENTIFIER sans se plaindre, ou de provoquer des erreurs de conversion non valides.

SQL Server accepte les GUID soit enveloppés dans {}, soit sans cela.

De plus, il ignore les caractères superflus à la fin de la chaîne. SELECT CAST('{5D944516-98E6-44C5-849F-9C277833C01B}ssssssssss' as uniqueidentifier) et SELECT CAST('5D944516-98E6-44C5-849F-9C277833C01BXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' as uniqueidentifier) réussissent tous les deux, par exemple.

Dans la plupart des classements par défaut, le LIKE '[a-zA-Z0-9]' finira par correspondre aux caractères tels que À ou Ë

Enfin, si vous convertissez des lignes dans un résultat en uniqueidentifier, il est important de placer la tentative de conversion dans une expression case, car la conversion peut survenir avant que les lignes ne soient filtrées par la variable WHERE

Donc (empruntant l’idée de @ r0d30b0y ) une version légèrement plus robuste pourrait être

;WITH T(C)
     AS (SELECT '5D944516-98E6-44C5-849F-9C277833C01B'
         UNION ALL
         SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}'
         UNION ALL
         SELECT '5D944516-98E6-44C5-849F-9C277833C01BXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
         UNION ALL
         SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}ssssssssss'
         UNION ALL
         SELECT 'ÀD944516-98E6-44C5-849F-9C277833C01B'
         UNION ALL
         SELECT 'fish')
SELECT CASE
         WHEN C LIKE expression + '%'
               OR C LIKE '{' + expression + '}%' THEN CAST(C AS UNIQUEIDENTIFIER)
       END
FROM   T
       CROSS APPLY (SELECT REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]') COLLATE Latin1_General_BIN) C2(expression)
WHERE  C LIKE expression + '%'
        OR C LIKE '{' + expression + '}%' 
55
Martin Smith

Pas le mien, j'ai trouvé ça en ligne ... je pensais partager.

SELECT 1 WHERE @StringToCompare LIKE 
       REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]');
54
r0d30b0y
SELECT something 
  FROM table1 
 WHERE column1 LIKE '[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]';

METTRE À JOUR:

... mais je préfère de loin l'approche dans la réponse de @ r0d30b0y:

SELECT something 
  FROM table1 
 WHERE column1 LIKE REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]');
21
onedaywhen

Je ne suis pas au courant de quoi que ce soit que vous pourriez utiliser «hors de la boîte» - vous devrez écrire cela vous-même, j'en ai bien peur.

Si vous le pouvez: essayez d’écrire cela dans une bibliothèque C # et de le déployer dans SQL Server en tant qu’assemblage SQL-CLR - vous pouvez utiliser des fonctions telles que Guid.TryParse(), qui est certainement beaucoup plus simple à utiliser que dans T-SQL ....

4
marc_s

Une variante de la réponse r0d30b0y consiste à utiliser PATINDEX pour rechercher dans une chaîne ...

PATINDEX('%'+REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]')+'%',@StringToCompare) > 0

Doit utiliser pour trouver des Guids dans une chaîne d'URL ..

HTH

Dave

2
Dave

Comme pour garder les choses simples. Un GUID en a quatre - même s'il ne s'agit que d'une chaîne

Où colonne comme '% -% -% -% -%'

1
Mike

Bien qu’il s’agisse d’un message plus ancien, il suffit de penser à un test rapide ...

SELECT  [A].[INPUT],
        CAST([A].[INPUT] AS [UNIQUEIDENTIFIER])
FROM   (
            SELECT '5D944516-98E6-44C5-849F-9C277833C01B' Collate Latin1_General_100_BIN AS [INPUT]
            UNION ALL
            SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}'
            UNION ALL
            SELECT '5D944516-98E6-44C5-849F-9C277833C01BXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
            UNION ALL
            SELECT '{5D944516-98E6-44C5-849F-9C277833C01B}ssssssssss'
            UNION ALL
            SELECT 'ÀD944516-98E6-44C5-849F-9C277833C01B'
            UNION ALL
            SELECT 'fish'
        ) [A]
WHERE   PATINDEX('[^0-9A-F-{}]%', [A].[INPUT]) = 0
1
Geary M. McIver

Ceci est une fonction basée sur le concept de certains commentaires précédents. Cette fonction est très rapide.

CREATE FUNCTION [dbo].[IsGuid] (@input varchar(50))  
    RETURNS bit AS  
BEGIN

RETURN 
    case when @input like '[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]'
    then 1 else 0 end
END
GO

/* 
Usage: 

select [dbo].[IsGuid]('123') -- Returns 0
select [dbo].[IsGuid]('ebd8aebd-7ea3-439d-a7bc-e009dee0eae0') -- Returns 1

select * from SomeTable where dbo.IsGuid(TableField) = 0 -- Returns table with all non convertable items!

*/
1
Ansonmus

J'utilise :

ISNULL(convert(nvarchar(50), userID), 'NULL') = 'NULL'
0
Villie

Vous pouvez écrire votre propre fichier UDF. Il s'agit d'une approximation simple pour éviter l'utilisation d'un assembly SQL-CLR.

CREATE FUNCTION dbo.isuniqueidentifier (@ui varchar(50))  
RETURNS bit AS  
BEGIN

RETURN case when
    substring(@ui,9,1)='-' and
    substring(@ui,14,1)='-' and
    substring(@ui,19,1)='-' and
    substring(@ui,24,1)='-' and
    len(@ui) = 36 then 1 else 0 end

END
GO

Vous pouvez ensuite l’améliorer pour vérifier s’il ne s’agit que de valeurs HEX.

0
pcofre

Utiliser RLIKE pour MYSQL

SELECT 1 WHERE @StringToCompare
RLIKE REPLACE('00000000-0000-0000-0000-000000000000', '0', '[0-9a-fA-F]');
0
Pyotr Alexeev