プロが教える店舗&オフィスのセキュリティ対策術

このジャンルでお願いします。

例えばあるカラムをインクリメントする場合に
MySQLだと
UPDATE mytable SET col=col+1 WHERE id=1;
というSQL文でできますが、
一方でプログラム(PHPなど)側で一旦その行を取り出して

$id = 1;
$col += 1;
UPDATE mytable SET col={$col} WHERE id={$id};

というやり方もあると思います。
どちらが良いとか悪い(?)とかあるのでしょうか?
実際にみなさんはどちらのやり方でやっているのでしょうか?またできれば理由もお願いします。

というのも、PHPなどのフレームワークでは値をインクリメントしたい場合は
ほとんどが後者のやり方になると思います。
自分的には前者のSQL文でやった方がなんとく良いのでは?と思ってるのですが、
フレームワークなどを使って更新処理を行うと後者のやり方になってしまうので

A 回答 (5件)

Zendの場合は、



Zend_Db_Table→配列やプロパティを渡すとSQLを構築して実行するのが担当される
Zend_Db_Mapper→他のActiveRecordなパターンを採用したフレームワークみたいに、findとかfindAllメソッドをそこに記述してやって、Zend_Db_Tableで叩くSQLのフィルタ的なものをゴリゴリ書いてやる
Zend_Model→SQLでSELECTされてきたデータを、1レコードごとにここに入れる(10レコードひっぱったならZend_Modelクラスは、10個インスタンスが作成される。)

という割り振りのようですね。
で、主題の質問の内容については、
http://framework.zend.com/manual/ja/zend.db.tabl …
こちらを見てみた感じ、
アップデートしたい値に、
Zend_Db_Exprクラスを適用してやる、というパターンのようですね。


本件と全く関係ないですが、
http://d.hatena.ne.jp/noopable/20100310/1268149192
こちらの記事がZendでModelを利用するに当たって参考になるかもしれません。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
いろいろ参考になりました。
読んでみて少しずつですがZendにおけるモデルの構成も理解できてきたと思います。

やっぱり自分的には機能がキッチリ分けられてるイメージがあるZendの方が好みですね。
そもそも種類が違うと思うので比較するのはどうかとは思いますが、
CakePHPとか使ってて便利(楽)だったんですけど、
便利すぎるがゆえにあまり自由が効かないというか、
Zendのように最低限の機能は提供するけど後は自由に使ってくださいっていうスタンスがいいですね。

お礼日時:2011/01/17 02:39

大変失礼しました。

酷い勘違いでした。
また、bm_hiroさん、ご指摘ありがとうございます。

UPDATE時に、ですね。
PHPのフレームワークは、一口に言っても沢山ありますが、takagoo100さんのご利用のフレームワークはなんでしょう。

例えば、CakePHPなら、フレームワークの範疇で、演算子使えます。
<?php

$conditions = array('id' => 1);
$fields = array('col' => 'col + 1');

$this->Mytable->updateAll($fields, $conditions);

?>
というように、Modelで定義されているupdateAllメソッドを使えば可能です。
※ただしこれは文字列のエスケープもクォートも行わないのでPOSTされた値を使うときにはそれらを手動でする必要があります。

そして、symfonyの標準のORマッパのDoctrineの場合、
<?php
$q = Doctrine_Query::create()
->update('Mytable')
->set('col', 'col + 1')
->where('id = 1');
?>
といった感じで出来るみたいです。
http://www.doctrine-project.org/projects/orm/1.2 …


合わせてCodeIgniterでも・・・と思ったのですが、こっちは簡単なやり方は見つけられませんでした。



また、フレームワークが実装しているORマッパやモデルなどといったものは、なんだかんだ処理をラップして
最終的にSQL文を構築し、PHPネイティブで用意されている関数やクラス(mysql_queryとかPDOとか)に渡しているだけですので
どこかにその生SQLを叩くメソッドがあります。
またCakePHPの例になってしまいますが、Modelがexecuteメソッドを持ってます。
<?php
$this->MyTable->execute("UPDATE mytable SET col=col+1 WHERE id=1");

//もしSELECT文ならqueryメソッドを使います。

?>


最悪ソレを使えば、takagoo100さんのやりたい処理は出来ると思います。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
CakePHPやCodeIgniterも少しですが使ったことがありますが、
なるほど、CakePHPではそういうやり方でできるんですね。

少し関係ないかもしれませんが
最近はZend Frameworkに興味がありまして構造を調べたりしてるのですが、
どうやらモデル関連には
Modelフォルダ
├ DbTableフォルダ
│├ GuestbookDbTableファイル
├ GuestbookMapperファイル
├ GuestbookModelファイル
というモデル一つ扱うにしてもなんか3つに分かれてるらしくて
そこら辺の理由を調べています^^

お礼日時:2011/01/14 01:51

後者は選ぶメリットはないと思いますが・・・



後者のフローはこうですよね。
(1)データを呼び出す
(2)プログラムでインクリメントする
(3)プログラムでデータを投入する

こうなるとトランザクションの問題が発生します。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
たしかにそうなのですが、メリットというか例えばある数を超えてたらインクリメントしたくない場合に
if ($col < 1000) { $col += 1; }
というふうに、わりと自由に制約などを付け加えることができると思うんです。
もちろんmysql側でも
IF(col+1 > 1000, 1000, col+1)
と記述すればできますけど、フレームワークの基本的なORマッパなどではできなくて
少し標準的(ここの定義が曖昧ですが・・・)なやり方からずれるかと。
そこらへんは元からあるORマッパに自分で機能を付け足したりしないといけないのかなと思ったり。。

お礼日時:2011/01/14 01:30

んーーー。

。。???
hogehoge78さんにしては珍しく、質問を読み違えちゃったんですね。と思った俺が間違っているのかもしれないと思った今日この頃。

俺自身、主キー以外でauto_incrementを使う事がないのでアレですが、この質問って、「既に存在しているレコードの中の1個のフィールドの値のカウントアップ」の話しに見えたのですが。。

んで、この質問に対する回答ですが、俺自身もMySQLの内部の挙動なんて分かってませんが、SQL文を2回投げるよりは、1回で済むほうが いいじゃないん?って思います。

なので、俺は UPDATE mytable SET col=col+1 WHERE id=1; でやります。
理由は 単純にフレームワーク使わないので、ゴリ押しで書くことが多いからです。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
すいません、インクリメントを例に出したのが間違いでした・・・
bm_hiroさんの仰るとおり、
1個のフィールドの値のカウントアップというか1個のフィールドの更新を
一旦プログラムなどで取り出してから行うか、
直に例えばカウントアップなら
UPDATE mytable SET col=col+2 WHERE id=1;
というやり方でやるのか
で、たしかに2回SQLを発行するぐらいなら1回の方がいいですよね。
実際に後者のやり方のフレームワークを使ってる方の意見も聞きたいです。

お礼日時:2011/01/13 00:58

MySQLで特別理由が無いなら、AUTO_INCREMENTをするのが普通です。



http://dev.mysql.com/doc/refman/4.1/ja/example-a …
    • good
    • 0

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