操作必须使用可更新的查询。 (错误3073)Microsoft Access

时间:2009-08-05 05:30:15

标签: ms-access vba access-vba jet

我写了这个查询:

UPDATE tbl_stock1 SET 
tbl_stock1.weight1 = (
    select (b.weight1 - c.weight_in_gram) as temp 
    from
        tbl_stock1 as b,
        tbl_sales_item as c 
    where
        b.item_submodel_id = c.item_submodel_id 
        and b.item_submodel_id = tbl_stock1.item_submodel_id 
        and b.status <> 'D' 
        and c.status <> 'D'
    ), 
tbl_stock1.qty1 = (
    select (b.qty1 - c.qty) as temp1 
    from
        tbl_stock1 as b,
        tbl_sales_item as c 
    where 
        b.item_submodel_id = c.item_submodel_id 
        and b.item_submodel_id = tbl_stock1.item_submodel_id 
        and b.status <> 'D' 
        and c.status <> 'D'
    )
WHERE
    tbl_stock1.item_submodel_id = 'ISUBM/1' 
    and tbl_stock1.status <> 'D';

我收到此错误消息:

Operation must use an updatable query. (Error 3073) Microsoft Access

但如果我在SQL Server中运行相同的查询,它将被执行。

谢谢, 迪内希

6 个答案:

答案 0 :(得分:2)

我非常确定JET数据库引擎将子查询视为不可更新的任何查询。这很可能是错误的原因,因此,您需要重新编写逻辑并避免子查询。

作为测试,您可能还会尝试删除在两个子查询中执行的计算(减法)。这个计算也可能不适合更新。

答案 1 :(得分:2)

使用Northwind考虑这个非常简单的UPDATE语句:

UPDATE Categories
   SET Description = (
                      SELECT DISTINCT 'Anything' 
                        FROM Employees
                     );

失败并显示错误'操作必须使用可更新的查询'。

Access数据库引擎simple不支持使用SET子句中的标量子查询的SQL-92语法。

Access数据库引擎具有自己的专有UPDATE..JOIN..SET语法但不安全,因为与标量子查询不同,它不需要值明确。如果值不明确,则引擎静默“随意”选择一个,即使您意识到问题,也很难(如果不是不可能的话)预测将应用哪一个。

例如,考虑Northwind中现有的Categories表和下面的daft(非)表作为更新的目标(愚蠢但很容易清楚地证明问题):

CREATE TABLE BadCategories
(
 CategoryID INTEGER NOT NULL, 
 CategoryName NVARCHAR(15) NOT NULL
)
;
INSERT INTO BadCategories (CategoryID, CategoryName) 
   VALUES (1, 'This one...?')
;
INSERT INTO BadCategories (CategoryID, CategoryName) 
   VALUES (1, '...or this one?')
;

现在为UPDATE

UPDATE Categories 
       INNER JOIN (
                   SELECT T1.CategoryID, T1.CategoryName
                     FROM Categories AS T1
                   UNION ALL 
                   SELECT 9 - T2.CategoryID, T2.CategoryName
                     FROM Categories AS T2
                  ) AS DT1
       ON DT1.CategoryID = Categories.CategoryID
   SET Categories.CategoryName = DT1.CategoryName;

当我运行这个时,我被告知已经更新了两行,这很有趣,因为在Categories表中只有一个匹配的行。结果是CategoriesCategoryID现在有'...或者这个?'值。我怀疑最近看到​​哪个值被写入表中是一场竞赛。

SET中有多个子句和/或WHERE子句与SET的子句匹配时,SQL-92标量子查询是详细的,但至少它消除了歧义(加上一个不错的优化器)应该能够检测到子查询是否匹配)。 SQL-99标准引入了MERGE,它可用于消除上述重复,但不用说Access也不支持。

Access数据库引擎缺乏对SQL-92标量子查询语法的支持对我来说是最糟糕的“设计特性”(读作“bug”)。

另请注意,Access数据库引擎的专有UPDATE..JOIN..SET语法无论如何都不能与set函数一起使用(Access-speak中的'totals queries')。请参阅Update Query Based on Totals Query Fails

答案 2 :(得分:1)

请记住,如果您复制最初在查询中包含查询或摘要查询的查询,即使您删除了这些查询并且只有链接表,查询也会(错误地)表现得像它仍然具有非-updateable字段,会给你这个错误。您只需根据需要重新创建查询,但这是一个阴险的小故障。

答案 3 :(得分:0)

您正在使用weight1qty1(分别)派生的值更新weight1qty1。这就是为什么MS-Access对更新感到窒息的原因。它可能也在后台做了一些优化。

我解决这个问题的方法是将计算转储到临时表中,然后从临时表中更新第一个表。

答案 4 :(得分:0)

代码中没有错误。但由于以下原因,错误被抛出。

  • 请检查您对MS-Access数据库文件具有读写权限的天气。
  • 存储它的数据库文件(比如在Folder1中)是只读的。?

假设您将数据库(MS-Access文件)存储在只读文件夹中,而在运行应用程序时,连接不会强制完全打开。因此,更改文件权限/其包含文件夹权限,如C:\Program files所有所有c驱动器文件都设置为只读,因此更改此权限可解决此问题。

答案 5 :(得分:-1)

在查询属性中,尝试将Recordset类型更改为动态集(不一致的更新)