- PR -

ユニークなIDの自動生成

投稿者投稿内容
ひろ
会議室デビュー日: 2007/07/31
投稿数: 9
投稿日時: 2007-09-06 10:30
MySQL5で
t1というテーブルのフィールドが
+-------+-------------+
| Field | Type |
+-------+-------------+
| id | int(11) |
| name | varchar(10) |
+-------+-------------+
のような構成で、IDが主キーとして
テーブルデータが
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
+----+------+
となっているときに、idが2番の行を削除してから
insert into t1 (name)values('z');
を実行したときに
+----+------+
| id | name |
+----+------+
| 1 | a |
| 2 | z |
| 3 | c |
| 4 | d |
+----+------+
と新しいIDが抜けた隙間になるようにIDを自動生成
したいのですがそういった事は可能でしょうか?
auto_increment属性だと、
+----+------+
| id | name |
+----+------+
| 1 | a |
| 3 | c |
| 4 | d |
| 5 | z |
+----+------+
になってしまいます。
auto_increment値を0にリセットしたらできるかなと思ったのですが
駄目でした。
どなたか良い方法をしっておられる方はおられないでしょうか?
そんなん無理だよという意見でも、無理だとわかる時点で
あきらめが着くので助かります。
よろしくお願いします。

[ メッセージ編集済み 編集者: ひろ 編集日時 2007-09-06 10:32 ]
うちうせん
ベテラン
会議室デビュー日: 2003/08/08
投稿数: 96
お住まい・勤務地: 福岡県
投稿日時: 2007-09-06 11:12
手間はかかりますが、IDを最初からなめていって空きがみつかった時点でそのIDを新IDにする手動検索のような感じでしょうか?
あとは削除するときに削除IDをどこかに記録しておくとか?
自動的に空きを埋める機能は知ってる限りではないと思いますが、追加されてたりするのかも?しれません。
その辺は他の人からのレスを待ちます。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-09-06 11:58
そういうIDをselect(とかそういうIDにinsert)するSQLを書くことはできますよ。

コード:
SELECT  MIN(t1.ID+1) FROM TABLE AS t1

LEFT JOIN TABLE AS t2 ON t1.ID+1=t2.ID
WHERE t2.ID Is Null

INSERT INTO TABLE(ID,NAME)
SELECT MIN(t1.ID+1),'でーた' FROM TABLE AS t1
LEFT JOIN TABLE AS t2 ON t1.ID+1=t2.ID
WHERE t2.ID Is Null



ただしこれの問題点は
| 3 | a |
| 4 | z |
| 6 | c |
| 7 | d |
のような場合「5」が空きIDとして返されます。
(この方法でselectした値と「1」のうち小さい方、とすればいいだけですけどね)

#MIN(TABLE.ID+1)をMIN(t1.ID+1)に修正

#ORDER BY t1.ID を削除

・・昔ブログにかいたやつなのに、、間違い多いwwww

[ メッセージ編集済み 編集者: べる 編集日時 2007-09-06 12:24 ]
ひろ
会議室デビュー日: 2007/07/31
投稿数: 9
投稿日時: 2007-09-06 13:15
すいません。質問させて下さい。

引用:

コード:
SELECT  MIN(t1.ID+1) FROM TABLE AS t1
LEFT JOIN TABLE AS t2 ON t1.ID+1=t2.ID
WHERE t2.ID Is Null





t1はもとのテーブルとしてt2はどこから出てきたのでしょうか?
上記SQL文を実行してみましたがエラーが返ってきます。
色々と調べて上記SQL文をなんとか読解しようとはしているのですが
なにぶんSQLの初心者なもので・・・
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2007-09-06 13:44
ごめんなさいTABLEという名前(しかもt1もかぶって、、)がよくなかったですね。
ひろさんの最初の例でいうとこうなるでしょうか。

コード:
SELECT  MIN(table1.ID+1) FROM t1 AS table1
LEFT JOIN t1 AS table2 ON table1.ID+1=table2.ID
WHERE table2.ID Is Null



table1もtable2も元は同じt1テーブルです。自己結合とか呼ばれたりします。
ひろ
会議室デビュー日: 2007/07/31
投稿数: 9
投稿日時: 2007-09-06 13:57
できました!
これで解決しそうです。

table1とtable2は一時的にt1をコピーしたものなんですね。
自己結合ですか。色々便利そうなので勉強してみます。

ありがとうございました。
shimix
ぬし
会議室デビュー日: 2004/08/05
投稿数: 512
お住まい・勤務地: 大分市
投稿日時: 2007-09-06 14:19
引用:

ひろさんの書き込み (2007-09-06 13:57) より:
table1とtable2は一時的にt1をコピーしたものなんですね。


いや「t1 AS table1」「t1 AS table2」などをコピーと呼んでは間違いの元だと思うので、正しく理解しておいてください。けっしてt1をコピーしてtable1,table2を作成しているわけではないので・・。
よっしー
大ベテラン
会議室デビュー日: 2007/05/17
投稿数: 143
投稿日時: 2007-09-06 15:03
IDを自分で採番するときは、トランザクションに気をつけた方が良いですよ。
同時に実行して、同じIDが取得されたら目が当てられません。
採番用の関数を作って中でダーティーリードした方が良いと思います。

素直にauto_incrementが安全だと思いますよ。

※追記
あと、デッドロックも気になります。

[ メッセージ編集済み 編集者: よっしー 編集日時 2007-09-06 15:05 ]

スキルアップ/キャリアアップ(JOB@IT)