我无法将varchar
列UserID
转换为INT
。我知道,请不要问为什么这个UserID
列最初没有创建为INT,长篇故事。
所以我尝试了这个,但它不起作用。并给我一个错误:
select CAST(userID AS int) from audit
错误:
转换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
答案 0 :(得分:18)
这个问题有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)
除非使用二进制排序规则,否则尝试替换空字符通常会有问题。
答案 1 :(得分:17)
您可以尝试更新表格以删除这些字符:
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位整数,后跟六个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)
之外的其他原因导致失败的行之前,可能需要进行一些试验和错误。 {1}} 和 CHAR(something else)
。就我们所知,你知道表中的值如下:
SELECT '15' + CHAR(9) + '23' + CHAR(0);
...也无法转换为整数,无论您是否已替换CHAR(0)
。
我知道你不想听,但我很高兴这对人们来说很痛苦,因为现在当人们对数据类型作出非常糟糕的决定时,他们会有更多的战争故事要推迟。
答案 2 :(得分:2)
我会尝试修改数字,看看你得到了什么:
select len(rtrim(ltrim(userid))) from audit
如果返回正确的值,则执行:
select convert(int, rtrim(ltrim(userid))) from audit
如果没有返回正确的值,那么我会进行替换以删除空白区域:
select convert(int, replace(userid, char(0), '')) from audit
答案 3 :(得分:2)
对于搜索结果的人来说,这比原来的更多。这对我有用......
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 :(得分:0)
这就是我解决这个问题的方法:
首先,我确保我需要转换为整数的列不包含任何空格:
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)
这对我有用,希望你也觉得它有用。