1

我已经声明了下表供审计触发器使用:

CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
  1. 触发器将在同一个事务中被多次调用。

  2. 第一次调用触发器时,我希望它插入一个具有当前 TRANSACTION_ID() 和时间的新行。

  3. 随后调用触发器时,我希望它返回现有的“id”(我为此调用 Statement.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 会改变“时间”。

我该如何解决这两个问题?

4

2 回答 2

1

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)。意思是,如果存在记录,则重新使用 id,否则使用 null。

另请参阅https://stackoverflow.com/a/18819879/14731,了解根据行是否已存在来插入或更新的可移植方式。


1. MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW())

如果您只想插入新行,请使用: INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())

MERGE如果将其用作键,则不设置列的值ID是没有意义ID的,因为那样它永远不会(即使在理论上)更新现有的行。您可以做的是使用另一个键列(在上述情况下,没有可以使用的列)。有关详细信息,请参阅文档MERGE

2. 在现有行上调用 MERGE 将改变“时间”

我不确定您是否谈论“时间”列的值已更改的事实。如果您使用MERGE ... VALUES(.., NOW()),这是预期的行为,因为该MERGE语句应该更新该列。

或者你的意思是旧版本的 H2 在同一个事务中返回不同的值(不像大多数其他数据库,在同一个事务中返回相同的值)。确实如此,但是对于 H2 版本 1.3.155 (2011-05-27) 及更高版本,此不兼容性已得到修复。另请参阅更改日志:“CURRENT_TIMESTAMP() 等现在在事务中返回相同的值。” 看起来这不是您的问题,因为您似乎使用的是 1.3.155 版本(错误消息 [90081-155] 包括构建/版本号)。

于 2011-06-10T14:38:00.077 回答
0

简短的回答:

MERGE INTO AUDIT_TRANSACTION_IDS (uuid, time) KEY (uuid, time) VALUES (TRANSACTION_ID(), NOW());

性能小提示:确保 uuid 已编入索引

长答案:

MERGE基本上是一个UPDATEwhich INSERTs 当没有发现更新的记录时。

Wikipedia 提供了更简洁、标准化的 MERGE语法,但您必须提供自己的更新和插入。(H2是否支持这不是我的回答)

那么如何MERGE在 H2 中使用更新记录呢?您定义要查找的键,如果发现您更新行(使用您提供的列名,您可以DEFAULT在此处定义,将列重置为其默认值),否则您插入行。

现在是什么NullNull表示未知,未找到,未定义,任何不是您要查找的内容。

这就是为什么Null工作是要查找的关键。因为这意味着没有找到记录。

MERGE INTO table1 (id, col1, col2) KEY(id) VALUES (Null, 1, 2)

Null有一个价值。它是一个值。

现在让我们看看你的 SQL。

MERGE INTO table1 (id, col1, col2) KEY(id) VALUES (DEFAULT, 1, 2)

这意味着什么?对我来说,它说我有这个 [DEFAULT, 1, 2],在 column 中找到我DEFAULTid,然后更新col1到 1 col2,如果找到,更新到 2。否则,将默认值插入id, 1 到col1, 2 到col2.

看到我在那里强调了什么吗?那有什么意思?是什么DEFAULT?你怎么DEFAULT比较id

DEFAULT只是一个关键字。

你可以做类似的事情,

MERGE INTO table1 (id, col1, timeStampCol) KEY(id) VALUES (Null, 1, DEFAULT)

但不要将 DEFAULT 放在键列中。

于 2011-06-15T01:35:16.880 回答