|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
Всем доброго времени суток... Заранее извиняюсь, возможно это уже неоднократно обсуждалось, но мне к сожалению не удалось найти информации, скорее всего из за пробелов в терминологии и теории SQL я просто не смог правильно задать критерий поиска. Проблема у меня следующая: Есть таблица numbers вида: id as INTEGER | number as TEXT . 1 89008006050 Не удается организовать в запросе следующую логику: ДОБАВИТЬ В number ЗНАЧЕНИЕ something, ЕСЛИ НЕ ТАКАЯ ЗАПИСЬ НЕ СУЩЕСТВУЕТ, (ну и если это возможно реализовать в одном запросе то прикрутить сюда еще: ИНАЧЕ ВЫБРАТЬ id ЗАПИСИ something) Сначала я кружился вокруг конструкции IF NOT EXIST но так и не понял как ее можно применить к INSERT, по крайней мере Код: sql 1.
или Код: sql 1.
возвращают ошибку вида "syntax error" Где-то даже нашел упоминание WHERE NOT EXIST, мол Код: sql 1.
но вроде сам понял что к INSERT неприменимо WHERE в принципе. Больше вариантов нет. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 10:04 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
оффтоп: а на этом форуме можно редактировать созданные темы? ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 10:07 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
inexx, Офтоп: нельзя. Вы бы, чем выдумывать операторы, почитали бы мануал! Он совсем небольшой: http://sqlite.org/lang.html ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 10:11 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
Например, оператор INSERT OR REPLACE и его ипостась - REPLACE. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 10:12 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
Спасибо за традиционное RTFM! ^__^, я читаю, пробую, и прошу подсказки здесь. INSERT OR REPLACE опробовано еще в самом начале поисков - "не торт" совсем, вот пример: id | number 1 89006005040 2 89007006050 3 89008007060 ну и поехали: Код: sql 1.
что имеем на выходе ? id |number 1 89006005040 2 89007006050 3 89008007060 4 89008007060 ну и толку ? ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 10:34 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
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.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 12:44 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
То есть фактически, определить наличие конкретной записи в таблице можно лишь при возникновении конфликта "ON CONFLICT" в стандарте, а для диалекта SQLite - "OR" А конфликт в свою очередь возникает лишь в случае обременения конкретный столбцов таблицы признаками "NOT NULL" или "UNIQUE"; в конкретном моем случае ограничение записей "UNIQUE" является применимым, т.к. мне собственно и нужно чтобы данная таблица содержала лишь уникальные записи. Хотя опять же зачем REPLACE (перезапись) "где смысл, где логика?" зачем перезаписывать то что уже есть? А что если таблица предусматривает наличие повторяющихся записей, и на определенном этапе в запросе необходимо выяснить присутствует ли хотя бы одна такая запись в таблице. Я просто поверить не могу что такой функционал не востребован, и не реализован. Ну и дабы не плодить тем, и не испытать терпение Google, хотел бы сразу спросить, по поводу конструкции SELECT CASE Меня интересует могут ли операндами в WHEN THEN быть другие запросы? Ну что то вроде: Код: sql 1. 2. 3.
я уже почти уверен, что нет... но все же ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 14:00 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
inexx, Если не нужно перезаписывать - не перезаписывайте. Ссылку я привел - смотрите варианты. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 14:45 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
inexx, Вы снова выдумываете новые операторы... ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 15:24 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
Атас! задача решена... но я честно сказать удивлен нетривиальностью решения казалось бы обыденной задачи. Основной проблемой оказалось то, в SQLite не реализован механизм IF - ELSE как таковой, хотя определенной функциональности можно добиться при помощи SELECT CASE , в случае с ветвящейся логикой запросов SELECT CASE не применимо, так как собственно никакие запросы не могут фигурировать, ни как условие WHEN , ни как действие THEN . Но это все таки возможно. Еще раз уточним задачу: Организовать ЗАПРОС таким образом, чтобы он ДОБАВЛЯЛ запрос ЕСЛИ ОНА НЕ СУЩЕСТВУЕТ уже в целевом поле таблицы. Возьмем к примеру всё ту же таблицу: id | number 1 89008007060 2 89007006050 3 89006005040 Код: sql 1. 2. 3. 4.
Итак поехали, для реализации нашей задачи нужно понять несколько тонкостей: Оператор SELECT принимает первым операндом не только имена полей, но и некое expr (expression/выражение) которое может являться и просто значением, н/п Код: sql 1.
при этом ни в коем случае не подумайте что SELECT это самое значение станет искать в таблице, "боже упаси", в данном случае происходит совершенно не поддающееся моей логике действие, ВНИМАНИЕ : SELECT возвращает таблицу равную по количеству записей целевой таблице т.е. равную по количеству строк, заполненное полностью нашим этим целевым значением . Применимо к нашей таблице это выглядит так (для тех кто еще не успел попробовать): Код: sql 1. 2. 3. 4.
(OffTop: Кто ни будь может объяснить логику этого действия? ) но это не важно мы этим свойством воспользуемся - раз SELECT может нам вернуть целевое значение, а из пустой таблицы он собственно ничего не вернет ( NULL ), значит вот он наш этакий первобытный аналог условия IF-ELSE . Остается лишь одна проблема, в конечном итоге у нас все таки на выходе таблица одинаковых значений, как получить из нее единичное значение? используя DISTINCT сей оператор используется для ограничение выборки уникальностью записей, а проще говоря избавляет от повторяющихся записей. Собираем все вместе и получаем следующий запрос Код: sql 1.
Пробуем... первый раз в таблицу добавится значение 89005556644 т.к. ранее его не было и Код: sql 1.
возвращал NULL . Но если вы повторите запрос вы увидите что ничего в таблицу не добавилось. PS: такой подход абсолютно универсален, UNIQUE или нет тут уже не важно. ... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 16:56 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
inexx, можно и проще: Код: sql 1. 2. 3.
... |
|||
:
Нравится:
Не нравится:
|
|||
16.02.2012, 19:06 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
Да, действительно так проще... и даже работает быстрее. И по моему всё выражение так же соответствует стандарту, как и в моем варианте, т.е. подход является универсальным для всех реализаций SQL. ... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2012, 10:13 |
|
Проверить существование записи, если нет то записать.
|
|||
---|---|---|---|
#18+
inexx, SELECT без FROM не по стандарту. Не на всех СУБД такая конструкция отработает. Чтобы не нарушать стадарт и не проиграть в скорости, можно так Код: sql 1. 2.
или так Код: sql 1. 2. 3.
... |
|||
:
Нравится:
Не нравится:
|
|||
17.02.2012, 13:45 |
|
|
start [/forum/topic.php?fid=54&msg=37664934&tid=2008956]: |
0ms |
get settings: |
11ms |
get forum list: |
13ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
31ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
52ms |
get tp. blocked users: |
2ms |
others: | 267ms |
total: | 398ms |
0 / 0 |