【问题标题】:Getting a string conversion error when trying to exclude a month尝试排除一个月时出现字符串转换错误
【发布时间】:2018-09-17 09:23:12
【问题描述】:

所以,我仍在学习 SQL 的来龙去脉,并试图找出我做错了什么。

SELECT P.productid, P.productname, O.orderdate
FROM Production.Products AS P INNER JOIN
Sales.OrderDetails AS D ON P.productid = D.productid
INNER JOIN Sales.Orders AS O ON D.orderid = O.orderid
WHERE (O.orderdate NOT BETWEEN '2015-09-01' AND '2015-09-31');

它会产生以下错误:

从字符转换日期和/或时间时转换失败 字符串。

对此的任何帮助将不胜感激。

【问题讨论】:

  • 发布确切的错误信息。
  • fwiw NOT BETWEEN '2015-09-01' AND '2015-09-31' 不会排除您需要从 1 日到 1 日之间使用的整个月份
  • 这是错误信息:从字符串转换日期和/或时间时转换失败。
  • @Icodin 这些值从何而来?原始字符串,日期参数?你总是打算匹配一整个月吗?拼写错误的修复很容易。使查询对此类问题具有弹性需要更多细节。例如,如果值是字符串,不要使用字符串,使用date 参数。使用 EOMONTH 获取任何参数的一个月的最后一天。
  • 不需要 SQL 知识。任何值得一提的编程语言都不应该将2015-09-31 识别为有效日期。

标签: sql sql-server tsql date datetime


【解决方案1】:

假设 orderdate 是日期/日期时间,您应该得到的错误是:

导致将 varchar 数据类型转换为 datetime 数据类型 在一个超出范围的值。

这是因为9 月有 30 天,而不是 31 天。改为2018-09-30

或者更好,使用EOMONTH()函数:

SELECT EOMONTH('2019-02-01')
-- 2019-02-28
SELECT EOMONTH('2020-02-01')
-- 2020-02-29 because 2020 is a leap year

或者更好,不要使用BETWEEN

WHERE NOT (O.orderdate >= '2015-09-01' AND O.orderdate < '2015-10-01')

【讨论】:

  • 感谢您的帮助。很抱歉我浪费了大家的时间,没有早点发现。
【解决方案2】:
DECLARE @Date DATE = '2018-09-01', @StartDate DATE, @EndDate DATE
SELECT @StartDate = DATEADD(MONTH, -1, DATEADD(DAY, 1, EOMONTH(@Date))), @EndDate = CAST(DATEADD(DAY, -(DAY(@Date)), @Date) AS DATE)

SELECT P.productid, P.productname, O.orderdate
FROM Production.Products AS P INNER JOIN
Sales.OrderDetails AS D ON P.productid = D.productid
INNER JOIN Sales.Orders AS O ON D.orderid = O.orderid
WHERE (O.orderdate NOT BETWEEN @StartDate AND @EndDate);

在第 1 行声明 3 个日期变量 @Date、@StartDate、@EndDate 并为 @Date 分配一个随机日期,如“2018-09-01” 在第 2 行到 @Date,获取开始和结束日期作为变量。 在 where 子句的第 3 行添加这些日期

解决方案:通过这些步骤,您永远不会收到错误日期开始和结束日期,因为这里您只提供一个随机日期,作为回报,您有 2 个日期,其中包含年+月的开始和结束日期。

【讨论】:

    【解决方案3】:

    我强烈建议您避免将BETWEEN(和NOT BETWEEN)与日期/时间数据类型一起使用。 Aaron Bertrand 有一个很好的博客来解释推理,What do Between and the Devil have in Common?

    SELECT P.productid, P.productname, O.orderdate
    FROM Production.Products P INNER JOIN
         Sales.OrderDetails D
         ON P.productid = D.productid INNER JOIN
         Sales.Orders O
         ON D.orderid = O.orderid
    WHERE O.orderdate < '2015-09-01' OR
          O.orderdate >= '2015-10-01';
    

    【讨论】:

      猜你喜欢
      • 2022-09-22
      • 2016-10-27
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多