无法将 varchar 转换为 int 或减去它们

Cannot convert varchar to int or subtract them

我有以下一组 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 中遇到的错误:

Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the varchar value '0.0' to data type int.

如何解决这个问题?

你应该修复数据。但我会推荐 explicit conversions:

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;

如果没有行被 returned,则转换它们:

alter table alter column cost decimal(20, 4);
alter table alter column disc decimal(20, 4);

注意:此答案使用 decimal(20, 4),您可以使用其他相关类型,但十进制似乎适合示例数据。

编辑:

在SQL服务器的早期版本中,我建议:

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() 因为下面的 return “1” -- '$', '.', '3e4' -- 但是 none 这些转换到小数。

尝试转换为精度足以涵盖您的实际数据集的小数类型,例如

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 是一个完全可以接受的值。

我建议创建一个具有所需结构的新 table,并将数据输入复制到新的 table。然后重命名您的 table。 下面是代码:

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';

这会有所帮助。