Слияние в таблицу, содержащие столбцы Auto_Increment

StackOverflow https://stackoverflow.com/questions/6306592

  •  26-10-2019
  •  | 
  •  

Вопрос

Я объявил следующую таблицу для использования с помощью триггеров аудита:

CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
  1. Триггер будет вызван несколько раз в одной и той же транзакции.

  2. В первый раз, когда триггер вызывает, я хочу, чтобы он вставил новую строку с текущей Transaction_ID () и времени.

  3. В последующие времена, когда триггер вызывается, я хочу, чтобы он вернул существующий «id» (я вызываю ratement.getGeneratedKeys () с этой целью), не изменяя «uuid» или «время».

В текущей схеме, кажется, есть две проблемы.

  1. Когда я призываю MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW()) Я получил: org.h2.jdbc.JdbcSQLException: Column "ID" contains null values; SQL statement: MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES (TRANSACTION_ID(), NOW()) [90081-155]

  2. Я подозреваю, что призыв слияния в существующем ряду изменит «время».

Как решить обе эти проблемы?

Это было полезно?

Решение

MERGE аналогично java.util.Map.put(key, value): Он вставит строку, если ее не существует, и обновит строку, если это произойдет. При этом вы все равно можете слиться в таблицу, содержащий AUTO_INCREMENT столбцы, пока вы используете другой столбец в качестве ключа.

Данный customer[id identity, email varchar(30), count int] ты мог merge into customer(id, email, count) key(email) values((select max(id) from customer c2 where c2.email='test@acme.com'), 'test@acme.com', 10). Анкет Значение, повторно используйте идентификатор, если запись существует, используйте NULL в противном случае.

Смотрите также https://stackoverflow.com/a/18819879/14731 для портативного способа вставить или обновлять в зависимости от того, существует ли ряд.


1. Слияние в Audit_transaction_ids (Uuid, Time) Key (ID) VALUES (Transaction_ID (), теперь ())

Если вы просто хотите вставить новый ряд, используйте:INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())

MERGE без установки значения для столбца ID не имеет смысла, если ID используется в качестве ключа, потому что таким образом он никогда не может (даже в теории) обновлять существующие строки. То, что вы могли бы сделать, это использовать другой столбец ключа (в приведенном выше случае, который не может быть использован). Смотрите документацию для MERGE Для деталей.

2. Вызов слияния в существующем ряду изменит «время»

Я не уверен, что вы говорите о том, что значение «Время столбца» изменяется. Это ожидаемое поведение, если вы используете MERGE ... VALUES(.., NOW()), поскольку MERGE Заявление должно обновить этот столбец.

Или, может быть, вы имеете в виду, что более старые версии H2 возвращали различные значения в одной и той же транзакции (в отличие от большинства других баз данных, которые возвращают одно и то же значение в одной и той же транзакции). Это верно, однако с помощью H2 версии 1.3.155 (2011-05-27), а затем эта несовместимость исправлена. Смотрите также изменить журнал: «Current_timestamp () и т. Д. Теперь возвращает такое же значение в транзакции». Похоже, это не проблема в вашем случае, потому что вы, похоже, используете версию 1.3.155 (сообщение об ошибке [90081-155] включает номер сборки / версии).

Другие советы

Короткий ответ:

Слияние в AUDIT_TRANCACTION_IDS (UUID, TIME) КЛЮЧ (UUID, TIME) Значения (Transaction_ID (), теперь ());

Маленький совет производительности: убедитесь, что UUID индексирован

Длинный ответ:

MERGE в основном UPDATE который INSERTS, когда не обнаружена записи.

Википедия дает более краткий, стандартизированный синтаксисСлияние Но вы должны предоставить свое собственное обновление и вставить. (Независимо от того, будет ли это поддерживать в H2 или нет, не является моим, чтобы ответить)

Итак, как вы обновляете запись, используя MERGE в H2? Вы определяете ключ для поиска, если он найден, вы обновляете строку (с именами столбцов, которые вы поставляете, и вы можете определить DEFAULT Здесь, чтобы сбросить свои столбцы к его значениям по умолчанию), в противном случае вы вставляете строку.

Теперь что есть Null? Null означает неизвестный, не найденный, не определен, что -то, что не ищете.

Поэтому Null Работает как ключ, чтобы найти вверх. Потому что это означает, что запись не найдена.

Слияние в таблицу 1 (id, col1, col2) значения (ID) (NULL, 1, 2)

Null имеет значение. это значение.

Теперь давайте посмотрим на ваш SQL.

Слияние в таблицу 1 (ID, COL1, COL2) значения (ID) (по умолчанию, 1, 2)

Что это подразумевает? Для меня это говорит, что у меня есть это [по умолчанию, 1, 2], Найди меня DEFAULT в столбце id, затем обновление col1 до 1, col2 до 2, если найдено. В противном случае вставьте дефолт в id, 1 к col1, 2 до col2.

Видите, что я там подчеркнул? Что это хотя бы значит? Что такое DEFAULT? Как сравнить DEFAULT к id?

DEFAULT это просто ключевое слово.

Вы можете делать такие вещи, как,

Слияние в таблицу 1 (id, col1, timestampcol) щедрости (ID) значения (null, 1, по умолчанию)

Но не ставите по умолчанию в столбце ключа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top