iPhoneでSQLite3を使う9(制約)

今回は、制約です。だんだん、iPhoneから遠ざかってる気がしてきましたがw
制約とはテーブルという器に、入れる値にルールをつける機能です。この列にはこんな値しか許さないというルールをつけることができます。
今回は次の4点を紹介しておきます。

  • NOT NULL制約
  • CHECK制約
  • UNIQUE制約
  • PRIMARY KEY制約

それぞれを説明します。
まず、NOT NULL制約です。これは、列にNULLを許さないという制約です。指定された列を、INSERTもしくはUPDATEする際に、制約がつけられた列に必須で値を要求します。値がNULLだとエラーとなります。
CHECK制約は、自分でオリジナルの制約をつける機能です。100以上しか許さないとか、制約を自分で設定することができます。
UNIQUE制約は、値の重複を許しません。制約がつけられた列に同じ値が設定できなくなります。そのためUNIQUE制約の列は、その値を検索条件にすることで1行に特定することができます。
PRIMARY KEY制約は、UNIQUE制約と同じです。値の重複を許しません。推測で申し訳ないですが、UNIQUE制約との違いは自動でインデックスが作られる点だと思います。


制約を設定するには、CREATE TABLE文で制約を付ける列に次のように指定することで行うことができます。

CREATE TABLE userinfo (
	'ID' integer PRIMARY KEY,
	'name' text NOT NULL,
	'screen_name' text UNIQUE,
	'profile_image_url' text,
	'followers_count' integer CHECK(followers_count >= 0),
	'friends_count' integer CHECK(friends_count >= 0),
	'text' text
);

ちょっと強引に、紹介した制約を全部こみこみしてみました。前回のサンプルソースで、2つ目のINSERTで同じIDをセットして実行してみると。

// Insert
UserInfo* userInfo;
userInfo = [UserInfo ID:@"111111"
                   Name:@"Name1"
             ScreenName:@"ScreenName1"
        ProfileImageUrl:@"http://url1"
         FollowersCount:[NSNumber numberWithInt:1]
           FriendsCount:[NSNumber numberWithInt:1]
                   Text:@"Text1"];
[self userInfoInsert:userInfo];
[userInfo release];

userInfo = [UserInfo ID:@"111111"
                   Name:@"Name2"
             ScreenName:@"ScreenName2"
        ProfileImageUrl:@"http://url2"
         FollowersCount:[NSNumber numberWithInt:1]
           FriendsCount:[NSNumber numberWithInt:1]
                   Text:@"Text2"];
[self userInfoInsert:userInfo];
[userInfo release];

実行すると、下記のように'constraint failed'となりました。ハンドリングするためにエラーについて、もっと詳細な情報が知りたいですね。エラーコードをsqlite3_errcodeもsqlite3_extended_errcodを使って参照してみましたが、どの制約でひっかかっても値が19を返して来ました。使えないw
データをいれる際に、あれば更新、なければ追加などの処理をする際に、あるかどうかを調べてからINSERTかUPDATEに振り分けるのじゃなくて、INSERTで重複データではじかれたらUPDATEするなんてことがしたいんですけどね。

2011-03-13 11:24:40.794 Sample[885:207] DB Open
2011-03-13 11:24:40.797 Sample[885:207] DB Transaction start
2011-03-13 11:24:40.798 Sample[885:207] DB Delete all
2011-03-13 11:24:40.799 Sample[885:207] DB Insert
2011-03-13 11:24:40.800 Sample[885:207] DB Insert
2011-03-13 11:24:40.801 Sample[885:207] Failed to insert from database with 'constraint failed'.
2011-03-13 11:24:40.802 Sample[885:207] DB Error Insert failed(ViewController/userInfoInsert:)
2011-03-13 11:24:40.803 Sample[885:207] DB Rollback
2011-03-13 11:24:40.814 Sample[885:207] DB Close



※以前のテーブルに制約を加えるには、テーブルを削除して作り直すのが簡単です。

DROP TABLE テーブル名;

で削除して、CREATE TABLEで作成してください。SQLite3で使ったことがないですが、制約を既存テーブルに追加するには、ALTER TABLE文を使います。


さてなにができるかが判れば、あとは皆さんで調べることができると思いますので、ちょっと荒目の説明にしました。詳細は皆さんで調べてみてください。