MySql必知必会实战练习(四)主键、外键、sql约束、联结表

  本博将对主键、外键、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进行了输出

posted @ 2018-11-27 10:30  Fate0729  阅读(1257)  评论(0编辑  收藏  举报