我有以下一组SQL语句。目的是找到每个项目的售价。
SELECT cost AS 'Price', disc AS 'Discount', (cost-disc) AS 'Selling Price'
FROM SALE
问题在于cost, scost, disc
列的数据类型为Varchar
。因此,我尝试转换这些列,但是没有用。不,我尝试更改列数据类型,如下所示:
UPDATE SALE
SET cost = '0.0'
WHERE cost IS NULL OR ISNUMERIC(cost) = 0;
ALTER TABLE SALE
ALTER COLUMN cost DECIMAL(12,0);
UPDATE SALE
SET scost = '0.0'
WHERE scost IS NULL OR ISNUMERIC(scost) = 0;
ALTER TABLE SALE
ALTER COLUMN scost DECIMAL(12,0);
UPDATE SALE
SET disc = '0.0'
WHERE disc IS NULL OR ISNUMERIC(disc) = 0;
ALTER TABLE SALE
ALTER COLUMN disc DECIMAL(12,0);
我在SQL Server Management Studio中遇到的错误:
第245层状态1的状态3行
将varchar值'0.0'转换为数据类型int时,转换失败。
如何解决这个问题?
答案 0 :(得分:2)
尝试转换为十进制类型,其精度足以覆盖您的实际数据集,例如
UPDATE SALE SET cost = '0.0' WHERE cost IS NULL OR ISNUMERIC(cost) = 0;
ALTER TABLE SALE ALTER COLUMN cost DECIMAL(12, 4);
您收到的确切错误消息似乎集中在字符串文字0.0
的中心,该字符串不能转换为整数。但是,假设您尝试转换为小数,这听起来不对,在这种情况下,0.0
是一个完全可以接受的值。
答案 1 :(得分:0)
您应该修复数据。但我建议显式转换:
select cost AS Price, disc AS Discount,
(try_convert(decimal(20, 4), cost) - try_convert(decimal(20, 4), disc) ) as selling_price
from sale;
您不应将数字存储为字符串。您可以通过以下操作查看是否有任何值无效
select cost, disc
from sale
where try_convert(decimal(20, 4), cost) is null or
try_convert(decimal(20, 4), disc) is null;
如果未返回任何行,则将其转换:
alter table alter column cost decimal(20, 4);
alter table alter column disc decimal(20, 4);
注意:此答案使用decimal(20, 4)
,您可以使用其他相关类型,但十进制似乎适合示例数据。
编辑:
在早期版本的SQL Server中,我建议:
select cost AS Price, disc AS Discount,
((case when cost not like '%[^0-9.]%' and cost not like '%.%.%'
then convert(decimal(20, 4), cost)
end) -
(case when disc not like '%[^0-9]%' and cost not like '%.%.%'
then try_convert(decimal(20, 4), disc)
end)
) as selling_price
from sale;
您可以使用类似的逻辑。我不建议使用isnumeric()
,因为以下内容返回“ 1”-'$'
,'.'
,'3e4'
-但这些都不转换为小数。
答案 2 :(得分:0)
我建议创建具有所需结构的新表,并将数据复制到新表中。然后重命名表。 下面是代码:
update SALE set cost='0.0' where cost='NULL' or cost IS NULL OR ISNUMERIC(cost) = 0;
update SALE set scost='0.0' where scost='NULL' or scost IS NULL OR ISNUMERIC(scost) = 0;
update SALE set disc='0.0' where disc='NULL' or disc IS NULL OR ISNUMERIC(disc) = 0;
CREATE TABLE SALENEW (cost decimal(18,2), scost decimal(18,2), disc decimal(18,2));
INSERT INTO SALENEW SELECT * FROM SALE;
EXEC sp_rename 'SALE', 'SALEBACKUP';
EXEC sp_rename 'SALENEW', 'SALE';
这会有所帮助。