【问题标题】:SQL Server : converting varchar to INTSQL Server:将 varchar 转换为 INT
【发布时间】:2021-05-21 04:03:47
【问题描述】:

我坚持将varcharUserID 转换为INT。我知道,请不要问为什么这个 UserID 列最初没有创建为 INT,说来话长。

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

select CAST(userID AS int) from audit

错误:

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

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

我尝试检测 ID 号和 ASCII 值 = 0 之后的那些尾随的 ASCII 字符。

我也试过LTRIMRTRIM,把char(0)换成'',但是还是不行。

当我像下面这样告诉固定数量的字符时,它起作用的唯一方法是,UserID 并不总是 4 个字符。

select CAST(LEFT(userID, 4) AS int) from audit

【问题讨论】:

  • 在表中 UserID 列只有整数值或任何 Varchar 值。例如:像这样的 122 或像这样的 122Adf...?
  • UserID 列只有整数值。谢谢!

标签: sql-server


【解决方案1】:

您可以尝试更新表格以删除这些字符:

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

但是,您还需要首先修复将这些不良数据放入表中的任何问题。与此同时,不妨试试:

SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), ''))
  FROM dbo.[audit];

但这不是一个长期的解决方案。修复数据(以及处理数据时的数据类型)。如果不能立即修复数据类型,那么可以通过添加检查约束来快速找到罪魁祸首:

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

编辑

好的,这绝对是一个 4 位整数,后跟 6 个 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;

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

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

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

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

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

SELECT '15' + CHAR(9) + '23' + CHAR(0);

...无论您是否替换了CHAR(0),它也无法转换为整数。

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

【讨论】:

  • 我试过“SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) FROM dbo.[audit];”,但它不起作用。我也尝试了 LTRIM 和 RTRIM,但也不起作用...感谢您的帮助
  • @Milacay 好吧,你确定CHAR(0) 是列中的only 无效值吗?请找出失败的单行,然后告诉我们的输出,例如:SELECT CONVERT(VARBINARY(32), UserID) FROM dbo.[audit] WHERE LEFT(UserID, 4) = '1581';
  • 我使用“varbinary(32)...”运行了您的查询,输出为:0x31353831000000000000。顺便说一句,这个 varchar 字段 (userID) 已从 Varbinary(128) 转换为 Varchar(128),现在我想将其转换为 INT 以与不同表上的 UserID 加入...谢谢@Aaron
  • 非常感谢@Aaron。 “SELECT CONVERT(INT, REPLACE(UserID, CHAR(0), '')) FROM @foo;”作品。对于造成的混乱,我深表歉意。
  • 为什么首先要转换成 varbinary?另请注意,从 varbinary 转换为 varchar 可能会产生不同的结果。试试SELECT CONVERT(VARCHAR(128), CONVERT(VARBINARY(128), 'foo')), CONVERT(VARCHAR(128), CONVERT(VARBINARY(128), 'foo'),1), LEN(CONVERT(VARCHAR(128), CONVERT(VARBINARY(128), 'foo'))), LEN(CONVERT(VARCHAR(128), CONVERT(VARBINARY(128), 'foo'),1));
【解决方案2】:

这个问题已经获得了 91,000 次浏览,所以也许很多人正在寻找一个更通用的解决方案来解决标题“将 varchar 转换为 INT”中的问题

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

SELECT TRY_CAST (userID AS INT)
FROM   audit 

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

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

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

在您的问题中存在已知错误值的特定情况下,我会使用以下内容。

CAST(REPLACE(userID COLLATE Latin1_General_Bin, CHAR(0),'') AS INT)

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

【讨论】:

  • 您能解释一下为什么添加 .0e0 会使其成为数字吗?
  • @Tigran 它不会变成数字。附加它有助于验证已经是数字的字符串是否为整数。例如。 123 写成 123.0e0 时会通过,但 123.45 会失败,因为 123.45.0e0 无效。
【解决方案3】:

这比原来的帖子更适合搜索结果的人。这对我有用...

declare @value varchar(max) = 'sad';
select sum(cast(iif(isnumeric(@value) = 1, @value, 0) as bigint));

returns 0

declare @value varchar(max) = '3';
select sum(cast(iif(isnumeric(@value) = 1, @value, 0) as bigint));

returns 3

【讨论】:

    【解决方案4】:

    我会尝试修剪数字以查看您得到的结果:

    select len(rtrim(ltrim(userid))) from audit
    

    如果返回正确的值,那么就这样做:

    select convert(int, rtrim(ltrim(userid))) from audit
    

    如果没有返回正确的值,那么我会做一个替换来删除空白:

     select convert(int, replace(userid, char(0), '')) from audit
    

    【讨论】:

    • 我尝试了所有 LTRIM、RTRIM,并将 char(0) 替换为 '',但也不起作用。诡异的!谢谢。
    【解决方案5】:

    这就是我解决问题的方法:

    首先,我确保需要转换为整数的列不包含任何空格:

    update data set col1 = TRIM(col1)
    

    我还检查了该列是否仅包含数字。
    您可以通过以下方式查看:

    select * from data where col1 like '%[^0-9]%' order by col1
    

    如果存在任何非数字值,您可以将它们保存到另一个表中,然后将它们从您正在处理的表中删除。

    select * into nonnumeric_data from data where col1 like '%[^0-9]%'
    delete from data where col1 like '%[^0-9]%'
    

    我的数据存在上述问题。所以在修复它们之后,我创建了一个 bigint 变量并将 varchar 列的值设置为我创建的整数列。

    alter table data add int_col1 bigint
    update data set int_col1 = CAST(col1 AS VARCHAR)
    

    这对我有用,希望你也觉得它有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-18
      • 2013-11-27
      • 2013-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多