列的访问验证规则可能是:日期、特定文本字符串或 null
Posted
技术标签:
【中文标题】列的访问验证规则可能是:日期、特定文本字符串或 null【英文标题】:Access validation rule for a column that could be: a date, a specific text string, or null 【发布时间】:2014-11-07 16:56:18 【问题描述】:我有一列可以是:
-
短日期:DD/MM/YYYY
字符串:“N/A”
空
我可以使用表中的验证规则字段来强制执行此操作吗?如果是,我该怎么做?
【问题讨论】:
它必须是一个有效的日期。所以 2001 年 1 月 11 日、1950 年 9 月 12 日、2018 年 1 月 22 日都很好。 2001 年 13 月 35 日 - 不行 【参考方案1】:尝试在字段级别使用单个验证规则进行验证可能有点麻烦,但由于您使用的是 Access 2010,因此可以使用更改前data macro:
那个宏的 XML 源代码是
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="BeforeChange">
<Statements>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">dateStringIsValid</Argument>
<Argument Name="Value">False</Argument>
</Action>
<ConditionalBlock>
<If>
<Condition>IsNull([dateString])</Condition>
<Statements>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">dateStringIsValid</Argument>
<Argument Name="Value">True</Argument>
</Action>
</Statements>
</If>
<ElseIf>
<Condition>UCase([dateString])="N/A"</Condition>
<Statements>
<Comment>force to uppercase for consistency</Comment>
<Action Collapsed="true" Name="SetField">
<Argument Name="Field">dateString</Argument>
<Argument Name="Value">UCase([dateString])</Argument>
</Action>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">dateStringIsValid</Argument>
<Argument Name="Value">True</Argument>
</Action>
</Statements>
</ElseIf>
<ElseIf>
<Condition>Len([dateString])=10</Condition>
<Statements>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">ddStr</Argument>
<Argument Name="Value">Mid([dateString],1,2)</Argument>
</Action>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">mmStr</Argument>
<Argument Name="Value">Mid([dateString],4,2)</Argument>
</Action>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">yyyyStr</Argument>
<Argument Name="Value">Mid([dateString],7,4)</Argument>
</Action>
<Action Collapsed="true" Name="OnError">
<Argument Name="GoTo">Next</Argument>
</Action>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">newDate</Argument>
<Argument Name="Value">DateSerial(Val([yyyyStr]),Val([mmStr]),Val([ddStr]))</Argument>
</Action>
<Action Collapsed="true" Name="OnError">
<Argument Name="GoTo">Fail</Argument>
</Action>
<ConditionalBlock>
<If>
<Condition>[MacroError].[Number]=0</Condition>
<Statements>
<Comment>make sure DateSerial() hasn't converted an invalid date to a valid one (e.g. 32/01/2014 ->
01/02/2014)</Comment>
<ConditionalBlock>
<If>
<Condition>(Year([newDate])=Val([yyyyStr])) And (Month([newDate])=Val([mmStr])) And
(Day([newDate])=Val([ddStr]))</Condition>
<Statements>
<Comment>reassemble to ensure consistent separators</Comment>
<Action Collapsed="true" Name="SetField">
<Argument Name="Field">dateString</Argument>
<Argument Name="Value">[ddStr] & "/" & [mmStr] & "/" &
[yyyyStr]</Argument>
</Action>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">dateStringIsValid</Argument>
<Argument Name="Value">True</Argument>
</Action>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</ElseIf>
</ConditionalBlock>
<ConditionalBlock>
<If>
<Condition>[dateStringIsValid]=False</Condition>
<Statements>
<Action Collapsed="true" Name="RaiseError">
<Argument Name="Number">1</Argument>
<Argument Name="Description">dateString is not valid.</Argument>
</Action>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</DataMacro>
</DataMacros>
(有关如何将数据宏 XML 代码传入和传出 Access 数据库的信息,请参阅问题here。)
顺便说一句,除了我对您之前的问题here 的回答之外,以下只是将您的日期/文本信息存储在单个(文本)字段中可能仍然不是一个好主意的几个原因,即使有所有这些花哨的验证:
通过将日期值存储为文本,您承诺在任何时候将字段值用作日期(而不只是逐字打印)将文本转换回实际日期值。这不仅令人讨厌,而且可能会对性能产生重大影响(请参见下面的第 3 点)。
通过将日期格式“硬连线”为dd/mm/yyyy
,您将其强加给您的用户。如今,人们希望应用程序尊重他们的偏好,因此如果有人决定他们想要使用 yyyy/mm/dd
格式——并且他们已经在 Windows 控制面板中指定了这一点——那么他们希望他们的应用程序使用它。
也许最重要的是,通过将日期存储为 dd/mm/yyyy
文本,您基本上可以保证您在单日文字 dd/mm/yyyy
值之外进行的任何搜索都不会是 sargable,并且需要进行表扫描。如果您选择了yyyy/mm/dd
,您至少可以通过直接字符串比较完成日期范围搜索,但是使用dd/mm/yyyy
(甚至mm/dd/yyyy
)字符串,您的搜索性能会受到影响。
【讨论】:
非常感谢您提供如此详细的答案。几个后续问题。 1) 对不同字段重复此操作的最佳方法是什么,我有大约 10 个需要验证的类似字段? 2. 如何导入您指定的 XML?我最终将您的示例逐行复制到宏编辑器中。再次感谢。以上是关于列的访问验证规则可能是:日期、特定文本字符串或 null的主要内容,如果未能解决你的问题,请参考以下文章
如何设置验证规则:MS 访问中的“任务开始日期 >= 项目开始日期”