アシアルブログ

アシアルの中の人が技術と想いのたけをつづるブログです

はじめから!リレーショナルデータベース:テーブル作成

こんにちは、志田です。
前回に引き続き、リレーショナルデータベースについてはじめから勉強していきましょう。

前回のまとめ





テーブルは、縦方向に並ぶ情報である「列」と、横方向に並ぶ「行」からなることを、前回勉強しました。
また、この縦方向に並ぶ「列」に対し、データの「型」を決めました。

今回は、まずデータベースを作り、そこに表を追加してみましょう。

データベースの作成



まずはデータベースを作成し、そこにテーブルを作るのが基本のやり方です。
Excelでいうと、新しいExcelのファイルを作ってブック(データベース)を作成し、シート(テーブル)を作るという動作に似ています。

では、MySQLに接続して、データベースを作成してみましょう。



mysql> CREATE DATABASE client;


CREATE DATABASE データベース名;
このコマンドでデータベースを作成することができます。

大文字のコマンドは全て、MySQLの命令や、予約語といって、特別な意味のある単語です。
(命令の書き方としては、小文字でもOKです。
 命令と自分が入力する内容の区別がつきやすいので、ここでは大文字を使うことにします)

命令の終わりには、「;」を付けて、命令文が終わりであることを示します。

こうして、データベースをいくつでも作成することができます。


データベースの利用



私達がExcelのファイルを操作するときも、どのファイルを開くか指定するように、
データベースにおいても、どのデータベースを使うか、命令する必要があります。



mysql> USE client;


USE データベース名

このUSEコマンドは、使うデータベースを切り替えることができます。

接続した直後の状態だとMySQLは、入力されたデータベースを操作するコマンドを
どのデータベースに対して実行してよいかわからないため、
こうして利用するデータベースを指定してやる必要があります。


表の作成



では、clientデータベースに表を作成してみましょう。

今回作成する表は、前回までに設計を行った、会社テーブル、部署テーブル、課名テーブル、担当者テーブルです。
表の作成は、CREATE文を使います。

まずは、会社テーブルを「company」として作成します。



mysql> CREATE TABLE company(
    ->   id      INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    ->   name    VARCHAR(255) NOT NULL,
    ->   address VARCHAR(255) NOT NULL,
    ->   tel     VARCHAR(15) NOT NULL
    -> );


表を作成するコマンドは、次のような文法になっています。

CREATE TABLE テーブル名 (カラム名 制約、オプション…);

前回までに考えたテーブルの構造と型の他に、「制約」というものが登場しました。
制約とは、そのカラムの決まりです。

例えば、companyテーブルの各カラムには「NOT NULL」という制約がついています。
これは、データを入れるときに、データがNULLではダメですという意味です。

NULLは、なにもない状態であることを指しています。
例えば、「0」は数字のゼロで、「」は文字がないという意味の空文字を示しています。
値そのものが入っていないことを表すのに、そのままでは表しにくいので「NULL」と表現しています。

companyテーブルでいうと、どのカラムも空ではいけない、なにかしらの値を入力しなければダメという意味です。

それから、idカラムには「PRIMARY KEY」という制約がついています。
これは、「このカラムはこの表で一意な値だ」
つまり、このidさえ指定すればレコードを指定できる、というカラムに対してつける制約です。

また、オプションというのは、カラムに補助的につける、まさにオプションです。
例えば、次の表で示す中にある「デフォルト」などは、有名なオプションのひとつです。

制約やオプションはこの他にもいくつかあります。
制約書き方意味
デフォルトDEFAULT 0
DEFAULT 'test' など
このカラムに何もデータを指定しないとき、デフォルトで入る値を指定します。
自動採番AUTO_INCREMENT自動で、1から順に連番をつけます。idなどのカラムに利用すると便利です。
ユニークUNIQUE列の中で、他と同じ値が取れないことを示します。例えば、ログインメールアドレスやユーザー名など、他の人と被っては困るものに付けます。


ということで、companyテーブルは、
・会社ID = id:データを入れれば自動で数字が割り振られる。companyテーブルの中で一意な値で、他と被ってはいけない
・会社名 = name:255文字までの可変長文字列で、空になってはいけない。
・会社住所 = address:255文字までの可変長文字列で、空になってはいけない。
・会社電話番号 = tel:15文字までの可変長文字列で、空になってはいけない。

というような構造の表になりました。
その他の表も、同じように作成してみます。

部署テーブルを、「group」として作成してみましょう。



mysql> CREATE TABLE group(
    ->   id          INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    ->   company_id  INT NOT NULL,
    ->   name        VARCHAR(30) NOT NULL
    -> );
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group(
  id          INT PRIMARY KEY NOT NULL,…(略)


作成しようとしましたが、エラーが出て作成出来ませんでした。
MySQLは、エラーのある付近を示してくれています…
どうやら、「group」という名前がよくなかったようです。

このように、MySQLでは、MySQLが使う命令語を「予約語」としているため、
予約語をテーブル名にすると、エラーが表示されます。

予約語は沢山ありますが、うっかり使ってしまいそうな単語は
select, create, in, by, group, from などでしょうか。
他にもあるので、テーブル名を決める際には確認してください。

では、groupsがエラーで作成できなかったので、「groups」にして作成しましょう。



mysql> CREATE TABLE groups(
    ->   id          INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    ->   company_id  INT NOT NULL,
    ->   name        VARCHAR(30) NOT NULL
    -> );


今度はうまくいきました。
続いて、残りのテーブルも作成します。

課名テーブル sections


mysql> CREATE TABLE sections(
    ->   id        INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    ->   group_id  INT NOT NULL,
    ->   name      VARCHAR(30) NOT NULL
    -> );
Query OK, 0 rows affected (0.00 sec)


担当者テーブル persons


mysql> CREATE TABLE persons(
    ->   id          INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
    ->   section_id  INT NOT NULL,
    ->   name        VARCHAR(30) NOT NULL,
    ->   email       VARCHAR(255) NOT NULL,
    ->   gender      ENUM('male', 'female') NOT NULL,
    ->   tel         VARCHAR(15),
    ->   date        DATE NOT NULL,
    ->   memo        TEXT
    -> );
Query OK, 0 rows affected (0.00 sec)


これで、全てのテーブルを作成することができました!
作成したテーブルの一覧を見るには、このコマンドを発行します。

SHOW TABLES;



mysql> SHOW TABLES;
+------------------+
| Tables_in_client |
+------------------+
| company          |
| groups           |
| persons          |
| sections         |
+------------------+
4 rows in set (0.00 sec)


4つの表ができていることが確認できました。
では、この表がどんな構造だったのか確認してみます。

表の構造を確認するには、このコマンドを発行します。

DESCRIBE テーブル名;
または
DESC テーブル名;



mysql> DESCRIBE company;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int(11)      | NO   | PRI | NULL    | auto_increment |
| name    | varchar(255) | NO   |     | NULL    |                |
| address | varchar(255) | NO   |     | NULL    |                |
| tel     | varchar(15)  | NO   |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)


この表ではそれぞれ、以下の情報を示しています。
・Field:カラム名
・Type:型
・Null:NOなら、NOT NULL(NULLはダメ)。YESなら、NULLが入ってもOK
・Key:キー項目であるかどうか。PRIがついていれば主キーであることを示す
・Default:何も指定されていなかったときにデフォルトでとる値
・Extra:その他、付けられているオプション

このようにして、データベースを作成し、テーブルを作り、テーブルの構造を確認しました。


テーブルの修正



作成したテーブルですが、後から見返すと、おかしなところを発見しました。
personsテーブルのemailカラムにNOT NULL制約がついています。

今の時代、メールアドレスを持たない人は珍しいですが、
それでもまさとしが先週もらった名刺には、メールアドレスがないものもありました。
ここは、メールアドレスは必須入力ではなく、任意入力にすべきです。
データベースを修正しましょう。

データベースの修正には、以下のコマンドを使います。
ALTER TABLE テーブル名 MODIFY 直したいカラム名 制約、オプション;

実際に、personsテーブルにコマンドを発行します。



mysql> ALTER TABLE persons MODIFY email VARCHAR(255);


イメージとしては、カラム情報の上書きです。
もともと、emailというカラムにはNOT NULL制約がついていましたが、
制約がない状態でカラムを上書きしました。

では、テーブルの構造が変わったかどうか、確認します。



mysql> desc persons;
+-----------+-----------------------+------+-----+---------+----------------+
| Field     | Type                  | Null | Key | Default | Extra          |
+-----------+-----------------------+------+-----+---------+----------------+
| id        | int(11)               | NO   | PRI | NULL    | auto_increment |
| setion_id | int(11)               | NO   |     | NULL    |                |
| name      | varchar(30)           | NO   |     | NULL    |                |
| gender    | enum('male','female') | NO   |     | NULL    |                |
| email     | varchar(255)          | YES  |     | NULL    |                |
| tel       | varchar(15)           | YES  |     | NULL    |                |
| date      | date                  | NO   |     | NULL    |                |
| memo      | text                  | YES  |     | NULL    |                |
+-----------+-----------------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)


きちんと変更され、emailのNULLがYESになっていることがわかりました。


今回のまとめ



今回は、以下の3つのことを学びました。
・データベースの作成
・データベースにテーブルを作成
・テーブルの構造を確認
・テーブルの構造を修正

データベースやテーブルを作るのは重要な作業ですが、
テーブルの構造を確認したり修正することで、
新しい修正事項などに、より柔軟に対応できます。

はじめから!リレーショナルデータベース:型を考える

こんにちは!志田です!
前回にひきつづき、リレーショナルデータベースをはじめから勉強していきましょう。


前回のまとめ



とっても便利なデータベースには、いろいろな種類があります。
アシアルブログの笹亀の記事でも、RDBとは違ったNoSQLについての説明がありました。
その中でも、一番ポピュラーなリレーショナルデータベースについて、勉強していきました。

前回は、がんばる企業戦士まさとしが、紙の取引先情報からデータベースの構造について分類をしていきました。
これを、「正規化」といいます。
正規化をすることで、無駄がなく、情報を更新したときに異常が起こらない、柔軟なデータベースを作ることができます。


行と列





前回作った表のひとつをみてみましょう。
表なので、行と列があります。
データベースでも、縦に伸びるデータを行(カラム)、横に伸びるデータを列(レコード)といいます。
レコードが1件1件のデータになります。
カラム名というのは、カラムにつけた名前です。見出しのようなものですね。

カラムは縦に見ればわかるとおり、全て同じデータ(数字、文字など)になっています。
このカラムに対してつけるのが、「」です。


MySQLの型



では、MySQLで使える型を見て行きましょう。

日本語でいうとMySQLでいうと用途
短い整数型tinyintフラグの処理などに使う。男なら1、女なら0など
整数型int数字に使う。会員番号や通し番号など。
浮動小数点型float, double体重など、小数点が必要な数字に使う。
固定長文字列型char(N)桁数の決まっている文字列。Nに文字数を入れる。郵便番号だと「113-0033」で8文字なので、char(8)
可変長文字列型varchar(N)>桁数の決まっていない文字列。255文字までならこれを使う。名前、住所など。名前だと長くても20文字くらいなので、varchar(20)
長い可変長文字列型textメモ、日記の本文など、長い文字列に使う。
日付型date日付に使う。誕生日など。「2012-10-04」
日付時刻型datetime日付と時刻を一緒に扱う。会員登録日などに使う。「2012-10-04 10:23:40」
文字列定数型enum('value1', 'value2',...)リストから選>ぶ形式の型。男=male、女=femaleだと、enum('male', 'female')となり、どちらかを指定する。


他にももっとたくさんの型があり、使い方や指定の方法などいろいろなのですが、
今回はよく使うこれらの型をご紹介しました。

文字列の「桁数」という概念が、ちょっとわかりにくいかもしれません。
例えば、紙の表を思い浮かべて下さい…。
「会社住所」の欄があまりに小さかったら、住所が全部書けませんよね。
ものにはそれぞれ、適切な欄の長さ・大きさがあります。
適切な文字数を決めることはつまり、桁数を決めるということです。

データベースを作る時は、テーブルの正規化を行い、正規化したテーブルに型をつけるという手順で作ります。
では、まさとしさんが、前回のテーブルにどのような型をつけたのか、みてみましょう。

まさとし 型をつける





まず、前回のテーブルの上から考えていきます。

会社テーブル

会社テーブルは、「会社ID」「会社名」「会社住所」「会社電話番号」からなります。
「会社ID」は数字なので、int型がよいでしょう。
「会社名」は、どんなに長くても255文字を超えるようなものはなかったので、varchar(255)にしましょう。
「会社住所」も同じく、長さは255文字程度あれば充分ですので、varchar(255)にします。
「会社電話番号」は、数字だけでできてるな、とまさとしさんは思いました。
・・・でも待てよ、市外局番は0から始まるものもある。それを整数型で扱ったとしたら、先頭の0が無視されちゃうのでは?

そうです。数字からなるデータでも、先頭の0が重要になってくるものは、
「計算のできる数字」でなく、「数字の文字列」にするのが良いです。
「会社電話番号」は、11桁の文字列であるvarchar(11)にしました。

部署テーブル、課名テーブル

部署テーブルと課名テーブルも同様に、
部署ID、会社ID、課ID、部署IDはint型、部署名、課名はvarchar(255)にしました。

担当者テーブル

担当者テーブルは、情報がたくさんあって大変そうです。
まず、他のテーブルと同じように、担当者ID、課IDはint型にし、名前はvarchar(20)にしました。

性別は、表では男性、女性となっています。
まさとしさんは、「じゃあ、これはchar型でいいかな…」と思い、テーブル設計書にcharとメモしました。

そこへ、先輩が通りかかって訊ねました。
「まさとし、それ、間違えて女ってDBに登録しちゃったら、どうするの?
2つのうちのどちらかから選ぶなら、絶対間違えないような型のほうがいいんじゃないの?」

たしかに…。文字列にすると、入力間違いが怖いです。
そこで、まさとしさんはtinyint(1)を使って、男性なら1、女性なら0を入力させることにしました。
これなら、1か0のどちらかしか選ぶ必要はないので、安心です。

「まさとし、それ、お前は1と0でわかりやすいからいいだろうけど、他の人が見たらわかんないよ?」

うう、先輩、確かに。
まさとしさんは、enum型を使い、男性か女性かをリストから選べるようにしました。
enum('male', 'female')とすることで、どちらかの値がDBに入ることになりました。

個人の電話番号は、会社電話番号を同じくvarchar(11)にしました。

日付というのは、名刺をもらった日のことを指しています。
これは、年月日だけがわかっていればいいので、date型にしました。

備考は、どのくらい長くなるかわかりませんから、text型にしました。


テーブル構造完成!





それぞれ考えた型を追記して、テーブル構造が完成しました!

このように、データベースを作るうえで大事な流れは、このようなものです。

(1) テーブルの構成を考える。
(2) 正規化をする。
(3) それぞれのカラムに適切な型をつける。

正規化をして表の構造を整えることも大事ですが、まさとしさんの先輩からの指摘のように、
そのカラムが取り得る値について考え、最適な型を考えるのも重要です。

では、次回は実際にデータベース上でテーブルを作り、操作を行なってみましょう。

はじめから!リレーショナルデータベース

こんにちは!ゲームだいすき志田です。
ゲームをやっていると、どのアイテムが足りないとか、自作キャラクターの性能だとか、
管理したいなぁってこと、ありますよね?ないですか?ありますね。

そんなとき、データベースを使いましょう!

今回は、DBとはなにか、というところと、簡単な正規化について勉強しましょう。


データベースとはなにか



とはいえ、最近、猫も杓子も「データベース」ですね。
…便利そうなのはわかるけど、DBってそもそもいったい何でしょうか。

データベースとは、Data Base、データの基地という意味で、
つまりはデータの集合です。

世の中には、いろいろな種類のデータベースがあります。
・リレーショナルデータベース(関係データベース)
・オブジェクトデータベース
・階層型データベース
・ネットワーク型データベース
・分散型データベース

この入門記事では、最もポピュラーでよく使う、「リレーショナルデータベース」を例にとり、説明していきます。
どのくらいポピュラーかというと、DBといったらリレーショナルデータベースを指すくらい有名なタイプのDBです。

なぜDBを使うのか



便利便利と言われているものの、なぜわざわざ新しいことを勉強してまで、DBを使うのでしょうか。
それは、こんなメリットがあるからです。

データの統合化・共有によるメリット

例えば、紙の社員名簿で社員を管理している会社を想像してください。
総務部で持っている社員名簿と、人事部で持っている社員名簿があったときに、
どちらかだけが更新されたら、データとしての一貫性が保てなくなります。

あっちの名簿にはAさんがいるのに、こっちにはAさんがいない!
Aさんは結局、いるの?いないの?ということになりかねません。
これが、統合化によるメリットです。
データはひとつにまとめましょう、ということです。

もうひとつのメリットが、共有です。
データと、それを扱うプログラムが独立していると便利なのです。
給与計算プログラムと日報プログラムといった、別のシステムが動いているときに、
どちらも同じ社員名簿DBを参照していると、先ほどのような一貫性がない状態を避けられます。

うーん、なんて便利なんでしょう…!

データベースシステムの構成



では、そのデータベース。どういった構成になっているのかを見てみましょう。



ユーザやシステムが、「名簿一覧が欲しい」と命令をします。
この命令をDBMS(Data Base Management System/データベース管理システム)が受け取ります。
DBMSはDBから、その命令に合ったデータを取得して、ユーザに返してあげます。

世間で、MySQLOracle…などと言っているのは、このDBMSの製品名です。
DBMSはHDDに格納されている実際のデータを管理し、命令を理解して結果を返しているのです。


まさとし はじめてのデータベース



HP作成の業務を終えたまさとしさんに、また新たな仕事が舞い込んできました。
「まさとし君、うちの会社の取引先リスト、データベースにならんかね?」

まさとしさんの会社の取引先リストは、なんと紙だったのです!
紙で管理していると、どこの会社のダレソレさんは退職しただの、住所移転しただの、
そういった情報がごちゃまぜになってしまいます。
それに…先輩の字はミミズがのたくったようで、全然読めないんです!

「わかりました、やってみます!」
がんばれまさとし!

まず、まさとしさんは、紙の情報を整理することにしました。



取引先リストを紙にまとめると、このようになりました。
「データベースに載せる項目は、こんなモンでいいかな…」

すると、まさとしさんの後ろを先輩が通りかかりました。

「おっ、まさとし、それって非正規形の表だね!」

非正規形の表とは



非正規形の表とは、更新異常が起こってしまう表のことをいいます。
更新異常には、3つの種類があります。

(1) 変更異常
情報を変更するとき、重複したすべての情報を変更しないと矛盾が発生してしまうことをいいます。
例えば、株式会社 とりもち商事の住所が変更になったら、どうなるでしょうか?
この表のうち、会社名が「株式会社 とりもち商事」であるデータ全ての住所を変更しなくてはなりません。
とても面倒です。

(2) 挿入異常
項目が混ざっているために、新しいデータを追加できない異常のことをいいます。
例えば、「新しく取引先を追加したい、だがまだ担当者はいない」という場合、この表にデータを追加することはできません。
(会社の情報と担当者の情報がいっしょくたになって入っているからです!)

(3) 削除異常
削除をしたときに矛盾が発生してしまうことをいいます。
例えば、「株式会社 とりもち商事」のデータは2件ありますが、高木さんと赤坂さんが退職された場合、
この表から2人の情報を削除してしまうと、とりもち商事の会社データ自体もなくなってしまいます。

つまり、非正規形の表がイケナイのは、なんでもかんでもごちゃまぜにしているからなのです。


正規化をする



ではこの非正規形の表、どうやったらいいかんじの表になるのでしょうか。
いいかんじの表にすることを、「正規化する」といいます。
正規化するとはつまり、ごちゃまぜになった表を分割して、わかりやすく、扱いやすくすることです。

正規化には、分割の段階によって、第一正規形、第二正規形、第三正規形、Boyce-Codd正規形(ボイス・コッド正規形)、第四正規形、第五正規形という種類にわかれています。
ただし、実際の業務においては、ボイス・コッド正規形や第四、第五正規形を行うことはあまりありませんので、
第一正規形から第三正規形まで、流れでできるようになりましょう。
慣れてしまえば、非正規形の表からすぐに第三正規形の表を導けるようになります。

第一正規形



第一正規形とは、重複して現れる部分を分離することです。
先ほどの表でいうと、重複しているのはどこでしょうか。
そう、「会社名、会社住所、会社電話番号、部署名、課名」が、名刺をくれた社員さんごとに重複していますね。
まずは、これを、値の集合のない表にしてみます。



会社と社員を分けて考えることで、ずいぶんすっきりしました。

ここで、関数従属性について考えてみます。

関数従属性



関数従属性とは、Aの値を決めるとBの値が決まるというものをいいます。

例えば、「会社名がわかれば、会社の住所と電話番号がわかる」
「会社名がわかれば、その会社に存在する部署がわかる」
「部署がわかれば、その部署に存在する課名もわかる」
「名前がわかれば、性別、メールアドレス、個人電話番号、登録日、備考がわかる」

では、このAがわかればBがわかるという関係ごとに、表を分割してみましょう。


第三正規形



関数従属性をもとに、表を分割してみました。



こう分けることで、会社の中に部署が、部署の中に課が、課の中に社員がいる、という関係が流れるようにわかりますね。

それぞれ、会社や部署には一意となるIDを振って、全体を眺めた時にわかりやすくしました。

会社IDが1である、「株式会社まーべらす」には、部署ID1と2である営業部、開発部がある。
営業部には営業課、開発部には製品開発課があり、
営業課には山口さん、田中さん。製品開発課には竹田さんがいる。

関数従属というと意味がわかりにくいですが、要は、マスタファイルを作るということなのです。
会社の情報は、会社マスタファイルだけで修正すれば楽ちんですね。

こうして、個々のデータ同士の関係を切れるぶんだけ切っていくことが、正規化するということです。

では、次回はこの正規化したテーブルをもとに、型について考えて行きましょう。

symfonyでMongoDBを使ってみました

こんにちは。笹亀です。

最近でも無いですが、なにかと注目を浴び続けているのがkey-valueストアです。TokyoTyrant, kumofs, ROMA, Flareなど種類も豊富で使用する用途によって使い分けするのがよいです。そんな中で自分がご紹介したいのはMongoDBです。

MongoDBはドキュメント指向データベースでNoSQLです。ご紹介理由としてはRDBMSから入るkey-valueストアとしてとてもわかりやすいからです。後はサポート言語が大量にあってWEBアプリケーションとして使用するのにとても相性がよいことです。
 ※PHPPythonRubyPerlなどなど

その他にたくさんの特徴があります。詳細については、下記のドキュメントにてご確認ください。
http://www.mongodb.org/display/DOCSJP/Home
 ※日本人なら日本語のドキュメントに限ります(一部英語のままらしい)

まずはインストールしてみます。下記から自分の環境にあったものをダウンロードします。
http://www.mongodb.org/display/DOCS/Downloads
自分の場合はMacの10.6なので下記のように取得します


wget http://downloads.mongodb.org/osx/mongodb-osx-x86_64-1.4.1.tgz


解凍してコマンドなどを設置(コピー)します。


tar zxvf mongodb-osx-x86_64-1.4.1.tgz
cd mongodb-osx-x86_64-1.4.1
sudo cp bin/* /usr/bin/
sudo cp -r include/* /usr/include/
sudo cp lib/libmongoclient.a /usr/lib/


mongoデーモンをデータの格納先を指定して起動します。


mongod --dbpath ~/mongodb  &


PHPからMongoDBを使えるようにします。


pecl install mongo
php.iniにextensionの箇所にmongo.soを追加する
apacheを再起動。


phpinfoでMongoが設定が反映されているか確認しましょう。



以上でPHPでMongoDBが使えるところまでいけます。

symfony(PHP)で使用する方法を記載します。まずは接続情報を記載します。MongoDBはスケーラブルに対応しておりますので今回はMaster-Slaveの情報の両方を記載します

config/mongo/databases.yml


all:
  master:
    param:
      dsn:     localhost:27017
      dbname:   test
  slave:
    param:
      dsn:     localhost:27017
      dbname:   test


次にsymfonyでMongoへ登録、取得(件数のみ)するためのクラスを作成します。

lib/MongoKeyValue.class.php


<?php
class MongoKeyValue 
{
  protected $connection_master = null;
  protected $connection_slave = null;
  protected $table_name = null;
  
  /**
   * コンストラクト
   * 
   * @param string $table_name
   * @return MongoKeyValue
   */
  public function _construct($table_name = '') {
    $this->table_name = $table_name;
    
    //コネクション情報をセット(Master&Slave
    $file = sfConfig::get('sf_config_dir').'/mongo/databases.yml';
    if (file_exists($file)) {
      $config = sfYaml::load($file);
    } else {
      throw new InvalidArgumentException('not mongo databases.yml');
    }

    $getDb = function ($name) use ($config)
    {
      $param = $config['all'][$name]['param'];
      $mongo = new Mongo($param['dsn']);
      return $mongo->selectDB($param['dbname']);
    };
    
    //コネクションをセット
    $this->connection_master = $getDb('master');
    $this->connection_slave  = $getDb('slave');
  }

  public function getMasterCollection()  
  {
    return $this->connection_master->selectCollection($this->table_name);
  }
  public function getSlaveCollection()  
  {
    return $this->connection_slave->selectCollection($this->table_name);
  }

  /**
   * データインサート処理
   * 
   * @param array $params
   * @return boolean
   */
  public function setKeyValue($params) {
    if (is_array($params)) {
      $result = $this->getMasterCollection()->insert($params);
      return $result;
    } else {
      return false;
    }
  }

  /**
   * 条件を設定してデータ件数を取得する
   * 
   * @param array $params 取得条件
   * @return integer
   */
  public function getKeyValue($params) {
    if (is_array($params)) {
      return $this->getSlaveCollection()->count($params);
    } else {
      return false;
    }
  }
  
}



準備ができたら実際にactionに記載して登録処理と件数を取得するものを作成して確認してみましょう。


  public function executeTest() {
    $mongo = new MongoKeyValue('test_table');
    $params['class_id'] = "1";
    $params['name']     = '笹亀弘';
    $mongo->setKeyValue($params);
    
    $params1['class_id'] = "1";
    $params1['name']     = 'ささがめひろし';
    $mongo->setKeyValue($params1);
    
    $params2['class_id'] = "2";
    $params2['name']     = 'ささがめひろし';
    $mongo->setKeyValue($params2);
    
    usleep(1000000);
    
    $params3['class_id'] = "1";
    print $mongo->getKeyValue($params3);
    exit;
  }



usleepしている箇所についてですが、Mongoで連続で登録してカウントの処理をするときに、Lock処理が入りませんので、登録処理を完了する前に件数を取得する部分が発行してしまい件数が合わない場合があります。そのためにsleepで処理を止めています。

カウント取得しているものには条件を指定します。ここではカウント取得条件はclass_idが1である件数を取得しています。また、MongoDBはPHPとは違い数値と文字列の数値を区別する必要がありますので、カウントを取得する際などには注意が必要です。


    $params3['class_id'] = "1";
    print $mongo->getKeyValue($params3);
  結果: 2
    $params4['class_id'] = 1;
    print $mongo->getKeyValue($params4);
  結果: 0



MySQLなどのようにMongoにもコマンドで実行して値を確認する方法もあります。使用するコマンドは「mongo」コマンドから値を操作することができます。


mongoの基本的なコマンドしか実行しておりませんので、その他にどういったものがあるかはコマンドのhelpで確認するか、ドキュメントよりご確認いただけたらと思います。


symfonyでMongoクラスを作成しましたが、こちらには登録処理とカウントする処理しかありません。その他にも削除する処理やデータを取得するものを拡張していただければ自由にMongoDBの値を扱うことが可能になります。

開発用のデータベース構築まとめてきなメモCentOS5.4+PostgreSQL8.3

開発用のデータベースをローカル環境内に構築する機会があったのでメモを残しておきます。

VMware Player3+CentOS5.4+PostgreSQL8.3

VMware Player3は以下のサイトからDLしてください。
http://www.vmware.com/jp/products/player/
centOSのイメージは以下からDLしてください。
http://ftp.riken.jp/Linux/centos/5/isos/i386/


●OSインストール
VMware Player3(以下VM)をインストール後VMを起動します。

1.新規仮想マシンの作成を選択


2.インストーラディスクイメージファイルを選択し、ダウンロードしたISOファイルを選択します。


3.仮想マシン名と格納場所は適時変更してください。
今回はデフォルトのまま進めます。


4.ディスク容量の指定
推奨サイズを入力し、仮想ディスクを単一ファイルとして格納を選択


5.完了ボタンを押す
内容を確認後完了ボタンを押します。


6.CentOSのインストール画面
パースはスキップします。



7.言語の選択


8.キーボードの選択


9.パーティションの設定
デフォルトのまま進めます

「はい」ボタンを押します。



10.ネットワーク設定
インストール後設定するのでデフォルトで進めます。


11.タイムゾーンの設定
デフォルトでアジア/東京になっているのでそのまま次へ進みます。


12.Rootユーザのパスワード設定
わかりにくいパスワードにしましょう。


13.インストールパッケージの選択
Desktop -Gnomeのチェックをはずし、今すぐカスタマイズするを選択します。


開発→開発ツールのチェックとベースシステム→ベース以外のチェックを全てはずします。



ベースはオプションパッケージからfirstboot-tulのチェックを外します。


14.インストールの開始



15.インストールの完了


VMを再起動した後にサスペンドにしてから戻してみましたが、
サスペンドにする前の画面イメージが表示されるようになっていました。


●ネットワーク設定
1.IPアドレスの設定


cd /etc/sysconfig/networking/

ネットワークディレクトリーに移動しlsコマンドを実行してください。
すると、イーサネットアダプター別の設定ファイルが表示されるのでviでifcfg-eth0を開きます。


vi ifcfg-eth0


以下の内容を環境に合わせて書き変えます。


BOOTPROTO=none
IPADDR=IPアドレス
NETMASK=255.255.255.0とか
GATEWAY=ゲートウェイのIPアドレス


2.DNSの設定
viでresolv.confを開きDNSIPアドレスを指定します。


vi /etc/resolv.con

nameserver 8.8.8.8

8.8.8.8はGoogleが提供しているDNSになります。
セカンダリーは8.8.4.4です。
Google Public DNS
http://code.google.com/intl/ja/speed/public-dns/
Google Public DNSの特徴としては速度とDNSキャッシュスプーフィング攻撃に強いことらしいです。
また、接続情報は24時間後に削除されるそうです。

3.VMの設定
IPアドレスを固定にしましたので、次はVMのブリッチ接続を設定します。
右下のアイコンをクリックし、仮想マシン設定を開きます。


仮想マシン設定から、ネットワーク接続「ブリッジ:物理ネットワークに直接接続」のラジオボタンを選択し、OKをクリックします


ネットワーク設定はこれで終わりです。
ここから先はターミナルを使用して設定します。

●centの初期設定
1.yumの設定
fastestmirrorプラグインをインストールしインストールパッケージダウンロード時の最適ミラーサイトを自動選択するようにします。


yum -y install yum-fastestmirror


インストールパッケージの一括アップデート


yum -y update




2.SELinuxの無効化
CentOS5.4はデフォルトでSELinuxが有効になっているので、無効にします。


setenforce 0


無効になっているか確認しましょう。
getenforceコマンドでSElinuxが有効化確認できます。


getenforce
Permissive

Permissiveが表示されれば無効になっています。
有効になっている場合はEnforcingが表示されます。


3.vimのインストール
vimvim-enhancedをインストールします。
理由はファイルタイプ別に色が変わって表示されたりするのでなんとなく。。。


yum -y install vim-enhanced



PostgreSQLのインストール

1.コミュニティーリポジトリーを使うための設定ファイルを取得します。
8.3をインストールしたいので、コミュニティーのリポジトリーをyumに設定します。


wget http://yum.pgsqlrpms.org/8.3/pgdg-centos-8.3-6.noarch.rpm
rpm -ivh pgdg-centos-8.3-6.noarch.rpm

登録されたか確認します。


ls -l /etc/yum.repos.d/

pgdg-83-centos.repoが表示されていれば完了です。

2.yumコマンドでPostgreSQLをインストールする


yum search postgresql
yum install postgresql-server


パッケージを確認して
Is this ok [y/N]:y
yを選択します。



==================================================================================================================================
 Package                                 Arch                  Version                              Repository               Size
==================================================================================================================================
Installing:
 postgresql-server                       i386                  8.3.8-1PGDG.rhel5                    pgdg83                  4.6 M
Installing for dependencies:
 compat-postgresql-libs                  i686                  4-1PGDG.rhel5                        pgdg83                   63 k
 postgresql                              i386                  8.3.8-1PGDG.rhel5                    pgdg83                  1.8 M
Updating for dependencies:
 postgresql-libs                         i386                  8.3.8-1PGDG.rhel5                    pgdg83                  204 k

Transaction Summary
==================================================================================================================================
Install      3 Package(s)
Update       1 Package(s)
Remove       0 Package(s)

Total download size: 6.7 M
Is this ok [y/N]: y


Complete!が表示されればインストール完了です。

VMware Playerが3にバージョンアップし、VMwareの設定とOSのインストールが簡単にできるようになってました。
Google Public DNSも今回初めてしったのですが、今月の3日に発表されたばかりだったみたいですね。

DoctrineでデータベースのViewを使って楽をする

PHPも好きですが本当はSQLも結構好きな岡本です。
アシアルに入社する前はネットショップ・システムに携わっており、
SQLでガリガリと売り上げや利用統計などを集計していました。
しかし、symfonyを使った開発ではデータベースに対する操作は基本的に、
ORマッパー(PropelやDoctrine)を介して行うため、SQLの強力な集計機能が恋しくなる時があります。

フォームから受け取ったデータをデータベースに保存するような更新系の処理は
insert文を書くよりもDoctrineでsaveメソッドを発行した方が楽だと思うのですが、
参照系の処理では集計やサブクエリを活用したselect文に比べると表現力に物足りなさを感じてしまいます。

「Viewに対してDQLが使えれば楽なのに」

と思っていたら、実は問題なく使えたのでやり方をお伝えします。

使い方は簡単で、データベース上にViewを作った後に


$ vi config/doctrine/schema.yml


へ実表と同じように設定ファイルを書き


$ symfony doctrine-build-model


を実行すればDoctrineのモデルが作成されます。

Viewですので更新処理は行えませんが、
参照系のカスタムメソッドは追加できます。

■サンプル


※クリックで拡大

ポイントの概念も売れた日付の記録すらない簡単な注文テーブル群でカッコ悪いのですが、
これを元にViewを作成してschema.ymlを書いてみます。

まずViewは名前と住所、注文商品数と合計金額そして粗利益を集計し
以下の様な表を作成します。



Viewを作成するSQLは以下のようになります。


CREATE VIEW  cart_order AS SELECT 
  cart.id ,
  member.name ,
  member.address ,
  (SELECT COUNT(sale.id) FROM sale WHERE cart_id = cart.id) AS sales_amount,
  (SELECT SUM(item.price) FROM sale LEFT JOIN item ON sale.item_id = item.id WHERE cart_id = cart.id) AS sales_price,
  (SELECT SUM(item.price) - SUM(item.cost) FROM sale LEFT JOIN item ON sale.item_id = item.id WHERE cart_id = cart.id) AS sales_margin
FROM
cart 
  LEFT JOIN member ON cart.member_id = member.id;

※データベースはMysqlを利用

このViewに対するschema.ymlは以下のようになります。


CartOrder: 
  tableName: cart_order
  columns: 
    id: 
      type: 
      size: 
      notnull: true
      primary: true
    name: 
      type: string
      size: 4000
    address: 
      type: string
      size: 4000
    sales_amount: 
      type: 
      size: 
    sales_price: 
      type: 
      size: 
    sales_margin: 
      type: 
      size: 


 DoctrineのようなORマッパーを使った開発でも、
Viewを使って予めテーブルを連結・集計しておけば情報の取得で楽が出来ます。
また、取得するカラムや行をViewで絞り込んでおけばセキュリティ的な面も固め易いと思います。
 また、Viewは便利ですが沢山作ると管理が大変になるため、
細かい条件の絞込みや表示の修正はDBモデルのカスタムメソッドで行うと、
管理もしやすく更に楽が出来ます。

フリーで使えるDBのモデリングツールまとめ

森川です。

巷ではエイプリルフールネタがおさかんですが、普通にデータベースのモデリングツールの紹介です(エイプリルフールネタが思いつかない…)。

普段MySQLならDBDesigner4、PostgreSQLならClayを使用しているのですが、他に何かよいツールはないものかと調べてみました。


Clay

言わずと知れた?モデリングツールです。Eclipseプラグインで、無償でも使用可能です。MySQLPostgreSQLで使用可能です。


無償版ではER-図や、DB定義書を出力できません。対応するDBが少なかったりもします。

個人的には、PostgreSQLを使用する場合によく使います。外部キー制約などにも対応しているのでそれほど困りません。

リバースエンジニアリングに対応しているのも気に入っている理由の一つです。

ちなみに、リバースエンジニアリングをするにあたってPostgreSQLJDBCドライバが必要ですが、ここからダウンロードできます。


DBDesigner4

こちらも有名なモデリングツールです(スクリーンショット)。わりと古くから使用されているので、情報もたくさんあるし、機能も豊富です。

Propelで利用できる形式のXML変換するツールなどもあるので、重宝します。

ただ、すでに開発が止まっているので、新しいバージョンは出てこないようです(オープンソースなのでフォークして新しいプロジェクトも立ち上がっているようです)。


MySQL Workbench

こちらはMySQL本家から出されているモデリングツールです。

リバースエンジニアリングも可能であったり、軽くさわっただけですができはそれなりによいと思います。何よりMySQL本家から出されているというのが安心です。

現在バージョンはRC2なので、あと少しで正式版としてリリースされるでしょう。DBDesigner4からファイルをインポートできるようなので、ぜひ使ってみたいところです。


WWW SQL Designer

こちらは完全にWebベースのモデリングツールです。ZIPファイルをダウンロードして解凍したら、そのファイルをPHPサーバ上に配置、それだけで一応動きます。

つい最近バージョンアップしたらしく、以前とはずいぶんインターフェースが変わっています。

MySQLにしかSQLとしてエクスポートできないようなのですが、以前はできていたPostgreSQLやPropelでのエクスポートには対応して欲しいところです。

さくっと手軽にという意味では確かに便利なのですが、ブラウザの再読込を誤ってやってしまうとすべてのデータが失われるので、あまり使いたくないというのが正直なところです。


A5:SQL Mk-2

こちらは日本人の方が開発しているモデリングツールです。もちろんインターフェースは日本語なので使いやすいです。

ただ、PostgreSQLで使用してみたところ、serial型が使えなかったりで少し面倒なことも多いです。また、インポート時にリレーションの情報が失われてしまいました。ER図のツールとしては少々役不足な感が否めません。

個人的にはモデリングツールというよりもテーブル定義書の雛形を作成させるために使用しています。手順としては、ODBC経由でデータベースに接続して、データベースをインポート、テーブル定義書の作成、といった感じです。

PostgreSQLODBC接続をするには、ここからダウンロードできます。


Execute Query

これはモデリングツールというよりもRDBMS操作ツールと紹介されることが多いですが、ER図を作成することもできます。

機能も豊富でスクリーンショットから確認することができます。

こちらはリレーションもきっちりとインポート・エクスポートできるので、かなり使えそうです。


まとめ

いろいろと調べてみましたが、PostgreSQLを使用するときはClayが一番こなれていると感じました。PostgreSQLに関してはDB定義からモデル定義まで一括して管理できるソフトがないのが困りものです。結局モデリングツールでER図を更新して、ALTER用のSQLも作って、さらにモデルの定義まで修正するとなるとどこかでずれが起きそうで避けたいところです。

MySQLに関しては今後はMySQL Workbenchの方がよいのではないかと思います。MySQL WorkbenchからもPropelの形式でエクスポートできるようになれば、完全に移行できそうです。