如何优雅地处理Access窗体中的NOT NULL SQL Server列?

问题描述 投票:1回答:3

我有一个MS Access前端链接到SQL Server数据库。

如果需要某些列,那么自然要做的就是在该列的定义中包含NOT NULL(在数据库级别)。但这似乎在Access方面造成了问题。将表单绑定到该表时,绑定到该列的字段最终非常不友好。如果用户从该字段中删除文本,则他们将无法离开该字段,直到他们输入内容为止。每当他们试图离开该字段时它们都是空白的,他们会收到此错误:

您尝试将Null值分配给不是Variant数据类型的变量。

这是一个非常可怕的错误消息 - 即使对于开发人员来说,更不用说可怜的用户了。幸运的是,我可以将其静音或用更好的消息替换它,并使用以下代码:

Private Sub Form_Error(DataErr As Integer, Response As Integer)
    If DataErr = 3162 Then
        Response = acDataErrContinue
        <check which field is blank>
        MsgBox "<some useful message>"
    End If
End Sub

但这只是部分修复。为什么用户不能离开现场?没有像样的现代用户界面那样限制焦点(想想网站,手机应用程序,桌面程序 - 任何东西,真的)。我们如何绕过必要字段来解决Access的这种行为?

我将发布我找到的两个解决方法作为答案,但我希望有更好的方法让我忽略。

sql-server vba ms-access access-vba
3个回答
0
投票

而不是更改后端表定义或尝试使用不同步链接表定义“欺骗”Access,而只是将任何“NOT NULL”列的控件从绑定字段更改为未绑定字段(即清除ControlSource)属性并更改控件名称 - 例如通过添加前缀 - 以避免与基础字段名称发生恼人的冲突。)。

这个解决方案肯定不会那么“脆弱”,但它需要您手动将绑定代码添加到许多其他Form事件中。为了提供与其他Access控件和表单一致的体验,我至少会实现Form_AfterInsert(), Form_AfterUpdate(), Form_BeforeInsert(), Form_BeforeUpdate(), Form_Current(), Form_Error(), Form_Undo()


附:虽然我不记得之前看到这样一个措辞不好的错误消息,但对于具有Required = True的Access表列,所描述的整体行为是相同的,这是与UI相当于NOT NULL列标准的Access UI。


0
投票

我建议你是否可以简单地更改sql server上的所有表以允许这些文本列的空值。对于位,数字列默认为0 sql server端。虽然我们的行业倾向于建议避免空值,并且许多开发人员也希望避免空值,因此他们取消检查允许空值SQL服务器端。问题是你永远不会逃避并且无论如何都要避免大量的空值。简单查询客户及其最后发票号+发票总额。但当然非常常见的是包括那些没有在该列表中购买任何东西的客户(没有ivoices的客户,或者没有任何可能存在儿童记录的情况的客户。我发现大约80%或者更多我在典型应用程序中的quires是LEFT连接。这意味着任何没有子记录的父记录都将返回所有这些子列为null。你将使用,看看,并且有必要处理吨和吨应用程序中的空值即使您的表设计永远不允许空值。您无法避免它们 - 您根本无法逃避那些讨厌的空值。

因为在代码和任何sql查询(那些非常常见的左连接)中会看到很多空值,所以最好的解决方案是简单地允许并将所有文本列设置为允许空值。我还可以说,如果一个应用程序设计师没有放下脚并做出一个强大的选择,总是使用空值,那么NULLS和ZLS数据的爬行是一个更糟糕的问题需要处理。

如果一个人无法控制或者无法做出这种选择,问题和问题会变得非常令人讨厌和痛苦。

在一天结束时,Access根本无法使用SQL服务器和允许ZLS列的选择。

对于迁移到sql server(并且我已经使用了10年以上),毫无疑问,对于所有文本列来说,null将是迄今为止最简单的选择。

因此,我建议您不要尝试围绕此问题进行编码,而只需将所有sql表更改为默认值,并为空列提供空值。

上面的结果可能需要对应用程序进行一些小的修改,但是在使用SQL服务器时,痛苦和努力将远远小于尝试修复或编码ZLS列的Access不良支持(实际上不支持)。

我还要注意,这个建议并不是一个很好的建议,但考虑到Access如何与SQL服务器一起使用,它只是最好的建议。某些数据库系统(oracle)确实有一个总体设置,即每个null都要转换为ZLS,因此您不必关心这样说:

select * from tblCustomers where (City is null) or (City is = "")

如上所示,您允许ZLS和null进入应用程序的瞬间就是您创建巨大怪物混乱的SAME瞬间。关于无效未定义的学术辩论仅仅是另一天的辩论。

如果您正在使用Access + SQL服务器进行开发,那么需要采用标准方法 - 我建议该方法只是将所有文本列设置为允许空值和日期列。对于数字和位列,将它们默认为0。

这归结为减少痛苦和工作。要么对应用程序进行一些MAJOR修改,要么说取消绑定文本列(这可能是一项大量的工作)。

要么

只需假设并设置所有文本列以允许空值。在这种情况下,它是邪恶的出租人,并且必须符合已交给你的工具包。

所以我没有解决方法,但只有一条路径和路线可以带来最少量的工作和痛苦。最痛苦的道路是允许空值。如果可以做出选择,这个建议当然只会起作用。


-1
投票

我提出的两个解决方法是:

  1. 不要使数据库列NOT NULL完全依赖Access表单来保证数据完整性而不是数据库。该表的读者将承担一个模糊的列,在实践中不会包含空值(只要表单验证代码是合理的)但理论上可能由于列在数据库中的定义方式而包含空值。没有100%的保证是麻烦的,但在现实中可能已经足够好了。 判决:简单但草率 - 谨慎行事
  2. 滥用必须手动刷新Access的外部表链接这一事实。在SQL Server中创建列NULL,刷新Access中的链接,然后在SQL Server中再次创建列NOT NULL - 但这次不要刷新Access中的链接。 结果是Access不会意识到该字段是NOT NULL,因此将使用户独自。他们可以根据需要在表格上移动,而不会得到神秘的错误3162或限制他们的焦点。如果他们在字段仍为空白时尝试保存表单,则会从底层数据库中获取ODBC错误。虽然这是不可取的,但可以通过检查Form_BeforeUpdate()中的空白字段并向用户提供可理解的错误消息来避免这种情况。 判决:更好的数据完整性,但更难以维护,有点hacky /惊人和脆弱,如果有人刷新表链接,可怕的错误/焦点限制将返回 - 然后再次,最糟糕的情况是灾难性的,因为结果只是用户烦恼,而不是数据完整性问题或应用程序中断
© www.soinside.com 2019 - 2024. All rights reserved.