- ベストアンサー
データベースで値をインクリメントする方法
- データベースで値をインクリメントする方法について解説します。
- MySQLではUPDATE文を使用して値をインクリメントすることができます。
- プログラム側では、一旦値を取り出してからインクリメントし、再度更新する方法が主流です。
- みんなの回答 (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.table.html こちらを見てみた感じ、 アップデートしたい値に、 Zend_Db_Exprクラスを適用してやる、というパターンのようですね。 本件と全く関係ないですが、 http://d.hatena.ne.jp/noopable/20100310/1268149192 こちらの記事がZendでModelを利用するに当たって参考になるかもしれません。
その他の回答 (4)
- hogehoge78
- ベストアンサー率80% (433/539)
大変失礼しました。酷い勘違いでした。 また、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/docs/manual/dql-doctrine-query-language/ja 合わせて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さんのやりたい処理は出来ると思います。
お礼
ご回答ありがとうございます。 CakePHPやCodeIgniterも少しですが使ったことがありますが、 なるほど、CakePHPではそういうやり方でできるんですね。 少し関係ないかもしれませんが 最近はZend Frameworkに興味がありまして構造を調べたりしてるのですが、 どうやらモデル関連には Modelフォルダ ├ DbTableフォルダ │├ GuestbookDbTableファイル ├ GuestbookMapperファイル ├ GuestbookModelファイル というモデル一つ扱うにしてもなんか3つに分かれてるらしくて そこら辺の理由を調べています^^
- yambejp
- ベストアンサー率51% (3827/7415)
後者は選ぶメリットはないと思いますが・・・ 後者のフローはこうですよね。 (1)データを呼び出す (2)プログラムでインクリメントする (3)プログラムでデータを投入する こうなるとトランザクションの問題が発生します。
お礼
ご回答ありがとうございます。 たしかにそうなのですが、メリットというか例えばある数を超えてたらインクリメントしたくない場合に if ($col < 1000) { $col += 1; } というふうに、わりと自由に制約などを付け加えることができると思うんです。 もちろんmysql側でも IF(col+1 > 1000, 1000, col+1) と記述すればできますけど、フレームワークの基本的なORマッパなどではできなくて 少し標準的(ここの定義が曖昧ですが・・・)なやり方からずれるかと。 そこらへんは元からあるORマッパに自分で機能を付け足したりしないといけないのかなと思ったり。。
- bm_hiro
- ベストアンサー率51% (200/388)
んーーー。。。??? hogehoge78さんにしては珍しく、質問を読み違えちゃったんですね。と思った俺が間違っているのかもしれないと思った今日この頃。 俺自身、主キー以外でauto_incrementを使う事がないのでアレですが、この質問って、「既に存在しているレコードの中の1個のフィールドの値のカウントアップ」の話しに見えたのですが。。 んで、この質問に対する回答ですが、俺自身もMySQLの内部の挙動なんて分かってませんが、SQL文を2回投げるよりは、1回で済むほうが いいじゃないん?って思います。 なので、俺は UPDATE mytable SET col=col+1 WHERE id=1; でやります。 理由は 単純にフレームワーク使わないので、ゴリ押しで書くことが多いからです。
お礼
ご回答ありがとうございます。 すいません、インクリメントを例に出したのが間違いでした・・・ bm_hiroさんの仰るとおり、 1個のフィールドの値のカウントアップというか1個のフィールドの更新を 一旦プログラムなどで取り出してから行うか、 直に例えばカウントアップなら UPDATE mytable SET col=col+2 WHERE id=1; というやり方でやるのか で、たしかに2回SQLを発行するぐらいなら1回の方がいいですよね。 実際に後者のやり方のフレームワークを使ってる方の意見も聞きたいです。
- hogehoge78
- ベストアンサー率80% (433/539)
MySQLで特別理由が無いなら、AUTO_INCREMENTをするのが普通です。 http://dev.mysql.com/doc/refman/4.1/ja/example-auto-increment.html
お礼
ご回答ありがとうございます。 いろいろ参考になりました。 読んでみて少しずつですがZendにおけるモデルの構成も理解できてきたと思います。 やっぱり自分的には機能がキッチリ分けられてるイメージがあるZendの方が好みですね。 そもそも種類が違うと思うので比較するのはどうかとは思いますが、 CakePHPとか使ってて便利(楽)だったんですけど、 便利すぎるがゆえにあまり自由が効かないというか、 Zendのように最低限の機能は提供するけど後は自由に使ってくださいっていうスタンスがいいですね。