プロが教えるわが家の防犯対策術!

データベースに存在するデータと重複しない乱数を生成したいです。
再帰を使用して書いてみたのですが、考え方、書き方は正しいでしょうか?
手順としては、
1.乱数を生成
2.DBに接続(select ~ from テーブル名 where like 生成した乱数、で戻り値があるか確認)
3.重複していたら自分自身を呼び出し、再度乱数を生成。


function Func_CreateUniqueID(){
$temp_rand=mt_rand();//乱数を作る。
echo "生成された乱数: $temp_rand<br>";
try{
$pdo=new PDO("mysql:host=localhost;dbname=データベース名","ユーザ名","パスワード");
$res=$pdo->query("select ランダムID from テーブル名 where ランダムID like '$temp_rand'");
while($row=$res->fetch(PDO::FETCH_ASSOC)){//while実行,IDが重複しているケース
Func_CreateUniqueID();//重複データが存在していたら自分自身を呼び出す。
}
unset($pdo);
}catch(PDOException $e){
var_dump($e->getMessage());
}
return $temp_rand;
}


こんな感じで書いたのですが、どうでしょうか?
アドバイスをお願いします。

A 回答 (3件)

少し前に質問者さんがやっている事とほぼ全く同じような事をしたので、大体どんな風に書いたか書きます。



$flg = false;
for($i=0;$i<3;$i++){
 $uniqueId = func_rand_int();// 1~2147483647(Mysqlのintの最大値)をランダムで発生
 $sql->query(sql_user_search($uniqueId));// $uniqueIdが登録されるかを調べる為のSQLを発行
 if(!$sql->fetch_assoc()){ // クエリー無しの場合
  // ここで登録処理
  $flg = true;
  break;
 }
}
//ループを抜けた所で$flgがtrueだったらOK、falseなら例外でNG

DBに1000万件のデータが入っていたとしても、
例外で登録が失敗する可能性は確率的に約1000万分の1

単純にuniqueidやmicrotimeを使って被らないIDを作るのもありですが、
IDから時間が推測出来るので
問題が無いくらいの確率を考えてこういうロジックでやりました。
    • good
    • 0
この回答へのお礼

ありがとうございます。
アドバイスを参考に書いてみました。

<?php

function Func_CreateUniqueID(){
try{
$pdo=new PDO("mysql:host=localhost;dbname=DBNANME","USRNAME","PASS");

for($i=1;$i<=10;$i++){
$rand_num=mt_rand();
echo "発生させた乱数:$rand_num<br>";

$sql="select * from TBNAME where COLNAME like '$rand_num'";
$res=$pdo->query($sql); //クエリ実行

if($res->fetch(PDO::FETCH_ASSOC)){
echo "重複する値が存在しますよ、もう一度ループします<br>";
}else{
echo "重複する値が無いですよ、ループを抜けます. break<br>";
echo "ループ回数:$i<br>";
return $rand_num;
break;
}
} //for文終わり
}catch(PDOException $e){
var_dump($e->getMessage());
}
}

?>


まだ何を使えば良いのか、戻り値は何か?など細かい書き方について調べる必要がありますが、とりあえずは動きそうです。
どうもありがとうございました^^

お礼日時:2009/12/05 13:46

INSERT IGNORE INTOでデータを強制インサートして、


mysql_affected_rows()で、戻り値が1ならOK、0なら再処理

ただし同じIDが振られる可能性が高いのであれば、あまりやるべきではない
念のためカウンタをつかって最多エラーヒット回数を別テーブルに
履歴としてのこしておくとよいかも。
    • good
    • 0
この回答へのお礼

IGNOREオプションをはじめて知りました。
改めて調べて利用してみようと思います。
ありがとうございました^^

お礼日時:2009/12/05 13:47

そもそもそういうユニークキー作る時ってmt_rand()を使うのではなくて


uniqid()を使ってユニークキーを作る。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!