我已声明下表供审计触发器使用:
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会改变“时间”。
如何解决这两个问题?
答案 0 :(得分: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)以及之后的情况,这种不兼容性是固定的。另请参阅change log:“CURRENT_TIMESTAMP()等现在在事务中返回相同的值。”看起来这不是你的问题,因为你似乎使用版本1.3.155(错误消息[90081-155]包括版本/版本号)。
答案 1 :(得分:0)
简答:
合并到AUDIT_TRANSACTION_IDS(uuid,time)KEY(uuid,time) VALUES(TRANSACTION_ID(),NOW());
一点性能提示:确保将uuid编入索引
长答案:
MERGE
基本上是UPDATE
INSERT
,当没有找到更新的记录时。
维基百科提供了更简洁,标准化的语法 MERGE但您必须提供自己的更新和插入。 (这是否会在H2中得到支持不是我的回答)
那么如何在H2中使用MERGE
更新记录?您可以定义要查找的密钥,如果发现您更新了行(使用您提供的列名,并且可以在此处定义DEFAULT
,则将列重置为其默认值),否则您将插入行。
现在什么是Null
? Null
表示未知,未找到,未定义,任何不是您正在寻找的东西。
这就是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)
这意味着什么?对我说,它说
我有[默认,1,2], 在列DEFAULT
中找到id
,
然后将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放在键列中。