<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>@blog.justoneplanet.info &#187; MySQL</title>
	<atom:link href="http://blog.justoneplanet.info/category/computer/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.justoneplanet.info</link>
	<description>JavaScript、PHP、MySQLを使ったり</description>
	<lastBuildDate>Sun, 25 Jul 2010 07:34:20 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>SQLの性能をテストする</title>
		<link>http://blog.justoneplanet.info/2010/05/22/sql%e3%81%ae%e6%80%a7%e8%83%bd%e3%82%92%e3%83%86%e3%82%b9%e3%83%88%e3%81%99%e3%82%8b/</link>
		<comments>http://blog.justoneplanet.info/2010/05/22/sql%e3%81%ae%e6%80%a7%e8%83%bd%e3%82%92%e3%83%86%e3%82%b9%e3%83%88%e3%81%99%e3%82%8b/#comments</comments>
		<pubDate>Sat, 22 May 2010 10:17:44 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=2571</guid>
		<description><![CDATA[以下のようにEXPLAINしてみるとイイ。

EXPLAIN SELECT *
    FROM  `parent`
    LEFT JOIN  `child`
    ON  `parent`.id =  `chil [...]]]></description>
			<content:encoded><![CDATA[<p>以下のようにEXPLAINしてみるとイイ。</p>
<pre class="brush: sql;">
EXPLAIN SELECT *
    FROM  `parent`
    LEFT JOIN  `child`
    ON  `parent`.id =  `child`.id_parent
    WHERE  `parent`.id = 1
</pre>
<p>どうやらchildテーブルを全て検索してるようだ。</p>
<table>
<thead>
<tr>
<th>table</th>
<th>type</th>
<th>possible_keys</th>
<th>key</th>
<th>ref</th>
<th>rows</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="">parent</td>
<td class="">const</td>
<td class="">PRIMARY</td>
<td class="">PRIMARY</td>
<td class="">const</td>
<td align="right">1</td>
</tr>
<tr class="even">
<td class="">child</td>
<td class="">ALL</td>
<td class=""><i>NULL</i></td>
<td class=""><i>NULL</i></td>
<td class=""><i>NULL</i></td>
<td align="right">311</td>
</tr>
</tbody>
</table>
<h3>■改善</h3>
<p>以下を実行してインデックスを付加し、クエリの性能を向上させる。</p>
<pre class="brush: sql;">
ALTER TABLE `child`
    ADD CONSTRAINT `fk_child_tbl_parent_tbl`
    FOREIGN KEY (`id_parent`) REFERENCES `parent` (`id`)
    ON DELETE CASCADE
    ON UPDATE NO ACTION;
</pre>
<p>劇的だ！ヾ(＠⌒▽⌒＠)ﾉchildテーブルを1行しか検索しなくなった。</p>
<table class="data" id="table_results">
<thead>
<tr>
<th>table</th>
<th>type</th>
<th>possible_keys</th>
<th>key</th>
<th>ref</th>
<th>rows</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td class="">parent</td>
<td class="">const</td>
<td class="">PRIMARY</td>
<td class="">PRIMARY</td>
<td class="">const</td>
<td align="right">1</td>
</tr>
<tr class="even">
<td class="">child</td>
<td class="">ref</td>
<td class="">fk_child_tbl_parent_tbl</td>
<td class="">fk_child_tbl_parent_tbl</td>
<td class="">const</td>
<td align="right">1</td>
</tr>
</tbody>
</table>
<div class="kakomi">
<h4>参考</h4>
<dl>
<dt>type</dt>
<dd>結合型。</dd>
<dd>const。テーブルに、一致するレコードが最大で 1 つ。</dd>
<dd>ref。前のテーブルのレコードの組み合わせのそれぞれに対して、インデックス値にマッチするすべてのレコードがこのテーブルから読み取られる。ref  は、『インデックスの左端の先頭部分のみが結合で使用される場合』、『インデックスが UNIQUE や PRIMARY KEY  ではない場合』に使用される。</dd>
<dd>ALL。前のテーブルのレコードの組み合わせのそれぞれに対して、フルテーブルスキャンが実行される。</dd>
<dt>possible_keys</dt>
<dd>テーブル内のレコードの検索に MySQL で使用可能なインデックスを示す。</dd>
<dt>key</dt>
<dd>MySQL が実際に使用を決定したキー（インデックス）を示す。</dd>
<dt>ref</dt>
<dd>テーブルからレコードを選択する際に key  とともに使用されるカラムまたは定数。</dd>
<dt>rows</dt>
<dd>クエリの実行に際して調べる必要があると MySQL によって判定されたレコードの数を示す。少ない方がイイ。</dd>
</dl>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2010/05/22/sql%e3%81%ae%e6%80%a7%e8%83%bd%e3%82%92%e3%83%86%e3%82%b9%e3%83%88%e3%81%99%e3%82%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>複数テーブル同時削除</title>
		<link>http://blog.justoneplanet.info/2010/05/22/%e8%a4%87%e6%95%b0%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e5%90%8c%e6%99%82%e5%89%8a%e9%99%a4/</link>
		<comments>http://blog.justoneplanet.info/2010/05/22/%e8%a4%87%e6%95%b0%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e5%90%8c%e6%99%82%e5%89%8a%e9%99%a4/#comments</comments>
		<pubDate>Sat, 22 May 2010 09:29:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=2564</guid>
		<description><![CDATA[以下のようにdelete文を使用すると、複数テーブルからレコードが削除できる。

DELETE
    `table`,
    `child`,
    `grandchild`
FROM
    `table`
LE [...]]]></description>
			<content:encoded><![CDATA[<p>以下のようにdelete文を使用すると、複数テーブルからレコードが削除できる。</p>
<pre class="brush: sql;">
DELETE
    `table`,
    `child`,
    `grandchild`
FROM
    `table`
LEFT JOIN
    `child`
ON
    `table`.id = `child`.`id_table`
LEFT JOIN
    `grandchild`
ON
    `child`.id = `grandchild`.`id_child`
WHERE
    `table`.id = 1
</pre>
<p>但し、外部キー制約でON DELETE  CASCADEを使った方が早い気がする。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2010/05/22/%e8%a4%87%e6%95%b0%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e5%90%8c%e6%99%82%e5%89%8a%e9%99%a4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>外部キー制約</title>
		<link>http://blog.justoneplanet.info/2010/05/22/%e5%a4%96%e9%83%a8%e3%82%ad%e3%83%bc%e5%88%b6%e7%b4%84/</link>
		<comments>http://blog.justoneplanet.info/2010/05/22/%e5%a4%96%e9%83%a8%e3%82%ad%e3%83%bc%e5%88%b6%e7%b4%84/#comments</comments>
		<pubDate>Sat, 22 May 2010 09:23:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=2562</guid>
		<description><![CDATA[以下のようにする。

ALTER TABLE `child`
    ADD CONSTRAINT `fk_child_tbl_parent_tbl`
    FOREIGN KEY (`id_parent`) REFE [...]]]></description>
			<content:encoded><![CDATA[<p>以下のようにする。</p>
<pre class="brush: sql;">
ALTER TABLE `child`
    ADD CONSTRAINT `fk_child_tbl_parent_tbl`
    FOREIGN KEY (`id_parent`) REFERENCES `parent` (`id`)
    ON DELETE CASCADE
    ON UPDATE NO ACTION;
</pre>
<p>こうするとparentテーブルからレコードAを削除した時に、レコードAのidとchildテーブルのid_parentが等しいレコードが同時に削除される。</p>
<p>ちなみにid_contentsは全く同じ型でないとALTER TABLEが失敗する。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2010/05/22/%e5%a4%96%e9%83%a8%e3%82%ad%e3%83%bc%e5%88%b6%e7%b4%84/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQLのrootパスワードを設定する</title>
		<link>http://blog.justoneplanet.info/2010/02/22/mysql%e3%81%aeroot%e3%83%91%e3%82%b9%e3%83%af%e3%83%bc%e3%83%89%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b/</link>
		<comments>http://blog.justoneplanet.info/2010/02/22/mysql%e3%81%aeroot%e3%83%91%e3%82%b9%e3%83%af%e3%83%bc%e3%83%89%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 15:03:09 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=2412</guid>
		<description><![CDATA[インストール直後は何もパスワードが設定されていないので注意すること！

SET PASSWORD FOR root@localhost=PASSWORD('password');

]]></description>
			<content:encoded><![CDATA[<p>インストール直後は何もパスワードが設定されていないので注意すること！</p>
<pre class="brush: sql;">
SET PASSWORD FOR root@localhost=PASSWORD('password');
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2010/02/22/mysql%e3%81%aeroot%e3%83%91%e3%82%b9%e3%83%af%e3%83%bc%e3%83%89%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>特定のユーザにmysqlリモート接続を許可する</title>
		<link>http://blog.justoneplanet.info/2010/02/19/%e7%89%b9%e5%ae%9a%e3%81%ae%e3%83%a6%e3%83%bc%e3%82%b6%e3%81%abmysql%e3%83%aa%e3%83%a2%e3%83%bc%e3%83%88%e6%8e%a5%e7%b6%9a%e3%82%92%e8%a8%b1%e5%8f%af%e3%81%99%e3%82%8b/</link>
		<comments>http://blog.justoneplanet.info/2010/02/19/%e7%89%b9%e5%ae%9a%e3%81%ae%e3%83%a6%e3%83%bc%e3%82%b6%e3%81%abmysql%e3%83%aa%e3%83%a2%e3%83%bc%e3%83%88%e6%8e%a5%e7%b6%9a%e3%82%92%e8%a8%b1%e5%8f%af%e3%81%99%e3%82%8b/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 17:07:53 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=2404</guid>
		<description><![CDATA[その前にポート3306は初期状態では閉じられているので開ける。

iptables -I INPUT -j ACCEPT -p tcp -s x.x.x.x --dport 3306

IPはクライアント側のIP。このI [...]]]></description>
			<content:encoded><![CDATA[<p>その前にポート3306は初期状態では閉じられているので開ける。</p>
<pre class="brush: bash;">
iptables -I INPUT -j ACCEPT -p tcp -s x.x.x.x --dport 3306
</pre>
<p>IPはクライアント側のIP。このIPからだけ接続できる。192.168.1.%のようにワイルドカードも使えるがセキュリティには注意しなくてはならない。</p>
<pre class="brush: bash;">
GRANT ALL PRIVILEGES ON *.* to user@'192.168.1.1' IDENTIFIED BY 'password';
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2010/02/19/%e7%89%b9%e5%ae%9a%e3%81%ae%e3%83%a6%e3%83%bc%e3%82%b6%e3%81%abmysql%e3%83%aa%e3%83%a2%e3%83%bc%e3%83%88%e6%8e%a5%e7%b6%9a%e3%82%92%e8%a8%b1%e5%8f%af%e3%81%99%e3%82%8b/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CONSTRAINT句</title>
		<link>http://blog.justoneplanet.info/2009/09/24/constraint%e5%8f%a5/</link>
		<comments>http://blog.justoneplanet.info/2009/09/24/constraint%e5%8f%a5/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 02:49:14 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=1944</guid>
		<description><![CDATA[以下のようなSQLを実行すると、commentテーブルのカラムtask_idのレコードには、taskテーブルのカラムidに存在するものしか存在できない。この参照整合性制約機能は多用すると少々問題が起こることもある。

C [...]]]></description>
			<content:encoded><![CDATA[<p>以下のようなSQLを実行すると、commentテーブルのカラムtask_idのレコードには、taskテーブルのカラムidに存在するものしか存在できない。この参照整合性制約機能は多用すると少々問題が起こることもある。</p>
<pre class="brush: sql;">
CREATE TABLE IF NOT EXISTS `comment` (
    `id` int(11) NOT NULL auto_increment,
    `task_id` int(11) default NULL,
    `description` text,
    `created_at` datetime default NULL,
    PRIMARY KEY  (`id`),
    KEY `comment_FI_1` (`task_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `task` (
    `id` int(11) NOT NULL auto_increment,
    `title` varchar(255) default NULL,
    `description` text,
    `status_id` int(11) default NULL,
    `created_at` datetime default NULL,
    `updated_at` datetime default NULL,
    PRIMARY KEY  (`id`),
    KEY `task_FI_1` (`status_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
ALTER TABLE `comment`
    ADD CONSTRAINT `comment_FK_1` FOREIGN KEY (`task_id`) REFERENCES `task` (`id`);
</pre>
<h3>■メリットとデメリット</h3>
<h4>メリット</h4>
<ul>
<li>誤ったデータをテーブルに含めないようにできる</li>
</ul>
<h4>デメリット</h4>
<ul>
<li>データ移行時に整合性をチェックするため時間がかかる</li>
<li>テーブル設計が複雑になる（運用上の整合性の考慮）</li>
</ul>
<h3>■代替案</h3>
<p>アプリケーション側での制御。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2009/09/24/constraint%e5%8f%a5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Database Security（データベースのセキュリティ）</title>
		<link>http://blog.justoneplanet.info/2009/05/23/php-database-security%ef%bc%88%e3%83%87%e3%83%bc%e3%82%bf%e3%83%99%e3%83%bc%e3%82%b9%e3%81%ae%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%ef%bc%89/</link>
		<comments>http://blog.justoneplanet.info/2009/05/23/php-database-security%ef%bc%88%e3%83%87%e3%83%bc%e3%82%bf%e3%83%99%e3%83%bc%e3%82%b9%e3%81%ae%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%ef%bc%89/#comments</comments>
		<pubDate>Sat, 23 May 2009 11:07:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[セキュリティ]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=1280</guid>
		<description><![CDATA[すなわちSQLインジェクションのための防御策である。
■SQLインジェクションの実例
以下のログインフォームで考える。

&#60;form method=&#34;post&#34; action=&#34;log [...]]]></description>
			<content:encoded><![CDATA[<p>すなわちSQLインジェクションのための防御策である。</p>
<h3>■SQLインジェクションの実例</h3>
<p>以下のログインフォームで考える。</p>
<pre class="brush: xml;">
&lt;form method=&quot;post&quot; action=&quot;login.php&quot;&gt;
Name: &lt;input type=&quot;text&quot; name=&quot;name&quot; /&gt;
Password: &lt;input type=&quot;password&quot; name=&quot;password&quot; /&gt;
&lt;input type=&quot;submit&quot; /&gt;
&lt;/form&gt;
</pre>
<p>以下のコードで存在するユーザかどうか、DBに問い合わせて検証する。</p>
<pre class="brush: php;">
&lt;?php
$password = md5($_POST['password']);
$sql = &quot;SELECT * FROM `user` WHERE `name` = '{$_POST['name']}' AND `password` = '{$password}'&quot;;
?&gt;
</pre>
<p>一見、何の問題も無いようだが、Nameに「1&#8242; OR 1 = 1 &#8211;」とすると以下のSQL文を実行することになる。</p>
<pre class="brush: sql;">
SELECT * FROM `user` WHERE `name` = '1' OR 1 = 1 --' AND `password` = 'password_str'
</pre>
<p>「&#8211;」以降は改行コードまで全てコメントとみなされ、条件「`name` = &#8217;1&#8242;」は殆ど成立しないが、条件「1 = 1」が常に成立し、全てのユーザデータが返ることになる。従って、アルゴリズムにもよるが、ログインが常にできてしまう。</p>
<h4>対策1</h4>
<p>以下のように、プリペアドステートメントを用いる。</p>
<pre class="brush: php;">
&lt;?php
try {
    $dsn = 'mysql:host=localhost;dbname=db';
    $dbh = new PDO($dsn, DB_USER, DB_PASS);
    $dbh-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $dbh-&gt;setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
}
catch(PDOException $e){
    //code
}
$password = md5($_POST['password']);
$sql = &quot;SELECT * FROM `user` WHERE `name` = ? AND `password` = ?&quot;;
$stmt = $dbh-&gt;prepare($sql);
$stmt-&gt;execute(array(
    $_POST['name'],
    $pasword
));
$result = $stmt-&gt;fetchAll();
?&gt;
</pre>
<h4>対策2</h4>
<p>以下のように、エスケープ処理を忘れずに行う。</p>
<pre class="brush: php;">
$dbh = mysql_connect(DB_HOST, DB_USER, DB_PASS);
mysql_select_db(DB_NAME, $dbh);
$password = md5($_POST['password']);
$name = mysql_real_escape_string($_POST['name']);
$sql = &quot;SELECT * FROM `user` WHERE `name` = '{$name}' AND `password` = '{$password}'&quot;;
</pre>
<p>但し、ログインフォームなので大概において英数字のユーザ名なのでフィルタリングすることをお勧めする。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2009/05/23/php-database-security%ef%bc%88%e3%83%87%e3%83%bc%e3%82%bf%e3%83%99%e3%83%bc%e3%82%b9%e3%81%ae%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP MySQL Improved Extension（mysqli）</title>
		<link>http://blog.justoneplanet.info/2009/05/11/php-mysql-improved-extension%ef%bc%88mysqli%ef%bc%89/</link>
		<comments>http://blog.justoneplanet.info/2009/05/11/php-mysql-improved-extension%ef%bc%88mysqli%ef%bc%89/#comments</comments>
		<pubDate>Sun, 10 May 2009 23:00:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[データベース]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=1160</guid>
		<description><![CDATA[mysqli拡張サポートによって、MySQL4.1以降で使える機能を利用できる。但し、個人的には全くこの手の関数を使わない。何故ならばMySQLに特化した関数であり、仮に他のDBに移行する場合、保守のコストがとっても高く [...]]]></description>
			<content:encoded><![CDATA[<p>mysqli拡張サポートによって、MySQL4.1以降で使える機能を利用できる。但し、個人的には全くこの手の関数を使わない。何故ならばMySQLに特化した関数であり、仮に他のDBに移行する場合、保守のコストがとっても高くなってしまうと考えているからだ。それにラーニングコストもかかるし、PDOのメソッド名とmysqliの関数名がごっちゃになる。</p>
<h3>■mysqliを使ったDBへの接続</h3>
<pre class="brush: php;">
&lt;?php
$dbh = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if(mysqli_connect_errorno()){
    //code for error
}
mysqli-&gt;close();
?&gt;
</pre>
<p>mysqliは例外をthrowしない。</p>
<pre class="brush: php;">
&lt;?php
$dbh = mysqli_connect(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if(!$dbh){
    //code for error
}
mysqli_close($dbh);
?&gt;
</pre>
<h3>■mysqliを使ったDBへのクエリ発行</h3>
<pre class="brush: php;">
&lt;?php
$name = mysqli-&gt;real_escape_string($_POST['name']);
$sql = &quot;SELECT `id`, `name` FROM `person` WHERE `name` = '$name'&quot;;
if(!$dbh-&gt;real_query($sql)){
    //print($dbh-&gt;error);
}
if($result = mysql-&gt;store_result()){
    while($row = $result-&gt;fetch_assoc()){
        print($row['id'] . ': ' . $row['name']);
    }
    $result-&gt;close();
}
?&gt;
</pre>
<p>$resultもcloseしなきゃならんとは。。。めんどい。。。</p>
<pre class="brush: php;">
&lt;?php
$name = mysqli_real_escape_string($_POST['name']);
$sql = &quot;SELECT `id`, `name` FROM `person` WHERE `name` = '$name'&quot;;
if(mysqli_real_query($dbh, $sql)){
    //print(mysqli_error());
}
if($result = mysql_store_result($dbh)){
    while($row = $result_fetch_assoc($result)){
        print($row['id'] . ': ' . $row['name']);
    }
    mysqli_free_result($result);
}
?&gt;
</pre>
<p>うーむ。実に不愉快だ。やはりmysqliは性に合わん！</p>
<h3>■mysqliを使ったプリペアドステートメント</h3>
<pre class="brush: php;">
&lt;?php
$sql = &quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES(?, ?, ?)&quot;;
if($stmt = $dbh-&gt;prepare($sql)){
    $stmt-&gt;bindParam('s', $id, $_POST['name'], $_POST['country_id']);
    $stmt-&gt;execute();
    $stmt-&gt;bind_result($result_id, $result_name);
    while($stmt-&gt;fetch()){
        print($result_id . ': ' . $result_name);
    }
    $stmt-&gt;close();
}
?&gt;
</pre>
<p>これじゃ、ソースを書きたくならないな。</p>
<pre class="brush: php;">
&lt;?php
$sql = &quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES(?, ?, ?)&quot;;
if($stmt = mysqli_prepare($dbh, $sql)){
    mysqli_stmt_bind_param($stmt, 's', $id, $_POST['name'], $_POST['country_id']);
    mysqli_stmt_execute()$stmt;
    mysqli_stmt_bind_result($dbh, $result_id, $result_name);
    while(mysqli_stmt_fetch()){
        print($result_id . ': ' . $result_name);
    }
    mysqli_stmt_close($stmt);
}
?&gt;
</pre>
<h3>■mysqliを使ったトランザクション</h3>
<pre class="brush: php;">
&lt;?php
$dbh-&gt;autocommit(false);
$dbh-&gt;query(&quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES('4', 'Jack', '2')&quot;);
$dbh-&gt;query(&quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES('5', 'Emily', '1')&quot;);
if(!$dbh-&gt;commit()){
    $dbh-&gt;rollback();
}
?&gt;
</pre>
<pre class="brush: php;">
&lt;?php
mysqli_autocommiti($dbh, false);
mysqli_query($dbh, &quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES('4', 'Jack', '2')&quot;);
mysqli_query($dbh, &quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES('5', 'Emily', '1')&quot;);
if(!mysqli_commit($dbh)){
    mysqli_rollback($dbh);
}
?&gt;
</pre>
<div class="kakomi">
<h4>mysqliの特徴</h4>
<p>「手続き型」と「オブジェクト指向型」の記述が可能である。</p>
</div>
<p>サーバによってはインストールされていない事もしばしばあるようだ。ますます使わんぞ、コリャ=3・・・</p>
<h4>命名</h4>
<p>余計なお世話型関数。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2009/05/11/php-mysql-improved-extension%ef%bc%88mysqli%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Data Object（PDO）</title>
		<link>http://blog.justoneplanet.info/2009/05/10/php-data-object%ef%bc%88pdo%ef%bc%89/</link>
		<comments>http://blog.justoneplanet.info/2009/05/10/php-data-object%ef%bc%88pdo%ef%bc%89/#comments</comments>
		<pubDate>Sun, 10 May 2009 14:54:11 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[データベース]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=1153</guid>
		<description><![CDATA[PDOには様々なDBに対する各々のドライバがある。一旦、インストールすれば（PDOを使用してDBへ接続している場合、）コードを殆ど書き換えることなく、DBを変更することが可能になる。
■PDOを使ったデータベースへの接続 [...]]]></description>
			<content:encoded><![CDATA[<p>PDOには様々なDBに対する各々のドライバがある。一旦、インストールすれば（PDOを使用してDBへ接続している場合、）コードを殆ど書き換えることなく、DBを変更することが可能になる。</p>
<h3>■PDOを使ったデータベースへの接続</h3>
<pre class="brush: php;">
&lt;?php
$dsn = 'mysql:host=localhost;dbname=dbname';
$dbh = new PDO($dsn, DB_USER, DB_PASS);
?&gt;
</pre>
<p>通常、PDOはエラーが発生しても何も表示しない（PDO::ERRMODE_SILENT）。これはセキュリティ上安全ではあるが、一方でデバッグを非常に困難にする。従って、例外を発生させ（ファイルに書き込みさせ）るようにすることも可能である。</p>
<pre class="brush: php;">
&lt;?php
try {
    $dsn = 'mysql:host=localhost;dbname=dbname';
    $dbh = new PDO($dsn, DB_USER, DB_PASS);
    $dbh-&gt;setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
    $dbh-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(Exception $e){
    //code
}
?&gt;
</pre>
<h3>■PDOを使ったデータベースへのクエリ発行</h3>
<h4>SELECT文</h4>
<p>SELECT文のような、結果セットを得ることを主目的としている場合は、以下のようにqueryメソッドを用いる。また、queryメソッドを用いた場合、戻り値はPDOStatementオブジェクトである。</p>
<pre class="brush: php;">
&lt;?php
$sql = &quot;SELECT * FROM `person` WHERE `name` = 'John'&quot;;
$result = $dbh-&gt;query($sql);
foreach($result as $row){
    print($row['name'] . ': ' . $row['country_id']);
}
?&gt;
</pre>
<p>但し、以下のように書いた場合、$rowには「数字キー」と「カラム名のキー」が両方含まれているので値が重複する。これはデフォルトのデータ取り出しモードがPDO::FETCH_BOTHであり、「数字キー」と「カラム名のキー」での配列になっているためである。</p>
<pre class="brush: php;">
&lt;?php
$sql = &quot;SELECT * FROM `person` WHERE `name` = 'John'&quot;;
$result = $dbh-&gt;query($sql);
foreach($result as $row){
    foreach($row as $value){
        print($value . PHP_EOL);
    }
}
/*
1
1
John
John
2
2
*/
?&gt;
</pre>
<div class="kakomi">
<h5>データ取り出しモードの変更</h5>
<p>データ取り出しモードを変更するには、以下のように結果セットが含まれるPDOStatementオブジェクト$resultに対して、setFetchModeメソッドを実行せねばならない。</p>
<pre class="brush: php;">
&lt;?php
$sql = &quot;SELECT * FROM `person` WHERE `name` = 'John'&quot;;
$result = $dbh-&gt;query($sql);
$result-&gt;setFetchMode(PDO::FETCH_OBJ);
foreach($result as $row){
    print($row-&gt;name . ': ' . $row-&gt;country_id);
}
?&gt;
</pre>
</div>
<div class="kakomi">
<h5>ユーザ入力の値をSQL文に組み込むためのメソッド</h5>
<p>通常、SQLインジェクションを回避するために、ユーザ入力の値をSQL文に含める際にはサニタイジングしなければならない。以下のように、quoteメソッドを用いることで可能である。</p>
<pre class="brush: php;">
&lt;?php
$name = $dbh-&gt;quote($_POST['name']);
$sql = &quot;SELECT * FROM `person` WHERE `name` = '$name'&quot;;
$result = $dbh-&gt;query($sql);
?&gt;
</pre>
<p>但し、いくつかのドライバはこのメソッドを実装していないので、後述のプリペアドステートメントを用いたほうが良い。</p>
</div>
<h4>INSERT文、UPDATE文、DELETE文</h4>
<p>INSERT文、UPDATE文、DELETE文には変更（処理）した行数を返すexecメソッドを用いる。</p>
<pre class="brush: php;">
&lt;?php
$sql = &quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES('4', 'Jack', '2')&quot;;
$num = $dbh-&gt;exec($sql);
print($num);//1
?&gt;
</pre>
<h3>■プリペアドステートメント（Prepared Statement）を用いたクエリの発行</h3>
<h4>プリペアドステートメントとは</h4>
<ul>
<li>1回のリクエストに対する処理の中で、SQL文の再利用を可能にする</li>
<li>DBがプリペアドステートメントをサポートしてない場合、PDOが内部の関数で可能にする</li>
<li>DBがプリペアドステートメントをサポートしている場合、DBの機能を使ってアプリケーションの性能の向上を可能にする</li>
<li>（SQLインジェクションを誘発させる）クォート漏れに対するリスク回避を可能にする</li>
</ul>
<pre class="brush: php;">
&lt;?php
$sql = &quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES(?, ?, ?)&quot;;
$stmt = $dbh-&gt;prepare($sql);
$stmt-&gt;execute(array(
    $id,
    $_POST['name'],
    $_POST['country_id']
));
?&gt;
</pre>
<p>INSERT文、UPDATE文、DELETE文には、ユーザ入力の値をSQL文に含めることが非常に多い。とはいえ、以下のようにSELECT文でも当然ながら、プリペアドステートメントを用いることはある。</p>
<pre class="brush: php;">
&lt;?php
$sql = &quot;SELECT * FROM `person` WHERE `name` = ?&quot;;
$stmt = $dbh-&gt;prepare($sql);
$stmt-&gt;execute(array('John'));
//$stmt-&gt;setFetchMode(PDO::FETCH_OBJ);
$result = $stmt-&gt;fetchAll();
var_dump($result);
/*
array(1) {
  [0]=&gt;
  array(6) {
    [&quot;id&quot;]=&gt;
    string(1) &quot;1&quot;
    [0]=&gt;
    string(1) &quot;1&quot;
    [&quot;name&quot;]=&gt;
    string(4) &quot;John&quot;
    [1]=&gt;
    string(4) &quot;John&quot;
    [&quot;country_id&quot;]=&gt;
    string(1) &quot;2&quot;
    [2]=&gt;
    string(1) &quot;2&quot;
  }
}
*/
?&gt;
</pre>
<p>但し、PHPのバージョンによって、（MySQL独自拡張の）LIMIT句に対するプリペアドステートメントにバグがあるため、それ（LIMIT句）以外での使用が望ましいと個人的には思う。また、LIMIT句は数値の値しか許容しないため、PHPで（型変換などを使って）サニタイジングすることは比較的に容易である。さらに、PDOStatementクラスに（結果を1行だけ返す）fetchメソッドが「あるバージョン」と「ないバージョン」があるため、このメソッドの使用はなるべく避けたほうが良い。</p>
<h3>■PDOを使ったトランザクションの実行</h3>
<p>以下のようにして、トランザクションを利用する。</p>
<pre class="brush: php;">
&lt;?php
try {
    $dsn = 'mysql:host=localhost;dbname=dbname';
    $dbh = new PDO($dsn, DB_USER, DB_PASS);
    $dbh-&gt;setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
    $dbh-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $dbh-&gt;beginTransaction();
    $dbh-&gt;exec(&quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES('4', 'Jack', '2')&quot;);
    $dbh-&gt;exec(&quot;INSERT INTO `person`(`id`, `name`, `country_id`) VALUES('5', 'Emily', '1')&quot;);
    $dbh-&gt;commit();
}
catch(Exception $e){
    $dbh-&gt;rollBack();
}
?&gt;
</pre>
<h4>各メソッドについて</h4>
<dl>
<dt>beginTransaction</dt>
<dd>トランザクションを開始する</dd>
<dt>commit</dt>
<dd>確定する</dd>
<dt>rollBack</dt>
<dd>破棄して最初の状態に戻す</dd>
</dl>
<div class="kakomi">
<h4>トランザクションとは</h4>
<p>「全て成功する」か「全て失敗する」かのどちらかしか存在しないことを保証する機能。この機能が必要な例として、たいていの参考書では「銀行の振込み」などが扱われる。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2009/05/10/php-data-object%ef%bc%88pdo%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Joins（SQLにおけるテーブル結合）</title>
		<link>http://blog.justoneplanet.info/2009/05/10/sql-joins%ef%bc%88sql%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e7%b5%90%e5%90%88%ef%bc%89/</link>
		<comments>http://blog.justoneplanet.info/2009/05/10/sql-joins%ef%bc%88sql%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e7%b5%90%e5%90%88%ef%bc%89/#comments</comments>
		<pubDate>Sat, 09 May 2009 19:03:51 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[データベース]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=1142</guid>
		<description><![CDATA[テーブル結合とは、複数のテーブルから一つのレコードセットをつくり出す。多くのアプリケーションは非常に複雑なテーブル結合を使っている。

サンプルテーブル
personテーブル


id
name
country_id

 [...]]]></description>
			<content:encoded><![CDATA[<p>テーブル結合とは、複数のテーブルから一つのレコードセットをつくり出す。多くのアプリケーションは非常に複雑なテーブル結合を使っている。</p>
<div class="kakomi">
<h4>サンプルテーブル</h4>
<h5>personテーブル</h5>
<table>
<tr>
<th>id</th>
<th>name</th>
<th>country_id</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>2</td>
</tr>
<tr>
<td>2</td>
<td>Mike</td>
<td>1</td>
</tr>
<tr>
<td>3</td>
<td>Nick</td>
<td>99</td>
</tr>
</table>
<h5>countryテーブル</h5>
<table>
<tr>
<th>id</th>
<th>name</th>
</tr>
<tr>
<td>1</td>
<td>USA</td>
</tr>
<tr>
<td>2</td>
<td>Japan</td>
</tr>
<tr>
<td>3</td>
<td>Canada</td>
</tr>
</table>
</div>
<h3>■内部結合（inner join）</h3>
<p>内部結合とは、一歩のテーブルに存在するcountry.idが、もう一方のテーブルに含まれていないとき、行の結合が失敗し結果セットから除外される結合である。</p>
<pre class="brush: sql;">
SELECT
    `person`.`id`,
    `person`.`name`,
    `country`.`name`
FROM
    `person`
INNER JOIN
    `country`
ON
    `person`.`country_id` = `country`.`id`;
</pre>
<p>ONキーワードで結合条件「`person`.`country_id` = `country`.`id`」と指定するとことができる。上述の場合、「INNER JOIN」でなく「JOIN」でも結果は等しいが、可読性の問題などが生じるため、結合の種類はSQL文に明記することをお勧めする。</p>
<div class="kakomi">
<h4>実行結果</h4>
<table>
<tr>
<th>id</th>
<th>name</th>
<th>name</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>Japan</td>
</tr>
<tr>
<td>2</td>
<td>Mike</td>
<td>USA</td>
</tr>
</table>
</div>
<h3>■左外部結合（left outer join）</h3>
<p>外部結合とは、どちらか一方のテーブルに存在する行が、結果セットに含まれる結合である。「left outer join」はFROM節の左側のテーブル（person）に合わせて結合する。以下のようにすると左外部結合ができる。</p>
<pre class="brush: sql;">
SELECT
    `person`.`id`,
    `person`.`name`,
    `country`.`name`
FROM
    `person`
LEFT OUTER JOIN
    `country`
ON
    `person`.`country_id` = `country`.`id`;
</pre>
<div class="kakomi">
<h4>実行結果</h4>
<table>
<tr>
<th>id</th>
<th>name</th>
<th>name</th>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>Japan</td>
</tr>
<tr>
<td>2</td>
<td>Mike</td>
<td>USA</td>
</tr>
<tr>
<td>3</td>
<td>Nick</td>
<td>NULL</td>
</tr>
</table>
</div>
<h3>■右外部結合（right outer join）</h3>
<p>「right outer join」はテーブル（country）に合わせて結合する。以下のようにすると右外部結合ができる。</p>
<pre class="brush: sql;">
SELECT
    `person`.`id`,
    `person`.`name`,
    `country`.`name`
FROM
    `person`
RIGHT OUTER JOIN
    `country`
ON
    `person`.`country_id` = `country`.`id`;
</pre>
<div class="kakomi">
<h4>実行結果</h4>
<table>
<tr>
<th>id</th>
<th>name</th>
<th>name</th>
</tr>
<tr>
<td>2</td>
<td>Mike</td>
<td>USA</td>
</tr>
<tr>
<td>1</td>
<td>John</td>
<td>Japan</td>
</tr>
<tr>
<td>NULL</td>
<td>NULL</td>
<td>Canada</td>
</tr>
</table>
</div>
<p>LEFTキーワードとRIGHTキーワードはどちらのデータに空白部分が含まれていても良いかを決めるワードである。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2009/05/10/sql-joins%ef%bc%88sql%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e3%83%86%e3%83%bc%e3%83%96%e3%83%ab%e7%b5%90%e5%90%88%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Relational Database and SQL（RDBとSQL）</title>
		<link>http://blog.justoneplanet.info/2009/05/10/relational-database-and-sql%ef%bc%88rdb%e3%81%a8sql%ef%bc%89/</link>
		<comments>http://blog.justoneplanet.info/2009/05/10/relational-database-and-sql%ef%bc%88rdb%e3%81%a8sql%ef%bc%89/#comments</comments>
		<pubDate>Sat, 09 May 2009 15:30:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[データベース]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=1130</guid>
		<description><![CDATA[■データベースの作成
以下のように、「CREATE DATABASE」文や「CREATE SCHEMA」文を使用する。

CREATE DATABASE &#60;dbname&#62;;


CREATE SCHEMA &#038; [...]]]></description>
			<content:encoded><![CDATA[<h3>■データベースの作成</h3>
<p>以下のように、「CREATE DATABASE」文や「CREATE SCHEMA」文を使用する。</p>
<pre class="brush: sql;">
CREATE DATABASE &lt;dbname&gt;;
</pre>
<pre class="brush: sql;">
CREATE SCHEMA &lt;dbname&gt;;
</pre>
<h3>■テーブルの作成</h3>
<p>以下のように、「CREATE TABLE」文を使ってテーブルを作成する。</p>
<pre class="brush: sql;">
CREATE TABLE &lt;tablename&gt; (
    &lt;colname&gt; &lt;coltype&gt; [&lt;colattributes&gt;],
    [...
    &lt;colname&gt; &lt;coltype&gt; [&lt;colattributes&gt;]]
);
</pre>
<p>例えば以下のようになる。</p>
<pre class="brush: sql;">
CREATE TABLE book (
    id INT NOT NULL PRIMARY KEY,
    isbn VARCHAR(13),
    title VARCHAR(255),
    author VARCHAR(255),
    publisher VARCHAR(255)
)
</pre>
<h3>■インデックスの作成</h3>
<pre class="brush: sql;">
CREATE INDEX &lt;indexname&gt; ON &lt;tablename&gt; (&lt;column&gt;[, ... &lt;column&gt;]);
</pre>
<p>例えば以下のようになる。</p>
<pre class="brush: sql;">
CREATE INDEX book_isbn ON book (isbn);
</pre>
<p>但し、一般的には以下のようにテーブルの作成と同時に行うことが多い。</p>
<pre class="brush: sql;">
CREATE TABLE `book` (
    `id` int(11) NOT NULL auto_increment,
    `isbn` varchar(13) default NULL,
    `title` varchar(255) default NULL,
    `author` varchar(255) default NULL,
    `publisher` varchar(255) default NULL,
    PRIMARY KEY  (`id`),
    KEY `book_isbn` (`isbn`)
);
</pre>
<h3>■データベースの削除</h3>
<pre class="brush: sql;">
DROP SCHEMA &lt;dbname&gt;;
</pre>
<h3>■テーブルの削除</h3>
<pre class="brush: sql;">
DROP TABLE &lt;tablename&gt;;
</pre>
<hr />
<h3>■データの操作</h3>
<h4>追加</h4>
<p>データを追加するには、以下のようにINSERT（ INTO）文を使用する。テーブルのカラム名は運用上のメリットが非常に大きいため、記述することを強くお勧めする（カラムの追加に対するSQL文の耐性）。</p>
<pre class="brush: sql;">
INSERT INTO &lt;tablename&gt;(&lt;colname&gt; [, ... , &lt;colname&gt;]) VALUES(&lt;value&gt; [, ... , &lt;value&gt;]);
</pre>
<h4>更新</h4>
<p>データを更新するためには、以下のようにUPDATE（~SET~）文を使用する。但し、以下のコードは全レコードが特定の値に上書きされてしまう。</p>
<pre class="brush: sql;">
UPDATE &lt;tablename&gt; SET &lt;colname&gt; = &lt;value&gt; [, ... , &lt;colname&gt; = &lt;value&gt;];
</pre>
<p>通常は、以下のようにWHERE節などと組み合わせて使用し、特定のレコードのみを更新する。</p>
<pre class="brush: sql;">
UPDATE `address_book` SET `name` = 'Mike' WHERE `id` = '1';
</pre>
<h4>削除</h4>
<p>データを削除するには、以下のようにDELETE文を使う。但し、以下のコードは全レコードが削除される。</p>
<pre class="brush: sql;">
DELETE  FROM &lt;tablename&gt;;
</pre>
<p>通常は以下のようにWHERE節などと組み合わせて使用する。</p>
<pre class="brush: sql;">
DELETE  FROM `address_book` WHERE `name` = 'John';
</pre>
<hr />
<h3>■データの表示</h3>
<p>データを表示するには、以下のようにSELECT文を使用する。</p>
<pre class="brush: sql;">
SELECT * FROM `address_book`;
</pre>
<p>通常、アプリケーションで全件のデータが必要なときというのは稀である。そして全件をSQLから抽出すると、サーバのメモリを圧迫することになる。従って、以下のようにWHERE節などと組み合わせて使うことが多い。</p>
<pre class="brush: sql;">
SELECT `tel` FROM `address_book` WHERE `name` = 'John';
</pre>
<h4>WHERE節について</h4>
<p>WHERE節では、条件をANDやORで複数指定できる。また、LIKE演算子を使用し大文字/小文字を区別しないようにしたり、「%（任意の複数文字）」や「_（任意の一文字）」の記号を使用して検索できる。</p>
<pre class="brush: sql;">
SELECT `tel` FROM `address_book` WHERE (`name` = 'John') OR (`name` LIKE '%Joh%' AND `age` = '27')';
</pre>
<p>正規表現と記法が異なるのが、個人的にはシックリこない。</p>
<div class="kakomi">
<h4>インデックス</h4>
<p>日本語に直訳すると「索引」。リソース内の特定の項目を検索するためのメカニズム。一般的にはアプリケーションがWHERE節などで検索に使用するカラムに対して指定される。</p>
<ul>
<li>「インデックス」はデータベースサーバがテーブルの行を特定するために使われる</li>
<li>「インデックス」は特殊なテーブルである</li>
<li>「インデックス」は行を特定するために使用される列と、行が物理的に配置されている場所を示す情報のみを含んでいる</li>
</ul>
<h4>主キー（primary key）</h4>
<p>一組のデータレコードを一意に識別するための特殊なインデックス</p>
<h4>テーブルの関係性</h4>
<p>テーブルの関係性として「1:1」と「1:複数」の場合は簡単に処理できるが、「複数:複数」の場合はintermediate tableなどを使用しなくてはならない。</p>
<dl>
<dt>1:1</dt>
<dd>子テーブルの1レコードが、親テーブルの1レコードと関連する</dd>
<dt>1:複数</dt>
<dd>子テーブルの複数レコードが、親テーブルの1レコードと関連する</dd>
<dt>複数:複数</dt>
<dd>子テーブルの複数レコードが、親テーブルの複数レコードと関連する</dd>
</dl>
<h4>関係性を意識したテーブルの作成</h4>
<h5>1:1</h5>
<p>以下のように、primary keyを共通にしてみると良い。</p>
<pre class="brush: sql;">
CREATE TABLE `book` (
    `id` int(11) NOT NULL,
    `isbn` varchar(13) default NULL,
    `title` varchar(255) default NULL,
    `author` varchar(255) default NULL,
    `publisher` varchar(255) default NULL,
    PRIMARY KEY  (`id`),
    KEY `book_isbn` (`isbn`)
);
CREATE TABLE `book_author` (
    `id` int(11) NOT NULL PRIMARY KEY,
    `author_id` int(11) NOT NULL
);
</pre>
<h5>1:多</h5>
<p>以下のように、REFERENCESを使用してbookテーブルを参照するようにする。</p>
<pre class="brush: sql;">
CREATE TABLE `book` (
    `id` int(11) NOT NULL auto_increment,
    `isbn` varchar(13) default NULL,
    `title` varchar(255) default NULL,
    `author` varchar(255) default NULL,
    `publisher` varchar(255) default NULL,
    PRIMARY KEY  (`id`),
    KEY `book_isbn` (`isbn`)
);
CREATE TABLE `book_chapter` (
    `id` int(11) NOT NULL PRIMARY KEY auto_increment,
    `isbn` varchar(13) REFERENCES `book`(`isbn`),
    `chapter_number` INT NOT NULL,
    `chapter_title` varchar(255)
);
</pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2009/05/10/relational-database-and-sql%ef%bc%88rdb%e3%81%a8sql%ef%bc%89/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mysqlのバックアップ</title>
		<link>http://blog.justoneplanet.info/2009/04/16/mysql%e3%81%ae%e3%83%90%e3%83%83%e3%82%af%e3%82%a2%e3%83%83%e3%83%97/</link>
		<comments>http://blog.justoneplanet.info/2009/04/16/mysql%e3%81%ae%e3%83%90%e3%83%83%e3%82%af%e3%82%a2%e3%83%83%e3%83%97/#comments</comments>
		<pubDate>Thu, 16 Apr 2009 08:28:30 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://blog.justoneplanet.info/?p=719</guid>
		<description><![CDATA[※データベースは数秒止まるけどがまん。動かしながらはチョット大変なので。。。

$ /etc/init.d/mysqld stop
$ cp -r /var/lib/mysql /tmp/mysql.bk2009xxxx [...]]]></description>
			<content:encoded><![CDATA[<p>※データベースは数秒止まるけどがまん。動かしながらはチョット大変なので。。。</p>
<pre class="brush: bash;">
$ /etc/init.d/mysqld stop
$ cp -r /var/lib/mysql /tmp/mysql.bk2009xxxx
$ /etc/init.d/mysqld start
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.justoneplanet.info/2009/04/16/mysql%e3%81%ae%e3%83%90%e3%83%83%e3%82%af%e3%82%a2%e3%83%83%e3%83%97/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
