Apache Derby: как мне сделать «вставить, если не существует»? - PullRequest
13 голосов
/ 02 января 2009

Я даю Apache Derby , он же JavaDB . Кажется, я не могу обойти двойные проблемы с ключами при вставке записей, которые могут уже существовать. Есть ли дерби, эквивалентный "insert if not exists" или "merge"?

Аналогично, есть ли способ сделать что-то вроде "drop table foo if exists"?

Ответы [ 7 ]

16 голосов
/ 10 января 2009

Я никогда не использовал Apache Derby, но общее решение, которое довольно независимо от базы данных, выглядит следующим образом:

Чтобы вставить значения 'a' и 'b' в таблицу foo (со столбцами с именами A, B), но только там, где их еще нет, попробуйте что-то вроде

INSERT INTO foo (  
  SELECT 'a' as A, 'b' as B
  FROM foo  
  WHERE  
    A = 'a' AND B = 'b'  
  HAVING count(*)=0  
 )

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

Это полезный трюк для создания идемпотентного SQL-скрипта (тот, который ничего не делает при втором запуске). Однако будьте осторожны при использовании этого в производственном коде, поскольку HAVING count(*)=0 может быть очень медленным на больших таблицах.

4 голосов
/ 21 октября 2009

Запрос на поддержку оператора SQL: 2003 MERGE регистрируется в системе отслеживания ошибок Derby как https://issues.apache.org/jira/browse/DERBY-3155

Вы можете проголосовать за этот вопрос или, что еще лучше, внести вклад в реализацию!

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

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

3 голосов
/ 01 апреля 2009

Стандартный способ, которым я пользовался с базами данных PostgreSQL, выглядит примерно так:

INSERT INTO foo ( col1, col2, col3, ... )
SELECT 'col1 value', 'col2 value', 'colc value', ...
WHERE NOT EXISTS (
  SELECT 0
  FROM foo
  WHERE col1 = 'col1 value'
  ...
)

Не уверен, насколько он портативный или строго ANSI-совместимый. Отсутствующее предложение FROM во внешнем операторе SELECT, в частности, может быть нестандартным. Попробуй хотя.

2 голосов
/ 31 августа 2014

Derby реализовал MERGE в 10.11: https://db.apache.org/derby/docs/10.11/ref/rrefsqljmerge.html
Обратите внимание, что вам необходимо обновить вашу БД до 10.11 перед ее использованием: https://db.apache.org/derby/docs/10.11/devguide/cdevupgrades.html

1 голос
/ 17 марта 2010

У меня была такая же проблема, и я получил эту работу для вставки только с одним значением / столбцом в Derby. (Я никогда не удосужился протестировать его с большим количеством данных, но у меня нет оснований предполагать, что это не следует делать):

INSERT INTO my_table (my_column)
    (SELECT 'new_value_to_insert'
    FROM my_table
    WHERE my_column = 'new_value_to_insert' 
    HAVING count(*)=0)
0 голосов
/ 29 сентября 2009

Я использую это решение, но вы должны использовать его, только если понимаете разницу между дубликатом из представления базы данных и дубликатом из представления пользователя

  • Дубликатами из представления базы данных являются две записи с одинаковым первичным ключом
  • Дубликаты из представления пользователя представляют собой две записи со всеми одинаковыми полями

        while (ResultSet.next()) {
        try {
        PreparedStatement insertion = myConn.prepareStatement("insert into table values (?)");
        insertion .setString(1, "test");
        insertion .executeUpdate();           
        } catch (SQLException e) {
            if(e.getSQLState().equals("23505"))//Found duplicate from database view
             {continue;}//ignore duplicate and continue with the insert statement
            else{try {                           
                  throw e;
            } catch (Exception ex) {  
                }
              }
            }
          }
    
0 голосов
/ 28 июля 2009

Нет встроенной поддержки для этого, чтобы обойти это, я использую eclipse-link, eclipse-link будет пытаться создавать таблицы и игнорировать любые ошибки, возникающие при попытке создания уже существующих таблиц.

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

...