3

varchar(50)列をuniqueidentifierに変換しようとしていますが、このエラーが常に表示され続けます。理由はわかりません。

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

列のデータは現在、有効な一意の識別子です。

私がやりたいことをする適切な方法は何ですか?

ありがとう

4

3 に答える 3

5

空の文字列を含む列はありますか?つまり、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'
于 2009-03-27T13:43:07.493 に答える
0

5000行のうち、16進数以外の文字を含む行がありました。

于 2009-03-27T13:49:37.837 に答える
0

これはすでに回答されていることは知っていますが、もう少しエレガントなアプローチがあります。有効な 16 進数 (つまり 0 ~ 9 および A ~ F) をテストするために句で許可されている単純な、正確に 1 文字のワイルドカード構文 (つまり) を使用できます。また、単一文字検索で句を使用することにより、有効な GUID の形式をより読みやすい方法で強制することもできます。有効な形式と比較する前に、すべての 16 進数を最初に 0 に正規化する必要があります。[]LIKELIKEUNIQUEIDENTIFIERREPLACE

設定

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
  • バイナリ照合を使用して、「0-9」および「AF」の範囲が、その範囲内の値を持ち、特に 10 進数ではない文字と一致しないようにする必要があります。たとえば、上付き文字「2」文字 ( ²) は 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
*/
于 2012-04-15T05:23:11.637 に答える