1. 程式人生 > >MySql必知必會實戰練習(四)主鍵、外來鍵、sql約束、聯結表 MySql資料庫約束

MySql必知必會實戰練習(四)主鍵、外來鍵、sql約束、聯結表 MySql資料庫約束

  本博將對主鍵、外來鍵、MySql資料庫約束和聯結表的相關特性進行總結和實戰

1. 主鍵

  表中的每一行都應該具有可以唯一標識自己的一列(或一組列),而這個承擔標識作用的列稱為主鍵

  如果沒有主鍵,資料的管理會十分混亂。比如會存在多條一模一樣的記錄,刪除和修改特定行十分困難

(1)哪些列可以作為主鍵?

  任何列都可以作為主鍵,只要它滿足以下條件:

  a. 任何兩行都不具有相同的主鍵值,就是說這列的值都互不相同

  b. 每個行都必須具有一個主鍵值,主鍵列不允許設定為NULL

  c. 主鍵列的值不建議進行修改和更新

(2)主鍵的建立

  最簡單的表:

CREATE TABLE t1(
   id int not null,
   name char(20)
);

  帶主鍵的表的建立:

CREATE TABLE t1(
   id int not null primary key,
   name char(20)
);

  帶複合主鍵的建立:

CREATE TABLE t1(
   id int not null,
   name char(20),
   primary key (id,name) 
);

  主鍵自增:

CREATE TABLE t1(
   id int primary key not null auto_increment,
   name char(20)
);

  建立後再決定主鍵:

CREATE TABLE t1(
   id int not null,
   name char(20)
);

alter table t1 add primary key (id);

2. 外來鍵

  外來鍵用來保證參照完整性,MySQL資料庫的MyIsAM儲存引擎本身並不支援外來鍵,對於外來鍵的定義只是起到一個註釋的作用,而InonoDB儲存引擎則完整支援外來鍵約束。

  設定外來鍵約束的兩個表之間會具有父子關係,一般來說,稱被引用的表為父表,引用的表稱為子表,字表中外來鍵的欄位的取值範圍由父表決定,並且資料型別必須和父表中一致。

  設定外來鍵在一定程度上會降低資料庫的速度。

(1)外來鍵的新增

ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_orders FOREIGN KEY (order_num) REFERENCES orders (order_num);
ALTER TABLE orderitems ADD CONSTRAINT fk_orderitems_products FOREIGN KEY (prod_id) REFERENCES products (prod_id);
ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_id) REFERENCES customers (cust_id);
ALTER TABLE products ADD CONSTRAINT fk_products_vendors FOREIGN KEY (vend_id) REFERENCES vendors (vend_id);

(2)外來鍵刪除

alter table products drop foreign key  fk_products_verdors;

3. MySql資料庫完整性約束

  參考之前的部落格:MySql資料庫約束

4. 聯結表

(1)等值聯結

   說的直白點就是根據select語句將多個表聯結在一起,但有一點需要注意的是聯結不是物理試題,它在實際的資料庫表中不存在,只存在於查詢的執行當中。

  首先看下建立聯結的例子:

  例1:select * from orders,orderitems where
     orders.order_num = orderitems.order_num;

  

  例2:select * from orders,orderitems;

  

  從上面兩個例子能明顯的看到使用where和不使用where的區別,在聯結兩個表時,你實際上做的是將第一個表中的每一行與第二個表中的每一行進行匹配,where語句作為過濾條件,它只包含那些匹配給定條件的行,沒有where語句,第一個表中的每行將與第二個表中的每行進行配對,而不管他們的邏輯上否可以在一起,沒有聯結條件的表關係返回的結果為笛卡兒積,檢索出的行的數目將是第一個表中的行數乘以第二個表中的行數。

  下面將用虛擬碼對兩個示例進行區分:

  示例1:

for row1 in table1:
    for row2 in table 2:
         if row1.condition == row2.condition:
                print(row1+row2)

  示例2:

for row1 in table1:
    for row2 in table2:
        print(row1+row2)

(2)內部聯結

  上面展示的等值聯結,其實也稱為內部聯結,對於這種聯結可以使用稍微不同的語法來明確指明聯結的型別,INNER JOIN .... ON

select * from 
    orders INNER JOIN orderitems 
    ON orders.order_num = orderitems.order_num;

  ANSI SQL規範首選INNER JOIN ... ON語法,使用明確的聯結語法確保不會忘記聯結條件,有時候這樣做也能影響效能。

(3)如果只想輸出指定聯結表的某列可以使用下列方法

select orders.*,orderitems.proc_id from 
    orders INNER JOIN orderitems 
    ON orders.order_num = orderitems.order_num;

  

  這樣可以指定列輸出

 (4)外部連結

  許多聯結將一個表中的行與另一個表中的行相關聯。但是有時候需要包含沒有關聯的那些行,這個時候就可以使用外部連結,外部聯結方式有右連結RIGHT OUTERJOIN ... ON和左聯結LEFT OUTER JOIN...ON

  看下面的三個示例進行比較就一目瞭然了

  例1:內聯結

SELECT customers.cust_id,orders.cust_id,orders.order_num
    from customers INNER JOIN orders
    ON customers.cust_id = orders.cust_id;

  例2:左外部連結

SELECT customers.cust_id,orders.cust_id,orders.order_num
    from customers LEFT OUTER JOIN orders
    ON customers.cust_id = orders.cust_id;

  輸出了10002行,相當於前面虛擬碼中customers表為外迴圈,只是將custonmers中沒匹配上的10002也輸出了

  例3:右外部連結

SELECT customers.cust_id,orders.cust_id,orders.order_num
    from customers RIGHT OUTER JOIN orders
    ON customers.cust_id = orders.cust_id;

  輸出了10005行,相當於前面虛擬碼中orders作為外迴圈,將orders中沒匹配上的10005進行了輸出