2012-04-13 71 views
2

我讀過類似的問題,但沒有關於使用ON DELETE和ON UPDATE的非常詳細的解釋,所以我很難理解這個問題,以及當您想要刪除或更新使用FK約束進行記錄,但在引用時不會刪除其他表中的記錄,而是將這些引用設置爲null或0或其他表中的某些內容。PHP,PDO,MySQL和InnoDB,如何使用FK更新/刪除記錄?

背景

我試圖創造的功能,這個數據庫(電子購物車系統),一庫,數據庫可以通過管理員(如CMS)來管理。

我選擇了InnoDB引擎來利用外鍵和事務。

我也使用PHP PDO對象而不是標準mysql_-函數來使用參數化查詢。

這是這些表的SQL創建代碼:

# TBL_MENU_CATEGORY 

DROP TABLE IF EXISTS tbl_menu_category; 
CREATE TABLE tbl_menu_category(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    name VARCHAR(50) 
) ENGINE = InnoDB; 

# TBL_PRODUCT_CATEGORY 

DROP TABLE IF EXISTS tbl_product_category; 
CREATE TABLE tbl_product_category(
    id INT NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY(id), 
    name VARCHAR(50) 
) ENGINE = InnoDB; 


# TBL_MENU_CAT_BASKET 

DROP TABLE IF EXISTS tbl_menu_cat_basket; 
CREATE TABLE tbl_menu_cat_basket(
    menu_id INT, 
    FOREIGN KEY(menu_id) REFERENCES tbl_menu_category(id), 
    cat_id INT, 
    FOREIGN KEY(cat_id) REFERENCES tbl_product_category(id) 
) ENGINE = InnoDB; 


# TBL_PRODUCT_CAT_BASKET 

DROP TABLE IF EXISTS tbl_product_cat_basket; 
CREATE TABLE tbl_product_cat_basket(
    cat_id INT, 
    FOREIGN KEY(cat_id) REFERENCES tbl_product_category(id), 
    product_id INT, 
    FOREIGN KEY(product_id) REFERENCES tbl_product(id) 
) ENGINE = InnoDB; 

這是在庫中的函數將子菜單添加到菜單(菜單>子菜單>產品)。

function addSubmenu($menu_id, $sub_name) { 
    $success = false; 
    if (dbTransaction()) { 
     $sql = "INSERT INTO tbl_product_cat(name) VALUES ('?');"; 
     dbQuery($sql, array($sub_name)); 
     $rows = dbRowsAffected(); 
     if ($rows == 1) { 
      $cat_id = dbLastInsertId(); 
      $sql = "INSERT INTO tbl_menu_cat_basket(menu_id, cat_id) VALUES ('?','?');"; 
      dbQuery($sql, array((int)$menu_id, (int)$cat_id)); 
      $rows = dbRowsAffected(); 
      if ($rows == 1) { 
       $success = true; 
      } 
     } 
     if ($success) 
      dbCommit(); 
      return "Add submenu successful."; 
     else 
      dbRollback(); 
      return "Add submenu failed."; 
    } 
} 

查詢是這樣執行的:

require_once "pdo.php"; # Creates PDO object '$db' 
$query; 

function dbQuery($sql, $data) { 
    global $db, $query; 
    $query = $db->prepare($sql); 
    $query->execute($data); 
} 

# other PDO & PDOStatement methods like this 
# (rowCount, lastInsertId, fetchAll, transaction-stuff). 

問題

我甚至不知道這是正確的。我遵循正確的道路還是錯誤地做事?

現在我被困在創建類似的功能來更新也有外鍵的記錄。我知道InnoDB會拋出一個錯誤,即記錄無法更新,因爲它有引用(我認爲?)。

我需要知道正確的程序更新記錄和我這樣做可用的功能。

我想知道ON DELETE和ON UPDATE約束,但我似乎無法找到任何好的新手友好的教程(MySQL文檔非常不友好,甚至不突出語法)。

我想做

當更新我想級聯更新,以便所有引用更新的記錄什麼。

當刪除記錄時,我只想刪除已刪除的記錄,但是可以重置對它的任何引用(如果刪除了某個產品類別,則不應該刪除該產品;​​如果刪除了該產品的所有訂單不應刪除,但產品價值設置爲0或空)

我怎麼能做到ON DELETE和ON UPDATE - 或者 - 我應該採取什麼程序來實現我想在這裏做的事情?

謝謝您的閱讀。

回答

1

在你的外鍵規範中指定ON UPDATE CASCADE ON DELETE SET NULL應該有訣竅。例如FOREIGN KEY(product_id) REFERENCES tbl_product(id) ON UPDATE CASCADE ON DELETE SET NULL。儘管我不得不想知道在哪裏可以預見改變主鍵值的情況。

您可能會感興趣的MySQL Workbench - 它可以幫助你直觀地設計架構和顯示相應的DDL語句。

+0

謝謝您的回答......所以,這一切就是它,然後?順便說一句,你的意思是隻要我不更改主鍵ID值,我可以更新其他領域沒有任何問題? – Ozzy 2012-04-13 16:31:46

+1

是的,外鍵機制只涉及外鍵規範中提到的字段。其他領域可以隨意修改。 – DCoder 2012-04-13 16:35:11

+0

感謝您的幫助:)。我現在明白了。當他向我們展示如何刪除記錄時,我對本教程http://www.phpwebcommerce.com/感到困惑。 – Ozzy 2012-04-13 16:36:30