我有一个 BEFORE INSERT TRIGGER用于计算 AUTO_INCREMENT列的值 ( id_2 )。
id_1 | id_2 | data
1 | 1 | 'a'
1 | 2 | 'b'
1 | 3 | 'c'
2 | 1 | 'a'
2 | 2 | 'b'
2 | 3 | 'c'
2 | 4 | 'a'
3 | 1 | 'b'
3 | 2 | 'c'
我有 PRIMARY(id_1, id_2) 并且我正在使用 InnoDB。之前,该表使用的是 MyISAM,我没有遇到任何问题:id_2被设置为 AUTO_INCREMENT ,因此 id_1 的每个新条目会生成新的 id_2在其自己的。现在,在切换到 InnoDB 之后,我有这个触发器来做同样的事情:
SET @id = NULL;
SELECT COALESCE(MAX(id_2) + 1, 1) INTO @id FROM tbl WHERE id_1 = NEW.id_1;
SET NEW.id_2= @id;
它工作得很好,除了现在 LAST_INSERT_ID()有错误的值(它返回 0)。很多代码依赖于 LAST_INSERT_ID()是正确的。然而,自 MySQL 5.0.12 以来,对 LAST_INSERT_ID 所做的任何更改在 TRIGGERS 内不影响全局值。有什么办法可以绕过这个吗?我可以轻松设置 AFTER UPDATE TRIGGER这改变了 LAST_INSERT_ID调用LAST_INSERT_ID(NEW.id_2) ,但是任何客户端都会得到 LAST_INSERT_ID设置为 0。
是否有任何可行的解决方法来强制 MySQL 维持 LAST_INSERT_ID 的状态?触发器内部发生了哪些变化?除了切换回支持开箱即用的 MyISAM 或运行另一个 SELECT max(id_2) FROM tbl WHERE id_1 = :id 之外,还有其他选择吗?作为事务的一部分以确保找到的行将是之前插入的行?
> SHOW CREATE TABLE tbl;
CREATE TABLE `tbl` (
`id_1` int(11) NOT NULL,
`id_2` int(11) NOT NULL,
`data` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id_1`,`id_2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
示例:
INSERT INTO tbl (id_1, id_2, data) VALUES (1, NULL, 'd');
SELECT LAST_INSERT_ID();
第一个语句将插入行 1 | 4 | 'd'到表中。第二条语句将返回 0 ,但我需要它返回 4 .
由 Ravinder Reddy 询问, 添加有关系统的简短说明:
我有一个包含篮子的表,还有另一个包含项目的表(tbl)。 basket 由应用程序创建并分配了一个来自 AUTO_INCREMENT 的 ID在篮子的 table 上。任务是将 items 插入 id = id_1 的篮子中, 进入 tbl ,在该篮子的范围内为他们分配一个唯一的 ID。每个 item 都有一些 data与之关联,可能会在同一个篮子中重复。所以在实践中,我试图存储所有 data单个篮子中的条目,然后能够通过其 id_1 引用(和检索)这些单独的条目- id_2对。
最佳答案
根据你的表结构描述,很明显它没有可以自动生成值的主键字段。 MySQL 的 information_schema.tables 不保存 auto_increment 值,但对于那些未定义 auto_increment 的字段,null。
触发问题:
您的触发器主体中使用的代码块似乎取决于 id 字段的显式计算和输入。它没有使用 auto_increment 字段的默认行为。
根据 MySQL's documentation on LAST_INSERT_ID :
LAST_INSERT_ID() returns a BIGINT UNSIGNED (64-bit) value
representing the first automatically generated value
successfully inserted for an AUTO_INCREMENT column
as a result of the most recently executed INSERT statement.
很明显,它仅适用于auto_increment 字段。
id_1 和 id_2 字段都没有属性 auto_increment。
由于这个原因,尽管您在插入时将 null 作为这些字段的输入传递,但不会自动生成任何值并将其分配给它们。
更改您的表以将 auto_increment 设置为那些 id_x 字段之一,然后开始插入值。一个警告是,在插入期间将值显式传递给 auto_increment 字段将导致 last_insert_id 返回一个 零 或最近自动生成的值,但不会NEW.id。在插入期间传递 null 或不选择 auto_increment 字段将触发为该字段生成新值,last_insert_id 可以选择并返回它。
以下示例演示了上述行为:
mysql> drop table if exists so_q27476005;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> create table so_q27476005( i int primary key );
Query OK, 0 rows affected (0.33 sec)
以下语句显示字段的下一个适用 auto_increment 值。
mysql> select auto_increment
-> from information_schema.tables
-> where table_name='so_q27476005';
+----------------+
| auto_increment |
+----------------+
| NULL |
+----------------+
1 row in set (0.00 sec)
让我们尝试在该字段中插入一个 null 值。
mysql> insert into so_q27476005 values( null );
ERROR 1048 (23000): Column 'i' cannot be null
上述语句失败,因为输入到 not null primary key 字段但未归因于 auto_increment。仅对于 auto_increment 字段,您可以传递 null 输入。
现在让我们看看 last_insert_id 的行为:
mysql> insert into so_q27476005 values( 1 );
Query OK, 1 row affected (0.04 sec)
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 0 |
+------------------+
1 row in set (0.00 sec)
由于输入是显式的,并且该字段未归因于auto_increment,
调用 last_insert_id 结果为 0。请注意,这也可以是其他值,
如果对另一个表的任何其他 auto_increment 字段有另一个 insert 调用,
在同一个数据库连接 session 中。
让我们看看表中的记录。
mysql> select * from so_q27476005;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
现在,让我们将 auto_increment 应用于字段 i。
mysql> alter table so_q27476005 change column i i int auto_increment;
Query OK, 1 row affected (0.66 sec)
Records: 1 Duplicates: 0 Warnings: 0
以下语句显示字段 i 的下一个适用 auto_increment 值。
mysql> select auto_increment
-> from information_schema.tables
-> where table_name='so_q27476005';
+----------------+
| auto_increment |
+----------------+
| 2 |
+----------------+
1 row in set (0.00 sec)
您可以交叉检查 last_insert_id 是否仍然相同。
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 0 |
+------------------+
1 row in set (0.00 sec)
让我们在字段 i 中插入一个 null 值。
mysql> insert into so_q27476005 values( null );
Query OK, 1 row affected (0.03 sec)
它成功地将一个null传递给一个primary key字段,
因为该字段属于 auto_increment。
让我们看看生成并插入了哪个值。
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
i 字段的下一个适用auto_increment 值是:
mysql> select auto_increment
-> from information_schema.tables
-> where table_name='so_q27476005';
+----------------+
| auto_increment |
+----------------+
| 3 |
+----------------+
1 row in set (0.00 sec)
mysql> select * from so_q27476005;
+---+
| i |
+---+
| 1 |
| 2 |
+---+
2 rows in set (0.00 sec)
现在,让我们观察一下当为字段提供显式输入时 last_insert_id 的结果。
mysql> insert into so_q27476005 values( 3 );
Query OK, 1 row affected (0.07 sec)
mysql> select * from so_q27476005;
+---+
| i |
+---+
| 1 |
| 2 |
| 3 |
+---+
3 rows in set (0.00 sec)
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 2 |
+------------------+
1 row in set (0.00 sec)
可以看到last_insert_id由于显式输入没有捕获到值。
但是,信息模式确实注册了下一个适用的值。
mysql> select auto_increment
-> from information_schema.tables
-> where table_name='so_q27476005';
+----------------+
| auto_increment |
+----------------+
| 4 |
+----------------+
1 row in set (0.08 sec)
现在,让我们观察当字段输入是自动/隐式时 last_insert_id 的结果。
mysql> insert into so_q27476005 values( null );
Query OK, 1 row affected (0.10 sec)
mysql> select last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 4 |
+------------------+
1 row in set (0.00 sec)
希望这些细节对您有所帮助。
关于mysql - 从 MySQL 中的 TRIGGER 中更改 LAST_INSERT_ID(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27476005/
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只