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 ANSIJOIN
语法-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