реализация Upsert's независимо от БД

Ragazzo

TDD interested
Имеется следующая проблема: часть данных пришедших от пользователя уже имеется в БД, часть - новые данные. Требуется решение независимое от конкретной БД, так-что некоторые фишки mysql или pgsql в этом плане отпадают, вопрос как лучше реализовать данную проблему? Не хотелось бы делать в 2 запроса вида: 1ый выбирает данные которые уже имеются(id), затем сравниваются полученные данные и уже формируются UPDATE'ы и INSERT'ы. Стоит ли все-таки переложить данную проблему как-то на php, но вот как именно сопоставить данные которые уже имеются в БД и новые данные?
 

baev

‹°°¬•
Команда форума
Тема закрыта

Правилами форума запрещается создание тем с малосодержательным названием:
Запрещается:
……
……
3. Создание новых тем, имеющих малосодержательное название. Например, "Помогите!!...", "Есть вопрос", "почему-то не работает". Такие темы удаляются без предупреждений;
……
 

AmdY

Пью пиво
Команда форума
Вложенный запрос
INSERT INTO table SELECT field, field2,.... FROM table WHERE ".implode(', ', $_GET['ids']) - пример.
 

Ragazzo

TDD interested
AmdY
немного не понял, ведь update сделать не получится 1одним этим запросом? Не понял запрос, в плане того, что он вставляет данные из этой же таблицы, если id уникальный ключ, то получится бред, не?
baev
переименуй пожалуйста тему тогда в "реализация Upsert's независимо от БД"
 

HEm

Сетевой бобер
ON DUPLICATE KEY UPDATE не подойдет? нужен уникальный ключ (например артикул, да?)
 

Ragazzo

TDD interested
HEm
Да, не подойдет, т.к в основном это все фишки одной из типов БД, а мне нужно чтобы на любой БД работало. Пока что сделал тупо влоб: 1ый запрос выбирает записи которые есть у пользователя(idшники записей), потом для пришедших данных у которых id попадают в этот диапазон делаю один update через CASE конструкцию sql, ну а другие одним insertom. Просто хотелось бы эти 3 запроса , заменить на 1. Была идея избавиться от 1го запроса(выборка idшников), путем передачи дополнительного параметра из формы для каждой записи(является ли запись новой или есть в БД), но это тоже как-то криво, хоть и можно избавиться от первого запроса.
 

HEm

Сетевой бобер
В зависимости от БД можно для каждой подобрать красивый запрос. Лучше не получится
 

Ragazzo

TDD interested
Попробую сделать сначала update потом insert в одной транзакции... посмотрим что будет.
 

zerkms

TDD infected
Команда форума
Ragazzo
Ничего не получится - в случае UPDATE несуществующей строки ничего не блокируется (да и блокировки в разных субд и с разными уровнями изоляции транзакций могут оказаться разные) - а потому, мы получаем классический race condition:
дву одновременных транзакции создадут одинаковые записи (или последняя отвалится, если у тебя есть какие-то констрейнты)

+1 за вендоро-специфичные решения.
 

Ragazzo

TDD interested
zerkms
Хм... ок, тогда придеться делать все-таки в зависимости от каждой БД (
 

prolis

Новичок
в пром решениях можно и так (если приходит всегда актуальная инфо, то старую не храним):
1. delete from table where id in (select id from source)
2.insert into table values (select * from source)
 

HEm

Сетевой бобер
prolis
ненене, не катит

У меня например в админке товару прописывают всякие связи, описания и прочее барахло, а выгрузка только меняет цену по артикулу.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
prolis
У меня например в админке товару прописывают всякие связи, описания и прочее барахло, а выгрузка только меняет цену по артикулу.
это намекает, кагбе, что артикул не обязан быть первичным ключом ;)
 

Ragazzo

TDD interested
флоппик
в любом случае удалять все - занасить все заново это бред :)
 

флоппик

promotor fidei
Команда форума
Партнер клуба
флоппик
в любом случае удалять все - занасить все заново это бред :)
а ты думаешь, upsert с технической точки зрения сильно от этого отличается? Дырки в автоинкременте при ON DUPLICATE KEY UPDATE в мускуле наглядно показывают, что это де-факто «удалять все - занасить все»
 

флоппик

promotor fidei
Команда форума
Партнер клуба
В оракле и мелкомягких скьюэлях кстати есть MERGE который и является Upsert-ом.
PHP:
MERGE INTO TABLE_NAME USING table_reference ON (condition)
   WHEN MATCHED THEN
   UPDATE SET column1 = value1 [, column2 = value2 ...]
   WHEN NOT MATCHED THEN
   INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...
 

флоппик

promotor fidei
Команда форума
Партнер клуба
а ты думаешь, upsert с технической точки зрения сильно от этого отличается? Дырки в автоинкременте при ON DUPLICATE KEY UPDATE в мускуле наглядно показывают, что это де-факто «удалять все - занасить все»
Вот тут я соврал чуть-чуть, оказывается, как себя ведет только InnoDB
 

Ragazzo

TDD interested
а ты думаешь, upsert с технической точки зрения сильно от этого отличается? Дырки в автоинкременте при ON DUPLICATE KEY UPDATE в мускуле наглядно показывают, что это де-факто «удалять все - занасить все»
в любом случае, несмотря на "дырки в mysql", это бред, так можно любую ситуацию подогнать под "удалить все - занести все", update для дураков, ага :D Не вариант вообщем :) Спасибо тем не менее всем, кто откликнулся.
 
Сверху