Domanda

Sto cercando di convertire un varchar (50) colonna a un'uniqueidentifier, ma questo errore continua a comparire per tutto il tempo, e non so perché:

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

I dati nella colonna è attualmente un uniqueidentifier valido.

Qual è il modo corretto di fare ciò che voglio?

Grazie

È stato utile?

Soluzione

Avete delle colonne che contengono stringhe vuote? Cioè NOT NULL, lunghezza della stringa = 0.

O avete GUID con caratteri non standard? Cioè Non 0-9, A-F?

Abbiamo alcuni GUID non standard nella mia applicazione che sono stati creati prima che ho ereditata ...

EDIT:

Per un aiuto futuro, questo script può aiutarti a trovare tutte le righe che non sono valide:

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

Le eventuali righe che hanno GUID validi appariranno, e può essere trovato:

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'

Altri suggerimenti

So che questo è già stato risposto, ma v'è un approccio un po 'più elegante. È possibile utilizzare il semplicistico, exactly-one-carattere jolly sintassi (cioè []) consentita in una clausola LIKE per verificare cifre esadecimali validi (cioè 0 - 9 e a - F). E, utilizzando una clausola LIKE con la ricerca a carattere singolo è anche possibile applicare il formato di un GUID valido / UNIQUEIDENTIFIER in maniera più leggibile allora il metodo REPLACE che deve normalizzare prima tutte le cifre esadecimali a 0 di prima di confrontare il formato valido .

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

TEST

L'esempio seguente mostra con 32 set di [0-9A-F] per ciascuna posizione hex cifre del GUID e ha i trattini (-) nelle posizioni corrette. Si prega di notare:

  • la barra rovesciata (\) alla fine di ogni riga del modello LIKE è T-SQL linea carattere di continuazione , e
  • è necessario utilizzare un confronto binario per garantire che le gamme di "0-9" e "A-F" non corrisponde alcun carattere che hanno valori in quella fascia, ma non sono specificamente cifre decimali. Ad esempio, il carattere apice "2" (²) non è un numero decimale 2, ma ha un valore di 2 quando utilizzato in un carattere jolly intervallo e usando regole di confronto Unicode (che sono le regole utilizzate per tutti i dati NVARCHAR e , anche VARCHAR IF il confronto è un metodo di confronto di Windows - nome di confronto non a cominciare SQL_). Test di fila # 9 verifica questo caso. Tuttavia, facendo un confronto binario richiede o rendendo il [0-9A-Fa-f] gamma pattern o avvolgendo la colonna in una funzione UPPER(). Utilizzare Latin1_General_100_BIN2 a meno che non si utilizza SQL Server 2000 o 2005, nel qual caso si dovrebbe usare 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, mentre questa domanda è stato chiesto nel contesto di SQL Server 2008, per chiunque l'utilizzo di SQL Server 2012 o più recente, il TRY_CONVERT funzione rende questo ancora più 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
*/

Fuori 5000 righe ho avuto uno contenente un carattere non esadecimale valido.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top