【问题标题】:SQL CONVERT not working when WHERE is added添加 WHERE 时 SQL CONVERT 不起作用
【发布时间】:2016-03-07 16:43:34
【问题描述】:

使用: SQL Server 2008 Management Studio,T-SQL

问题描述:我基本上有两个带有AccountNumber 列的表。在一个表中存储为NUMERIC,在另一个表中存储为VARCHAR(不幸的是,这种数据类型差异无法更改)。

因此,为了保持一致性,为了将它们都转换为数值数据类型,我尝试的解决方案是仅在 VARCHAR 表中使用 LEFT JOIN,并将 AccountNumber 列转换为 NUMERIC

效果很好,查询将运行。

然而, 我一添加WHERE 子句,它就会崩溃并出现如下所示的错误。如您所见,使用WHERE 子句,我基本上只是对特定的(NUMERICAccountNumber 进行查询搜索。

当来自LEFT JOINAccountNumber 列是NUMERIC 时,为什么会出现此转换错误问题?

/*
Assumptions:
    A.AFIELD is numeric
    B.BFIELD is varchar

Result:
    Msg 8114, Level 16, State 5, Line 10
    Error converting data type varchar to numeric.
*/

SELECT A.AccountNumber, B.AccountNumber
FROM A
LEFT JOIN 
    (SELECT CONVERT(NUMERIC, B.AccountNumber) AccountNumber
     FROM B
     WHERE ISNUMERIC(B.AccountNumber) = 1) B ON B.AccountNumber = A.AccountNumber
WHERE A.AccountNumber = 1234567890
/*NOTE: I am searching the originally numeric AccountNumber field for a numeric, yet it's erroring out*/

【问题讨论】:

  • 它告诉你 B 中有一个值不能转换为数字。
  • case when isnumeric() then convert(numeric) end

标签: sql-server tsql numeric varchar


【解决方案1】:

你应该转换成VARCHAR:

select A.AccountNumber, B.AccountNumber
from A
left join
    (
    select AccountNumber
    from B
    where ISNUMERIC(B.AccountNumber)=1
    ) B on B.AccountNumber = CONVERT(VARCHAR(10),A.AccountNumber)
where A.AccountNumber = 1234567890;

【讨论】:

  • 拉马克,感谢您的回复。出于其他原因,最好将 B 转换为数字。基本上,此查询将被扔到 Excel 数据连接中,最终用户会将数字 AccountNumbers 列表放入 Excel 列中。 VBA 脚本会将它们全部循环在一起并将它们放入查询的 WHERE 部分并返回结果。
  • @Chase 我没发现问题,您可以在WHERE 条件中将值用作数字
  • 抱歉 - 进一步详细说明,一些最终用户将使用数字,而其他用户将使用 varchars(例如,'01234567890')。这有点烦人,但这取决于他们从哪个记录系统获取 AccountNumbers。所以转换为 numeric 将确保正确的结果,而转换为 varchar 可能会返回正确的结果。我想更根本的是WHY我的查询出错了?
  • @Chase Lamak 建议的转换仅在WHEREON 子句中使用。输出(SELECT 列表)包括未转换的两列。所以你可以使用任何你喜欢的东西来导出。
【解决方案2】:

也许我的评论“它告诉你 B 中有一个值不能转换为数字”不够清楚。试试这个:

select A.AccountNumber, B.AccountNumber
from A
left join
    (
    select CONVERT(numeric,B.AccountNumber) AccountNumber
    from B
    where ISNUMERIC(B.AccountNumber)=1
    ) B on coalesce(B.AccountNumber,0) = A.AccountNumber
where A.AccountNumber = 1234567890;

这是一个简单的演示:

DECLARE @t1 TABLE
  (
    accountnumber NUMERIC
  );
DECLARE @t2 TABLE
  (
    accountnumber VARCHAR(20)
  );

INSERT  @t1 ( [accountnumber] )
VALUES  ( 1 ),
        ( 2 ),
        ( 3 );

INSERT  @t2 ( [accountnumber] )
VALUES  ( '1' ),
        ( '3' ),
        ( 'NonConvertible' );


SELECT  A.accountnumber, B.accountNumber
FROM    @t1 AS [A]
LEFT JOIN (
            SELECT
                CASE 
                    -- Still not 100% safe because ISNUMERIC isn't
                    WHEN ISNUMERIC(B.accountnumber) = 1
                    THEN CONVERT(NUMERIC, accountnumber) 
                    ELSE CONVERT(NUMERIC, NULL)
                END AS accountNumber
            FROM    @t2 AS [B]
            WHERE   ISNUMERIC(accountNumber) = 1
--          ) B ON B.accountNumber = A.accountnumber
          ) B ON COALESCE(B.accountNumber, 0) = A.accountnumber
WHERE   A.accountnumber = 1;

【讨论】:

  • 我真的会问反对者,为什么?只是为了满足?
  • 我不是反对者,但是是什么让您认为这可以防止错误发生?
  • 很简单,错误指向它 :) 这就是 MS SQL 服务器的工作方式。我觉得人们在不理解某些事情时只是投反对票是不礼貌的。
  • 我知道错误的含义,我只是说这并不能真正解决每种情况。例如,将'1e1' 添加到您的@t2 表中,看看会发生什么
  • @Lamak,1e1 会是一个问题,是的,对于 2008,我想不出一个简单的解决方案。在 2012 年,您可以简单地将原始查询与 TRY_CONVERT(numeric, accountnumber) 一起使用
猜你喜欢
  • 2014-08-29
  • 1970-01-01
  • 2015-01-27
  • 2016-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多