【问题标题】:Conversion failed when converting the varchar value 'U' to data type int将 varchar 值“U”转换为数据类型 int 时转换失败
【发布时间】:2020-01-07 18:01:58
【问题描述】:

对于字段 Q1_cQ2_c,我收到“将 varchar 转换为 int 的错误”。

那些字段是CHAR(1),这些字段的值是1、2、3、4、5或U,但是当有U时它不会转换,所以我试图将U 的值更改为0 之类的其他值。我也尝试过CAST(a.q2_c as varchar(1)) = 'U' - 但这也不起作用。我应该使用INT 还是VARCHAR()?我也尝试过使用CONVERT 而不是CAST

ALTER VIEW [dbo].[vCDCP_rptInfantImprove]
as
select distinct
         IND.tb_cdcp_individuals as Individuals_IndividualID 
       , A.[tb_cdcp_individuals] as ATQInfant_IndividualID
       , A.CreateDate as ATQInfant_CreateDate
       , CAST(a.q1_c as varchar(3)) as A_Q1
       , CAST(a.q2_c as varchar(3)) as A_Q2
        ---Infant Sum
       , Sum(isnull(cast(a.Q1_c as int),0)) + Sum(isnull(cast(a.Q2_c as int),0)) as InfantSum
        ---Change U to 0
       , case when CAST(a.q1_c as int) = 'U' then 0 else 0 end as Unknown1
       , case when CAST(a.q2_c as int) = 'U' then 0 else 0 end as Unknown2
from DBO.tb_cdcp_ATQInfant a
left join DBO.tb_cdcp_individuals ind on a.[tb_cdcp_individuals] = ind.[tb_cdcp_individuals]
where ind.agegroup_c = 'C' 
group by IND.tb_cdcp_individuals, A.tb_cdcp_individuals, A.CreateDate   
       ,     a.q1_c
       ,     a.q2_c
GO

【问题讨论】:

  • 好吧,'U' 不是int,那么您如何期望CAST(a.q1_c as int),更不用说CAST(a.q1_c as int) = 'U' 工作了?
  • 我一点也不粗鲁,错误和数据实际上是在告诉你这里有问题。您收到一条错误消息,告诉您 'U' 无法转换为 int。您告诉我们您有一个专栏,您尝试转换为 int 的值为 '1','2','3','4','5','U',而您然后重新尝试将转换后的int 值与'U' 进行比较;这实际上意味着您尝试将 letter U 转换为 int 两次。那永远行不通。 'U' 不是数字。
  • @Dee 你能粘贴一些示例数据吗?在您的查询中,我看到 a.q1_c (和 a.Q2_c )被强制转换为 varchar(3) 和 int。因此,对本专栏所包含的数据类型感到困惑。提前谢谢你。
  • @sam 正如问题的第二句话所解释的,这些字段的值是 1、2、3、4、5 或 U
  • @Dee 这个怎么样:a.q1_c = 'U' then 0 else a.q1_c end as Unknown1

标签: sql sql-server


【解决方案1】:

你可以通过几种不同的方式来解决这个问题:

由于字段是字符格式,所以将'u'替换为'0',然后转换成int:

CAST(Replace(q1_c,'u','0') as int)

或者如果您想创建一个新的计算字段,您可以直接创建一个整数字段:

Case when q1_c='u' then 0 else CAST(q1_c as int) end as q1_c_calc

希望这会有所帮助。

【讨论】:

  • 如果我注释掉 "Sum(isnull(cast(a.Q1_c as int),0)) + Sum(isnull(cast(a.Q2_c as int),0)) as InfantSum ”。所以现在不知道如何计算总和。
  • 实际上我使用了第一部分 CAST(Replace(q1_c,'u','0') as int) 作为 InfantSum 并且错误消失了。如果可行,我将标记为答案。谢谢。
【解决方案2】:

我想到的一个简单想法是定义另一个表......每个可能的值都有一个CHAR(1),对应的数字有一个INT。然后,只需 JOIN 到该表。毫无疑问,如果 SQL 引擎只包含 5 行,它就会简单地将整个内容放入内存中。如果有一天需要编码更多的值,这很容易做到。

【讨论】:

  • 我喜欢这个想法,特别是因为如果在 1 到 5 边已经有一个“U”,则总是可能需要更多的编码。它还消除了添加繁琐的 CAST 或 CASE 语句的需要。
【解决方案3】:

假设您不能做任何其他事情来清理存储在表中的数据或做任何事情来控制插入到所述表中的值,您可以使用 TRY_CONVERT 或 TRY_CAST。如果 CHAR(1) 无法转换为 INT,则这两个函数都返回 NULL。您只需测试 NULL,这样您就不必担心可能会意外插入任何其他 rouge 字符。

IF OBJECT_ID('tempdb..#sample') IS NOT NULL
    BEGIN
        DROP TABLE #sample
    END
GO
CREATE TABLE #sample
(
    q1_c  CHAR(1),
    q2_c  CHAR(1)
)
INSERT INTO #sample(q1_c , q2_c )
VALUES ('1','1'),('2','2'),('3','3'),('4','4'),('5','5')
       ,('u','U'),('$','$'), ('#','#'), ('^','^'), ('&','&'), ('*','*'),
       ('1','1'),('2','2'),('3','3'),('4','4'),('5','5')

SELECT CASE WHEN TRY_CAST(q1_c AS INT) IS NULL THEN '0' ELSE q1_c END A_Q1, 
       CASE WHEN TRY_CONVERT(INT, q2_c) IS NULL THEN '0' ELSE q2_c END A_Q2,
       SUM(TRY_CAST(q1_c AS INT)) sumQ1_c, SUM(TRY_CONVERT(INT, q2_c)) sumQ2_c
FROM #sample
GROUP BY q1_c, q2_c

【讨论】:

    【解决方案4】:

    这不起作用有多种原因:

    首先,您必须确保您尝试转换的值与您尝试转换的类型兼容。 CAST(a.q1_c as int) 在值为 1,2,3,4,5 时可以正常工作,但在值为 'U' 时会失败。如果您确定值是 1、2、3、4、5 或 U,则可以使用 'case'

    CAST(case when a.q1_c = 'U' then 0 else a.q1_c end  as int) = 'U'
    

    如果没有,ISNUMERIC() 可能适用于这种情况。

    还有 CAST(a.q1_c as int) = 'U' 你想在这里做什么?为什么不只是 a.q1_c = 'U' ?

    【讨论】:

      【解决方案5】:

      请试试这个:

      ALTER VIEW [dbo].[vCDCP_rptInfantImprove]
      as
      select distinct
               IND.tb_cdcp_individuals as Individuals_IndividualID 
             , A.[tb_cdcp_individuals] as ATQInfant_IndividualID
             , A.CreateDate as ATQInfant_CreateDate
             , CAST(a.q1_c as varchar(3)) as A_Q1
             , CAST(a.q2_c as varchar(3)) as A_Q2
              ---Infant Sum
      
             , Sum(isnull( case when a.Q1_c = 'U' then 0 else cast(a.Q1_c as int) end,  0 )) + Sum(isnull( case when a.Q2_c = 'U' then 0 else cast(a.Q2_c as int) end,  0 )) as InfantSum
              --- Remove cast here and not sure what goes in else part.
             , case when a.q1_c = 'U' then 0 else a.q1_c end as Unknown1
             , case when a.q2_c = 'U' then 0 else a.q2_c end as Unknown2
      from DBO.tb_cdcp_ATQInfant a
      left join DBO.tb_cdcp_individuals ind on a.[tb_cdcp_individuals] = ind.[tb_cdcp_individuals]
      where ind.agegroup_c = 'C' 
      group by IND.tb_cdcp_individuals, A.tb_cdcp_individuals, A.CreateDate   
             ,     a.q1_c
             ,     a.q2_c
      GO
      

      【讨论】:

        猜你喜欢
        • 2011-12-01
        • 2012-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多