Требуется решение для переноса SQL (вставка + обновление) - PullRequest
2 голосов
/ 21 декабря 2010

Мне нужно выполнить очень простую операцию с базой данных - положить некоторые значения в таблицу по ключу, если строка существует - обновить ее, если нет - создать новую.Проблема в том, что мне нужно сделать это переносимым способом - то есть один и тот же запрос должен работать на MySQL, SQL Server, Oracle и предпочтительно также на DB2, Postgres и т. Д. Поэтому, хотя я мог бы использовать REPLACE или INSERT ... ON DUPLICATE KEY UPDATE в MySQLЯ не уверен, что они будут поддерживать такой синтаксис.И я действительно хочу избежать, если по типу базы данных, потому что это было бы невозможно поддерживать.Я также не хочу на самом деле запрашивать значение перед обновлением, потому что я подозреваю, что это значительно замедлит процесс (мне нужно сделать это несколько раз).

Пока что лучшее, что я придумал, это просто делать:

  UPDATE table SET data='data' WHERE key='key';
  INSERT INTO table(key, data) VALUES ('key', 'data');

один из них всегда будет успешным, а другой - неудачным, но мне все равно, что один из запросов завершится неудачей.Это выглядит как-то не элегантно.Любые предложения, как сделать это лучше?

Ответы [ 3 ]

5 голосов
/ 21 декабря 2010

Единственное полностью независимое от базы данных решение, использующее несколько современных баз данных, - это вызвать Обновление, а затем Вставку в двух операциях. Некоторые базы данных не допускают отправку нескольких операторов за одну операцию, а некоторые базы данных могут не возвращать количество строк, затронутых обновлением, поэтому я бы не стал полагаться на это.

Update MyTable
Set Data = 'Data'
Where KeyCol = 'key';

(отдельный звонок)

Insert Into MyTable(KeyCol, Data)
Select 'key', 'Data'
From ( Select 1 As Value ) As Z
Where Not Exists    (
                    Select 1
                    From MyTable As T1
                    Where T1.KeyCol = 'key'
                    );
2 голосов
/ 21 декабря 2010

Сначала выполните UPDATE. Ваш клиентский код будет проинформирован о количестве обновленных строк. Если обновленный счетчик строк равен нулю, выполните INSERT.

Точный способ возврата обновленного числа строк в ваш клиентский код зависит от того, какую библиотеку доступа к базе данных вы используете. Например, в Java это возвращаемое значение PreparedStatement.executeUpdate(), а в Python DB-API доступ к нему осуществляется с помощью cursor.rowcount.

Вам необходимо убедиться, что весь процесс происходит в рамках сериализуемой транзакции, чтобы избежать конфликтов с параллельными авторами.

1 голос
/ 21 декабря 2010

MERGE и WHEN NOT MATCHED являются частью ANSI SQL 2003. За исключением, конечно, он не поддерживается единообразно.

Ваше решение, хотя и умное, опасно, потому что неясно, что должен делать клиент.Игнорировать все ошибки?Если так, что случится, если оба они потерпят неудачу.

Вместо этого не пытайтесь сделать это портативным.Используйте хранимые процедуры и / или DAL для устранения различий между бэкэндами, поскольку это, несомненно, не будет вашей единственной проблемой в любом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...