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

问题描述 投票:2回答:6

我写了这个查询:

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中运行相同的查询,它将被执行。

谢谢,dinesh

ms-access vba access-vba jet
6个回答
2
投票

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

作为测试,您可能还尝试删除在两个子查询中执行的计算(减法)。此计算也可能无法与更新很好地协作。


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表中只有一个匹配的行。结果是Categories表与CategoryID现在有'......或者这个?'值。我怀疑最后看到哪个值被写入表中是一场竞赛。

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


1
投票

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


0
投票

您正在更新weight1qty1,其值依次来自weight1qty1(分别)。这就是为什么MS-Access对更新感到窒息的原因。它可能也在后台进行一些优化。

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


0
投票

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

  • 请检查您是否已授予MS-Access数据库文件的读写权限。
  • 存储它的数据库文件(例如在Folder1中)是只读的。?

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


-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.