質問

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

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

列内のデータは現在有効な uniqueidentifier です。

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

ありがとう

役に立ちましたか?

解決

あなたは、空の文字列を含むすべての列を持っていますか?即ちNOT NULLと、文字列の長さ= 0ます。

それとも、非標準文字を任意のGUIDを持っていますか?即ちない0-9、A-F?

私たちは、私はそれを継承する前に作成された私のアプリケーションでいくつかの非標準のGUIDを持っている...

EDITます:

将来のヘルプについては、このスクリプトは有効でない任意の行を見つけることができます:

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'

他のヒント

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

設定

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

テスト

以下の例では、32 セットの使用を示しています。 [0-9A-F] GUID の 16 桁の位置ごとにダッシュ (-) を適切な場所に配置します。ご注意ください:

  • バックスラッシュ (\) の各行の末尾 LIKE パターンは T-SQL 行継続文字, 、 そして
  • バイナリ照合を使用して、「0 ~ 9」および「A ~ F」の範囲が、その範囲内の値を持つが特に 10 進数ではない文字と一致しないことを確認する必要があります。たとえば、上付き文字「2」(²) は 10 進数の 2 ではありませんが、範囲ワイルドカードで使用すると値 2 になります。 そして Unicode 比較規則を使用します (これは、すべての項目に使用される規則です)。 NVARCHAR データ そしてVARCHAR もし 照合順序は Windows 照合順序です -- 照合順序名 ない で始まります SQL_)。テスト行 #9 はこのケースを検証します。ただし、バイナリ比較を行うには、範囲パターンを作成する必要があります。 [0-9A-Fa-f] または列を UPPER() 関数。使用 Latin1_General_100_BIN2 SQL Server 2000 または 2005 を使用している場合を除き、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
*/

私は非進、有効な文字を含むものを持っています。

5000行のうち、
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top