“ PDO :: lastInsertId”の代替/“ mysql_insert_id”
-
08-07-2019 - |
質問
" lastInsertId"を使用しているといつも聞きます。 (PDOを使用していない場合はmysql_insert_id())は悪です。トリガーの場合、それは明らかにそうです。なぜなら、INSERTが作成した最後のIDではないものを返す可能性があるからです。
$DB->exec("INSERT INTO example (column1) VALUES ('test')");
// Usually returns your newly created ID.
// However when a TRIGGER inserts into another table with auto-increment:
// -> Returns newly created ID of trigger's INSERT
$id = $DB->lastInsertId();
代替手段は何ですか?
解決
ADOdbのルート( http://adodb.sourceforge.net/ )に移動すると、挿入IDを手前に作成し、挿入時に明示的にIDを指定できます。これは移植可能に実装でき(ADOdbはさまざまなデータベースをサポートしています...)、正しい挿入IDを使用していることを保証します。
PostgreSQLのSERIALデータ型は似ていますが、テーブルごと/シーケンスごとであり、リクエスト時に最後の挿入IDが必要なテーブル/シーケンスを指定する点が異なります。
他のヒント
私見、それは「悪」だけと考えられています。他のSQLデータベース(存在する場合)にはほとんどないためです。
個人的には非常に便利だと思うので、他のシステムでは他のもっと複雑な方法に頼る必要はないことを願っています。
代わりの方法は、代わりにシーケンスを使用することです。そのため、挿入を行う前に自分でIDを生成します。
残念ながら、MySQLではサポートされていませんが、Adodbなどのライブラリは別のテーブルを使用してそれらをエミュレートできます。ただし、エミュレーション自体はlastInsertId()または同等のものを使用すると思いますが、少なくともシーケンスにのみ使用されるテーブルでトリガーを使用する可能性は低くなります
実際には最新の技術でもないようですが、書き込みロックを使用して、最後に挿入されたIDを確実に取得します。
洗練されておらず、効率的でもありませんが、挿入したデータに一意のフィールドが含まれている場合、SELECTは明らかに目的のものを生成できます。
例:
INSERT INTO example (column1) VALUES ('test');
SELECT id FROM example WHERE column1 = 'test';
これを試すことができます:
$sql = "SELECT id FROM files ORDER BY id DESC LIMIT 1";
$PS = $DB -> prepare($sql);
$PS -> execute();
$result = $PS -> fetch();