Sql CDate使DateAdd公式失败

Sql CDate使DateAdd公式失败,sql,ms-access,Sql,Ms Access,我希望我能被原谅,因为我只是通过问一个原因,而不是一个解决方案来轻微违反规则 我有以下代码: INSERT INTO destinationTable (RecordMonth, ...) SELECT t1.Expr1, ... FROM ( SELECT CDate(Format("01-" & Right([t1].[Year-Month],2) & "-" & Left([t1].[Year-Month],4),"dd/mm

我希望我能被原谅,因为我只是通过问一个原因,而不是一个解决方案来轻微违反规则

我有以下代码:

INSERT INTO destinationTable (RecordMonth, ...)
SELECT t1.Expr1, ...
FROM
    (   
    SELECT 
        CDate(Format("01-" & Right([t1].[Year-Month],2) & "-" & Left([t1].[Year-Month],4),"dd/mm/yyyy")) AS Expr1, 
        /* ...other fields with no bearing... */
    FROM tcsvMonthData AS t1
    )
WHERE t1.Expr1 >= DateAdd("m",-6,(SELECT MAX(Expr1) FROM t1))
t1
中的
[年-月]
是一个varchar类型字段

此脚本失败,Access将显示以下错误消息:“条件表达式中的数据类型不匹配。”

如果删除
CDate
块,脚本将正常工作。很高兴找到了答案,但我不明白为什么会出现错误
CDate
将字段约束为日期类型。在
format
之后,该字段应该已经是日期类型了,因此
CDate
是多余的,但它应该不会有什么害处(至少在我的头脑中不会)。另外,据我所知,
DateAdd
不像说,
Year
,它不会将输入字段转换为字符串,它应该保持一个日期类型。这是怎么回事

编辑:
Year-Month
描述记录发生的月份,如下所示:
2017-11
。它是一个varchar类型,目标是将其作为dd/mm/yyyy格式的适当日期时间字段,其中每个月由该月的第一天表示。因此,5月是2018年5月1日等等。

我在sql server中找到了一个解决方案,请使用cdate代替ms access的cast

 select  cast(format(cast('01-' + left('07/23/2018',2) + '-' + right('07/23/2018',4) as date),'dd/MM/yyyy') as date) AS Expr1

更改列的静态日期。

我已经很久没有使用Access了,但我认为问题不在于使用CDate(),而在于在内部字符串上使用Format()。Format()需要对日期进行操作,但您给它一个字符串。因为格式化失败,所以周围的CDate()也失败了

您需要在Format()之前使用CDate(),如下所示:

        Format(CDate ("01-" & Right([t1].[Year-Month],2) & "-" & Left([t1].[Year-Month],4),"dd/mm/yyyy")) AS Expr1, 
您可能需要做一些调整,以使其运行,但基本的想法应该是可行的


下面被拒绝的答案之所以有效,是因为Cast-As-Date(在功能上等同于CDate)在Format()之前和之后都使用,所以Format()被传递了一个日期。该示例中的第二个强制转换是多余的

你把这件事搞得太复杂了。CDate是您所需要的全部:

CDate([t1].[Year-Month]) AS Expr1
编辑:

要接受空值,请过滤掉这些值,或使用CVDate传递空值:

或使用Nz提供默认值:


这对MS Access有何帮助?我非常感谢您费尽周折找到了一个适用于Sql Server的解决方案,但是我这里的问题不是“如何修复它?”而是“它为什么会失败?”。我提出这个问题的原因是为了更好地了解Access的工作原理,以便将来避免类似的问题。格式化后,字段应该已经是日期类型了。。不。格式返回一个字符串。我试过了,但老实说,这似乎适得其反。如果我将
CDate
放入
Format
中,则最终结果是一个字符串类型字段,随后的
DateAdd
也会失败。作为一个小提示,我认为你的括号放错地方了
CDate
应该在“dd/mm/yyyyy”之前关闭,对吗?是的,Format()以指定格式获取日期并返回字符串。在Access中,日期存储为时间码,人类无法读取。因此,在原始示例中,将字符串日期转换为时间代码,然后使用Format()将其转换回具有不同格式的字符串。如果您只是想存储日期,那么可以完全跳过Format()。真的!另一个简化整个过程的函数是
DateValue
,但它们都以某种方式失败。您建议的解决方案会引发以下错误消息“无效使用null”。我会检查一下,我在试验这里提出的解决方案时没有造成其他混乱,但我开始怀疑问题实际上在
DateAdd
函数cdate中没有“失败”,但它不接受空值作为输入。宾果
Year-Month
不应该为空,所以我甚至没有考虑过它,但本周确实有一行字段为空。这很可能也是所有其他尝试失败的原因。谢谢
CVDate([t1].[Year-Month]) AS Expr1
Nz(CVDate([t1].[Year-Month]), Date()) AS Expr1