質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

3回答

8821閲覧

MySQLで、『グループごとの連番を不整合なくINSERTする方法』ってあるのでしょうか

opoonabst

総合スコア264

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

1グッド

2クリップ

投稿2017/08/26 17:17

2ちゃんねるのようにスレッドごとに一意の連番が付与されるような機能を実現したいと思っているのですが、
良い方法が思いつきません。

書き込みテーブル
|ID(主キー、自動連番)|スレッドID|書き込み番号|内容|
|:--|:--:|--:|
|1|1|1|hogehoge|
|2|1|2|fugafuga|
|3|1|3|piyopiyo|
|4|2|1|foofoo|
|5|2|2|barbar|
|6|3|1|fizfiz|
|7|3|2|bazbaz|
|8|3|3|dardar|

パッと思いついたのは

sql

1INSERT INTO 書き込み(スレッドID, 書き込み番号, 内容) 2VALUES (1, (SELECT MAX(書き込み番号) + 1 FROM 書き込みテーブル WHERE スレッドID=1), 'nyaaa');

こんな感じにSQL中でグループの書き込み番号MAX値+1を取得する方法ですが、
これだけでは場合によっては重複などの不整合を起こす可能性があるように思えます。
ユニーク制約で弾くことはできそうですが、できればエラー自体発生させたくありません。

良い感じに実現する方法はあるでしょうか・・・

お知恵を貸していただけると幸いです。

SVC34👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

###序

最近はWEBプログラムもSQLも書いていないのでちょっとしたリハビリです。間違っていたらすいません。
気付いた人いたら、どんどん訂正してください。

###レス番管理テーブルを作ったらどうでしょう?

商業アプリとかでは割とよくやる手法ですが、レス番だけのテーブルを作ります。

スレッドID(PRIMARY KEY AUTO_INCREMENT)レス番(INT NOT NULL)
123451
123465

###排他処理をしながらレス番を取得

該当スレッドに書き込みを行いたい時は、まずトランザクションを開始した後、レス番管理テーブルに対してスレッドID指定でSELECTをかけてレス番を取得しますが、その際、該当レコードをロックして悲観的排他処理を行います。

SQL

1START TRANSACTION; 2SELECT `レス番` AS MY_NUM FROM `レス番管理テーブル` WHERE `スレッドID` = '該当スレID' FOR UPDATE;

これで、別の接続が同じスレッドIDのレス番を取得しようとしても、上記のトランザクションがコミットされるまで読み取りが行えず、別の接続は待機します。

###書き込みテーブルに書き込みを行った後、レス番管理テーブルをUPDATEしてコミット

SQL

1INSERT INTO `書き込みテーブル` 2 (`スレッドID`, `レス番`, `内容`) 3 VALUES 4 ('該当スレID', MY_NUM + 1, 'あいうえお'); 5 6UPDATE `レス番管理テーブル` SET `レス番` = MY_NUM + 1 WHERE `スレッドID` = '該当スレID'; 7COMMIT;

トランザクションがコミットされると、待機していた別の接続の試みが自動で実行されるはずです(タイムアウトしていない場合)。

###終わりに

なお、トランザクションが必須になるので、InnoDBなどのストレージエンジンを利用してください。

以上

投稿2017/08/27 01:19

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/08/27 01:26

確か、AUTO_INCREMENT等は、制約に違反して書き込みが失敗した場合やロールバックを行った場合でも、オートナンバリングは戻らないはずなんですよね。 だから、連番の値が飛んでしまうので、レス番にAUTO_INCREMENTを利用するのはあまり得策ではないと考えます。
guest

0

この手の処理はランク付けで対応します

SQL

1create table tbl (ID int not null unique auto_increment, 2tid int,content varchar(20)); 3insert into tbl(tid,content) values 4(1,'hogehoge'),(1,'fugafuga'),(1,'piyopiyo'), 5(2,'foofoo'),(2,'barbar'), 6(3,'fizfiz'),(3,'bazbaz'),(3,'dardar'); 7

SQL

1select ID,tid,(select count(*)+1 from tbl as t2 where t1.tid=t2.tid and t1.ID>t2.ID) as rank,content 2from tbl as t1; 3

ランク付けを毎回やってもいいですが、コストの高い処理なので
必要に応じて、新規レコードを追加するときにupdateして
更新してもよいかと思います

投稿2017/08/28 00:47

yambejp

総合スコア114747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

シンプルな解決策は、スレッドごとにテーブルを作って書き込み番号をAUTO INCREMENTにすればいいかなと思います。
もちろん、テーブルが多くなりすぎることが予想できるので、スレッドの書き込みが1000件になったら過去分用テーブルにまとめていく感じかなと。

投稿2017/08/27 00:26

oskbt

総合スコア1895

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問