SQL Server 在以前可以工作的选择上返回错误

Posted

技术标签:

【中文标题】SQL Server 在以前可以工作的选择上返回错误【英文标题】:SQL Server returning an error on a select that used to work 【发布时间】:2020-09-03 14:05:25 【问题描述】:

我在存储过程中有以下代码:

SELECT 
    CONCAT(' ', CONVERT(date, fc.dataven), ' '), 
    fc.adoc, fc.nome, 
    CONCAT(CONVERT(money, fc.ecred), '  €')  
FROM
    fc, fl
WHERE
    dataven BETWEEN DATEFROMPARTS(IIF(MONTH(GETDATE()) = 1, YEAR(GETDATE())-1, YEAR(GETDATE())),
                                  IIF(MONTH(GETDATE()) = 1, 12, MONTH(GETDATE()) - 1), 25) 
                AND DATEFROMPARTS(IIF(MONTH(GETDATE()) = 0, YEAR(GETDATE()), YEAR(GETDATE())),
                                  IIF(MONTH(GETDATE()) = 0, 12, MONTH(GETDATE())), 31)
    AND adoc NOT LIKE '' 
    AND cmdesc LIKE 'v%'  
    AND evalpo = '0' 
    AND (cmdesc LIKE '%factura%' OR cmdesc LIKE '%cred%')
    AND fc.nome = fl.nome 
    AND fl.pais LIKE 1
GROUP BY
    fc.adoc, fc.dataven, fc.nome, fc.ecred
ORDER BY 
    fc.nome 

这很有魅力,几天前我改变了一个条件,从:

cmdesc like '%factura%'

收件人:

(cmdesc like '%factura%' or cmdesc like'%cred%')

现在,运行程序,我收到以下错误:

消息 289,第 16 级,状态 1,第 1 行 无法构造数据类型日期,某些参数的值无效。

我正用头撞墙,但找不到错误。有人可以帮我吗?

【问题讨论】:

如果您将条件更改为简单的 cmddesc,例如 '%cred%',您会收到错误消息吗?仅当您同时应用这两个条件时才会发生错误?从我所看到的......错误在于 DATEFROMPARTS() 函数。我猜有些数据无法解析为日期。 “以前工作”、“几天前我改变了一个条件”... ***.com/questions/48631439/error-constructing-date Bad habits to kick : using old-style JOINs - 旧式 逗号分隔的表格列表 样式已替换为 ANSI 中的 proper ANSI JOIN 语法-92 SQL 标准(25 多年前),不鼓励使用它 我们在九月。 9 月只有 30 天而不是 31 天。8 月有 31 天,这就是它以前工作的原因。 【参考方案1】:

更改第二个DATEFROMPARTS,因为您每个月都没有 31 天:

SELECT 
    CONCAT(' ', CONVERT(date, fc.dataven), ' '), 
    fc.adoc, fc.nome, 
    CONCAT(CONVERT(money, fc.ecred), '  €')  
FROM
    fc, fl
WHERE
    dataven BETWEEN DATEFROMPARTS(IIF(MONTH(GETDATE()) = 1, YEAR(GETDATE())-1, YEAR(GETDATE())),
                                  IIF(MONTH(GETDATE()) = 1, 12, MONTH(GETDATE()) - 1), 25) 
                AND CAST(DATEADD(day,-day(GETDATE()),DATEADD(month, 1,GETDATE())) as DATE)

    AND adoc NOT LIKE '' 
    AND cmdesc LIKE 'v%'  
    AND evalpo = '0' 
    AND (cmdesc LIKE '%factura%' OR cmdesc LIKE '%cred%')
    AND fc.nome = fl.nome 
    AND fl.pais LIKE 1
GROUP BY
    fc.adoc, fc.dataven, fc.nome, fc.ecred
ORDER BY 
    fc.nome 

【讨论】:

很棒的收获。我没有深入研究传递给函数的值。只有这么多时间!【参考方案2】:

您不能像那样使用 OR 运算符。试试这个:

SELECT 
CONCAT(' ', CONVERT(date, fc.dataven), ' '), 
fc.adoc, fc.nome, 
CONCAT(CONVERT(money, fc.ecred), '  €')  
FROM
fc, fl
WHERE
(dataven BETWEEN DATEFROMPARTS(IIF(MONTH(GETDATE()) = 1, YEAR(GETDATE())-1, YEAR(GETDATE())),
                              IIF(MONTH(GETDATE()) = 1, 12, MONTH(GETDATE()) - 1), 25) 
            AND DATEFROMPARTS(IIF(MONTH(GETDATE()) = 0, YEAR(GETDATE()), YEAR(GETDATE())),
                              IIF(MONTH(GETDATE()) = 0, 12, MONTH(GETDATE())), 31)
AND adoc NOT LIKE '' 
AND cmdesc LIKE 'v%'  
AND evalpo = '0' 
AND cmdesc LIKE '%factura%'
AND fc.nome = fl.nome 
AND fl.pais LIKE 1)

OR //<-- here is the trick

 (dataven BETWEEN DATEFROMPARTS(IIF(MONTH(GETDATE()) = 1, YEAR(GETDATE())-1, YEAR(GETDATE())),
                              IIF(MONTH(GETDATE()) = 1, 12, MONTH(GETDATE()) - 1), 25) 
            AND DATEFROMPARTS(IIF(MONTH(GETDATE()) = 0, YEAR(GETDATE()), YEAR(GETDATE())),
                              IIF(MONTH(GETDATE()) = 0, 12, MONTH(GETDATE())), 31)
AND adoc NOT LIKE '' 
AND cmdesc LIKE 'v%'  
AND evalpo = '0' 
AND cmdesc LIKE '%cred%'
AND fc.nome = fl.nome 
AND fl.pais LIKE 1)

GROUP BY
fc.adoc, fc.dataven, fc.nome, fc.ecred
ORDER BY 
fc.nome 

【讨论】:

AND 和 OR 优先级,看这里:ramkedem.com/en/sql-server-and-or 啊,但是它们在 OR 条件周围有括号,这会改变您链接到的页面中最后一个代码中的顺序。 正确,但就我对这个查询的理解而言,您需要使用 AND 链构建 2 个子结果并将它们与 OR 合并。错误是您不能在与其他 AND 链接的 AND 语句中使用 OR 构建这 2 个集合【参考方案3】:

你错过了 like'%cred%'

之间的空格

cmdesc 像 '%factura%' 或 cmdesc 像 '%cred%'

【讨论】:

以上是关于SQL Server 在以前可以工作的选择上返回错误的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 用户定义函数返回表——不能从选择查询中调用它

与以前的 SQL Server 版本相比,ROUND 函数返回不同的结果 SQL Server 2016

SQL SERVER 从 If Exists 中选择多个字段

在 C# 中的 SQL Server 上合并选择

SQL Server 2008 R2导出数据脚本的方法

连接sqlserver数据库时报错,请问怎么解决