SQL Server 2008 将VARCHAR(50)转换为Uniqueidentifier

3 人关注

我想把一个varchar(50)列转换为uniqueidentifier,但这个错误一直在冒出来,我不知道为什么。

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

该列中的数据目前是一个有效的唯一标识符。

做我想做的事的正确方法是什么?

1 个评论
gbn
请问你要转换的字符串是什么?
sql-server
tsql
sql-server-2008
type-conversion
uniqueidentifier
alexn
alexn
发布于 2009-03-27
3 个回答
cjk
cjk
发布于 2019-06-10
已采纳
0 人赞同

你有任何包含空字符串的列吗?即NOT NULL,字符串长度=0。

或者你是否有任何非标准字符的GUID? 例如,不是0-9,A-F?

在我的应用程序中,我们有一些非标准的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')

任何有无效Guids的行都会显示出来,可以通过以下方式找到。

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'
Solomon Rutzky
Solomon Rutzky
发布于 2019-06-10
0 人赞同

我知道这个问题已经被回答过了,但是还有一个稍微优雅的方法。你可以使用 LIKE 子句中允许的简单的、 只有一个字符的通配符 语法(即 [] )来测试有效的十六进制数字(即0-9和A-F)。而且,通过使用带有单字符搜索的 LIKE 子句,你也可以以一种更可读的方式执行有效的GUID/ UNIQUEIDENTIFIER 的格式,而 REPLACE 方法在与有效格式进行比较之前必须首先将所有十六进制数字规范化为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);

下面的例子显示,在GUID的每个十六进制数字位置使用32组[0-9A-F],并在适当的地方有破折号-)。请注意。

  • LIKE模式中,每一行末尾的反斜杠\)是T-SQL的续行字符,以及
  • 你应该使用二进制排序,以确保 "0-9 "和 "A-F "的范围不匹配任何在该范围内有价值但不具体是十进制数字的字符。例如,上标 "2 "字符²)不是十进制的2,但是当它被用于范围通配符使用Unicode比较规则时,它的值是2(这是用于所有NVARCHAR数据甚至VARCHAR的规则,如果整理方式是Windows整理方式--整理方式名称不是SQL_开头)。测试行#9验证了这种情况。然而,做二进制比较需要做范围模式[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
    5     4EB30267-0EB4-413A-9Z05-6EDDB943C7D8
    6     (NULL)