在Web应用程序中给出此表设计:
CREATE TABLE `invoice` (
`invoice_nr` int(10) unsigned NOT NULL AUTO_INCREMENT,
`revision` int(10) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`invoice_nr`,`revision`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci
插入新发票修订并获取指定的修订号是最方便可靠的方法是什么?
第一个明显的方法让我觉得在共享环境中不可靠:
SELECT MAX(revision)+1 AS next_revision -- E.g. 2
FROM invoice
WHERE invoice_nr = 31416;
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, 2);
这个替代方案看起来略微更好(我不知道它是否真的更好):
INSERT INTO invoice (invoice_nr, revision)
SELECT 31416, MAX(revision)+1
FROM invoice
WHERE invoice_nr = 31416;
...但除非我运行新查询,否则我无法知道修订号:
SELECT MAX(revision) AS last_revision
FROM invoice
WHERE invoice_nr = 31416;
是否有推荐的方法?
App在PHP上运行,具有良好的旧mysql扩展名 - mysql_query()
等等。
答案 0 :(得分:3)
Mysql有一个名为last_insert_id()
的函数,它返回上一个自动生成的ID。因此,您可以在插入数据后直接SELECT last_insert_id()
。
PHP有一个内置函数,用于执行此操作,称为mysql_insert_id()
。
有关此内容的更多信息:http://www.php.net/manual/en/function.mysql-insert-id.php
虽然这一切都是真实的并且通常很有用但实际上并不是这里的目标。我怎么做这个是生成表。一个称为发票,其中包含自动增量字段,另一个称为invoice_revisions。这应该与具有添加的视野字段的发票表具有相同的格式。
然后,当您更新发票表时,首先执行以下操作:
INSERT INTO invoice_revision SELECT i.*,IFNULL(max(ir.revision),0)+1 AS revision FROM invoice i LEFT JOIN invoice_revision ir on ir.invoice_nr = i.invoice_nr WHERE i.invoice_nr = ?
然后照常更新发票表。这样,您可以在invoice_revisions表中的发票表和所有先前版本的列表中获得最新数据。
请注意,如果您使用的是Myisam表,并在该表的auto_increment中设置修订版:
http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html
答案 1 :(得分:0)
如果你在插入物周围放置一个正确的隔离事务并选择nobody,则可以在两个语句之间改变这些表。
另一种方法是使用存储过程来执行这两个命令并返回结果。
答案 2 :(得分:0)
我从MySQL手册中收集了一些技巧。我想我应该在这里分享他们的记录。
如果您锁定表格,其他同步进程将排队。然后,你不需要任何特殊的技巧来避免欺骗:
LOCK TABLES invoice WRITE;
SELECT MAX(revision)+1 AS next_revision -- E.g. 2
FROM invoice
WHERE invoice_nr = 31416;
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, 2);
-- Or INSERT INTO ... SELECT
UNLOCK TABLES;
LAST_INSERT_ID()函数接受可选参数。如果设置,它将返回此值,并且还将其存储为当前会话,因此下一次调用LAST_INSERT_ID()将返回该值。这是模拟序列的一种方便方法:
CREATE TABLE `sequence` (
`last_value` INT(50) UNSIGNED NOT NULL DEFAULT '1' COMMENT 'Last value used'
);
START TRANSACTION;
UPDATE sequence
SET last_value=LAST_INSERT_ID(last_value+1);
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, LAST_INSERT_ID());
COMMIT;