忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

MySQL AUTO_INCREMENT カラムの自動生成値を取得するLAST_INSERT_ID()について

各種マスタやトランザクションテーブルの構造として、ユニークな主キーとなる AUTO_INCREMENT カラムを持ち、必要であれば、その他のカラムでインデックスを持ったりします。

AUTO_INCREMENT カラムは INSERT 時に指定しなくても MySQL がユニークな数値を割り振ってくれます。
そのため、データを登録する場合は、主キーの値を考えずにどんどん INSERT ができます。

ただし、紐付けするデータが無い場合は良いのですが、伝票データ等でヘッダデータと明細データのテーブルが在る場合、 最初にヘッダデータを登録し、その後でヘッダデータの主キーに紐づく様に明細データを登録することになります。

ヘッダデータの INSERT の後、主キーの値を取得する必要が出てきますが、 そこで LAST_INSERT_ID() 関数の出番となります。
この LAST_INSERT_ID() 関数ですが AUTO_INCREMENT カラムを持つテーブルに対して INSERT 後に SELECT を行えば、主キーの値が取得できます。

テスト用のテーブル生成SQL

先ずはテスト用のテーブルの生成を行います。
以下の通り主キーとして「id」カラム、さらにデータとしてVARCHAR型の「val」カラムを宣言します。

CREATE TABLE t_auto (
    id  INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
    val VARCHAR(32) NOT NULL
);

それではこのテーブルにデータを INSERT して LAST_INSERT_ID() を取得してみます。

レコードの追加とAUTO_INCREMENT値の取得を行うSQL

INSERT INTO t_auto(val) VALUES('test1');
SELECT LAST_INSERT_ID();
SELECT * FROM t_auto;

実行結果は以下の通りです。

MariaDB [test]> INSERT INTO t_auto(val) VALUES('test1');
Query OK, 1 row affected (0.06 sec)

MariaDB [test]> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                1 |
+------------------+
1 row in set (0.00 sec)

MariaDB [test]> SELECT * FROM t_auto;
+----+-------+
| id | val   |
+----+-------+
|  1 | test1 |
+----+-------+
1 row in set (0.00 sec)

MariaDB [test]>

上記の結果から、自動で主キーが割り振られたことが分かります。
再度、「val」カラムに 'test2' のデータを設定してみますと、以下の様になります。

MariaDB [test]> INSERT INTO t_auto(val) VALUES('test2');
Query OK, 1 row affected (0.05 sec)

MariaDB [test]> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                2 |
+------------------+
1 row in set (0.00 sec)

MariaDB [test]> SELECT * FROM t_auto;
+----+-------+
| id | val   |
+----+-------+
|  1 | test1 |
|  2 | test2 |
+----+-------+
2 rows in set (0.00 sec)

MariaDB [test]>

確かに、AUTO_INCREMENT のカラムが加算されているのが分かります。

さて、ここでトランザクション処理を INSERT の前後にはさむ形にして、追加処理をロールバックしてみます。
以下の様なSQLを実行します。

トランザクション処理でINSERTをはさむSQL

BEGIN;
INSERT INTO t_auto(val) VALUES('test3');
ROLLBACK;
SELECT LAST_INSERT_ID();
SELECT * FROM t_auto;

実行結果は以下の様になります。
INSERT は確かにロールバックされてテーブルに 'test3' のデータは残っていませんが、 主キーの「id」は1個加算され「3」になりました。

この結果が大事なところで、トランザクション処理では現在の AUTO_INCREMENT のカラムの値が、他の接続先からの INSERT で値が競合しない様になっていますので、今回の様に AUTO_INCREMENT 値は「3」となります。

よって次に INSERT 処理を正常に行えば AUTO_INCREMENT 値は「4」となります。

MariaDB [test]> BEGIN;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> INSERT INTO t_auto(val) VALUES('test3');
Query OK, 1 row affected (0.01 sec)

MariaDB [test]> ROLLBACK;
Query OK, 0 rows affected (0.01 sec)

MariaDB [test]> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                3 |
+------------------+
1 row in set (0.00 sec)

MariaDB [test]> SELECT * FROM t_auto;
+----+-------+
| id | val   |
+----+-------+
|  1 | test1 |
|  2 | test2 |
+----+-------+
2 rows in set (0.00 sec)

MariaDB [test]>

今度はトランザクションをコミットする様にして実行すると、確かに AUTO_INCREMENT 値は「4」となっています。

MariaDB [test]> BEGIN;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> INSERT INTO t_auto(val) VALUES('test4');
Query OK, 1 row affected (0.01 sec)

MariaDB [test]> COMMIT;
Query OK, 0 rows affected (0.03 sec)

MariaDB [test]> SELECT LAST_INSERT_ID();
+------------------+
| LAST_INSERT_ID() |
+------------------+
|                4 |
+------------------+
1 row in set (0.00 sec)

MariaDB [test]> SELECT * FROM t_auto;
+----+-------+
| id | val   |
+----+-------+
|  1 | test1 |
|  2 | test2 |
|  4 | test4 |
+----+-------+
3 rows in set (0.00 sec)

MariaDB [test]>











PR

コメント

コメントを書く