【问题标题】:Operation must use an updatable query. (Error 3073)操作必须使用可更新的查询。 (错误 3073)
【发布时间】:2009-08-05 05:30:15
【问题描述】:

我已经写了这个查询:

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

谢谢, 吃饭

【问题讨论】:

    标签: vba ms-access jet


    【解决方案1】:

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

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

    【讨论】:

    • 取决于子查询。 WHERE 子句中的子查询没有这种效果。 FROM 中的子查询可能会也可能不会,这取决于各种问题。主要问题是 Jet/ACE 是否可以解析关系类型,以便明确告知要更新哪条记录。如果您在 Access 本身中运行 SQL,要尝试的一件事是 DISTINCTROW 谓词,它有时可以使不可更新的查询可更新。
    • “主要问题是 Jet/ACE 是否可以解析关系类型,以便明确告知要更新哪条记录”——嗯,Access 数据库引擎的 UPDATE..JOIN 语法不'不需要明确的值:事实上,如果它确实产生了不明确的值,它会默默地任意选择一个,并且很难预测会选择哪一个(我怀疑我们以前最喜欢的关于 PK 和磁盘上的集群)。在 UPDATE SET 子句中缺乏对标量子查询的支持是 IMO Access 数据库引擎最糟糕的“设计功能”(阅读“错误”)。
    【解决方案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;
    

    当我运行它时,我被告知有两行已更新,这很有趣,因为类别表中只有一个匹配的行。结果是带有CategoryIDCategories 表现在具有“...还是这个?”价值。我怀疑这是一场竞赛,看哪个值最后写入表中。

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

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

    另请注意,Access 数据库引擎的专有 UPDATE..JOIN..SET 语法无论如何都不能用于集合函数(Access 中的“总计查询”)。见Update Query Based on Totals Query Fails

    【讨论】:

    • 虽然这一切都很有趣,但这并不是解决问题的方法,其中有很多。每个数据库引擎都有这样的情况,即理论上应该可更新的语句是不可更新的,所以你对 Jet/ACE SQL 方言的这种已知和记录的行为进行如此大的宣传真是太无礼了。
    • @David-W-Fenton:我认为您确实知道我对“Access 甚至无法执行 SQL-92 UPDATE 问题”的解决方案是 ;)
    • @David-W-Fenton:“每个数据库引擎都有应该在理论上可更新的 [视图] 案例”——我今天想起了 1693 年的一句名言:“奥蒙德公爵昨天查看了他的部队,并命令所有拥有海湾或灰色马的人将它们换成黑色”,这被认为是已知最早的视图更新示例;)
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      您正在更新 weight1qty1 的值,而这些值又派生自 weight1qty1(分别)。这就是为什么 MS-Access 对更新感到窒息。它可能还在后台进行了一些优化。

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

      【讨论】:

      • -1 Access 数据库引擎根本不支持 SQL-92 的“标量子查询”语法。
      • 为什么缺乏 Jet/ACE 证明不赞成这个答案,事实上,这是一个可行的问题解决方案?在我看来,你的问题在于 Jet/ACE,而不是这个答案。
      【解决方案5】:

      代码中没有错误。但是由于以下原因引发了错误。

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

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

      【讨论】:

        【解决方案6】:

        在查询属性中,尝试将 Recordset Type 更改为 Dynaset (Inconsistent Updates)

        【讨论】:

        • -1 Access 数据库引擎根本不支持 SQL-92 的“标量子查询”语法。
        • @onedaywhen:当您实际上是要对 Jet/ACE 投反对票时,为什么还要对答案投反对票?
        • @David-W-Fenton:问题本质上是“为什么我的 SQL Server 查询不能在 Access(ACE、Jet 等)中运行?”更改记录集类型完全没有抓住重点,因此投反对票。至于否决 Jet/ACE,要是这么简单就好了;它需要大约十年的时间每天通知人们它的许多缺陷,我坚持我的断言,“Access 数据库引擎缺乏对 SQL-92 标量子查询语法的支持对我来说是它最糟糕的‘设计特性’(阅读‘bug ')。”
        猜你喜欢
        • 2010-09-15
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 2015-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多