MySQL + UPDATE + PDOStatement::rowCount の罠

MySQLのセットアップはテーブル作成とかも含めて、非常に面倒なので、作成途中(開発中)はSQLiteで作って動作確認して、作成大詰めの段階でMySQLに切り替え完成・・・という工程はわりかし一般的?だと思う。ファイル一個でバックアップ・リストアも簡単で開発効率も上がります、僕は。

で、SQLite + PDO で何の問題もなくある程度コーディングが終わり、MySQLに移行して検証していると、おかしな挙動の解決に半日かかってしまった備忘録のエントリです。

データを空更新、特定の行を取得して、編集画面表示、その後、内容を変えずに同じデータで更新すると、update文は成功するのに、作用した行数が0を返す・・・。だいたい下のような感じ。

<?php
/*************************************************************

  あらかじめ下記mysqlクライアントで実行

  >> CREATE TABLE test_table(id INTEGER,data CHAR(255));
  >> INSERT INTO test_table values(1,'Kenji Nakagawa');

**************************************************************/
$pdo = new PDO('sqlite:log.sqlite');

if(modify_name(1,'Kenji Nakagawa'))
{
  header('location: list.php');
}

function modify_name($id,$name)
{
  global $pdo;

  $rv = false;
  $sql = 'update test_table set name = ? where id = ?';

  if(false !== ($stmt = $pdo->prepare($sql)))
    {
      if(false !== ($result = $stmt->execute(array($name,$id))))
        {
          $rv = $stmt->rowCount();
        }
    }

  return $rv;
}

この一連のコーディングでの最大の失敗は、rowCount()メソッドが返す行数で、update文の成功・失敗を判断したところ。分かってしまえば、何でもないことだけど、はまってしまった。

分かったことは、

MySQL + UPDATE文の実行では、PDOStatement::rowCount() は「実際に変更した(あった?)行数」(←ここ重要)を返す

・・・・ということ。

元々のレコードと同じデータをupdateすると、update文の実行はfalseは返さない(成功する)が、rowCount()は1ではなく、0を返す・・・。PHPサイトのドキュメントを検索したらちゃんと書いてありました・・・・とほほ(T-T)

UPDATE を使用する場合、MySQL では新旧の値が同じときには更新処理を行いません。 このことから、必ずしも mysql_affected_rows() の返す値が マッチする行の数と一致するとは限りません。返す値は実際に更新処理が行われた 行の数です。

そんな・・・・僕が勉強したときにちょろっと読んだMySQL入門書には書いてない!(笑)

ってわけで、解説書なんかで勉強するときは、いかに良い本に巡り会うことの重要性を改めて痛感しました。。。

MySQL Workbenchのメニューを日本語に。

※2015年5月12日 追記
グーグル検索などでこの記事に辿りつくアクセスが多いのですが、この記事はもう最新のバージョンにはあてはまりません。ご注意を。OneDriveにおいてあるファイルを最新のバージョンには絶対適用してはいけません。おそらくWorkbench自体がエラーで立ち上がらなくなるでしょう。記録のためだけに置いてあります。あしからず、ご了承くださいm(__)m

追記ここまで。 続きを読む

MySQL for Excel

知らない間に、MySQL for Excel という素敵なツールがあるのに気づき(遅すぎ)、会社のPCにダウンロードしてインストールして、テストサーバー(CentOS6 / MySQL 5.1)に接続してみました。。。

家のパソコンにはエクセルなんて無用の長物なのでインストールしていないし、持ってもいない。

結果、撃沈。

Authentication with old password no longer suppored. Use 4.1+ style….

とかいう、エラーダイアログが出て止まる。んー、ユーザーの設定は全部phpMyAdmin経由で使用しているから、古いパスワードが埋め込まれてんのかな?と思い、sshで接続してmysqlコマンドで、下記確認。

select user,host,password from mysql.user;

新しいパスワードは、アスタリスク(*)から始まるけど、全部16文字の古い形式やった。。。どおりで通らんはず。

全部パスワードを設定しなおしたった。

mysql

これで、MySQL for Excel で無事に接続でけた。

テーブルのインポートから・・・mysqlexcelでもデータのインポートだけなら、Connector/ODBCをインストールしてODBC 経由で普通にできるやん!という無粋なことは言っちゃいけない。

でもって、テーブルのレコード追加・編集まで・・・使い慣れた表計算グリッドでデータをぶち込めたり、上書きできたり、という。素敵!

mysqlexcel2

しかし・・・結局のところ、エクセル使いの方は、アクセスを使うと思うし・・・Windowsで飯を食ってる人はそもそもSQLServer使うし・・・、MySQL for Excelは誰が何のために使うのだろうか・・・? そもそもMySQLを日常的に使用する開発者がわざわざExcelなんて使うだろうか? ふつうはOpen Officeでそ?僕なんて、いまだにIBMのLotus Symphony 3だし。

ってわけで、HDDの肥やしになる。

facebook のメッセージ機能

たまに使う程度のiPhone用のfacebookアプリのメッセージ。ちょっと前からメッセージをタップすると、「メッセンジャーアプリに移行しました」みたいな画面になって、これまでのメッセージが見れなくなってしまいました。

なんじゃこれ? これは強制なのか?

若干の苛立ちを覚えつつ、(メッセンジャーアプリの)インストールボタンを押すと、App Storeが開き、「messenger」のインストール画面が開くんですが、レビューで酷評されるのを見て、入れるのやめた(^^;;;

facebookアプリを開き直して、メッセージをタップすると、普通に今までのメッセージが表示された。一定時間毎にこの「インストールしろ」画面が出るのかな???(ーー;;;

とりあえずインストールボタンを押したら前の画面に戻ったので、強制ってわけじゃないのかな? いずれにしろ、メッセージ自体が無くなってしまうのかな? よくわからん。

ま、facebook自体あんまり使ってないけど、たまに使う度にいろいろ変わっててイライラするな・・・。

 

#注記
iPhoneのfacebookアプリが更新されて、完全にメッセンジャーアプリに移行されてしまいました。
いままでのもので十分なんだけどな・・・昔のバージョンにロールバックできないものなのか・・・。

tar コマンド

会社で使用しているテストサーバー機(CentOS 5.5)は、ちょっと前に流行ったネットトップの小さいPC。小さくて場所を取らず、簡単に持ち帰りもでき、重宝していたのですが・・・CPUがATOM Dプロセッサなので、いかんせんパフォーマンスが悪いです。

4月後半ぐらいから社内機の一斉Windows7化の波にさらされ(^^ゞ、メインマシンが置き換えられた結果、今までメインとして使っていたWindowsXPが余ったので、これを新しいテストサーバー機にしようと画策。速攻でCentOS6に入れ替えた。

データベースやソース管理のリポジトリなど、結構めんどくさいデータが山ほどあるので、ぜんぶ TARでまとめてホットコピーすることにした。

UNIX系のコマンドには精通していないので、TARを打つにもいちいちネットで検索(笑)

パーミッションやユーザー・グループ情報を保持したままTARで固めて、新マシンで解凍しようと思ったんだけど・・・ネットで検索して引っかかってくるブログ記事の情報が錯綜してて・・・

(1) 固めるときにも、解凍するときにも、-p オプションが必要
(2) 解凍するときだけ、-p オプションを付ければ良い。
(3) -p オプションを付けて固めて、解凍するときに、–same-owner が必要

など、いろんな情報が出てきて、正直、どれが正しいのかわからんかった。

man tar を読むと・・・、

-p , –same-permissions, –preserve-permissions
許可情報を全て抽出する

とある。
抽出ってことは、固めるときは、デフォルトでユーザー情報やパーミッションは保持されてるってこと???
抽出って、extract ですよね・・・? 違うのかな???

よく分からん。

結局、固めるときは、 tar cvzf xxxx.tar.gz target 、解凍するときに、tar xvzfp xxxx.tar.gzでやった。rootユーザーで。

ちゃんとコピーされったっぽい(^^ゞ 明日から、テストサーバーの検証作業をちょびちょびやっていこう・・・いけるのかな?、また、ルーチンワークが入る前に、終わらせたい。