#sql #h2
#sql #h2
Вопрос:
Описание
Я пытаюсь сделать что-то вроде:
DELETE FROM ...
-- `<my_id>` is any given long scalar value
WHERE <my_id> = (SELECT id FROM ... WHERE ...);
Этот синтаксис не совсем корректен. Если подзапрос select содержит более одной строки, то мы получаем ошибку типа:
Скалярный подзапрос содержит более одной строки
Однако моя предполагаемая цель действительно:
- если подзапрос возвращает ровно 1 значение, равное скалярному значению (
<my_id>
) ==> удалить - остальное (0, или 2 или более значений, или 1 неравное значение) ==> не удалять (игнорировать)
Вопрос
Я не хочу ни IN
того, ни EXISTS
другого. Мне нужно что-то вроде «equals», которое может сравнивать скалярное значение с возможно многозначными строками.
Какой синтаксис в SQL для этого?
Стек
В частности, я тестирую это с помощью H2.
Комментарии:
1. Я удалил несовместимые теги базы данных. Пожалуйста, помечайте только ту базу данных, которую вы действительно используете.
2. Спасибо, Гордон 👍
Ответ №1:
Один из методов:
DELETE FROM ...
WHERE <my_id> IN (SELECT id FROM ... WHERE ...) AND
(SELECT COUNT(*) FROM . . . WHERE . . .) = 1;
Однако это проще записать как:
DELETE FROM ...
WHERE <my_id> = (SELECT MAX(id)
FROM . . .
WHERE . .
HAVING COUNT(*) = 1
) ;
Если счетчик не 1
равен, то подзапрос ничего не возвращает и совпадения нет (поэтому ничего не удаляется).
Комментарии:
1. Спасибо, Гордон!
HAVING
В моем словаре SQL не хватало. Поскольку мы проверяем, что у нас есть только одна строка сHAVING COUNT(*) = 1
, я думаю, использованиеMAX
— это просто своего рода трюк. Нам просто нужна некоторая функция агрегирования, и, напримерMIN
, в этом случае она будет работать точно так же, какMAX
… верно?2. @juanmirocks . . . Точно. Если имеется одна строка, то
MIN()
иMAX()
возвращает то же значение.