<?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>SpaLinux.com &#187; mysql foreign key</title>
	<atom:link href="http://spalinux.com/tag/mysql-foreign-key/feed" rel="self" type="application/rss+xml" />
	<link>http://spalinux.com</link>
	<description>Resources for Relaxing Linux System Administrators</description>
	<lastBuildDate>Sat, 21 Jan 2012 16:07:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>ทดสอบ FOREIGN KEY Constraints ใน MySQL</title>
		<link>http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints</link>
		<comments>http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints#comments</comments>
		<pubDate>Sat, 23 Jan 2010 10:13:04 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mysql constraints]]></category>
		<category><![CDATA[mysql foreign key]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1061</guid>
		<description><![CDATA[บทความนี้ต่อจาก การสร้าง FOREIGN KEY Constraints ใน MySQL เพื่อทดสอบการ เพิ่ม แก้ไข ลบ ข้อมูล โดยในเวลาเริ่มแต่ละหัวข้อจะใช้ข้อมูลนี้เป็นหลัก mysql&#62; SELECT * FROM groups; +----------+------------+ &#124; group_id &#124; group_name &#124; +----------+------------+ &#124;      101 &#124; Accounting &#124; &#124;      102 &#124; Engineer   &#124; &#124;      103 &#124; IT         &#124; &#124;      104 &#124; Manager    &#124; +----------+------------+ 4 rows in set (0.00 sec) mysql&#62; SELECT * FROM [...]]]></description>
			<content:encoded><![CDATA[<p>บทความนี้ต่อจาก <a href="http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints">การสร้าง FOREIGN KEY Constraints ใน MySQL</a> เพื่อทดสอบการ เพิ่ม แก้ไข ลบ ข้อมูล โดยในเวลาเริ่มแต่ละหัวข้อจะใช้ข้อมูลนี้เป็นหลัก</p>
<pre><span id="more-1061"></span>mysql&gt; <strong>SELECT * FROM groups;
</strong>+----------+------------+
| group_id | group_name |
+----------+------------+
|      101 | Accounting |
|      102 | Engineer   |
|      103 | IT         |
|      104 | Manager    |
+----------+------------+
4 rows in set (0.00 sec)</pre>
<pre>mysql&gt; <strong>SELECT * FROM users;
</strong>+---------+----------+-----------+
| user_id | group_id | user_name |
+---------+----------+-----------+
|     501 |      101 | Ms.A      |
|     502 |      102 | Ms.B      |
|     503 |      102 | Mr.C      |
|     504 |      103 | Mr.D      |
|     505 |      104 | Mr.E      |
+---------+----------+-----------+
5 rows in set (0.00 sec)</pre>
<h4>การ DELETE ข้อมูล</h4>
<p>หลังจากใส่ FOREIGN KEY ในตาราง users เรียบร้อยแล้ว ทดสอบการลบ DELETE กลุ่ม &#8216;IT&#8217; ออกจาก table &#8216;groups&#8217;</p>
<pre>mysql&gt; <strong>DELETE FROM groups WHERE group_id='103';
</strong><span style="color: #ff0000;">ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails
</span>(`test_db`.`users`, CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`))</pre>
<p>ข้อมูลกลุ่ม &#8216;IT&#8217; ยังอยู่ใน table &#8216;groups&#8217;</p>
<pre>mysql&gt; <strong>SELECT * FROM groups;
</strong>+----------+------------+
| group_id | group_name |
+----------+------------+
|      101 | Accounting |
|      102 | Engineer   |
|      103 | IT         |
|      104 | Manager    |
+----------+------------+
4 rows in set (0.00 sec)</pre>
<p>เราไม่สามารถลบ group &#8216;IT&#8217; ได้ เนื่องจากมีการอ้างอิงจาก table &#8216;users&#8217;</p>
<p>หากต้องการจะลบ ต้องแก้ไขข้อมูลที่มีการอ้างอิงมายัง group &#8216;IT&#8217; นี้ (group_id=103) เช่นในที่นี้ต้องเปลี่ยน group_id ของ &#8216;Mr.D&#8217; ไปเป็นกลุ่มอื่น เช่นเปลี่ยนเป็น กลุ่ม &#8216;Engineer&#8217;</p>
<p>ตรวจสอบว่าใครอยู่ group &#8216;IT&#8217; บ้าง</p>
<pre>mysql&gt; <strong>SELECT * FROM users WHERE group_id=103;
</strong>+---------+----------+-----------+
| user_id | group_id | user_name |
+---------+----------+-----------+
|     504 |      103 | Mr.D      |
+---------+----------+-----------+
1 row in set (0.00 sec)</pre>
<p>เปลี่ยนกลุ่มของ &#8216;MR.D&#8217; เป็น Engineer</p>
<pre>mysql&gt; <strong>UPDATE users SET group_id=102 WHERE user_id=504;
</strong>Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0</pre>
<p>ตรวจสอบว่าใครอยู่ group &#8216;IT&#8217; อีกครั้ง</p>
<pre>mysql&gt; <strong>SELECT * FROM users WHERE group_id=103;
</strong>Empty set (0.00 sec)</pre>
<p>ทดสอบการลบกลุ่ม IT</p>
<pre>mysql&gt; <strong>DELETE FROM groups WHERE group_id=103;
</strong>Query OK, 1 row affected (0.00 sec)</pre>
<p>ครั้งนี้จะสามารถลบได้แล้ว เพราะไม่มี user คนไหนอยู่ในกลุ่มนี้แล้ว</p>
<h4>การ INSERT, UPDATE ข้อมูล</h4>
<p>จะด้วยความผิดพลาดของโปรแกรมหรือตั้งใจ สมมติเราเพิ่ม users ใหม่ แล้วตั้ง group_id=109 ซึ่งไม่มีอยู่ใน table &#8216;groups&#8217;</p>
<pre>mysql&gt; <strong>INSERT INTO users (user_id, group_id, user_name) VALUES (506, <span style="color: #ff0000;">109</span>, 'Mr.X');
</strong><span style="color: #ff0000;">ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
</span>(`test_db`.`users`, CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`))</pre>
<p>เราจะไม่สามารถ INSERT ข้อมูลแบบนี้ได้ ต้องไปสร้าง group_id 109 ใน table &#8216;groups&#8217; ก่อน</p>
<p>เช่นเดียวกัน เราไม่สามารถ UPDATE ข้อมูลที่ไม่ถูกต้องได้</p>
<pre>mysql&gt; <strong>UPDATE users SET group_id=109 WHERE user_id=505;
</strong><span style="color: #ff0000;">ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails
</span>(`test_db`.`users`, CONSTRAINT `users_ibfk_1` FOREIGN KEY (`group_id`) REFERENCES `groups` (`group_id`))</pre>
<h4>การ DROP TABLE</h4>
<p>หากยังมีการอ้างอิงฟิลด์ข้อมูลอยู่ เราไม่สามารถ DROP TABLE ที่ยังมีข้อมูลอ้างอิงอยู่ได้ เช่นในที่นี้เราไม่สามารถ DROP TABLE groups ได้</p>
<pre>mysql&gt; <strong>DROP TABLE groups;
</strong><span style="color: #ff0000;">ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails</span></pre>
<p>ถึงแม้ไม่มีข้อมูล rows ใดเลยใน users ก็ไม่สามารถ DROP TABLE groups ได้</p>
<pre>mysql&gt; <strong>DELETE FROM users;
</strong>Query OK, 5 rows affected (0.00 sec)</pre>
<pre>mysql&gt; <strong>DROP TABLE groups;
</strong>ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails</pre>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints">การสร้าง FOREIGN KEY Constraints ใน MySQL</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>การสร้าง FOREIGN KEY Constraints ใน MySQL</title>
		<link>http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints</link>
		<comments>http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints#comments</comments>
		<pubDate>Sat, 23 Jan 2010 09:22:39 +0000</pubDate>
		<dc:creator>editor</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[mysql constraints]]></category>
		<category><![CDATA[mysql foreign key]]></category>

		<guid isPermaLink="false">http://spalinux.com/?p=1053</guid>
		<description><![CDATA[ส่วนใหญ่แล้วการออกแบบฐานข้อมูลจะมีการใช้บางฟิลด์ข้อมูล เพื่อเชื่อมโยงความสัมพันธ์ระหว่าง table ทำให้ต้องมีการคำนึงถึงเวลา เพิ่ม แก้ไข หรือ ลบฟิลด์ที่ใช้เชื่อมนั้น ไม่เช่นนั้นข้อมูลในฐานข้อมูลอาจมีปัญหาได้ MySQL สนับสนุนคุณสมบัติการใช้ FOREIGN KEY Constraints เพื่อแก้ไขปัญหานี้ได้ แต่ต้องใช้ table เป็นแบบ InnoDB ในบทความนี้ขออธิบายปัญหาที่เกิดขึ้น พร้อมยกตัวอย่างวิธีการใช้ FOREIGN KEY Constraints เพื่อป้องกันปัญหาได้ ตัวอย่างเช่น ต้องการสร้างฐานข้อมูลสำหรับเก็บชื่อ users และแต่ละคนเป็นสมาชิกได้ 1 กลุ่มจากตาราง groups เริ่มต้นออกแบบ table ง่ายๆ ได้ดังนี้ mysql&#62; CREATE TABLE groups (  group_id     INT UNSIGNED NOT NULL,  group_name   VARCHAR(255),  PRIMARY KEY    (group_id) ); mysql&#62; CREATE TABLE [...]]]></description>
			<content:encoded><![CDATA[<p>ส่วนใหญ่แล้วการออกแบบฐานข้อมูลจะมีการใช้บางฟิลด์ข้อมูล เพื่อเชื่อมโยงความสัมพันธ์ระหว่าง table ทำให้ต้องมีการคำนึงถึงเวลา เพิ่ม แก้ไข หรือ ลบฟิลด์ที่ใช้เชื่อมนั้น ไม่เช่นนั้นข้อมูลในฐานข้อมูลอาจมีปัญหาได้</p>
<p>MySQL สนับสนุนคุณสมบัติการใช้ FOREIGN KEY Constraints เพื่อแก้ไขปัญหานี้ได้ แต่ต้องใช้ table เป็นแบบ InnoDB ในบทความนี้ขออธิบายปัญหาที่เกิดขึ้น พร้อมยกตัวอย่างวิธีการใช้ FOREIGN KEY Constraints เพื่อป้องกันปัญหาได้</p>
<p><span id="more-1053"></span></p>
<p>ตัวอย่างเช่น ต้องการสร้างฐานข้อมูลสำหรับเก็บชื่อ users และแต่ละคนเป็นสมาชิกได้ 1 กลุ่มจากตาราง groups เริ่มต้นออกแบบ table ง่ายๆ ได้ดังนี้</p>
<pre>mysql&gt; <strong>CREATE TABLE groups (
 group_id     INT UNSIGNED NOT NULL,
 group_name   VARCHAR(255),
 PRIMARY KEY    (group_id)
);</strong></pre>
<pre>mysql&gt; <strong>CREATE TABLE users (
 user_id      INT UNSIGNED NOT NULL,
 group_id     INT UNSIGNED NOT NULL,
 user_name    VARCHAR(255),
 PRIMARY KEY    (user_id)
);</strong></pre>
<p>ใส่ข้อมูลทดสอบดังนี้</p>
<pre>mysql&gt; <strong>INSERT INTO groups (group_id, group_name) VALUES
 (101, 'Accounting'),
 (102, 'Engineer'),
 (103, 'IT'),
 (104, 'Manager');</strong></pre>
<pre>mysql&gt; <strong>INSERT INTO users (user_id, group_id, user_name) VALUES
 (501, 101, 'Ms.A'),
 (502, 102, 'Ms.B'),
 (503, 102, 'Mr.C'),
 (504, 103, 'Mr.D'),
 (505, 104, 'Mr.E');</strong></pre>
<p>จากฐานข้อมูลตัวอย่าง เราใช้ฟิลด์ group_id ในการเชื่อมโยงความสัมพันธ์ระหว่าง groups และ users เพื่อระบุว่า แต่ละ users อยู่ใน group ใด</p>
<p>หากมีการแก้ไขข้อมูล เช่นต้องการลบ (DELETE) ข้อมูล group ที่ชื่อ &#8216;IT&#8217; ออกจากฐานข้อมูล หากไม่มีวิธีการตรวจสอบ ไปลบแค่จากตาราง &#8216;groups&#8217; จะทำให้ ข้อมูลของ &#8216;Mr.D&#8217; ในตาราง &#8216;users&#8217; มีปัญหาทันที เพราะไม่สามารถอ้างอิงกลับมายังชื่อ group ได้</p>
<p>โดยดีฟอลต์ การสร้าง table ใน MySQL หากไม่มีการระบุชนิด ในคำสั่ง &#8216;CREATE TABLE&#8217; ตารางที่สร้างได้จะเป็นแบบ MyISAM ซึ่งไม่สามารถสร้าง FOREIGN KEY ได้</p>
<p>สามารถใช้คำสั่ง &#8216;SHOW ENGINES&#8217; ใน mysql เพื่อตรวจสอบชนิดของ table ที่สร้างได้</p>
<pre>mysql&gt; <strong>SHOW ENGINES;
</strong>+------------+---------+------------------------------------------------------------+--------------+------+------------+
| Engine     | Support | Comment                                                    | Transactions | XA   | Savepoints |
+------------+---------+------------------------------------------------------------+--------------+------+------------+
| ndbcluster | NO      | Clustered, fault-tolerant tables                           | NULL         | NULL | NULL       |
| MRG_MYISAM | YES     | Collection of identical MyISAM tables                      | NO           | NO   | NO         |
| CSV        | YES     | CSV storage engine                                         | NO           | NO   | NO         |
| <strong><span style="color: #0000ff;">MyISAM</span>     </strong>| <strong><span style="color: #0000ff;">DEFAULT</span> </strong>| Default engine as of MySQL 3.23 with great performance     | NO           | NO   | NO         |
| <strong><span style="color: #0000ff;">InnoDB</span></strong>     | <strong><span style="color: #0000ff;">YES</span></strong>     | Supports transactions, row-level locking, and <strong><span style="color: #0000ff;">foreign keys</span></strong> | YES          | YES  | YES        |
| MEMORY     | YES     | Hash based, stored in memory, useful for temporary tables  | NO           | NO   | NO         |
+------------+---------+------------------------------------------------------------+--------------+------+------------+</pre>
<p>ถ้าจะใช้ FOREIGN KEY ได้นั้น table ที่มีการอ้างอิงกันทั้งหมด ต้องเป็นชนิด InnoDB คือต้องระบุออปชั่น ENGINE=InnoDB เวลาสร้าง table</p>
<p>เมื่อสร้างเป็น InnoDB แล้ว ระบุฟิลด์ที่ต้องการตรวจสอบ constraints ใน table ที่ใช้อ้างอิงไปยัง table อื่น</p>
<p>เช่นในที่นี้เราต้องการให้ table &#8216;users&#8217; ใช้ฟิลด์ชื่อ group_id เพื่ออ้างอิงไปยัง table &#8216;groups&#8217; เราต้องระบุ FOREIGN KEY ใน table &#8216;users&#8217;</p>
<p>วิธีการระบุการอ้างอิง FOREIGN KEY ฟิลด์ &#8216;group_id&#8217; จาก table &#8216;groups&#8217;</p>
<pre><span style="color: #0000ff;"><strong>FOREIGN KEY (group_id) REFERENCES groups(group_id)</strong></span></pre>
<p>วิธีการเปลี่ยน table จาก MyISAM ให้เป็น InnoDB และเพิ่ม FOREIGN KEY ทำได้ 2 วิธี</p>
<p> 1. ใช้คำสั่ง &#8216;ALTER TABLE&#8217; เพื่อแก้ไข<br />
 2. ใช้คำสั่ง &#8216;DROP TABLE&#8217; ทิ้งไปแล้วสร้างใหม่ แต่ข้อมูลที่มีอยู่จะหายหมด</p>
<h4>ใช้คำสั่ง ALTER TABLE เพื่อเปลี่ยนชนิดเป็น InnoDB</h4>
<p>เราสามารถใช้คำสั่ง &#8216;ALTER TABLE&#8217; เพื่อเปลี่ยนชนิดของ table หรือแก้ไขฟิลด์ต่างๆ ได้</p>
<p>การใช้คำสั่ง ALTER TABLE เพื่อเปลี่ยนชนิด table เป็นแบบ InnoDB</p>
<pre>mysql&gt; <strong>ALTER TABLE groups ENGINE=InnoDB;
</strong>Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0</pre>
<pre>mysql&gt; <strong>ALTER TABLE users ENGINE=InnoDB;
</strong>Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0</pre>
<p>เพิ่ม FOREIGN KEY ใน table &#8216;users&#8217;</p>
<pre>mysql&gt; <strong>ALTER TABLE `users` ADD FOREIGN KEY (group_id) REFERENCES groups(group_id);
</strong>Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0</pre>
<p>หมายเหตุ ต้องดูผลลัพธ์การใช้คำสั่ง ALTER TABLE ด้วย ว่าการเปลี่ยนแปลง table สำเร็จหรือไม่</p>
<h4>ลบแล้วสร้าง TABLE ใหม่แบบ InnoDB และใช้ FOREIGN KEY</h4>
<p>ใช้คำสั่ง DROP TABLE เพื่อลบ table &#8216;users&#8217;</p>
<pre>mysql&gt; <strong>DROP TABLE users;
</strong>mysql&gt; <strong>DROP TABLE groups;</strong></pre>
<p>ใช้คำสั่ง CREATE TABLE เพื่อสร้าง table ใหม่ แล้ว ใส่ข้อมูลลงไปเหมือนเดิม</p>
<pre>mysql&gt; <strong>CREATE TABLE groups (
 group_id     INT UNSIGNED NOT NULL,
 group_name   VARCHAR(255),
 PRIMARY KEY    (group_id)
) <span style="color: #0000ff;">ENGINE=InnoDB</span>;</strong></pre>
<pre>mysql&gt; <strong>INSERT INTO groups (group_id, group_name) VALUES
 (101, 'Accounting'),
 (102, 'Engineer'),
 (103, 'IT'),
 (104, 'Manager');</strong></pre>
<pre>mysql&gt; <strong>CREATE TABLE users (
 user_id      INT UNSIGNED NOT NULL,
 group_id     INT UNSIGNED NOT NULL,
 user_name    VARCHAR(255),
 PRIMARY KEY    (user_id),
<span style="color: #0000ff;"> FOREIGN KEY (group_id) REFERENCES groups(group_id)
</span>) <span style="color: #0000ff;">ENGINE=InnoDB;</span></strong></pre>
<pre>mysql&gt; <strong>INSERT INTO users (user_id, group_id, user_name) VALUES
 (501, 101, 'Ms.A'),
 (502, 102, 'Ms.B'),
 (503, 102, 'Mr.C'),
 (504, 103, 'Mr.D'),
 (505, 104, 'Mr.E');</strong></pre>
<p>สังเกตสิ่งที่เพิ่มขึ้น</p>
<h4>ข้อมูลอ้างอิง</h4>
<ul>
<li><a href="http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html" target="_blank">MySQL 5.1 Reference Manual :: 13.6.4.4 FOREIGN KEY Constraints</a></li>
<li><a href="http://spalinux.com/2010/01/testing_mysql_foreign_key_constraints">ทดสอบ FOREIGN KEY Constraints ใน MySQL</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://spalinux.com/2010/01/creating_mysql_foreign_key_constraints/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

