Гость
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Проверить существование записи, если нет то записать. / 14 сообщений из 14, страница 1 из 1
16.02.2012, 10:04
    #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
16.02.2012, 10:07
    #37664535
inexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверить существование записи, если нет то записать.
оффтоп: а на этом форуме можно редактировать созданные темы?
...
Рейтинг: 0 / 0
16.02.2012, 10:11
    #37664544
RXL
RXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверить существование записи, если нет то записать.
inexx,

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



Вы бы, чем выдумывать операторы, почитали бы мануал! Он совсем небольшой: http://sqlite.org/lang.html
...
Рейтинг: 0 / 0
16.02.2012, 10:12
    #37664546
RXL
RXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверить существование записи, если нет то записать.
Например, оператор INSERT OR REPLACE и его ипостась - REPLACE.
...
Рейтинг: 0 / 0
16.02.2012, 10:34
    #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
16.02.2012, 12:44
    #37664934
RXL
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
16.02.2012, 14:00
    #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
16.02.2012, 14:45
    #37665290
RXL
RXL
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверить существование записи, если нет то записать.
inexx,

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

Вы снова выдумываете новые операторы...
...
Рейтинг: 0 / 0
16.02.2012, 16:56
    #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
16.02.2012, 19:06
    #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
17.02.2012, 10:13
    #37666623
inexx
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверить существование записи, если нет то записать.
Да, действительно так проще... и даже работает быстрее.
И по моему всё выражение так же соответствует стандарту, как и в моем варианте, т.е. подход является универсальным для всех реализаций SQL.
...
Рейтинг: 0 / 0
17.02.2012, 13:45
    #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
27.11.2012, 16:12
    #38055064
ttogrul
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверить существование записи, если нет то записать.
inexx,описанный вами запрос,не будет работать если изначально у вас таблица будет пуста.ТО есть в пустую таблицу он новую запись никак добавить не сможет.
...
Рейтинг: 0 / 0
Форумы / SQLite [игнор отключен] [закрыт для гостей] / Проверить существование записи, если нет то записать. / 14 сообщений из 14, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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