题
我已经声明了下表,以供审计触发器使用:
CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
触发器将在同一交易中多次调用。
首次调用扳机时,我希望它使用当前的TransAction_ID()和时间插入新行。
随后调用触发器,我希望它返回现有的“ ID”(我调用statement.getGeneratedKeys()到该端),而不会更改“ uuid”或“ time”。
当前的模式似乎有两个问题。
当我调用时
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]
我怀疑在现有行上调用合并会改变“时间”。
如何解决这两个问题?
解决方案
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.合并到AUDIT_TRANSACTION_IDS(UUID,time)键(id)值(transaction_id(),now())
如果您只想插入新行,请使用: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_TRANSACTION_IDS(UUID,time)键(uuid,time)值(transaction_id(),now());
少量性能提示:确保索引索引
长答案:
MERGE
基本上是一个 UPDATE
哪个 INSERT
当没有发现的记录更新时。
维基百科提供了更简洁的标准化语法合并 但是您必须提供自己的更新和插入。 (是否在H2中支持这不是我的回答)
那么如何使用 MERGE
在H2中?您定义要查找的钥匙,如果发现它更新了行(带有您提供的列名,可以定义 DEFAULT
在这里,要将您的列重置为默认值),否则插入行。
现在是什么 Null
? Null
意味着未知,未找到,未定义,任何不是您想要的东西。
这就是为什么 Null
作为要查找的关键。因为这意味着找不到记录。
合并到table1(id,col1,col2)键(id)值(null,1,2)
Null
有一个价值。这是一个价值。
现在让我们看看您的SQL。
合并到table1(id,col1,col2)键(id)值(默认为1,2)
那意味着什么?对我来说,它说我有这个[默认值1,2], 找到我 DEFAULT
在列中 id
, ,然后更新 col1
到1, col2
至2,如果发现。否则,将默认值插入到 id
, ,1至 col1
, ,2至 col2
.
看看我在那里强调什么?那有什么意思?什么是 DEFAULT
?你如何比较 DEFAULT
至 id
?
DEFAULT
只是一个关键字。
你可以做类似的事情
合并到table1(id,col1,timestampcol)键(id)值(null,1,默认值)
但是不要将默认值放在密钥列中。