insert, update 両方のテストは面倒


データ更新で、レコードがあれば update,
無ければ insert というロジックは、よくあると思います。

このとき、両方のテストをしなきゃいけないのが面倒です。
insert が正常でも、update にバグがあるかもしれないからです。

//レコードが無ければ insert
if ( $exist == false ) {

    $sql = "insert into 社員マスタ ( ShainNo, Name, Address, Tel ) values ( $ShainNo, '$Name', '$Address', '$Tel' )";

//レコードがあれば update
} else {

    $sql = "update 社員マスタ set Name = '$Name', Address = '$Address', Tel = '$Tel' where ShainNo = $ShainNo";

}

//ホントはプリペアドステートメントにしてね
$dbh->exec($sql);

でも、本記事の最後に述べる「ズボラ方式」にすると、
テスト工数も減らせるし、楽です。

正規のコーディングの場合

例えば「社員マスタ」の更新なら、
社員番号 / 名前 / 住所 / 電話番号 ・・・ の項目を、
1個ずつ、問題なく格納されるかをチェックします。

まず insert のテストをします。問題なければ update のテストですが、
同じ値でそのまま update するのはダメです。
insert で登録した値とは 別の値で update します。

例えば、[山田] で insert したら、
[山田2] で update して、確実に update したかをチェックします。

これをしないと、
「しまった! update で住所だけ更新がモレてた!」
と後になって気付くことも ありえます。

仮に、テーブル定義から自動でSQLを生成する
O/Rマッパー?(←ゴメン よく知らないの)があれば
コーディングもテストも楽ですが、そんなものも無く、
SQLを直接ゴリゴリ書く会社も未だあります。

以下は、そんな会社のプログラマーのための、
「ズボラ方式」の紹介です。

ズボラ方式

insert では、一度に全カラムを登録するのではなく、
主キーのみ登録(insert)して、直後に他のカラムを update します。

「社員マスタ」の場合、名前や住所は空白のまま、
まず主キーの社員番号のみ 値を設定して insert します。
そして直後に、名前や住所に値を設定して update します。

(最初から update の場合は、update の処理のみ おこないます。)


//レコードが無ければ 主キーのみ insert
if ( $exist == false ) {
    $sql = "insert into 社員マスタ ( ShainNo ) values ( $ShainNo )";
    $dbh->exec($sql);
}

//レコードの有無にかかわらず update
$sql = "update 社員マスタ set Name = '$Name', Address = '$Address', Tel = '$Tel' where ShainNo = $ShainNo";
$dbh->exec($sql);

//しつこいけどプリペアドステートメントでね

ズボラ方式の利点は、insert のコーディングとテスト工数を
削減できることにあります。
insert と update のロジックが ほぼ同じだからです。

問題点?

●insert のときは、insert と update で2回アクセスが発生する。

頻繁に更新するテーブルなら1回のアクセスに抑えるべきですが、
マスタ登録のように たまに更新する程度なら、
2回アクセスでも問題ないと思います。

●ほんの一瞬だが、名前や住所が空白のレコードが存在することになる。

もし気になるなら、insert ~ update をトランザクションにすることで、
空白のレコードが 他のユーザに見えないようにできます。

●別のズボラ方法として、delete 後 insert してもいい?( update 省略のため )

これは・・・、なるべく やめましょう。
何となくですが。