SQL Server 2008 R2数据类型转换错误
SQL Server 2008 R2 data type conversion error
我有一列数据类型为 varchar
,其中一些包含数字(十进制)值。我需要找到所有数值大于 100 的行。我正在使用 ISNUMERIC
过滤包含数字的行,之后我尝试使用 CAST
或 CONVERT
来更改数字到 decimal
值。我读到另一个建议,说使用子查询可以解决问题,但我也试过了,但没有成功
这是我收到的错误消息:
Arithmetic overflow error converting varchar to data type numeric.
代码:
select field_name
from table_name
where ISNUMERIC(field_name) = 1 and
field_name in (select cast(field_name as decimal)
from table_name
where ISNUMERIC(field_name) = 1
and field_name not like '%,%'
and field_name not like '%-%'
and field_name != '.'
and field_name > 100.00)
这是您的查询:
select field_name
from table_name
where ISNUMERIC(field_name) = 1 and
field_name in (select cast(field_name as decimal)
from table_name
where ISNUMERIC(field_name) = 1 and
field_name not like '%,%' and
field_name not like '%-%' and
field_name <> '.' and
field_name > 100
)
您假设 where
子句在 select
之前过滤。这不是真的。实际上,SQL服务器将cast()
推给了读取数据的操作。然后应用过滤器。
其实子查询和普通的table表达式也不保证求值顺序。什么是 case
(至少在这种情况下不涉及聚合)。因此,您可以将查询写为:
select field_name
from table_name
where (case when ISNUMERIC(field_name) = 1 and
field_name not like '%,%' and
field_name not like '%-%' and
field_name <> '.'
then cast(field_name as decimal)
end) > 100;
我认为没有理由使用子查询。
查询有一些问题,但导致错误的主要问题相当简单:您的 field_name > 100.00
条件没有将 VARCHAR
字段转换为进行比较之前的数字类型。将其更改为 CONVERT(DECIMAL(38, 18), [field_name])
将修复您看到的错误。
运行 下面一次,看看它是否有效,然后再次取消对 AND [field_name] > 100.00
行和 运行 的注释,你将得到关于 [=53 的错误=]:
DECLARE @table_name TABLE (field_name VARCHAR(50) NOT NULL);
INSERT INTO @table_name (field_name) VALUES ('1234.5678');
INSERT INTO @table_name (field_name) VALUES ('12.78');
INSERT INTO @table_name (field_name) VALUES ('s');
INSERT INTO @table_name (field_name) VALUES ('2015-01-30');
INSERT INTO @table_name (field_name) VALUES ('51234.5678');
INSERT INTO @table_name (field_name) VALUES ('987651234.56789124');
SELECT field_name
FROM @table_name
WHERE ISNUMERIC([field_name]) = 1
AND [field_name] IN (
SELECT CAST([field_name] AS DECIMAL)
FROM @table_name
WHERE ISNUMERIC([field_name]) = 1
AND [field_name] NOT LIKE '%,%'
AND [field_name] NOT LIKE '%-%'
AND [field_name] != '.'
-- AND [field_name] > 100.00
AND CONVERT(DECIMAL(38, 18), [field_name]) > 100.00
);
但是,还有一些问题:
- 如问题中所示,子查询对 return 转换值列表没有意义。有可能为了在此处发布查询而更改了查询,因此以其真实形式更有意义,但不需要子查询,也无济于事。
CAST
到 DECIMAL
没有指定精度和小数位数。默认值分别为 18 和 0。意思是,您正在将字符串转换为 DECIMAL(18, 0)
。这在这里似乎没有任何影响,但最好指定值。 运行宁 SELECT CAST('123.456' AS DECIMAL)
将 return 只是 123
.
- 您实际上不需要过滤掉带逗号的值,因为这些值可以被删除,留下可以转换的值。当然,除非你有一些像
12,34,56,78
这样的代码。但是如果它们是有效数字,比如1,234.56
,那么你可以使用REPLACE([field_name], ',', '')
将以下两行添加到上面示例顶部的 INSERT 中将错误:
INSERT INTO @table_name (field_name) VALUES ('1,234.5678');
INSERT INTO @table_name (field_name) VALUES ('.');
所有这些都可以通过执行以下操作来处理(将上面的查询替换为下面的查询,但保留 DECLARE
和 INSERT
s):
SELECT field_name, CAST([field_name] AS DECIMAL(38, 18)) AS [DecimalValue]
FROM @table_name
WHERE ISNUMERIC(field_name) = 1
AND field_name NOT LIKE '%,%'
AND field_name NOT LIKE '%-%'
AND field_name <> '.'
AND CONVERT(DECIMAL(38, 18), REPLACE([field_name], ',', '')) > 100.00;
我有一列数据类型为 varchar
,其中一些包含数字(十进制)值。我需要找到所有数值大于 100 的行。我正在使用 ISNUMERIC
过滤包含数字的行,之后我尝试使用 CAST
或 CONVERT
来更改数字到 decimal
值。我读到另一个建议,说使用子查询可以解决问题,但我也试过了,但没有成功
这是我收到的错误消息:
Arithmetic overflow error converting varchar to data type numeric.
代码:
select field_name
from table_name
where ISNUMERIC(field_name) = 1 and
field_name in (select cast(field_name as decimal)
from table_name
where ISNUMERIC(field_name) = 1
and field_name not like '%,%'
and field_name not like '%-%'
and field_name != '.'
and field_name > 100.00)
这是您的查询:
select field_name
from table_name
where ISNUMERIC(field_name) = 1 and
field_name in (select cast(field_name as decimal)
from table_name
where ISNUMERIC(field_name) = 1 and
field_name not like '%,%' and
field_name not like '%-%' and
field_name <> '.' and
field_name > 100
)
您假设 where
子句在 select
之前过滤。这不是真的。实际上,SQL服务器将cast()
推给了读取数据的操作。然后应用过滤器。
其实子查询和普通的table表达式也不保证求值顺序。什么是 case
(至少在这种情况下不涉及聚合)。因此,您可以将查询写为:
select field_name
from table_name
where (case when ISNUMERIC(field_name) = 1 and
field_name not like '%,%' and
field_name not like '%-%' and
field_name <> '.'
then cast(field_name as decimal)
end) > 100;
我认为没有理由使用子查询。
查询有一些问题,但导致错误的主要问题相当简单:您的 field_name > 100.00
条件没有将 VARCHAR
字段转换为进行比较之前的数字类型。将其更改为 CONVERT(DECIMAL(38, 18), [field_name])
将修复您看到的错误。
运行 下面一次,看看它是否有效,然后再次取消对 AND [field_name] > 100.00
行和 运行 的注释,你将得到关于 [=53 的错误=]:
DECLARE @table_name TABLE (field_name VARCHAR(50) NOT NULL);
INSERT INTO @table_name (field_name) VALUES ('1234.5678');
INSERT INTO @table_name (field_name) VALUES ('12.78');
INSERT INTO @table_name (field_name) VALUES ('s');
INSERT INTO @table_name (field_name) VALUES ('2015-01-30');
INSERT INTO @table_name (field_name) VALUES ('51234.5678');
INSERT INTO @table_name (field_name) VALUES ('987651234.56789124');
SELECT field_name
FROM @table_name
WHERE ISNUMERIC([field_name]) = 1
AND [field_name] IN (
SELECT CAST([field_name] AS DECIMAL)
FROM @table_name
WHERE ISNUMERIC([field_name]) = 1
AND [field_name] NOT LIKE '%,%'
AND [field_name] NOT LIKE '%-%'
AND [field_name] != '.'
-- AND [field_name] > 100.00
AND CONVERT(DECIMAL(38, 18), [field_name]) > 100.00
);
但是,还有一些问题:
- 如问题中所示,子查询对 return 转换值列表没有意义。有可能为了在此处发布查询而更改了查询,因此以其真实形式更有意义,但不需要子查询,也无济于事。
CAST
到DECIMAL
没有指定精度和小数位数。默认值分别为 18 和 0。意思是,您正在将字符串转换为DECIMAL(18, 0)
。这在这里似乎没有任何影响,但最好指定值。 运行宁SELECT CAST('123.456' AS DECIMAL)
将 return 只是123
.- 您实际上不需要过滤掉带逗号的值,因为这些值可以被删除,留下可以转换的值。当然,除非你有一些像
12,34,56,78
这样的代码。但是如果它们是有效数字,比如1,234.56
,那么你可以使用REPLACE([field_name], ',', '')
将以下两行添加到上面示例顶部的 INSERT 中将错误:
INSERT INTO @table_name (field_name) VALUES ('1,234.5678'); INSERT INTO @table_name (field_name) VALUES ('.');
所有这些都可以通过执行以下操作来处理(将上面的查询替换为下面的查询,但保留 DECLARE
和 INSERT
s):
SELECT field_name, CAST([field_name] AS DECIMAL(38, 18)) AS [DecimalValue]
FROM @table_name
WHERE ISNUMERIC(field_name) = 1
AND field_name NOT LIKE '%,%'
AND field_name NOT LIKE '%-%'
AND field_name <> '.'
AND CONVERT(DECIMAL(38, 18), REPLACE([field_name], ',', '')) > 100.00;