Question

Je suis en train de convertir une colonne varchar (50) à un uniqueidentifier, mais cette erreur cesse d'apparaître tout le temps, et je ne sais pas pourquoi:

"Msg 8169, Level 16, State 2, Line 1 Conversion failed when converting from a character string to uniqueidentifier."

Les données dans la colonne est actuellement uniqueidentifier valide.

Quelle est la bonne façon de faire ce que je veux?

Merci

Était-ce utile?

La solution

Avez-vous des colonnes contenant des chaînes vides? C'est à dire. NOT NULL, la longueur de chaîne = 0.

Ou avez-vous avec GUIDs caractères non standard? C'est à dire. non 0-9, A-F?

Nous avons quelques GUIDs non standard dans ma demande qui ont été créés avant hérité ...

EDIT:

Pour l'avenir de l'aide, ce script peut vous aider à trouver toutes les lignes qui ne sont pas valides:

SELECT    REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(GUID, '1', '0'), '2', '0'), '3', '0'), '4', '0'), '5', '0'), '6', '0'), '7', '0'), '8', '0'), '9', '0'), 'A', '0'), 'B', '0'), 'C', '0'), 'D', '0'), 'E', '0'), 'F', '0'), COUNT(*)
FROM TABLE
GROUP BY REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(GUID, '1', '0'), '2', '0'), '3', '0'), '4', '0'), '5', '0'), '6', '0'), '7', '0'), '8', '0'), '9', '0'), 'A', '0'), 'B', '0'), 'C', '0'), 'D', '0'), 'E', '0'), 'F', '0')

Toutes les lignes qui ont Guids non valides apparaissent et peuvent être trouvés par:

SELECT    *, REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(GUID, '1', '0'), '2', '0'), '3', '0'), '4', '0'), '5', '0'), '6', '0'), '7', '0'), '8', '0'), '9', '0'), 'A', '0'), 'B', '0'), 'C', '0'), 'D', '0'), 'E', '0'), 'F', '0')
FROM TABLE
WHERE REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(GUID, '1', '0'), '2', '0'), '3', '0'), '4', '0'), '5', '0'), '6', '0'), '7', '0'), '8', '0'), '9', '0'), 'A', '0'), 'B', '0'), 'C', '0'), 'D', '0'), 'E', '0'), 'F', '0') != '00000000-0000-0000-0000-0000000000'

Autres conseils

Je sais que cela a déjà répondu, mais il y a une approche un peu plus élégante. Vous pouvez utiliser le simpliste, la syntaxe exactement-one-caractère générique (c.-à-[]) permise dans une clause de LIKE pour tester les chiffres hexadécimaux valides (à savoir 0 - 9 et a - F). Et, à l'aide d'une clause de LIKE avec la recherche d'un seul caractère, vous pouvez également appliquer le format d'un GUID valide / UNIQUEIDENTIFIER d'une manière plus lisible alors la méthode de REPLACE qui doit d'abord normaliser tous les chiffres hexadécimaux à des 0 avant de comparer au format valide .

SETUP

SET NOCOUNT ON;
IF (OBJECT_ID('tempdb.dbo.#GUIDs') IS NOT NULL)
BEGIN
  DROP TABLE #GUIDs;
END;

CREATE TABLE #GUIDs (ID INT NOT NULL, TheGUID VARCHAR(50) NULL);

INSERT INTO #GUIDs (ID, TheGUID)
  SELECT tmp.ID, tmp.TheGUID
  FROM  (
      SELECT  1, 'E1A21B62-ACC4-4ACB-B284-0F0233F19EDA' -- valid
      UNION ALL
      SELECT  2, '50178543-11E6-40D2-87F1-9C4676DCF542' -- valid
      UNION ALL
      SELECT  3, '' -- invalid: empty string
      UNION ALL
      SELECT  4, '4EB30267-0EB4-413A-9B05-6EDDB943C7D8' -- valid
      UNION ALL
      SELECT  5, '4EB30267-0EB4-413A-9Z05-6EDDB943C7D8' -- invalid: has a "Z"
      UNION ALL
      SELECT  6, NULL -- invalid: is NULL
      UNION ALL
      SELECT  7, '18EAE6C5-7256-4598-AA0A-837718145001' -- valid
      UNION ALL
      SELECT  8, '18eae6c5-7256-4598-aa0a-837718145001' -- valid (lowercase version of #7)
      UNION ALL
      SELECT  9, '18EAE6C5-7²56-4598-AA0A-837718145001' -- invalid: has superscript "2"
        ) tmp (ID, TheGUID);

Tests

L'exemple ci-dessous montre à l'aide de 32 ensembles de [0-9A-F] pour chaque position hex chiffres du GUID et a les tirets (-) dans les endroits appropriés. S'il vous plaît noter:

  • la barre oblique inverse (\) à la fin de chaque ligne dans le motif de LIKE est le T-SQL ligne Suite caractère et
  • vous devez utiliser un classement binaire pour faire en sorte que les plages de « 0-9 » et « A-F » ne correspond pas à tous les caractères qui ont des valeurs dans cette plage, mais ne sont pas spécifiquement chiffres après la virgule. Par exemple, l'indice supérieur caractère « 2 » (de ²) n'est pas une 2 décimales, mais il a une valeur de 2 lorsqu'elle est utilisée dans un générique de gamme et en utilisant des règles de comparaison Unicode (qui sont les règles utilisées pour toutes les données NVARCHAR et même VARCHAR IF le classement est un classement Windows - nom de classement pas en commençant par SQL_). Test ligne n ° 9 vérifie ce cas. Cependant, en faisant une comparaison binaire nécessite soit rendre le motif de gamme [0-9A-Fa-f] ou enveloppant la colonne dans une fonction de UPPER(). Utilisez Latin1_General_100_BIN2 sauf si vous utilisez SQL Server 2000 ou 2005, dans ce cas, vous devez utiliser Latin1_General_BIN.
SELECT  ID, TheGUID, CONVERT(UNIQUEIDENTIFIER, TheGUID) AS [Converted]
FROM    #GUIDs
WHERE   UPPER(TheGUID) COLLATE Latin1_General_100_BIN2 LIKE
'[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]\
[0-9A-F]';


SELECT  ID, TheGUID AS [BAD]
FROM    #GUIDs
WHERE   UPPER(TheGUID) COLLATE Latin1_General_100_BIN2 NOT LIKE
'[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-\
[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]\
[0-9A-F]'
OR      TheGUID IS NULL;

Et, alors que cette question a été posée dans le contexte de SQL Server 2008, pour toute personne utilisant SQL Server 2012 ou plus récent, le TRY_CONVERT fonction permet encore plus facile:

SELECT  tmp.ID, tmp.TheGUID AS [BAD]
FROM    #GUIDs tmp
WHERE   TRY_CONVERT(UNIQUEIDENTIFIER, tmp.[TheGUID]) IS NULL;
/*
ID    BAD
3     
5     4EB30267-0EB4-413A-9Z05-6EDDB943C7D8
6     (NULL)
9     18EAE6C5-7²56-4598-AA0A-837718145001
*/

Sur 5000 lignes I avait un contenant un caractère non valide hex.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top