我有这个查询
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.P77
和CFE_SERVICE_EVTS.C10_2
具有日期时间格式。我把它们变成了varchar。然而,当我运行查询时,我有以下错误
Msg 245,Level 16,State 1,Line 1将varchar值'toto'转换为数据类型int时转换失败。
显然,我无法将toto
转换为整数。很公平。但是,从我的角度来看,我已经将日期时间格式转换为varchar格式,因此它应该可以完成工作。
我哪里错了?
由于
答案 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.P77
是NULL
,因为第一个条件。那么,怎么样:
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;