Pergunta

Eu estou tentando converter uma coluna varchar (50) a um uniqueidentifier, mas esse erro continua aparecendo o tempo todo, e eu não sei por que:

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

Os dados na coluna é atualmente um uniqueidentifier válido.

O que é a maneira correta de fazer o que eu quero?

Graças

Foi útil?

Solução

Você tem colunas que contêm cadeias vazias? Ou seja, NOT NULL, comprimento da corda = 0.

Ou você tem quaisquer GUIDs com caracteres não-padrão? Ou seja, Não 0-9, A-F?

Temos alguns GUIDs não-padrão no meu aplicativo que foram criados antes eu herdei isso ...

EDIT:

Para futura ajuda, este script pode ajudar a encontrar todas as linhas que não são válidas:

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')

Qualquer linhas que têm GUIDs inválidos vai aparecer, e pode ser encontrado por:

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'

Outras dicas

Eu sei que isso já foi respondida, mas não há uma abordagem um pouco mais elegante. Você pode usar o simplista, exatamente-uma-caractere curinga sintaxe (ou seja []) permitido em uma cláusula LIKE para testar dígitos hexadecimais válidos (ou seja, 0 - 9 e a - F). E, usando uma cláusula LIKE com a única personagem-procurar você também pode aplicar o formato de um GUID / UNIQUEIDENTIFIER válida de uma forma mais legível, em seguida, o método REPLACE que tem de primeiro normalize todos os dígitos hexadecimais a 0 de antes de comparar com o formato válido .

CONFIGURAÇÃO

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);

TESTES

O exemplo a seguir mostra o uso de 32 conjuntos de [0-9A-F] para cada posição hexadecimal dígitos do GUID e tem os traços (-) nos locais apropriados. Por favor nota:

  • a barra invertida (\) no final de cada linha no padrão LIKE é o Linha T-SQL caráter Continuação , e
  • você deve usar um agrupamento binário para garantir que as faixas de "0-9" e "A-F" não encontrou nenhum caracteres que têm valores nesse intervalo, mas não são especificamente dígitos decimais. Por exemplo, o sobrescrito "2" caracteres (²) não é um decimal 2, mas tem um valor de 2 quando usado em um curinga gama e usando regras de comparação Unicode (que são as regras utilizadas para todos os dados NVARCHAR e , mesmo VARCHAR IF o agrupamento é um agrupamento do Windows - nome de agrupamento não começando com SQL_). Teste linha # 9 verifica neste caso. No entanto, fazendo uma comparação binário exige quer fazendo com que o padrão de faixa de [0-9A-Fa-f] ou empacotar a coluna numa função UPPER(). Use Latin1_General_100_BIN2 a menos que você estiver usando SQL Server 2000 ou 2005, caso em que você deve usar 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;

E, enquanto isso pergunta foi feita no contexto do SQL Server 2008, para qualquer um usando o SQL Server 2012 ou mais recente, a TRY_CONVERT função torna isso ainda mais fácil:

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
*/

Fora de 5000 linhas eu tinha um contendo um caractere não hex-válido.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top