在本文中,我們將學習如何通過PHP 5的一個基本抽象類別使用外鍵約束來更新兩個InnoDB表的資料。 我們將通過具體樣本來說明如何通過伺服器端指令碼語言來使用外鍵約束。
一、利用外鍵約束更新MySQL中的資料
現在,最流行的開源關係型資料庫管理系統非MySQL莫屬,而MySQL又支援多個儲存引擎,其中預設的也是速度較快的儲存引擎為MyISAM,對許多讀者來說,在開發自己資料庫驅動的web應用程式之前,可能已經使用了它很長一段時間了。
然而,有時候我們的項目可能需要額外的特性,例如需要處理外鍵約束,這時我們就需要用到其它類型的MySQL儲存引擎。在這種情況下,InnoDB表將非常適合我們的要求,儘管在效能方面可能比MyISAM表要稍遜一籌。大家知道,使用InnoDB表外鍵約束主要優點之一就是,它使我們可以在資料庫層級處理和維護多個表之間的關係,而無需將此任務推給與這些表打交道的應用程式的某些模組或者程式庫。
當然,前面的幾篇文章中,我們已經就IndoDB表的外鍵約束做過相應介紹,但是那裡都是通過手工方式來操作外鍵約束的。在本文中,我們將說明如何在更新和刪除父表中的資料時,如何通過指令碼語言來觸發相應子表的串聯更新和刪除操作。
這裡,我們部落格應用程式的資料層由兩個表構成,在前面的樣本中,對這些表的操作,都是通過手工鍵入SQL命令完成的,現在,我們將介紹如何使用PHP程式設計語言來完成這些工作。之所以選擇PHP,是因為它目前MySQL最常見的搭配語言,下面我們以PHP 5為例來說明如何外鍵約束操作兩個InnoDB表。 通過閱讀本文,您將更加真切地體會到外鍵約束的特性。
現在,我們開始見證PHP 5和外鍵約束結合在一起所帶來的威力吧!
二、以級聯方式更新和刪除資料庫中的資料
古人云,溫故而知新,那麼先讓我們來回顧一下前面學過的內容吧。之前,我們介紹過如何運用外鍵約束串聯更新和刪除存放部落格文章評論的InnoDB表中的資料。如果您尚未閱讀前面的文章也不要緊,下面我們簡單回顧這些內容。
這裡是我們的樣本中用到的兩個表的定義,如下所示:
Code highlighting produced by Actipro CodeHighlighter (freeware)
DROP TABLE IF EXISTS `test`.`blogs`;
CREATE TABLE `test`.`blogs` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`title` TEXT,
`content` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `test`.`comments`;
CREATE TABLE `test`.`comments` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`blog_id` INT(10) UNSIGNED DEFAULT NULL,
`comment` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `blog_ind` (`blog_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
上面的代碼定義了兩個表,需要注意一下第二個,因為它為“blog_id”欄位規定了一個約束,所以當post表中的資料被更新和刪除時,將觸發相應的級聯操作。
為了幫您理解這一過程,我們可以在表中填上一些資料,這時可以通過SQL語句INSERT來完成,如下:
Code highlighting produced by Actipro CodeHighlighter (freeware)
INSERT INTO blogs (id, title, content, author) VALUES (NULL,'Title of the first blog entry', 'Content of the first blog entry', 'IAN')
INSERT INTO comments (id, blog_id, comment, author) VALUES (NULL, 1, 'Commenting first blog entry', 'Tom'), (NULL, 1, 'Commenting first blog entry', 'Rose')
現在,我們唯一的一條部落格資料已經有了兩條評論資料,如果由於任何原因需要更新部落格及其評論資料的話,可以通過下列命令完成:
Code highlighting produced by Actipro CodeHighlighter (freeware)
UPDATE blogs SET id = 2, title = 'Title of the first blog entry', content = 'Content of the first blog entry', author = 'John Doe' WHERE id = 1
這看起來非常簡單,但是,如果我說將部落格資料連同相應的評論資料一同刪除會更加簡單,您能會相信嗎?如果不信的話,請看下面的SQL語句:
Code highlighting produced by Actipro CodeHighlighter (freeware)
DELETE FROM blogs WHERE id = 2
如您所見,這就是刪除指定部落格及其評論所需的全部SQL代碼,這足以證明通過外鍵約束維護兩個InnoDB表的完整性到底有多麼的方便。
迄今為止,我們已經簡單回顧之前所學的內容,接下來,我們將繼續探索這些表的約束的各種優點。 就像本文開頭部分介紹的那樣,我們將開始講解如何通過PHP 5內建的MySQL抽象類別來產生對我們的樣本表的串聯更新。
wordend 相關閱讀:
玩轉MySQL中的外鍵約束
玩轉MySQL的外鍵約束之串聯刪除篇
MSSQL Server和MySQL區別
三、利用PHP 5以級聯方式更新資料庫
好了,現在開始詳細介紹如何使用流行的伺服器端指令碼語言PHP 5來以級聯方式更新我們的樣本表。為此,我們需要編寫允許我們訪問上面定義的InnoDB表的代碼,就本例而言,我們使用PHP 5的MySQL抽象類別來達此目的。下面給出具體的代碼:
Code highlighting produced by Actipro CodeHighlighter (freeware)
class MySQL
{
private $result = NULL;
private $link = NULL;
//串連到MySQL
public function __construct($host, $user, $password, $database)
{
if (FALSE === ($this->link = mysqli_connect($host, $user, $password, $database)))
{
throw new Exception('Error : ' . mysqli_connect_error());
}
}
//執行查詢
public function query($query)
{
if (is_string($query) AND empty($query) === FALSE)
{
if (FALSE === ($this->result = mysqli_query($this->link, $query)))
{
throw new Exception('Error performing query ' . $query . ' Error message :' .mysqli_error($this->link));
}
}
}
//從結果集返回資料
public function fetch()
{
if (FALSE === ($row = mysqli_fetch_object($this->result)))
{
mysqli_free_result($this->result);
return FALSE;
}
return $row;
}
//擷取插入ID
public function getInsertID()
{
return mysqli_insert_id($this->link);
}
//結果集中的行數
public function countRows()
{
if ($this->result !== NULL)
{
return mysqli_num_rows($this->result);
}
}
//關閉資料庫連接
function __destruct()
{
mysqli_close($this->link);
}
}
如上所示,上面定義的MySQL抽象類別十分簡單,它提供了許多常用的方法,用於執行查詢、統計結果集行數以及擷取插入ID。需要格外注意的是,這個類內部使用了PHP擴充mysqli來跟MySQL打交道,所以整體看來是很容易理解的。
好了,我們已經定義了一個可以用於跟MySQL資料庫相互動的PHP 5類,現在我們要做的就是利用它的API對前面定義的InnoDB表執行串聯更新。
wordend 相關閱讀:
玩轉MySQL中的外鍵約束
玩轉MySQL的外鍵約束之串聯刪除篇
MSSQL Server和MySQL區別
四、MySQL抽象類別
現在,為了示範如何使用上述的MySQL類串聯更新前文中的資料表,我們需要重新定義那兩個表,以便使其只能執行這些更新的操作。這裡是它們的定義,這兩個表將作為我們的樣本部落格應用程式的資料層:
Code highlighting produced by Actipro CodeHighlighter (freeware)
DROP TABLE IF EXISTS `test`.`blogs`;
CREATE TABLE `test`.`blogs` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`title` TEXT,
`content` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `test`.`comments`;
CREATE TABLE `test`.`comments` (
`id` INT(10) UNSIGNED AUTO_INCREMENT,
`blog_id` INT(10) UNSIGNED DEFAULT NULL,
`comment` TEXT,
`author` VARCHAR(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `blog_ind` (`blog_id`),
CONSTRAINT `comments_ibfk_1` FOREIGN KEY (`blog_id`) REFERENCES `blogs` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
如上所述,通過給最後一個表中的blog_id欄位規定外鍵約束,我們已經把兩個表聯絡在了一起,接下來讓我們使用前面定義的MySQL抽象類別給它們填入必要的資料。我們假設這個類被單獨放入一個名為mysqlclass.php檔案中,下面的指令碼將向blog表中插入單篇部落格文章,並向comments表中插入兩則評論:
Code highlighting produced by Actipro CodeHighlighter (freeware)
require_once 'mysqlclass.php';
$db = new MySQL('host', 'user', 'password', 'test');
//在blogs資料庫表中插入新資料
$db->query("INSERT INTO blogs (id, title, content, author) VALUES (NULL,'Title of the first blog entry', 'Content of the first blog entry', 'IAN')");
$insid = $db->getInsertID();
//在comments資料庫表中插入新評論
$db->query("INSERT INTO comments (id, blog_id, comment, author) VALUES (NULL, $insid, 'Commenting first blog entry', 'Tom'), (NULL, $insid, 'Commenting first blog entry', 'Rose')");
雖然我們的這個MySQL類能夠抽象地訪問資料庫,但是相應的SQL查詢還得手工編寫。同時,它正好可以使我們可以展示每當第一個表中的資料更新時,如何使用該類來更新與第一個資料表相關的評論。
執行該串聯更新操作的代碼片斷如下所示:
Code highlighting produced by Actipro CodeHighlighter (freeware)
//更新blogs表中的資料(comments表中的有關資料將自動更新)
$db->query("UPDATE blogs SET id = 2, title = 'Title of the first blog entry', content = 'Content of the first blog entry', author = 'John Doe' WHERE id = 1");
儘管另外添加了一個與上述InnoDB表打交道的抽象類別,但是觸發串聯更新所需的SQL代碼仍然保持高度簡潔。這說明,各表之間的關係的完整性仍然是在資料庫層級進行維護的,而不是由PHP 5應用程式所維護的。
五、小結
到目前為止,我們詳細講解了如何通過PHP 5內建的抽象類別使用外鍵約束來更新兩個InnoDB表中的資料。 我們希望本文能夠對您利用伺服器端指令碼使用外鍵約束時能夠有所啟發。在後面的文章中,我們將繼續探討外鍵約束有關的內容。