Derby Apache: как я могу сделать, “вставляют, если не существует”?

public Long addIntegers(Integer a, Integer b) {
    Integer sum = a + b;

    return sum;
}

Вы почти правы в этом. Я понимаю, почему вы думаете, что это сработает, но вы не можете выйти из Integer -> Long ни косвенно, ни через приведение. Вам нужно пойти Integer -> int -> long -> Long, и Java может сделать только 1 скачок неявно .

Сначала давайте посмотрим, что на самом деле делает a + b. Он распаковывает a и b из Integer в примитивные int с и складывает их вместе, в результате чего получается int. Затем он автоматически упаковывает это в Integer, потому что это тип переменной sum, которую вы определили.

Но, подождите, мы видим выше (Integer -> int -> long -> Long), что Integer на самом деле дальше от того места, где мы хотим быть, а не ближе!

Итак, давайте вернемся к a + b, который возвращает int. Мы хотим Long. Мы могли бы привести результат к long:

public Long addIntegers(Integer a, Integer b) {
    return (long) (a + b);
}

В таком случае у нас есть int - результат нашего выражения суммы - и мы явно приведем к long, и Java делает последний неявный шаг и автоматически помещает его в Long.

Однако, хотя приведение в порядке в нашем случае, это часто признак плохого дизайна, поэтому я стараюсь по возможности избегать его использования. К счастью, в нашем случае мы можем избежать броска. Нам просто нужно переключить неявный шаг и явные шаги (т.е. неявно преобразовать из int -> long и явно преобразовать из long -> Long)

public Long addIntegers(Integer a, Integer b) {
    return Long.valueOf(a + b);
}

В этом примере Long.valueOf принимает примитив long и возвращает Long, но наши вычисления a + b возвращают int, поэтому Java неявно преобразует int в long.

13
задан Limbic System 2 January 2009 в 18:46
поделиться

6 ответов

Стандартным путем я использовал с PostgreSQL DBs, что-то как следующее:

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, совместимый, это все же. Пропавшие без вести ИЗ пункта во внешнем операторе SELECT особенно могут быть нестандартными. Дайте ему движение все же.

3
ответ дан 1 December 2019 в 21:25
поделиться

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

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

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

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

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

16
ответ дан 1 December 2019 в 21:25
поделиться

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

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

0
ответ дан 1 December 2019 в 21:25
поделиться

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

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

      while (ResultSet.next ()) {
     пытаться {
     PreparedStatement insert = myConn.prepareStatement («вставить в значения таблицы (?)»);
     вставка .setString (1, «тест»);
     вставка .executeUpdate (); 
     } catch (SQLException e) {
     if (e.getSQLState (). equals ("23505")) // Найден дубликат из представления базы данных
     {continue;} // игнорируем дубликаты и продолжаем оператор вставки
     else {попробуйте { 
     бросить е;
     } catch (Exception ex) { 
     }
     }
     }
     }
    
0
ответ дан 1 December 2019 в 21:25
поделиться

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

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

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

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

4
ответ дан 1 December 2019 в 21:25
поделиться

У меня была та же проблема, и у меня это работало для вставки только с одним значением / столбцом в 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)
1
ответ дан 1 December 2019 в 21:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: