いつもお世話になっております。
create table AAA(
ID int(6) primary key not null auto_increment,
DATA varchar(30),
)engine=MyISAM;
というテーブルにおいて、
insertをすると、IDが1から順に割り振られていきますが、
途中のレコードをdeleteすると、そこが空きのID番号となってしまい、
次にinsertすると、空き番号が残ってしまいます。
やりたいことは、その空き番号を有効活用するために、
auto_incrementを使用せずに、空き番号を適当に取得して、
insertをしたいのです。
何か効率的な良い方法をご存知の方がいらっしゃいましたら、
ご教授いただけると幸いです。
よろしくお願いいたします。
No.4ベストアンサー
- 回答日時:
#2回答者です。
IDの通番を格納した表を使って、差分検索しない場合、どういうSQLで得られるかというと、以下のようなSQLになります。
<空き番号の内、最小値を求める(その1)>
select max(ID)+1 as empty_ID
from
(select 0 as ID
union
select ID from AAA) as z
where ID<(
select
min(ID) as ID
from(
select
(select count(*) from AAA where ID<=x.ID) as rownum,
ID
from AAA as x
) as y
where rownum<>ID
);
何をやっているかというと、次のようなことを行っています。
(1)行に通番を付ける
(2)通番とIDが不一致になる最小のIDを求める
(3)IDの最小値未満のデータをunionでくっつけ、最大のID+1を得る
IDの通番を格納した表を使用する方法では、次のようなSQLになります。通番は、ID_tbl表に入っているものとします。
<空き番号の内、最小値を求める(その2)>
select min(ID) as empty_ID
from ID_tbl as x
where not exists(select * from AAA where ID=x.ID)
;
差分検索するための通番管理表を作成するのが、面倒とも思えるでしょうが、空き番号を得るSQLが、かなり簡単になります。
また、MySQL 5.0以降では、ストアドプロシジャを使えますから、通番管理表を簡単に作ることも可能です。
(1)管理表の定義
drop table if exists ID_tbl;
create table ID_tbl
(ID int primary key);
(2)通番を格納するストアドプロシジャの定義
drop procedure if exists ID_gen; -- 存在したら削除
delimiter // -- 終端記号の変更
create procedure ID_gen
(in p1stVal int, -- 初期値
in pEndVal int, -- 終了値
in pIncVal int, -- 増分
in pMsgItv int, -- 何行毎に経過メッセージを出力
out pRowNum int
)
-- -------------------------------------------
-- 多量データ生成
-- -------------------------------------------
begin
declare RowNum int; -- 格納行カウンタ
declare wVal int;
declare fAscDesc smallint; -- 昇順/降順 0:昇順、1:降順
declare cAsc smallint default 0;
declare cDesc smallint default 1;
-- 昇順か降順か
if p1stVal<=pEndVal and pIncVal>=0 then
set fAscDesc=cAsc;
else
set fAscDesc=cDesc;
end if;
--
set RowNum=0;
set wVal=p1stVal;
--
while (fAscDesc=cAsc and wVal<=pEndval) or (fAscDesc=cDesc and wVal>=pEndval) do
insert into ID_tbl
values(wVal);
set RowNum=RowNum+1;
if pMsgItv>0 then
if RowNum%pMsgItv=0 then
select
concat(cast(RowNum as char(5)),
' row insert,wVal=',
cast(wVal as char(5))
) as msg;
end if;
end if;
set wVal=wVal+pIncVal;
end while;
set pRowNum=RowNum;
end;
//
delimiter ; -- 終端記号を元に戻す
(3)ストアドプロシジャの実行
call ID_gen(1, -- 初期値
5000, -- 終了値
1, -- 増分
100, -- 経過メッセージ間隔(行数)
@rownum);
select @rownum;
chukenkenkou様
複数回にわたり、大変にご親切なご回答をいただきまして、誠にありがとうございました。大変に恐縮しております。
やりたいことも実現できそうです。
ありがとうごうございました。
No.6
- 回答日時:
#5さんの言う「実際には削除せず、削除フラグを設ける」というのは、
更新の方が削除より、インデクスなどの影響範囲が狭まるためで、高トラフィック環境等でよく行われる方法です。
しかし、削除フラグを立てただけのデータがいつまでも存在するのも問題で、例えば5年後、10年後にはそういったデータが多量件数になっているかも知れません。インデクスの段数も多くなってしまい、通常の検索の性能も劣化してしまうかも知れません。バックアップやリストアの時間も、長くなってしまいます。
これらを許容でき、よほどディスクスペースに余裕があるのでないなら、いずれ夜間バッチやメンテ日で、削除フラグを立てたデータを実際に消すといった作業が必要になります。
chukenkenkou様
何度も丁寧なご回答いただきまして、大変にありがとうございました。
大変に勉強になりました。
ありがとうございました。
No.5
- 回答日時:
そもそもデータは削除する物ではありません。
削除フラグだけたてて表示しないようにするのが賢明。
つまり「空き番号」は発生しません。
yambejp様
ご回答をありがとうございました。
ご指摘、ごもっともですね。
別のテーブルでは、削除フラグを立てる方法も利用しようと思います。
ありがとうございました。
No.3
- 回答日時:
>このようなことをする設定か何かあると良いなと思うのですが、
いかがなものでしょうか
ですから、その回答をしたつもりです。シリアルファイルではそれは不可能です。その番号までを別のファイルに読み込み、データを入れてからまたその次から読むという格好にしなければなりません。それをしないためにはファイルをランダムファイルにしなければならないのです。
Willyt様
ご回答をありがとうございました。
RDBというのはランダムアクセスファイルになっているのかと思っているのですが、少しハイレベルな感じで今回はよく理解できませんでした。後学のためにも時間を見つけて勉強しておきます。
ありがとうございました。
No.2
- 回答日時:
MySQLのバージョンは何ですか?
空いている番号の内、最小値を使いたいのでしょうか?
一番簡単で安定した性能を出せるのは、1~nの連番を格納した表を作り、その表とAAA表で差分検索する方法です。
この回答への補足
chukenkenkou様
ご回答ありがとうございます。
MySQLのバージョンは5.0です。
>空いている番号の内、最小値を使いたいのでしょうか?
その通りです。
>一番簡単で安定した性能を出せるのは、1~nの連番を格納した表を作り、その表とAAA表で差分検索する方法です。
なるほどです。MySQL自体にはそういった空き番号の最小値を取得する機能はなさそうな感じですね。こういったニーズはあまり無いものなのでしょうか?
他に何か方法がありそうでしたら、またご教授いただければ幸いです。
No.1
- 回答日時:
通常のファイルはシリアルアクセスになっていますから、その大きさは入れたデータの量になります。
任意の番号に入れたいならランダムアクセスファイル宣言をすればキーを指定して任意の場所に入力できます。しかし、そのためには例えば1000番まで割り振るなら予め1000個分の空き領域を占有することになりますからHDがオーバーフローしないように注意して下さい。この回答への補足
Willyt様
早速のご回答、ありがとうございました。
少し私の質問が分かりにくかったかもしれません。
補足させてください。
10件のレコードをinsertすると、
IDは1から順に10まで割り振られます。
例えば3番目のレコードを削除した場合、
次にinsertした場合は、auto_incrementのために、
ID=11のレコードとして記録されますが、
3番がすでに空き番号となっているので、
ID=3のレコードとして記録されて欲しいのです。
このようなことをする設定か何かあると良いなと思うのですが、
いかがなものでしょうか?
よろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL my_itemsテーブルのIDにAUTO_INCREMENT を追加ができるかで 1 2023/01/03 09:09
- MySQL PHPとMySQLを使った掲示板の作り方 1 2022/06/02 13:00
- MySQL エラー 1068 (42000): 複数の主キーが定義されていますエラー 2 2022/11/17 04:36
- MySQL `picture` varchar(255) のコマンドで間違いないでしょうか? 1 2022/11/21 04:08
- PHP php エラー 2 2022/10/23 16:43
- MySQL MYSQL エラー 2 2022/10/18 11:37
- MySQL テーブル作成です。どこかのスペルが間違っているか記号など スペースかな? 1 2022/10/01 05:08
- MySQL 次の時間帯の勝率の合計を求めるSQL文 1 2023/07/04 17:12
- MySQL あと、MySQLの文字コードはutf8 気になりますね 1 2022/12/01 07:22
- MySQL MySQLのテーブル作成で 自信がありません。 2 2022/08/28 05:35
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・「黒歴史」教えて下さい
- ・2024年においていきたいもの
- ・我が家のお雑煮スタイル、教えて下さい
- ・店員も客も斜め上を行くデパートの福袋
- ・食べられるかと思ったけど…ダメでした
- ・【大喜利】【投稿~12/28】こんなおせち料理は嫌だ
- ・前回の年越しの瞬間、何してた?
- ・【お題】マッチョ習字
- ・モテ期を経験した方いらっしゃいますか?
- ・一番最初にネットにつないだのはいつ?
- ・好きな人を振り向かせるためにしたこと
- ・【選手権お題その2】この漫画の2コマ目を考えてください
- ・2024年に成し遂げたこと
- ・3分あったら何をしますか?
- ・何歳が一番楽しかった?
- ・治せない「クセ」を教えてください
- ・【大喜利】【投稿~12/17】 ありそうだけど絶対に無いことわざ
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・集合写真、どこに映る?
- ・自分の通っていた小学校のあるある
- ・フォントについて教えてください!
- ・これが怖いの自分だけ?というものありますか?
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・10代と話して驚いたこと
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
SQLで日付別のIDを生成するには
-
SQLでカラムを追加し、条件に合...
-
データベースの複製の仕方(mysql)
-
#1062 - '0' は索引 'PRIMARY' ...
-
下記の問合せを行うクエリを、P...
-
あってますか?SQL
-
WHERE `年月日` = '晴' OR `年...
-
SQLです教えてくださいお願いし...
-
SQLを作ったのですがうまくいき...
-
(初心者)MySQLやmaraDBで、crea...
-
SQLです教えてくださいお願いし...
-
SQLです教えてくださいお願いし...
-
SQLです教えてください。
-
SQLです教えてくださいお願いし...
-
SQLです教えてくださいお願いし...
-
SQLです教えてくださいお願いし...
-
utf8bomとutf8mb4の違いがいま...
-
「総降水量が100mm以上になる...
-
SQLで漢字名称を都道府県や市区...
-
SQLあってますか?こう?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
select文の実行結果に空白行を...
-
割合(パーセント)を求めるには?
-
時間帯テーブルから直近空き時...
-
Mysqlで変数を使ったSELECT文の...
-
空きのID番号を取得する方法
-
24時間以内に更新されたデータ...
-
任意の上位の集計を取得するには?
-
複数のテーブルの集計
-
SQLで連続したカラムが何個ある...
-
SQLローダーCSV取込で、囲み文...
-
単一グループのグループ関数で...
-
テーブルの最後(最新)のレコー...
-
【PL/SQL】FROM区に変数を使う方法
-
group byの並び順を変えるだけ...
-
ファイルの漢数字の順番につい...
-
並べ替えについて
-
SQL*Loader Append
-
レコードの登録順がおかしい
-
BLOBやCLOBのパフォーマンスを...
-
where句中のtrim関数について
おすすめ情報