2008年2月15日

[PHP-users 33286] Re:MySql で二重書き込みを防ぐには?

ミカヤです。

> --
> -- テーブルの構造 `counter2`
> --
>
> CREATE TABLE `counter2` (
> `bid` int(10) NOT NULL,

> `ac` int(11) NOT NULL DEFAULT '0',
> `pc` int(11) NOT NULL DEFAULT '0',
> `mb` int(11) NOT NULL DEFAULT '0',
> `date` int(11) NOT NULL,
> UNIQUE KEY `bid` (`bid`),
> UNIQUE KEY `date` (`date`)
> ) ENGINE=MyISAM DEFAULT CHARSET=ujis;

このユニークキーの設定では「複数」にユニークキーになってしまいます。
この設定だとbidとdateのどちらもユニークでなければならないので望みのデータ保存は出来ません。

「複合」のユニークキーは下のように設定します。
-- -------------------------------------
CREATE TABLE IF NOT EXISTS `counter2` (
`bid` int(10) NOT NULL,
`ac` int(11) NOT NULL default '0',
`pc` int(11) NOT NULL default '0',
`mb` int(11) NOT NULL default '0',
`date` int(11) NOT NULL,
UNIQUE KEY `datebid` (`date`,`bid`)
) ENGINE=MyISAM DEFAULT CHARSET=ujis;
-- -------------------------------------
こうするとdateとbidのセットでユニーク、という設定になります。

> $type = $_GET[type];
> $bid = $_GET[bid];
>
> $sql = <<< EOSQL
> INSERT INTO counter2
> (datebid,date,bid,$type)
> VALUES
> ($m$bid,$m,$bid,1)
> ON DUPLICATE KEY UPDATE
> {$type}={$type}+1;
> EOSQL;
> mysql_query($sql);
説明が足りなかったのかも知れませんが、このコードはテーブルに「datebid」というユニークキーの列を追加したという前提で書いたものです。
これをそのまま使用しても、テーブルにdatebidという列がないので普通にUnknown columnのエラーが出ませんか?

環境に合わせるなら次のようなコードになるんじゃないでしょうか。
// -------------------------------------
$type = $_GET[type];
$bid = $_GET[bid];

$sql = <<< EOSQL
INSERT INTO counter2
(date,bid,ac,$type)
VALUES
($m,$bid,1,1)
ON DUPLICATE KEY UPDATE
ac=ac+1, {$type}={$type}+1;
EOSQL;
mysql_query($sql);
// -------------------------------------


あとおせっかいかもしれませんが、自動で吐き出すタグのURLとはいえGETのクエリ文字列をそのままSQLに埋め込むのは危険だと思いますよ。
// -------------------------------------
$type = mysql_real_escape_string($_GET[type]);
$bid = mysql_real_escape_string($_GET[bid]);
// -------------------------------------
せめてこれくらいの対策はしたほうがいいです。


> -----Original Message-----
> From: php-users-bounces@xxxxx
> [mailto:php-users-bounces@xxxxx] On Behalf Of 萩原
> Sent: Friday, February 15, 2008 4:50 PM
> To: PHP-users ML
> Subject: [PHP-users 33284] Re:MySql で二重書き込みを防ぐには?
>
> ミヤカ様
>
> ありがとうございます。
>
> ご指示いただいたスクリプトを試してみました。
> しかし、INSERTとUPDATEともにうまく処理されませんでした。
>
> 自分でもON DUPLICATE KEY について調べてみましたが、
> 原因が特定できません。
>
> 何か基本的な事が間違っているのでしょうか?
>
> 今までのスクリプトをストップできないので、
> counter2というテスト用テーブルを作成して試しています。
>
>
>
> //カウント
> if(!$res[0]){ //なかったらインサート
>
> $sql = "insert into counter set bid = '$_GET[bid]',date =
> '$m',$_GET[type] = '1',ac = '1'"; mysql_query($sql); echo $sql;
>
> }else if($res[0]){ //あったらカウント追加
>
> $sql = "update counter set $_GET[type] = $_GET[type]+1,ac =
> ac+1 where date = '$m' && bid = '$_GET[bid]'";
>
> mysql_query($sql);
> echo $sql;
>
> }
>
> ここまでは正常に処理されています
>
> //カウント(ここからご指示いただいたスクリプトテストです)
> $type = $_GET[type];
> $bid = $_GET[bid];
>
> $sql = <<< EOSQL
> INSERT INTO counter2
> (datebid,date,bid,$type)
> VALUES
> ($m$bid,$m,$bid,1)
> ON DUPLICATE KEY UPDATE
> {$type}={$type}+1;
> EOSQL;
> mysql_query($sql);
>
>
> --
> -- テーブルの構造 `counter2`
> --
>
> CREATE TABLE `counter2` (
> `bid` int(10) NOT NULL,
> `ac` int(11) NOT NULL DEFAULT '0',
> `pc` int(11) NOT NULL DEFAULT '0',
> `mb` int(11) NOT NULL DEFAULT '0',
> `date` int(11) NOT NULL,
> UNIQUE KEY `bid` (`bid`),
> UNIQUE KEY `date` (`date`)
> ) ENGINE=MyISAM DEFAULT CHARSET=ujis;
>
>
> ※以下のタグでカウンターを読み込んでいます
>
> <img src='http://******.***/count.php?bid=1&type=pc'
> width="1" height="1">
>
> お忙しいところお手数お掛けいたします。
>
>
> 萩原
>

_______________________________________________
PHP-users mailing list PHP-users@xxxxx
http://ml.php.gr.jp/mailman/listinfo/php-users
PHP初心者のためのページ - 質問する前にはこちらをお読みください
http://oldwww.php.gr.jp/php/novice.php3

投稿者 xml-rpc : 2008年2月15日 17:31
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/69759
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。