MySQLでオートインクリメントの最新番号を求めるには、どうしたらいいのでしょうか?


検索したら「LAST_INSERT_IDを使う」っとあったのですが、INSERTしてデータを追加した後でないと、取得できないようです。

私の認識不足やSQLの書き方が悪いのかも知れませんが、もしINSERTしなくても最新のオークインクリメントの番号を、取得できる方法がありましたら、教えていただければと思います。

※MySQLは4.0系でお願いします。

回答の条件
  • 1人2回まで
  • 登録:2007/09/18 01:11:55
  • 終了:2007/09/18 14:27:02

回答(6件)

id:hayashi4 No.1

hayashi4回答回数76ベストアンサー獲得回数12007/09/18 01:27:07

id:kt26

URLだけ出されても・・・

2007/09/18 01:38:21
id:KUROX No.2

KUROX回答回数3542ベストアンサー獲得回数1402007/09/18 01:53:17

ポイント20pt

Oracleさんはシーケンス使えるので問題ないのですと

いうことでOracleのこの機能をMysqで使うのには

どうすればいいかを検索かけました。

実装方法はこんな感じのようです。

http://www.art-code.org/2006/06/auto_increment.html

>INSERTしなくても最新のオークインクリメントの番号を、

>取得できる方法

INSERTしなくても、INSERTした後のオークインクルメント番号

を知りたいという意味だと思うんですが・・。

ちょっと私にはわかりませんね。

それ以前に、知らなくても実装する方法はないんでしょうか?

id:kt26

う~ん、URL先でも上手くいかないですね。そっくり同じにしてみたのですが。


>>INSERTしなくても、INSERTした後のオークインクルメント番号

>>を知りたいという意味だと思うんですが・・。

ここでいう「意味」とは、私の本質問の意図の事ですか?


オートインクリメントの番号をINSERTせずに知りたいというのは、WEBコンテンツのフォーム登録確認時に表示したいからです。


例えば、「この投稿には○番のIDが付与されます。よろしいですか?」と言うような、フォーム登録の確認で、使用したいのです。


通常、オートインクリメントを与えたフィールド(例えばid)は、登録があると自動的に番号が付加されますが、データを削除されても順番に番号が付いていきます。(idが100,101,102とデータがある場合、102を削除したら次は103になる)


だから、既存の最新データのidを取得し、+1して「登録番号」としても、実際に登録される番号が違う可能性があります。


なので、登録する前に実際に付加されるオートインクリメントの数値を知りたいと思いました。

2007/09/18 04:05:02
id:kakicg No.3

kakicg回答回数44ベストアンサー獲得回数32007/09/18 06:07:24

ポイント20pt

最後にINSERTしたidは

SELECT LAST_INSERT_ID( ) ;

で得る事ができます。でもデータベースにアクセスする人が複数いる場合は、自分が次に使うidが今表示させたid+1になるとは限らないですよ。INSERTしなければ次のidは確定できないと考えた方が良さそうです。

id:kn1967 No.4

kn1967回答回数2915ベストアンサー獲得回数3012007/09/18 08:35:46

ポイント25pt

想像してみてください。

A君が書き込んで確認画面が出た
(A君には101という番号が返された。)
  ↓
B君が書き込んで確認画面が出た
(B君には102という番号が返された。)
  ↓
B君のほうが先に確認済みボタンをクリックした。
(オートインクリメントなので101で登録された)

といったような具合になるとダメですよね。


では、

A君が書き込んで確認画面が出た
(A君には101という番号が返された。)
  ↓
B君が書き込んだら他の人が作業中と言う事で待たされた。
  ↓
B君は何度も書き込みボタンをクリックするが「他の人が作業中」と言う事で待たされた。
  ↓
A君が確認済みボタンをクリックした。
(オートインクリメントなので1で登録された)
  ↓
B君は何度もクリックを続けていたが、やっとの事で確認画面が返ってきた。
(B君には102という番号が返された。)

というように作業中はデータベースをロック(独占)すれば良いのだが、

上記のようにB君はいつ接続できるともしれないデータベースに何度も挑戦するような形になり

タイミングが悪ければ後から接続を試みたC君やD君に先を越されて

B君はいつまでも待たされる可能性がでてくる・・・。


上記のようにロックしてしまえば番号はズレたりしませんが

あまり賢い処理方法とは言えないですよね。

で、結局のところ、一旦仮に書き込んでしまうといった手順が必要になってくると言う事になります。

レコードに仮登録中フラグを立てておいて、確認が取れた時点でフラグを消去。

定期的に規定の時間を過ぎてもフラグが立ったままのレコードは強制削除。

仮登録日時と確認日時の2つを持たせるという手でも良いでしょう。


phpMyAdminで表示されているauto_incrementの値については

phpMyAdminでauto_incrementの値を表示している最中に

新しいレコードを書き込むSQLを平行して実行し、書き込めたかどうか、

そして、その後でauto_incrementの値はどうなっているのかを確認してみてください。

書き込めなかったとすればロックされている。

書き込めたとすればphpMyAdminでの表示はその時点だけのものだった。

という違いが理解できる事でしょう。

id:kt26

詳しくありがとうございます。

確認する=>レコードを登録する=>正式に登録する場合はUPDATE


と言うのは理屈として理解できますし、おそらくこの方法しかないのかも知れません。


しかし、フラグ処理や「一定時間~」に関する処理を入れると、それだけ余計な処理も増えるので、それが問題ですね。

2007/09/18 14:25:38
id:Yota No.5

Yota回答回数453ベストアンサー獲得回数282007/09/18 08:50:20

ポイント20pt

次のAUTO_INCREMENT値(id)をテーブル(hoge)から取得する。

SELECT IFNULL(MAX(id)+1,1) AS next_id FROM hoge ;

参照したURL。

http://dev.mysql.com/doc/refman/4.1/ja/control-flow-functions.ht...

id:kt26

登録数によってID番号が決まるようで、レコードを削除したらnext_idの値も減るので、これは利用できないと思います。

2007/09/18 14:22:48
id:b-wind No.6

b-wind回答回数3344ベストアンサー獲得回数4402007/09/18 09:24:38

ポイント20pt

まず結論から言うと事前に知る方法はないです。

MySQL の AUTO INCREMENT はシーケンスではないので。


で、代替手段としては INSERT してしまってから処理完了後、UPDATE をかけるか、採番用に別にテーブルを作成しシーケンスの代わりに使うかぐらいです。

  • id:kt26
    ちょっと質問の意図がわかりづらいかもしれませんので、コメントにて追記します。

    phpMyAdminでテーブルを選択し、ヘッダーメニューにある「操作」をクリックすると、テーブルオプションのauto_incrementの欄に、次に与えられる値が入っています。

    そういう表示をしたいという質問です。(phpMyAdminのソースを見てもわからなかったので…。)
  • id:KUROX
    IDを確定させるために、とりあえずINSERTさせてしまいます。
    その後UPDATEを行えばどうでしょうか?

    で登録されないのならロールバック。

  • id:Yota
    >登録数によってID番号が決まるようで
    レコードの数とAUTO_INCREMENTの値は関係ありません。
    削除しても歯抜けになるだけです。
  • id:kn1967
    >フラグ処理や「一定時間~」に関する処理を入れると、
    >それだけ余計な処理も増えるので、それが問題ですね。

    既にご承知だと思いますが、今回の件に限らず、
    機能を付けるために処理が増えるというのは致しかた無かったりしますので
    (1)「処理コストの増大によるシステム負荷の増大」
    (2)「機能の必要性」
    の2つを天秤にかけて取捨選択するしかないですね。
  • id:kt26
    コメントありがとうございます。

    自分で考えた以外に「もう少し簡潔に出来ないものか」っと思ってはてなを利用していますが、おっしゃるように致し方ない部分も発生しますよね。

    とりあえず、出来る方法はみなさんが書いていただいたとおりなので、あとは本当に必要か否か検討します。

    ありがとうございました。
  • id:suzukitaro
    みんなめちゃくちゃ嘘ばっかりで、当方もかなり悩みました。▄█▀█●
    こんな人たちが、日本のITを支えていると思ったら、怖いよ~

    いまさらですが、参考になれば。
    php前提で、ソースモロ書きですが適当に置き換えください。


    //Numberフィールド(auto_increment)のID 最新番号を求める
    //Auto_increment 次の自動インクリメント値

    $sql_str = "SHOW TABLE STATUS";
    $sql_ret = mysql_query($sql_str, $conn) or die('お前エラーだよ 2ch_inc.php' . mysql_error() );
    $row = mysql_fetch_array($sql_ret);
    $next_auto_increment = $row[Auto_increment];

    もう遅かったかな?
  • id:b-wind
    >みんなめちゃくちゃ嘘ばっかりで、当方もかなり悩みました。▄█▀█●
    >こんな人たちが、日本のITを支えていると思ったら、怖いよ~
    大口叩く割には君も間違ってる。

    SHOW TABLE STATUS で取得した値は確かに次の AUTO INCREMENT の値だが、それを「自分が使えるとは限らない」。

    具体的には複数のコネクションが同時実行された場合にどのコネクションがその値を使うかは早い者勝ち。
    トランザクションを使用しても無理。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません