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

池谷 美歌也 mikaya_ikeya @ pakureserve.jp
2008年 2月 15日 (金) 17:31:43 JST


ミカヤです。

> --
> -- テーブルの構造 `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 @ php.gr.jp
> [mailto:php-users-bounces @ php.gr.jp] 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 メーリングリストの案内