t-sql在一个案例中可能有不同的数据类型?

时间:2016-06-03 13:22:55

标签: sql sql-server tsql datetime

我有这个查询

SELECT
CASE WHEN dbo.CFE_PPHY.P77 IS NOT NULL OR dbo.CFE_PPHY.P77 <>'' 
       THEN MONTH(dbo.CFE_PPHY.P77)
     WHEN dbo.CFE_PPHY.P70 IS NOT NULL OR dbo.CFE_PPHY.P70 <>'' 
       THEN MONTH(dbo.CFE_SERVICE_EVTS.C10_2)
     ELSE COALESCE(CONVERT(VARCHAR,dbo.CFE_PPHY.P77)+
          CONVERT(VARCHAR,dbo.CFE_SERVICE_EVTS.C10_2),'toto') END 
 AS CFELiasse_DateEffetEIRL_MM_N
FROM CFE_PPHY LEFT JOIN CFE_SERVICE_EVTS ON CFE_PPHY.colA = CFE_SERVICE_EVTS.colB

ELSE部分令我头疼。

CFE_PPHY.P77CFE_SERVICE_EVTS.C10_2具有日期时间格式。我把它们变成了varchar。然而,当我运行查询时,我有以下错误

  

Msg 245,Level 16,State 1,Line 1将varchar值'toto'转换为数据类型int时转换失败。

显然,我无法将toto转换为整数。很公平。但是,从我的角度来看,我已经将日期时间格式转换为varchar格式,因此它应该可以完成工作。

我哪里错了?

由于

4 个答案:

答案 0 :(得分:4)

您必须将所有案例表达式转换为varchar。 SQL决定将该字段视为int,因此&#39; toto&#39;是无效的。如果所有表达式都转换为varchar,则应该解决此错误。

http://blog.sqlauthority.com/2010/10/08/sql-server-simple-explanation-of-data-type-precedence/

答案 1 :(得分:3)

仔细查看您的case表达式:在第一个和第二个条件分支中,您将返回MONTH(...,这显然是整数。

但是在第三个分支中,您将返回varchar,因此SQL服务器会根据以前分支的数据类型尝试将其转换为int,并且无法执行此操作。

答案 2 :(得分:2)

试试这个,

SELECT CASE 
        WHEN dbo.CFE_PPHY.P77 IS NOT NULL
            OR dbo.CFE_PPHY.P77 <> ''
            THEN convert(VARCHAR, MONTH(dbo.CFE_PPHY.P77))
        WHEN dbo.CFE_PPHY.P70 IS NOT NULL
            OR dbo.CFE_PPHY.P70 <> ''
            THEN convert(VARCHAR, MONTH(dbo.CFE_SERVICE_EVTS.C10_2))
        ELSE COALESCE(CONVERT(VARCHAR, dbo.CFE_PPHY.P77) + CONVERT(VARCHAR, dbo.CFE_SERVICE_EVTS.C10_2), 'toto')
        END AS CFELiasse_DateEffetEIRL_MM_N
FROM CFE_PPHY
LEFT JOIN CFE_SERVICE_EVTS ON CFE_PPHY.colA = CFE_SERVICE_EVTS.colB

答案 3 :(得分:1)

首先,转换为字符串时,始终包含一个长度(在SQL Server中)。默认长度因上下文而异,可能不正确。

其次,没有必要将日期/时间值与''进行比较。这对于日期/时间来说不是真正有效的值 - 尽管它确实被转换为0,即1900-01-01。 NULL比较应该足够了。否则,明确。

第三,如果任何参数为NULL,字符串连接将返回NULL

第四,表别名使查询更容易编写和阅读。

据我所知,你的case有点复杂。在ELSE中,我们知道dbo.CFE_PPHY.P77NULL,因为第一个条件。那么,怎么样:

SELECT (CASE WHEN p.P77 IS NOT NULL
             THEN CAST(MONTH(p.P77) as VARCHAR(255))
             WHEN p.P70 IS NOT NULL
             THEN CAST(MONTH(e.C10_2) as VARCHAR(255))
             ELSE 'toto'
        END) AS CFELiasse_DateEffetEIRL_MM_N
FROM CFE_PPHY p LEFT JOIN
     CFE_SERVICE_EVTS e
     ON p.colA = e.colB;
相关问题