7

私はこのテーブルを持っています

 CREATE TABLE IF NOT EXISTS `t5` (
  `id` int(11) NOT NULL auto_increment,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `a` (`a`,`b`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1  ;

a_b は一意のキーです。

そして、私はこのようなphpコードを持っています

 $db = DBFactory::getInstance();
 $db->selectDB('test');
 $db->query("insert into t5 (a, b) values(1, 1) on duplicate key update a=1, b=1");
 var_dump(mysql_insert_id());

 $cur = $db->query("select last_insert_id()");
 var_dump(mysql_fetch_assoc($cur));

このコードを 2 回実行すると、私の PC では結果が 1 番目になります

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "1"
}

2位

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

ご覧のとおり、mysql_insert_id() はどちらも同じ値「1」を返します。挿入後の実際の ID を知りたいのですが、次の auto_increment 値は知りたくないので、これで問題ありません。

しかし、別の環境でこのコードを 2 回実行すると、次のようになります。

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "1"
}

2位

int(2)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

違いがわかるように、2 回目の結果 mysql_insert_id() は last_insert_id() と同じ値を返します。

この結果は恐ろしいものですが、その理由はわかりません。私のコードは両方の環境で約 3 か月間正常に動作しましたが、これは今日まで発生しませんでした。誰か説明できますか?約 30 日前に 2 番目の環境の PHP バージョンを 5.3.8 にアップグレードしましたが、その他の変更はありません。これはバグですか?

アップデート

3 番目の mysql サーバー (5.1.38-log) に切り替えます。2 番目の挿入は int(0) array(1) { ["last_insert_id()"]=> string(1) "0" } を返します。

そのため、問題はおそらくmysqlのバージョンに関するものであることに気付きました。

最後に、テーブル定義をこれに変更しました

DROP TABLE IF EXISTS `t5`;
CREATE TABLE IF NOT EXISTS `t5` (
  `id` int(11) NOT NULL auto_increment,
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `t` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `a` (`a`,`b`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

スクリプトも編集します

$db = DBFactory::getInstance();
$db->selectDB('test');
$db->query("insert into t5 (a, b, t) values(1, 1, ".time().") on duplicate key update a=1, b=1, t=".time());
//$db->query("insert ignore into t5 (a, b) values(1, 1)");
var_dump(mysql_insert_id());

$cur = $db->query("select last_insert_id()");
var_dump(mysql_fetch_assoc($cur));

異なる mysql サーバーは同じ mysql_insert_id を返しますが、last_insert_id() は異なります

5.0.24a-コミュニティ-nt

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

5.0.51a-ログ

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "2"
}

5.1.38-ログ

int(1)
array(1) {
  ["last_insert_id()"]=>
  string(1) "0"
}

この動作を制御するシステム変数はありますか? 誰かがそれを知っていれば、それは嬉しいことです。解決策がない場合、私ができる唯一のことは、このような挿入を強制して、別の値でフィールドを更新することです...

4

1 に答える 1

3

あなたが使用しようとしているlast_insert_id()のは意図されていない方法だと思います-これらの場合、何も挿入していないため、戻り値も信頼しないでください。MySQL ドキュメントから:

テーブルに AUTO_INCREMENT 列が含まれていて、INSERT ... UPDATE が行を挿入する場合、LAST_INSERT_ID() 関数は AUTO_INCREMENT 値を返します。代わりにステートメントが行を更新する場合、LAST_INSERT_ID() は意味がありません。

ただし、そのための回避策があるようです(同じドキュメント)-last_insert_idを手動で設定します:

ただし、LAST_INSERT_ID(expr) を使用してこれを回避できます。id が AUTO_INCREMENT 列であるとします。LAST_INSERT_ID() を更新に意味のあるものにするには、次のように行を挿入します。

INSERT INTO table (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;

于 2011-12-09T13:32:34.327 に答える