varchar(50)列をuniqueidentifierに変換しようとしていますが、このエラーが常に表示され続けます。理由はわかりません。
"Msg 8169, Level 16, State 2, Line 1 Conversion failed when converting from a character string to uniqueidentifier."
列のデータは現在、有効な一意の識別子です。
私がやりたいことをする適切な方法は何ですか?
ありがとう
varchar(50)列をuniqueidentifierに変換しようとしていますが、このエラーが常に表示され続けます。理由はわかりません。
"Msg 8169, Level 16, State 2, Line 1 Conversion failed when converting from a character string to uniqueidentifier."
列のデータは現在、有効な一意の識別子です。
私がやりたいことをする適切な方法は何ですか?
ありがとう
空の文字列を含む列はありますか?つまり、NULLではなく、文字列の長さ=0です。
または、非標準文字を使用したGUIDはありますか?つまり、0-9ではありません、AF?
アプリケーションには、継承する前に作成された非標準のGUIDがいくつかあります...
編集:
今後のヘルプとして、このスクリプトは、無効な行を見つけるのに役立ちます。
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')
無効なGUIDがある行はすべて表示され、次の場所で見つけることができます。
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'
5000行のうち、16進数以外の文字を含む行がありました。
これはすでに回答されていることは知っていますが、もう少しエレガントなアプローチがあります。有効な 16 進数 (つまり 0 ~ 9 および A ~ F) をテストするために句で許可されている単純な、正確に 1 文字のワイルドカード構文 (つまり) を使用できます。また、単一文字検索で句を使用することにより、有効な GUID の形式をより読みやすい方法で強制することもできます。有効な形式と比較する前に、すべての 16 進数を最初に 0 に正規化する必要があります。[]
LIKE
LIKE
UNIQUEIDENTIFIER
REPLACE
設定
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);
テスト
[0-9A-F]
次の例では、GUID の 16 進数の位置ごとに を 32 セット使用-
し、適切な場所にダッシュ ( ) を使用しています。ご注意ください:
\
の各行の末尾にあるバックスラッシュ ( ) は、 T-SQL 行継続文字です。LIKE
²
) は 10 進数の 2 ではありませんが、範囲ワイルドカードで使用され、 Unicode 比較規則 (すべてのNVARCHAR
データに使用される規則であり、照合のIFでさえも) を使用すると、値は 2 になります。は Windows 照合です -- 照合名がで始まらない)。テスト行 #9 は、このケースを検証します。ただし、バイナリ比較を行うには、範囲パターンを作成するか、関数で列をラップする必要があります。使用するVARCHAR
SQL_
[0-9A-Fa-f]
UPPER()
Latin1_General_100_BIN2
ただし、SQL Server 2000 または 2005 を使用している場合は、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;
また、この質問は SQL Server 2008 のコンテキストで行われましたが、SQL Server 2012 以降を使用している場合は、TRY_CONVERT関数を使用するとさらに簡単になります。
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
*/