powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Проверить существование записи, если нет то записать.
14 сообщений из 14, страница 1 из 1
Проверить существование записи, если нет то записать.
    #37664531
inexx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем доброго времени суток...
Заранее извиняюсь, возможно это уже неоднократно обсуждалось, но мне к сожалению не удалось найти информации, скорее всего из за пробелов в терминологии и теории SQL я просто не смог правильно задать критерий поиска.
Проблема у меня следующая:
Есть таблица numbers вида:
id as INTEGER | number as TEXT
. 1 89008006050

Не удается организовать в запросе следующую логику:
ДОБАВИТЬ В number ЗНАЧЕНИЕ something, ЕСЛИ НЕ ТАКАЯ ЗАПИСЬ НЕ СУЩЕСТВУЕТ,
(ну и если это возможно реализовать в одном запросе то прикрутить сюда еще:
ИНАЧЕ ВЫБРАТЬ id ЗАПИСИ something)

Сначала я кружился вокруг конструкции IF NOT EXIST но так и не понял как ее можно применить к INSERT, по крайней мере
Код: sql
1.
IF NOT EXIST INSERT INTO numbers (number) VALUES ('something');


или
Код: sql
1.
INSERT IF NOT EXISTS INTO numbers (number) VALUES ('something') IF NOT EXIST ;


возвращают ошибку вида "syntax error"

Где-то даже нашел упоминание WHERE NOT EXIST, мол
Код: sql
1.
INSERT INTO numbers (number) VALUES ('something')  WHERE NOT EXIST ('something') ;


но вроде сам понял что к INSERT неприменимо WHERE в принципе.

Больше вариантов нет.
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37664535
inexx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
оффтоп: а на этом форуме можно редактировать созданные темы?
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37664544
RXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inexx,

Офтоп: нельзя.



Вы бы, чем выдумывать операторы, почитали бы мануал! Он совсем небольшой: http://sqlite.org/lang.html
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37664546
RXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Например, оператор INSERT OR REPLACE и его ипостась - REPLACE.
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37664593
inexx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо за традиционное RTFM! ^__^, я читаю, пробую, и прошу подсказки здесь.
INSERT OR REPLACE опробовано еще в самом начале поисков - "не торт" совсем, вот пример:

id | number
1 89006005040
2 89007006050
3 89008007060

ну и поехали:
Код: sql
1.
INSERT OR REPLACE INTO numbers (sim_number) VALUES ('89008007060');



что имеем на выходе ?
id |number
1 89006005040
2 89007006050
3 89008007060
4 89008007060

ну и толку ?
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37664934
RXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inexx,

Видимо плохо читаете...
http://sqlite.org/lang_conflict.html

авторREPLACE

When a UNIQUE constraint violation occurs, the REPLACE algorithm deletes pre-existing rows that are causing the constraint violation prior to inserting or updating the current row and the command continues executing normally. If a NOT NULL constraint violation occurs, the REPLACE conflict resolution replaces the NULL value with he default value for that column, or if the column has no default value, then the ABORT algorithm is used. If a CHECK constraint violation occurs, the REPLACE conflict resolution algorithm always works like ABORT.

Код: sql
1.
CREATE UNIQUE INDEX numbers_uk_number ON numbers (number)
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37665170
inexx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
То есть фактически, определить наличие конкретной записи в таблице можно лишь при возникновении конфликта "ON CONFLICT" в стандарте, а для диалекта SQLite - "OR"
А конфликт в свою очередь возникает лишь в случае обременения конкретный столбцов таблицы признаками "NOT NULL" или "UNIQUE";
в конкретном моем случае ограничение записей "UNIQUE" является применимым, т.к. мне собственно и нужно чтобы данная таблица содержала лишь уникальные записи. Хотя опять же зачем REPLACE (перезапись) "где смысл, где логика?" зачем перезаписывать то что уже есть?
А что если таблица предусматривает наличие повторяющихся записей, и на определенном этапе в запросе необходимо выяснить присутствует ли хотя бы одна такая запись в таблице.
Я просто поверить не могу что такой функционал не востребован, и не реализован.

Ну и дабы не плодить тем, и не испытать терпение Google, хотел бы сразу спросить, по поводу конструкции SELECT CASE
Меня интересует могут ли операндами в WHEN THEN быть другие запросы?
Ну что то вроде:
Код: sql
1.
2.
3.
SELECT CASE SELECT blabla1 FROM testtable1
 WHEN (SELECT blabla2 FROM testtable2) THEN (INSERT INTO testtsble3(blabla3) VALUES ('как же все это...'))
END


я уже почти уверен, что нет... но все же
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37665290
RXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inexx,

Если не нужно перезаписывать - не перезаписывайте. Ссылку я привел - смотрите варианты.
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37665384
RXL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inexx,

Вы снова выдумываете новые операторы...
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37665659
inexx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Атас! задача решена... но я честно сказать удивлен нетривиальностью решения казалось бы обыденной задачи.
Основной проблемой оказалось то, в SQLite не реализован механизм IF - ELSE как таковой, хотя определенной функциональности можно добиться при помощи SELECT CASE , в случае с ветвящейся логикой запросов SELECT CASE не применимо, так как собственно никакие запросы не могут фигурировать, ни как условие WHEN , ни как действие THEN .
Но это все таки возможно.
Еще раз уточним задачу:
Организовать ЗАПРОС таким образом, чтобы он ДОБАВЛЯЛ запрос ЕСЛИ ОНА НЕ СУЩЕСТВУЕТ уже в целевом поле таблицы.
Возьмем к примеру всё ту же таблицу:
id | number
1 89008007060
2 89007006050
3 89006005040
Код: sql
1.
2.
3.
4.
CREATE TABLE numbers (id INTEGER PRIMARY KEY AUTOINCREMENT, sim_number TEXT);
INSERT INTO numbers(sim_number) VALUES('89008007060');
INSERT INTO numbers(sim_number) VALUES('89007006050');
INSERT INTO numbers(sim_number) VALUES('89006005040');


Итак поехали, для реализации нашей задачи нужно понять несколько тонкостей:
Оператор SELECT принимает первым операндом не только имена полей, но и некое expr (expression/выражение) которое может являться и просто значением, н/п
Код: sql
1.
SELECT '89006005040' FROM numbers


при этом ни в коем случае не подумайте что SELECT это самое значение станет искать в таблице, "боже упаси", в данном случае происходит совершенно не поддающееся моей логике действие, ВНИМАНИЕ :
SELECT возвращает таблицу равную по количеству записей целевой таблице т.е. равную по количеству строк, заполненное полностью нашим этим целевым значением .
Применимо к нашей таблице это выглядит так (для тех кто еще не успел попробовать):
Код: sql
1.
2.
3.
4.
'89006005040'
89006005040
89006005040
89006005040


(OffTop: Кто ни будь может объяснить логику этого действия? )
но это не важно мы этим свойством воспользуемся -
раз SELECT может нам вернуть целевое значение, а из пустой таблицы он собственно ничего не вернет ( NULL ), значит вот он наш этакий первобытный аналог условия IF-ELSE .
Остается лишь одна проблема, в конечном итоге у нас все таки на выходе таблица одинаковых значений,
как получить из нее единичное значение? используя DISTINCT сей оператор используется для ограничение выборки уникальностью записей, а проще говоря избавляет от повторяющихся записей.
Собираем все вместе и получаем следующий запрос
Код: sql
1.
INSERT INTO numbers(sim_number) SELECT DISTINCT '89005556644' FROM numbers WHERE NOT EXISTS (SELECT sim_number FROM numbers WHERE sim_number = '89005556644')


Пробуем...
первый раз в таблицу добавится значение 89005556644 т.к. ранее его не было и
Код: sql
1.
SELECT sim_number FROM numbers WHERE sim_number = '89005556644'


возвращал NULL .
Но если вы повторите запрос вы увидите что ничего в таблицу не добавилось.

PS: такой подход абсолютно универсален, UNIQUE или нет тут уже не важно.
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37665979
Stupid_BOT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inexx,
можно и проще:
Код: sql
1.
2.
3.
INSERT INTO numbers(sim_number) 
SELECT '89005556644' Zuza
WHERE NOT EXISTS (SELECT 1 FROM numbers WHERE sim_number = Zuza);
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37666623
inexx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, действительно так проще... и даже работает быстрее.
И по моему всё выражение так же соответствует стандарту, как и в моем варианте, т.е. подход является универсальным для всех реализаций SQL.
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #37667155
Stupid_BOT
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
inexx,
SELECT без FROM не по стандарту. Не на всех СУБД такая конструкция отработает. Чтобы не нарушать стадарт и не проиграть в скорости, можно так
Код: sql
1.
2.
SELECT '89005556644' Zuza FROM <таблица с одной записью>
WHERE ... ;

или так
Код: sql
1.
2.
3.
SELECT '89005556644' Zuza FROM <любая не пустая таблица>
WHERE...
LIMIT 1;
...
Рейтинг: 0 / 0
Проверить существование записи, если нет то записать.
    #38055064
ttogrul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
inexx,описанный вами запрос,не будет работать если изначально у вас таблица будет пуста.ТО есть в пустую таблицу он новую запись никак добавить не сможет.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Проверить существование записи, если нет то записать.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]