SQL Server:将varchar转换为INT

Mil*_*cay 31 sql-server

我坚持将varchar列转换UserIDINT.我知道,请不要问为什么这个UserID专栏最初没有创建为INT,长篇大论.

所以我尝试了这个,但它不起作用.并给我一个错误:

select CAST(userID AS int) from audit
Run Code Online (Sandbox Code Playgroud)

错误:

转换varchar值时转换失败'1581 ......................................... .................................................. .................................'到数据类型int.

我做了select len(userID) from audit,它返回128个字符,这不是空格.

我试图检测ID号和ASCII值= 0后跟踪的ASCII字符.

更新!!!

我也试过LTRIM,RTRIM和替换char(0)'',但不起作用.

当我告诉下面这个固定数量的字符时它唯一的工作方式,但UserID并不总是4个字符.

select CAST(LEFT(userID, 4) AS int) from audit
Run Code Online (Sandbox Code Playgroud)

谢谢,

Mar*_*ith 18

这个问题有91,000个观看次数,所以也许很多人在标题"错误将varchar转换为INT"中寻找更通用的解决方案

如果您使用的是SQL Server 2012+,则可以使用一种处理此无效数据的方法 TRY_CAST

SELECT TRY_CAST (userID AS INT)
FROM   audit 
Run Code Online (Sandbox Code Playgroud)

在以前的版本中,您可以使用

SELECT CASE
         WHEN ISNUMERIC(RTRIM(userID) + '.0e0') = 1
              AND LEN(userID) <= 11
           THEN CAST(userID AS INT)
       END
FROM   audit 
Run Code Online (Sandbox Code Playgroud)

NULL如果无法转换值,则返回两者.

在具有已知错误值的问题中,我会使用以下内容.

CAST(REPLACE(userID COLLATE Latin1_General_Bin, CHAR(0),'') AS INT)
Run Code Online (Sandbox Code Playgroud)

除非使用二进制排序规则,否则尝试替换空字符通常会有问题.

  • @Tigran它没有使它成为数字.附加此内容有助于验证已经是数字的字符串是否为整数.例如,`123`在写为`123.0e0`时会通过但是`123.45`会因为`123.45.0e0`无效而失败. (2认同)

Aar*_*and 17

您可以尝试更新表以摆脱这些字符:

UPDATE dbo.[audit]
  SET UserID = REPLACE(UserID, CHAR(0), '')
  WHERE CHARINDEX(CHAR(0), UserID) > 0;
Run Code Online (Sandbox Code Playgroud)

但是,您还需要先解决将这些不良数据放入表中的问题.在此期间或许尝试:

SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), ''))
  FROM dbo.[audit];
Run Code Online (Sandbox Code Playgroud)

但这不是一个长期的解决方案.修复数据(以及数据类型).如果无法立即修复数据类型,则可以通过添加检查约束快速找到罪魁祸首:

ALTER TABLE dbo.[audit]
  ADD CONSTRAINT do_not_allow_stupid_data
  CHECK (CHARINDEX(CHAR(0), UserID) = 0);
Run Code Online (Sandbox Code Playgroud)

编辑

好的,所以这肯定是一个4位整数,后跟六个CHAR(0)实例.我发布的解决方法绝对适用于我:

DECLARE @foo TABLE(UserID VARCHAR(32));
INSERT @foo SELECT 0x31353831000000000000;

-- this succeeds:
SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) FROM @foo;

-- this fails:
SELECT CONVERT(INT, UserID) FROM @foo;
Run Code Online (Sandbox Code Playgroud)

请确认此代码本身(好吧,第一个SELECT,无论如何)适合您.如果确实如此,那么你得到的错误来自不同行中的一个不同的非数字字符(如果它没有,那么也许你有一个没有修复特定错误的构建).要尝试缩小范围,可以从以下查询中获取随机值,然后遍历字符:

SELECT UserID, CONVERT(VARBINARY(32), UserID)
  FROM dbo.[audit]
  WHERE UserID LIKE '%[^0-9]%';
Run Code Online (Sandbox Code Playgroud)

所以取一个随机行,然后将输出粘贴到这样的查询中:

DECLARE @x VARCHAR(32), @i INT;
SET @x = CONVERT(VARCHAR(32), 0x...); -- paste the value here
SET @i = 1;
WHILE @i <= LEN(@x)
BEGIN
  PRINT RTRIM(@i) + ' = ' + RTRIM(ASCII(SUBSTRING(@x, @i, 1)))
  SET @i = @i + 1;
END
Run Code Online (Sandbox Code Playgroud)

在遇到由于某些其他原因而失败的行之前,这可能需要一些试验和错误CHAR(0)- 因为您无法真正过滤掉包含的行,CHAR(0)因为它们可能包含CHAR(0) CHAR(something else).就我们所知,你知道你在表格中有值:

SELECT '15' + CHAR(9) + '23' + CHAR(0);
Run Code Online (Sandbox Code Playgroud)

...无论你是否已被替换,它也无法转换为整数CHAR(0).

我知道你不想听,但我很高兴这对人们来说很痛苦,因为现在当人们对数据类型做出非常糟糕的决定时,他们会有更多的战争故事要推迟.