代码之家  ›  专栏  ›  技术社区  ›  MarredCheese Lionia Vasilev

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

  •  1
  • MarredCheese Lionia Vasilev  · 技术社区  · 6 年前

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

    如果需要某个列,那么自然要包括 NOT NULL 在该列的定义中(在数据库级别)。但这似乎给访问端带来了问题。当您将表单绑定到该表时,绑定到该列的字段最终会变得非常不友好。如果用户从该字段中删除文本,则在输入内容之前,他们将无法离开该字段。每次他们试图在字段为空时离开该字段时,都会出现以下错误:

    试图将空值赋给不是变量数据类型的变量。

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

    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
    

    但那只是部分修复。为什么用户不能离开字段?没有一个像样的现代用户界面能像这样限制人们的注意力(想想网站、手机应用程序、桌面程序——任何东西,真的)。我们如何才能绕过这种访问所需字段的行为?

    我会把我找到的两个解决方法作为答案,但我希望有更好的方法,我忽略了。

    1 回复  |  直到 6 年前
        1
  •  0
  •   C Perkins    6 年前

    与其更改后端表定义或试图用不同步的链接表定义“欺骗”访问,不如更改任何“not null”列的控件 从绑定到未绑定字段 (即 清除 ControlSource 财产 并更改控件名(例如,通过添加前缀)以避免与基础字段名发生恼人的冲突。)

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


    p.s.虽然我不记得以前看到过这样一个措辞糟糕的错误消息,但是对于一个带有 Required = True ,这是与 NOT NULL 列条件。

        2
  •  0
  •   Albert D. Kallal    6 年前

    我建议您可以简单地更改sql server上的所有表,以允许这些文本列为空。对于位,数字列将它们默认为0 SQL Server端。虽然我们的行业倾向于建议避免空值,而且许多开发人员也希望避免空值,因此他们取消了对允许空值的sql server端的检查。问题是无论如何你都不能逃避和避免成吨的零。简单地查询一下所说的客户及其最后一个发票号码+发票总额。当然,很常见的情况是,将那些没有购买任何东西的客户(还没有试管婴儿的客户,或是那些没有孩子记录的大量可能病例的客户)包括在内。我发现在一个典型的应用程序中,大约80%或更多的需求是左连接。因此,这意味着没有子记录的任何父记录都将以空值返回所有这些子列。即使表设计不允许空值,也要处理应用程序中的大量空值。你无法避免它们-你只是无法逃避那些讨厌的零。

    因为在代码和任何sql查询(那些非常常见的左连接)中都会看到大量的空值,所以最好的解决方案就是简单地允许并设置所有文本列为允许空值。我还可以说,如果一个应用程序设计者没有下定决心,做出一个总是使用nulls的强有力的选择,那么nulls和zls数据的潜入将是一个更糟糕的问题。

    如果一个人不能控制或者不能做出这样的选择,那么这个问题就会变得非常棘手和痛苦。

    归根结底,access根本不适用于sql server和允许zls列的选择。

    对于迁移到sql server(我已经做了10多年了),毫无疑问,对所有文本列使用nulls是目前最容易的选择。

    因此,我建议您不要试图围绕这个问题编写代码,而只需将所有SQL表更改为默认值,并允许空列为空。

    上面的结果可能需要对应用程序进行一些小的修改,但是在使用SQL Server时,要解决ZLS列访问不良(实际上不支持)的问题,所付出的代价和精力将远远小于尝试修复或编写代码。

    我还将注意到,这一建议并不是一个很好的建议,但考虑到access如何与sql server一起工作的限制,这只是一个最好的建议。一些数据库系统(Oracle)确实有一个总体设置,即每个空值都要转换为ZLS,因此您不必在意这样说:

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

    如上所示,允许zls和nulls同时进入应用程序的那一刻,就是您创建了一个巨大的怪物混乱的那一刻。而学术界关于未定义零的争论仅仅是另一天的争论。

    如果您使用access+sql server进行开发,那么需要采用一种标准的方法-我建议这种方法只是将所有文本列设置为允许空值和日期列。对于数字和位列,将其默认为0。

    这就意味着更少的痛苦和工作。 或者对应用程序进行一些重大修改,比如取消绑定文本列(这可能是一项巨大的工作)。

    只需假设并设置所有文本列允许为空。在这种情况下,它是一个邪恶的出租人,一个人必须遵守已经交给你的工具袋。

    所以我没有办法,但只有一条路和一条路可以走,这将导致最少的工作量和痛苦。最不痛苦的道路是允许零。这项建议当然只有在人们可以作出选择的情况下才能奏效。

        3
  •  -1
  •   MarredCheese Lionia Vasilev    6 年前

    我想出的两个解决办法是:

    1. 不生成数据库列 NOT NULL 并且只依赖访问表单来获得数据完整性,而不是数据库。该表的读取器将被一个不明确的列所负担,该列实际上不包含空值(只要表单验证代码是正确的),但由于在数据库中定义列的方式,理论上可能包含空值。没有100%的保证是很麻烦的,但在现实中可能已经足够好了。

      判决 :简单但草率-小心行事

    2. 滥用访问外部表的链接必须手动刷新的事实。列 NULL 在SQL Server中,刷新Access中的链接,然后使列 非空 同样在sql server中-但是这次,不要刷新access中的链接。

      结果是access没有意识到 非空 因此,会让用户一个人呆着。他们可以根据需要移动表单,而不会出现神秘的错误3162或焦点受到限制。如果他们试图在字段仍然为空的情况下保存表单,他们将从基础数据库中得到一个odbc错误。虽然这不可取,但是可以通过检查 Form_BeforeUpdate() 并为用户提供可理解的错误消息。

      判决 :对于数据完整性更好,但维护起来也更麻烦,有点老套/令人吃惊,而且很脆弱,如果有人刷新表链接,可怕的错误/焦点限制将返回-然后,最坏的情况并不是灾难性的,因为后果仅仅是用户annOyance,不是数据完整性问题或应用程序中断

    推荐文章