Проблемы с обновлением SQL в MS Access - Операция должна использовать обновляемый запрос - PullRequest
15 голосов
/ 11 февраля 2009

У меня есть запрос на выборку, который выполняет некоторые манипуляции с текстом, чтобы по существу переформатировать поле, чтобы я мог найти его в другой таблице:

Если в моей первой таблице, если у меня есть поле типа "J1 / 2", он ищет идентификатор записи в другой таблице с J1 и J2 в соответствующих полях.

Это все хорошо работает.

Теперь я хочу обновить исходную таблицу, чтобы мне больше не приходилось выполнять поиск с использованием этой строковой манипуляции, но мои попытки обновить запросы заканчиваются словами «Операция должна использовать обновляемый запрос»

Есть идеи?

Мой оператор SELECT:

SELECT DISTINCT
t1.DD,
t1.TN,
t1.DD & " J" & MID(t1.TN,2,1) AS CalculatedStart,
t1.DD & " J" & MID(t1.TN,4,1) AS CalculatedEnd,
t2.ID
FROM t1 INNER JOIN t2
ON (t1.DD & " J" & MID(t1.TN,2,1)=t2.StartLink)
AND (t1.DD & " J" & MID(t1.TN,4,1)=t2.EndLink)
WHERE t1.TN Like "J?/?"
AND t1.DD Like "M*";

Напомним - это работает нормально, и я получаю необходимый t2.ID на другом конце.

Итак, я хочу сделать что-то вроде:

UPDATE t1 SET t2ID = (
    SELECT Query1.ID
    FROM Query1
    WHERE t1.DD=Query1.DD
    AND t1.TN=Query1.TN
    )
WHERE t1.TN Like "J?/?"
AND t1.DD Like "M*";

Только это не удалось. Это происходит внутри самого MS Access, поэтому я не могу представить себе фактическую проблему с разрешениями, как кажется, что большинство проблем «Операция должна использовать обновляемый запрос».

РЕДАКТИРОВАТЬ: Попытка упростить случай, который не работает.

Этот запрос ОБНОВЛЕНИЯ в порядке:

UPDATE t1
SET t2ID="Unknown"
WHERE TN LIKE "J?/?"
AND DD LIKE "M*";

Этот сбой (Спасибо Гедке - этот пример, очевидно, дает сбой, потому что подзапрос возвращает более 1 результата. Я упростил попытку найти мою проблему)

UPDATE t1
SET t2ID=(SELECT ID FROM t2)
WHERE TN LIKE "J?/?"
AND DD LIKE "M*";

Так у меня какой-то неправильный синтаксис подзапроса?

РЕДАКТИРОВАТЬ: Этот оператор SELECT тоже хорошо:

SELECT t1.OA, t1.DD, t1.TN, t1.HATRIS,
    query1.DD, query1.TN, query1.ID
FROM t1 INNER JOIN query1
ON t1.DD=query1.DD
AND t1.TN=query1.TN

Кроме того, использование счетчика в приведенном выше операторе выбора показывает, что для каждой комбинации (DD, TN) возвращается ровно 1 идентификатор

EDIT:

Простейший случай, который я сейчас получил - используя различные операторы SELECT, у меня теперь есть таблица с двумя столбцами - первичный ключ t1 и значение, которое я хочу вставить в t1.

Я все еще не могу написать

UPDATE t1 SET t1.f2 = (SELECT t2.f2 FROM t2 WHERE t2.f1 = t1.f1)

где первичным ключом t1 является f1. Даже добавление WHERE t1.f1 IN (SELECT f1 FROM t2) не помогает. (Добавлено, чтобы исключить возможность того, что подзапрос возвращает 0 результатов)

Ответы [ 7 ]

17 голосов
/ 11 ноября 2009

Я должен взвесить комментарий Дэвида У. Фентона к ОП.

Это очень раздражающая проблема с Jet / ACE. Но попробуйте либо:

  1. перейти к свойствам запроса (нажмите фон панели, где таблицы отображаются) и установить «Уникальные записи» на «Да»
  2. Вариант 1 является эквивалентом добавления несколько странно выглядящий DISTINCTROW ключевое слово для SELECT пункт, например

UPDATE DISTINCTROW tblClient 
       INNER JOIN qryICMSClientCMFinite 
          ON tblClient.ClientID = qryICMSClientCMFinite.ClientID
   SET tblClient.ClientCMType = "F";

Это решает так много проблем, связанных с этим сообщением об ошибке, что оно почти смешно.

Это MS Access в двух словах - если вы не знаете секретный обходной путь для проблемы x, вы можете потратить несколько дней, чтобы найти ответ. Знать 10000 обходных путей для программы Access. Достаточно ли этого предупреждения для непосвященных?

Ben

7 голосов
/ 10 декабря 2009

Это сработало для меня (Access 2000)

UPDATE DISTINCTROW T1 inner join T2 on T2.f1 = T1.f1  SET f2 = f2;
6 голосов
/ 04 ноября 2009

Я не прочитал всю ветку, но это решение, которое я использую:

update (select * from t1 inner join t2 on t1.key = t2.key) set t1.field1 = t2.field2

и это прекрасно работает в MS Access для меня.

6 голосов
/ 11 февраля 2009

Подзапрос (SELECT ID FROM t2) не может работать, если в t2 только одна запись. Какой идентификатор вы ожидаете использовать?

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

Тот факт, что вы используете DISTINCT, может вызвать у меня подозрение, что подзапрос возвращает более одной строки в вашем более сложном примере. Это, вероятно, самая распространенная проблема с присваиванием результата подзапроса: недопустимое условие where.

Другая проблема, с которой я столкнулся при назначении из подзапроса, - это неправильный синтаксис внутреннего запроса *1007*. По крайней мере, с SQL 2000 и 2005 сервер обработки запросов молча завершится с ошибкой и в таких случаях вернет NULL. (Насколько я могу судить, это ошибка: я не вижу причины, по которой что-то, что будет возвращать ошибку на верхнем уровне, было бы молча разрешено в подзапросе ... но это так.)

EDIT: Просто для того, чтобы ни мы с Полом не сходили с ума, я создал следующие таблицы:

t1 | ID, FK, Data
t2 | ID2, Data2

Я не наложил какие-либо ограничения, кроме первичного ключа на ID и ID2. Все поля были текстовыми, что отличается от того, что я обычно использую для идентификаторов, но не должно иметь значения.

t1:

ID  FK  Data
Key1        Data1
Key2        Data2
Key3        Data3

t2:

ID2 Data2
Key1    DataA
Key2    DataB
Key3    DataC

Запрос вида:

UPDATE t1 SET t1.FK = (select ID2 from t2 where t2.ID2 = t1.ID);

Не удалось с тем же сообщением, которое получил Павел.

select *, (select ID2 from t2 where t2.ID2 = t1.ID) as foreign from t1, 

работает как положено, поэтому мы знаем, что синтаксис подзапроса не виноват.

UPDATE t1 SET t1.FK = 'Key1'

также работает как положено, поэтому у нас нет поврежденного или не обновляемого места назначения.

Примечание: если я изменю бэкэнд базы данных с нативного на SQL 2005, обновление будет работать! Немного погуглил, и я обнаружил, что Access MVP предлагают DLOOKUP заменить подзапрос:

http://www.eggheadcafe.com/software/aspnet/31849054/update-with-subquerycomp.aspx

Очевидно, что это ошибка в Access SQL, которую следует избегать при использовании SQL Express 2000 или более поздней версии. (Результаты Google по запросу «Access update subquery» подтверждают эту теорию).

См. Здесь, как использовать этот обходной путь: http://www.techonthenet.com/access/functions/domain/dlookup.php

1 голос
/ 25 июня 2014

У меня была та же ошибка («Операция должна использовать обновляемый запрос») при использовании Access 2010, и я выполнял простой запрос на обновление с внутренним объединением. Все, что я делал, это добавлял первичный ключ к таблице, к которой я присоединялся (у меня уже был один, конечно, к таблице, которую я обновлял), и все работало.

1 голос
/ 04 марта 2010

Мое решение было изменить мой sql таким образом.

  update (select o.pricein, g.pricein from operations o left join goods g on g.id = o.goodid where o.opertype = 4 and o.acct = 1) 
  set o.pricein = g.pricein
0 голосов
/ 12 февраля 2009

Для этого: ОБНОВЛЕНИЕ t1 SET t1.f2 = (ВЫБЕРИТЕ t2.f2 ОТ t2, ГДЕ t2.f1 = t1.f1)

UPDATE t1 INNER JOIN t2 ON t1.f1 = t2.f1 SET t1.f2 = [t2].[f2];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...