MS Access指定链接表的表插入顺序? (NULL外键错误)

时间:2010-11-10 16:41:30

标签: sql-server ms-access

短版

是否有办法强制(或提示)Microsoft Access以特定顺序(表之间)执行插入(通过可更新查询),或告诉它查询中的一列依赖于(该查询中另一列的自动生成值?

更长的版本

当我通过表单将值插入到可更新的查询中时,该查询跨越2个连接表(两者都是MS SQL Server上的链接表),我收到以下错误:

ODBC - 呼叫失败。

[Microsoft] [ODBC SQL Server驱动程序] [SQL Server]无法将值NULL插入列< fk column>',table'< tablename>';列不允许空值。 INSERT失败(#515)[Microsoft] [ODBC SQL Server驱动程序] [SQL Server]该语句已终止。 (#3612)

这是因为Access无法识别第二个表的fk列应该与查询中第一个表的pk列具有相同的值(或者没有成功执行查询,因此会发生这种情况)。

在通过Microsoft SQL Server ODBC连接器连接到MS SQL Server 2005(Express或Workgroup)的Access 2000,2003,2007上观察到此行为。

在家里玩

对于那些想在家里玩这个游戏的人来说,这里是如何重现我所描述的行为。首先,在SQL Server中创建测试表:

CREATE TABLE People
(
    PersonID INT IDENTITY NOT NULL
        CONSTRAINT PK_People PRIMARY KEY,
    FullName NVARCHAR(100) NOT NULL
);
CREATE TABLE Gamers
(
    PersonID INT NOT NULL
        CONSTRAINT PK_Gamers PRIMARY KEY
        CONSTRAINT FK_Gamers_People REFERENCES People (PersonID)
            ON DELETE CASCADE
            ON UPDATE CASCADE,
    Alias NVARCHAR(100) NOT NULL
);

然后,创建一个新的空白Access数据库并创建引用上面创建的表的新链接表。在Relationships编辑器中创建表之间的关系(Access将正确地确定它是一对一的关系)。然后创建以下查询:

SELECT People.PersonID AS People_PersonID, People.FullName,
    Gamers.PersonID AS Gamers_PersonID, Gamers.Alias
FROM People
    INNER JOIN Gamers ON People.PersonID = Gamers.PersonID;

请注意,上述查询 可以正常插入数据集视图(当然,只要输入FullName)。

然后,创建一个表单,将RecordSource设置为上面的查询。为FullName和Alias创建文本框。然后切换到窗体视图并尝试插入数据。运气好的话,你会看到上面引用的错误信息。

可能的解决方法

解决此问题的一种方法是为子表中的数据创建子表单。通过合适的边框和着色,它对用户几乎是透明的。但是,这有一些问题。首先,必须添加额外的代码以防止在父表单完成之前输入子表单(否则Access将向用户提供关于主/子链接字段的密集错误)。此外,用户无法对子窗体中的任何字段进行排序/过滤,因为它只会过滤子窗体记录(其中总是只有一个)。话虽如此,这是我现在使用的解决方案。

我希望你们中的一个人知道更好的解决方案。谢谢你的阅读。

3 个答案:

答案 0 :(得分:1)

您可以使用:

Private Sub FullName_AfterUpdate()
If Me.Dirty Then Me.Dirty = False

End Sub

这将强制创建人物记录。

答案 1 :(得分:1)

虽然Remou提供的解决方案确实有效,但我目前使用的解决方案有点不同。它不一定更好或更坏,这个解决方案与Remou提出的解决方案之间的选择取决于具体情况。

我在SQL Server上创建了一个可更新视图(使用INSTEAD OF触发器),它提供了与Access中的查询相同的数据。接下来,我在Access中创建了一个链接表,它引用了视图,然后修改了表单以使用该视图而不是查询。简单,对吧?

棘手的部分是在更改连接字符串时维护伪索引(我经常这样做),因为我不想在SQL Server中的视图上创建索引(因为基础表中的数据经常更新)和Access只能插入/更新带索引的表。解决方案是在更改连接字符串后重新创建索引。 (有关该特定问题的更多信息,请参阅my writeup

答案 2 :(得分:0)

您是否尝试在MSAccess数据库中的表之间绘制关系?我认为它会让你这样做,这样MSAccess就会'知道'执行插入的顺序。