将 nvarchar 值“$28,926.25”转换为数据类型 int 时转换失败

0 sql t-sql sql-server

USE AdventureWorks2014

SELECT 
    result.BusinessEntityID, 
    p.FirstName, p.LastName, 
    result.TotalSales, '2011' AS SalesYear, 
    CASE 
        WHEN CAST(result.TotalSales AS int) > 1000000 THEN 'MillionPlus'
        WHEN CAST(result.TotalSales AS int) < 100000 THEN 'Warning'
        ELSE 'Met Expectations'
    END AS BonusCategory
FROM 
    person.Person AS P, 
    (SELECT sp.BusinessEntityID, FORMAT(sum(soh.SubTotal), 'c', 'en-us') AS TotalSales 
     FROM sales.SalesPerson as sp 
     RIGHT JOIN sales.SalesOrderHeader as SOH ON sp.BusinessEntityID = soh.SalesPersonID
     WHERE soh.orderdate LIKE '%2011%'
     GROUP BY sp.BusinessEntityID) AS result 
WHERE 
    result.BusinessEntityID = p.BusinessEntityID 
    OR result.TotalSales IS NULL
ORDER BY 
    result.BusinessEntityID 
Run Code Online (Sandbox Code Playgroud)

完整的错误信息


将 nvarchar 值“$28,926.25”转换为数据类型 int 时,消息 245,级别 16,状态 1,第 2 行转换失败。

Joe*_*orn 5

在几乎任何平台上进行编程时,在数字值(如123.45字符串或文本值)之间进行转换时要理解的事情"123.45"是一种令人惊讶的缓慢且昂贵的操作。它们可能看起来相同,但它们是不同的价值观,并且很大程度上由于国际化/文化问题,它们之间的转换并非微不足道。 始终寻求最小化这些转换,并且在您确实需要它们时将其保留到最后一刻。

SQL Server 在这里也不例外。混合数字和文本可能非常挑剔。

对于这个问题,嵌套的内部查询采用sum(soh.SubTotal)表达式,它是一个数字,并将其包装在一个FORMAT()函数调用中,这将创建一个文本字段。我们稍后尝试在外部查询中使用结果,就好像它再次是一个数字一样

不要那样做!

等待格式化结果,直到SELECT外部语句的 子句,在最后可能的时刻。这允许我们CAST()CASE表达式内部完全删除s 。

此外,永远不要使用旧的A,B WHERE连接语法。它已经过时了超过 25 年。

USE AdventureWorks2014
SELECT result.BusinessEntityID, p.FirstName, p.LastName, 
    FORMAT(result.TotalSales,'c','en-us') As TotalSales, '2011' as SalesYear, 
    CASE 
        WHEN result.TotalSales > 1000000 THEN 'MillionPlus'
        WHEN result.TotalSales < 100000 THEN 'Warning'
        ELSE 'Met Expectations'
    END as BonusCategory
FROM person.Person as P
INNER JOIN (
       SELECT sp.BusinessEntityID, FORMAT(sum(soh.SubTotal),'c','en-us') as TotalSales 
       FROM sales.SalesPerson as sp 
       RIGHT JOIN sales.SalesOrderHeader as SOH 
            ON sp.BusinessEntityID = soh.SalesPersonID
       WHERE soh.orderdate LIKE '%2011%'
       GROUP BY sp.BusinessEntityID
    ) result ON (result.BusinessEntityID = p.BusinessEntityID OR result.TotalSales is null)
ORDER BY result.BusinessEntityID 
Run Code Online (Sandbox Code Playgroud)

更好的是,甚至不要在 SELECT 子句中转换为字符串/文本!让客户端程序或报告工具处理这部分。这是我们可以遵循第一段中“将转换留到最后一刻”指导的另一种方式。