Jas*_*ett 6 mysql triggers lastinsertid
我的INSERT声明如下:
INSERT INTO officer (officer_number,
name,
bank_id)
VALUES ('',
'',
8)
ON DUPLICATE KEY UPDATE officer_number = '',
name = '',
bank_id = 8,
id = LAST_INSERT_ID(id)
Run Code Online (Sandbox Code Playgroud)
这样做的方式一直很好.当我添加以下触发器时它停止工作:
CREATE TRIGGER officer_update BEFORE UPDATE ON `officer`
FOR EACH ROW SET NEW.updated_at = NOW(), NEW.created_at = OLD.created_at
Run Code Online (Sandbox Code Playgroud)
并不是officer记录没有被插入.似乎触发器是劫持LAST_INSERT_ID()或其他东西.我这样说是因为下一个执行的查询是这样的:
INSERT INTO account (import_id,
branch_id,
account_number,
officer_id,
customer_id,
open_date,
maturity_date,
interest_rate,
balance,
opening_balance)
VALUES ('123',
'4567',
'789',
'0', # This is the officer id which is of course invalid
'321',
'1992-04-22',
'2012-05-22',
'0.0123',
'0',
'10000')
Run Code Online (Sandbox Code Playgroud)
由于我使用相同的文件运行了几十个成功的导入,我没有更改我的代码,现在我的导入在我添加此触发器后无效,我必须推断出触发器是罪魁祸首.我与另一个表有类似的情况,并删除触发器修复问题.
所以我的问题是:
我有另一个触发器officer.created_at(和很多其他表created_at的),我宁愿避免某种尴尬的解决方案,我有一个触发器,created_at但一个DEFAULT CURRENT_TIMESTAMP开启updated_at.出于某种原因,MySQL只允许每个表一个自动时间戳,所以我不能做CURRENT_TIMESTAMP两个created_at和updated_at.
这里是SHOW CREATE TABLE为officer:
CREATE TABLE `officer` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`officer_number` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`bank_id` bigint(20) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `officer_number` (`officer_number`,`name`),
UNIQUE KEY `officer_number_2` (`officer_number`,`bank_id`),
KEY `bank_id` (`bank_id`),
CONSTRAINT `officer_ibfk_1` FOREIGN KEY (`bank_id`) REFERENCES `bank` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=102735 DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
如果错误已经存在,您的INSERT ... ON DUPLICATE KEY UPDATE似乎是一种防止错误的方法。officer_number您是否需要进行更新(以触发触发器),或者您可以改为使用INSERT IGNORE?:
INSERT IGNORE INTO officer (officer_number,
name,
bank_id)
VALUES ('',
'',
8);
Run Code Online (Sandbox Code Playgroud)
如果已经存在,那将不会执行任何操作officer_id,从而完全消除更新的需要(因此LAST_INSERT_ID())。
如果这是不可能的,那么也许你INSERT ... ON DUPLICATE KEY UPDATE可以进行调整。我不清楚目的:
id = LAST_INSERT_ID(id)
Run Code Online (Sandbox Code Playgroud)
LAST_INSERT_ID()(不带任何参数),返回由最近执行的 INSERT 语句为 AUTO_INCRMENT 列设置的第一个自动生成的值,以影响此类列。
但是,如果您提供参数,它将返回该参数的值,并且下一次调用LAST_INSERT_ID()(不带任何参数)将返回相同的值。例如:
SELECT LAST_INSERT_ID(100);
+---------------------+
| LAST_INSERT_ID(100) |
+---------------------+
| 100 |
+---------------------+
SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 100 |
+------------------+
Run Code Online (Sandbox Code Playgroud)
所以,如果我们假设id == 100,那么这应该是真的:
SELECT LAST_INSERT_ID(id);
+--------------------+
| LAST_INSERT_ID(id) |
+--------------------+
| 100 |
+--------------------+
SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 100 |
+------------------+
Run Code Online (Sandbox Code Playgroud)
接下来:
id = LAST_INSERT_ID(id)
Run Code Online (Sandbox Code Playgroud)
应该与以下内容相同:
id = id
Run Code Online (Sandbox Code Playgroud)
或者,正如乔什·戴维斯(Josh Davis)所建议的那样,根本没有必要。你尝试过简单id = id吗?当你排除它时到底会发生什么?
该手册指出:
但是,如果混合引用 LAST_INSERT_ID() 和 LAST_INSERT_ID(expr),则效果未定义
和:
生成的 ID 按 每个连接保存在服务器中。这意味着该函数返回给给定客户端的值是为该客户端影响 AUTO_INCRMENT 列的最新语句生成的第一个 AUTO_INCRMENT 值。该值不会受到其他客户端的影响,即使它们生成自己的 AUTO_INCRMENT 值。
当您同时使用LAST_INSERT_ID()和 时LAST_INSERT_ID(expr),行为是未定义的。此外,TRIGGER 可以被视为一个连接(它直接在服务器上运行),而 INSERT 和 CREATE 语句可能是从不同的连接调用的。鉴于此,以及已报告的与版本之间的 LAST_INSERT_ID 相关的各种更改和错误,您的方法可能会出现问题。
回到 Josh Davis 所说的,我倾向于解决id = LAST_INSERT_ID(id)INSERT 语句中的使用问题。officer_id了解如何在INSERT INTO account语句中导出 接收零值的值也会很有帮助。
| 归档时间: |
|
| 查看次数: |
2805 次 |
| 最近记录: |