操作数类型冲突:日期与int不兼容吗?

时间:2019-06-17 17:30:10

标签: sql sql-server tsql sql-server-2016

有人可以帮助我吗,我有以下TSQL引发错误(它是表视图的一部分)。

SELECT MAX([WEEK]) FROM MyTable WHERE [Year] = DATEPART(YYYY, GETDATE())

这是一个View Case语句的一部分,

CASE 
    WHEN [WEEK] <= (SELECT MAX([WEEK]) FROM MyTable WHERE [Year] = DATEPART(YYYY, GETDATE())) THEN 
        [YEAR]
END YTD,

这将引发错误:操作数类型冲突:日期与int不兼容

该表定义为:

CREATE TABLE [dbo].[MyTable](
  [Week] [tinyint] NULL,
  [Year] [date] NULL,
) ON [PRIMARY]
GO

如何在不更改表字段类型的情况下使TSQL工作?

[年份]字段包含YYYY-MM-DD格式的记录。

这是在SQL Server 2016上。

1 个答案:

答案 0 :(得分:0)

调用dateyear是一个非常糟糕的命名选择。
您发布的SQL语句似乎是完全合理的-因为当您看到名为year的列时,您希望它包含年份(意思是一个整数),而不包含日期值。

您应该考虑重命名该列或更改其数据类型,只是为了节省可怜的混蛋的时间,这些杂种将不得不一年后对该代码进行维护工作,因为可能是您自己。 / p>

不用说,Year()函数将返回一个int值-自然,该值不能与日期值进行比较-您如何将532与2019年5月1日进行比较?就是比较苹果和橘子。

您有一个SARGable选项和一个非SARGable选项来解决此问题。
简而言之,SARGable表示一种条件,当相关索引存在时,该条件允许数据库引擎使用索引查找。

约翰·卡佩莱蒂(John Cappelletti)在his comment中建议使用非SARGable选项-将datepart用于列和值:

 WHERE datepart(YEAR,[Year]) = DATEPART(YEAR, GETDATE())

如果在year列中没有索引,或者表不是很大,那么索引扫描与索引查找实际上不是问题,或者选择速度不是问题,这是一个很好的选择。

SARGable选项使用的条件略有不同-像his comment中建议的HABO(尽管我认为我的版本稍微简单一些):

WHERE [Year] => DATEFROMPARTS(DATEPART(YEAR, GETDATE()), 1, 1)
AND [Year] < DATEFROMPARTS(DATEPART(YEAR, GETDATE()) + 1, 1, 1)

当您在Year列上有索引并且表足够大时,这是一个更好的选择,这样索引扫描与索引查找将对选择性能产生足够的影响。