增加新行的值

时间:2010-06-23 12:10:08

标签: php mysql innodb

在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()等等。

3 个答案:

答案 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手册中收集了一些技巧。我想我应该在这里分享他们的记录。

1。表锁定

如果您锁定表格,其他同步进程将排队。然后,你不需要任何特殊的技巧来避免欺骗:

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;

2。 LAST_INSERT_ID(表达式)

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;