Операция должна использовать обновляемый запрос. (Ошибка 3073) Microsoft Access - PullRequest
2 голосов
/ 05 августа 2009

Я написал этот запрос:

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 ]

2 голосов
/ 06 августа 2009

Рассмотрим этот очень простой оператор UPDATE, используя Northwind:

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

Сбой при ошибке «Операция должна использовать обновляемый запрос».

Простой движок базы данных Access не поддерживает синтаксис SQL-92 с использованием скалярного подзапроса в предложении SET.

Механизм базы данных Access имеет собственный проприетарный синтаксис UPDATE..JOIN..SET, но небезопасен, потому что, в отличие от скалярного подзапроса, он не требует однозначных значений. Если значения неоднозначны, то движок беззвучно «выбирает» один из них, и трудно (если не невозможно) предсказать, какое из них будет применено, даже если вы знали о проблеме.

Например, рассмотрим существующую таблицу Categories в Northwind и следующую таблицу с ошибками (не) в качестве цели для обновления (глупо, но просто, чтобы ясно продемонстрировать проблему):

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 с CategoryID теперь имеет '... или эту?' значение. Я подозреваю, что это была гонка, чтобы увидеть, какое значение записывается в таблицу последним.

Скалярный подзапрос SQL-92 является многословным, когда в SET есть несколько предложений и / или предложение WHERE соответствует предложениям SET, но, по крайней мере, устраняет неоднозначность (плюс приличный оптимизатор должен быть в состоянии обнаруживает, что подзапросы являются близкими совпадениями). В стандарт SQL-99 введено MERGE, которое можно использовать для устранения вышеупомянутого повторения, но само собой разумеется, что Access также не поддерживает это.

Недостаточная поддержка ядром базы данных Access синтаксиса скалярных подзапросов в SQL-92 является для меня худшей «конструктивной особенностью» (читай «ошибка»).

Также обратите внимание, что собственный синтаксис UPDATE..JOIN..SET ядра СУБД Access никоим образом не может использоваться с функциями набора («итоговые запросы» в Access-speak). См. Обновление запроса на основе итоговых ошибок запроса .

2 голосов
/ 05 августа 2009

Я вполне уверен, что JET DB Engine рассматривает любой запрос с подзапросом как необновляемый. Скорее всего, это является причиной ошибки, поэтому вам нужно переработать логику и избежать подзапросов.

В качестве теста вы также можете попытаться удалить вычисление (вычитание), выполняемое в каждом из двух подзапросов. Этот расчет может не очень хорошо играть с обновлением.

1 голос
/ 01 марта 2018

Имейте в виду, что если вы скопируете запрос, в котором изначально были запросы или сводные запросы, как часть запроса, даже если вы удалили эти запросы и имели только связанные таблицы, запрос будет (по ошибке) работать так, как если бы он не Обновление полей и даст вам эту ошибку. Вы просто воссоздаете запрос, как хотите, но это коварный маленький глюк.

0 голосов
/ 06 декабря 2013

В коде нет ошибок. Но ошибка выбрасывается по следующей причине.

  • Проверьте, дали ли вы права на чтение и запись в файл базы данных MS-Access.
  • Файл базы данных, где он хранится (скажем, в папке 1), доступен только для чтения ..?

предположим, что вы храните базу данных (файл MS-Access) в папке, доступной только для чтения, при запуске приложения соединение не открывается принудительно. Следовательно, измените разрешение на файл / содержащую его папку, как в C:\Program files, для всех большинства всех дисков c установлен только для чтения , поэтому изменение этого разрешения решает эту проблему.

0 голосов
/ 05 августа 2009

Вы обновляете weight1 и qty1 значениями, которые, в свою очередь, являются производными от weight1 и qty1 (соответственно). Вот почему MS-Access задыхается от обновления. Возможно, он также выполняет некоторую оптимизацию в фоновом режиме.

Я бы обошел это путем выгрузки вычислений во временную таблицу, а затем обновления первой таблицы из временной таблицы.

0 голосов
/ 05 августа 2009

В свойствах запроса попробуйте изменить тип набора записей на Dynaset (несогласованные обновления)

...