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

Sql 无法将varchar转换为int或减去它们,sql,sql-server,sql-server-2008,sql-server-2005,Sql,Sql Server,Sql Server 2008,Sql Server 2005,我有以下一组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

我有以下一组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,第16级,状态1,第3行
将varchar值“0.0”转换为数据类型int时,转换失败


如何解决这个问题?

您应该修复数据。但我建议显式转换:

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);
注意:此答案使用的是
十进制(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'
--但这些都不能转换为十进制。

您应该修复数据。但我建议显式转换:

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);
注意:此答案使用的是
十进制(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'
--但这些都不能转换为十进制。

尝试转换为精度足以覆盖实际数据集的十进制类型,例如

UPDATE SALE SET cost = '0.0' WHERE cost IS NULL OR ISNUMERIC(cost) = 0;
ALTER TABLE SALE ALTER COLUMN cost DECIMAL(12, 4);

您得到的确切错误消息似乎以字符串literal
0.0
不能转换为整数为中心。但是,如果您试图转换为十进制,那么这听起来并不正确,在这种情况下,
0.0
是一个完全可以接受的值。

尝试转换为精度足以覆盖实际数据集的十进制类型,例如

UPDATE SALE SET cost = '0.0' WHERE cost IS NULL OR ISNUMERIC(cost) = 0;
ALTER TABLE SALE ALTER COLUMN cost DECIMAL(12, 4);

您得到的确切错误消息似乎以字符串literal
0.0
不能转换为整数为中心。但是,假设您试图转换为十进制,那么这听起来并不正确,在这种情况下,
0.0
是一个完全可以接受的值。

我建议创建一个具有所需结构的新表,并将datain复制到新表中。然后重命名您的表。 代码如下:

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

这将有所帮助。

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

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

这将有所帮助。

@Neetu-您也可以使用
CONVERT
而不是从2012年开始提供的
TRY\u CONVERT
(如您标记的2008和2005所述),它说:Msg 195,级别15,状态10,第4行“decimal”不是可识别的内置函数名。使用CONVERT代替TRY\u CONVERT,它显示0条记录。甚至在桌子上scost@Neetu-您也可以使用
CONVERT
而不是从2012年开始提供的
TRY\u CONVERT
(如您标记的2008和2005所述)。它说:Msg 195,级别15,状态10,第4行“decimal”不是可识别的内置函数名。使用CONVERT代替TRY\u CONVERT,它显示0条记录。即使在表scostCheck中,也要检查varchar列中是否有逗号。ISNUMERIC找不到它们,因为它将检查所有数字类型(包括货币)。错误消息建议cost为int,而不是varchar。在不使用前面的
UPDATE
的情况下尝试ALTER。检查varchar列中是否有逗号。ISNUMERIC找不到它们,因为它将检查所有数字类型(包括货币)。错误消息建议cost为int,而不是varchar。在没有前面的
更新的情况下尝试更改。您好,现在它显示:(0行受影响)Msg 5074,级别16,状态1,第3行对象“DF_SALE_scost”依赖于列“scost”。Msg 4922,级别16,状态9,第3行ALTER TABLE ALTER COLUMN scost失败,因为一个或多个对象访问此列。@Neetu这看起来是一个错误,源于架构中完全不同的问题。您好,现在它显示:(0行受影响)Msg 5074,级别16,状态1,第3行对象“DF_SALE_scost”依赖于列“scost”。Msg 4922,级别16,状态9,第3行ALTER TABLE ALTER COLUMN scost失败,因为一个或多个对象访问此列。@Neetu这看起来像是一个错误,源于架构中完全不同的问题。是的,至少这样,现在一切正常。ThanxYeah,至少有了这个,现在一切都正常了。塔克斯