Вставить оператор с NOT IN подзапросом - PullRequest
0 голосов
/ 10 ноября 2011

Я пытаюсь обновить строку, если она существует, в противном случае вставить (при обновлении дубликата ключа) в MS Access, с ответом на этот вопрос Запрос доступа к SQL - Обновить строку, если существует, вставить, если не

Мой запрос на вставку имеет вид:

INSERT INTO mytbl(id, title, notes) 
(SELECT 10, 'test', 'a'
From mytbl
WHERE 10 Not IN (select id from mytbl)
)

Но я получаю ошибку синтаксиса SQL. Что мне здесь не хватает?

Ответы [ 4 ]

2 голосов
/ 10 ноября 2011

Вам не нужны круглые скобки снаружи SELECT:

INSERT INTO mytbl(id, title, notes) 
SELECT TOP 1 10, 'test', 'a'
FROM DummyTableWithExactlyOneRecord
WHERE 10 Not IN (select id from mytbl)

Для обработки ошибки дублирующего ключа я добавил предложение TOP 1.

То, как ваш запрос был изначально написан, если 10 не является идентификатором в mytbl, то часть запроса SELECT будет возвращать запись для каждой существующей строки в mytbl. Поскольку вы не ссылаетесь ни на какие поля в таблице, все они будут одинаковыми строками. Например, если бы в mytbl было четыре строки, вы бы получили:

10    test    a
10    test    a
10    test    a
10    test    a

Затем он попытается выполнить вставку для каждой из этих возвращаемых строк. Первый будет успешным, а остальные потерпят неудачу с ошибкой дубликата ключа. Предложение TOP 1 говорит, что просто используйте запись TOP 1. Порядок не имеет значения в этом случае. Поскольку все ваши поля являются литералами, все строки будут одинаковыми.

Обратите внимание, что вы можете сделать то же самое, заменив DISTINCT на TOP 1. Однако я ожидаю, что производительность будет хуже, если только двигатель БД не будет достаточно умен, чтобы сразу понять, что каждый ряд будет одинаковым.

РЕДАКТИРОВАТЬ : DummyTableWithExactlyOneRecord является локальной таблицей с ровно одной записью. Как отметил @onedaywhen в своем комментарии ниже, если в таблице, из которой ВЫ ВЫБИРАЕТЕСЬ, нет записей вообще, запись не будет вставлена.

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

0 голосов
/ 10 ноября 2011

SQL DDL :

CREATE PROCEDURE AddMyStuff 
(
 :id CHAR(10), 
 :title VARCHAR(15), 
 :notes VARCHAR(100) = '{{NONE}}'
)
AS
INSERT INTO mytbl (id, title, notes) 
SELECT :id, :title, :notes
  FROM MySystemTableAlwaysHasExactlyOneRow
 WHERE :id NOT IN (SELECT id FROM mytbl);

SQL DML :

EXECUTE AddMyStuff 10, 'test', 'a';
0 голосов
/ 10 ноября 2011

Что интригует здесь, так это то, что вы пытаетесь вставить постоянные значения в таблицу, в то же время проверяя УНИКАЛЬНЫЙ ИНДЕКС (или PK) еще не существует.Таким образом, ваше предложение WHERE должно быть структурировано таким образом, чтобы оно приводило к условию FALSE и, следовательно, не создавало строку для вставки.

Рассматривали ли вы следующий SQL:

INSERT INTO mytbl(id, title, notes) 
SELECT 10, 'test', 'a'
From mytbl
WHERE id NOT IN (SELECT id FROM mytbl WHERE id = 10)

Обычно константные значения вставляются с использованием:

INSERT INTO mytbl(id, title, notes) VALUES (10, 'test', 'a');

Если это псевдо-код для заполнения формытаблица с пропуском SQL или что-то в этом роде, может быть проще просто перехватить код ошибки для нарушения PK и сообщить об ошибке пользователю.

Надеюсь, это поможет.

0 голосов
/ 10 ноября 2011

Полагаю, вы ищете ID, а не 10

попробуйте это

WHERE id NOT IN (SELECT id FROM mytbl)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...