各種マスタやトランザクションテーブルの構造として、ユニークな主キーとなる AUTO_INCREMENT カラムを持ち、必要であれば、その他のカラムでインデックスを持ったりします。
AUTO_INCREMENT カラムは INSERT 時に指定しなくても MySQL がユニークな数値を割り振ってくれます。
そのため、データを登録する場合は、主キーの値を考えずにどんどん INSERT ができます。
ただし、紐付けするデータが無い場合は良いのですが、伝票データ等でヘッダデータと明細データのテーブルが在る場合、 最初にヘッダデータを登録し、その後でヘッダデータの主キーに紐づく様に明細データを登録することになります。
ヘッダデータの INSERT の後、主キーの値を取得する必要が出てきますが、 そこで LAST_INSERT_ID() 関数の出番となります。
この LAST_INSERT_ID() 関数ですが AUTO_INCREMENT カラムを持つテーブルに対して INSERT 後に SELECT を行えば、主キーの値が取得できます。
テスト用のテーブル生成SQL
先ずはテスト用のテーブルの生成を行います。
以下の通り主キーとして「id」カラム、さらにデータとしてVARCHAR型の「val」カラムを宣言します。
1 2 3 4 | CREATE TABLE t_auto ( id INT AUTO_INCREMENT NOT NULL PRIMARY KEY , val VARCHAR (32) NOT NULL ); |
それではこのテーブルにデータを INSERT して LAST_INSERT_ID() を取得してみます。
レコードの追加とAUTO_INCREMENT値の取得を行うSQL
1 2 3 | INSERT INTO t_auto(val) VALUES ( 'test1' ); SELECT LAST_INSERT_ID(); SELECT * FROM t_auto; |
実行結果は以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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' のデータを設定してみますと、以下の様になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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
1 2 3 4 5 | 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」となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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」となっています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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]> |
コメント