MySQL快速入門(二)——Java進階學習第十六天

文檔版本 開發工具 測試平臺 工程名字 日期 作者 備註
V1.0 2016.05.10 lutianfei none

SQL多表操作

外鍵約束

  • 作用:保證數據的完整性。
  • 定義外鍵約束

    • 可以直接在create語句中定義外鍵
      • foreign key 當前表名 (字段名) references 目標表名 (目標表的主鍵)
  • 創建完語句後,可以直接使用修改語句定義

    • alter table 表名 add foreign key 當前表名 (字段名) references 目標表名 (目標表的主鍵);
  • 作用:保證數據的完整性。

  • 例子

    • alter table emp add foreign key emp(dno) references dept(did); //把dno作爲did的外鍵,且did必須是主鍵
  • 有一個部門的表,還有一個員工表,

    create database day16;
    use day16;
    create table dept(
        did int primary key auto_increment,
        dname varchar(30)
    );

    create table emp(
        eid int primary key auto_increment,
        ename varchar(20),
        salaly double,
        dno int
    );

    insert into dept values(null,'研發部');
    insert into dept values(null,'銷售部');
    insert into dept values(null,'人事部');
    insert into dept values(null,'扯淡部');
    insert into dept values(null,'牛寶寶部');

    insert into emp values(null,'班長',10000,1);
    insert into emp values(null,'美美',10000,2);
    insert into emp values(null,'小鳳',12000,3);
    insert into emp values(null,'如花',14000,2);
    insert into emp values(null,'芙蓉',11000,1);
    insert into emp values(null,'東東',800,null);
    insert into emp values(null,'波波',1000,null);

update emp set salaly=2500 where eid = 5;


數據庫的設計

  • 多表設計中三種實體關係


一對多表的設計

  • 一對多:在多方需要添加一個字段,並且和一方主鍵的類型必須是相同的。

    • 把該字段作爲外鍵指向一方的主鍵。
  • 建表原則(都是在多方表中維護):

    • 在多方表中添加一個字段,把該字段作爲外鍵,並且指向一方表中的主鍵。
    • 將關係的屬性及非多方的主標識加入到多方表
    • 多方表的外鍵是非多方實體的主標識
  • 畫圖舉例部門與員工的關係

多對多表的設計

  • 在生活中一個學生可以選擇多門課程,每一門課程也可以被多個學生所選擇。這些例子在數據庫設計中可以使用多對多來完成。

  • 建表原則:

    • 需要創建第三張表,該表中至少有兩個字段,作爲外鍵分別指向多對多雙方主鍵
    • 聯繫的屬性及兩個實體的主標識形成關係表。
    • 關係表的主鍵爲兩個實體主標識的組合
    • 拆開兩個一對多的關係,中間創建一箇中間表,至少有兩個字段。作爲外鍵指向兩個多對多關係表的主鍵


一對一表的設計(很少用)

  • 在生活中,1對1的應用比較少,因爲完全可以作爲一張表出現。但是有可能公司的業務原因,而需要設計1對1的表結構。例如:一個公司對應一個地址,一個地址也只能對應一個公司。
  • 建表原則:
    • 主鍵對應
      • 將兩個表的主鍵進行關聯
    • 唯一外鍵對應
      • 在任何一方加一個外鍵,但是需要設置成唯一(unique),指向另一方的主鍵

  • 簡單購物的網站表結構設計
    • 包含哪些實體? 用戶 訂單 商品 分類


多表查詢 —— 笛卡爾積

  • 笛卡爾積的概念:(瞭解)

  • 查詢的語法
    select * from 表A,表B; 返回的結果就是笛卡爾積。

  • 多表查詢時,如果不指定表之間的連接條件,則連接變成笛卡爾乘積操作,笛卡爾積的效果如本頁所示。

  • 進行笛卡爾積後,查詢結果中存在大量無意義的數據,示例中只有A表中的A_ID和B表中A_ID一致的行纔有意義,這樣我們通過加上WHERE過濾條件得到想要的數據。這種橫跨多表的查詢操作一般用連接完成。

  • 如果一張表的記錄爲m,另一張表的記錄是n,兩個表做交叉連接後,查詢結果的數量爲m*n條。


多表查詢—內鏈接
  • 兩個表之間是有聯繫的,通過一個外鍵關聯
  • 內連接分成兩種
    • 普通內連接
      • 前提條件:需要有外鍵的。
      • 提交關鍵字 inner join … on
      • select * from dept inner join emp on dept.did = emp.dno;
    • 隱式內連接(用的是最多的)
      • 可以不使用inner join … on關鍵字
      • select * from dept,emp where dept.did = emp.dno;


多表查詢—外鏈接
  • 左外鏈接(看左表,把左表所有的數據全部查詢出來)

    • 前提條件:需要有外鍵的。
    • 語法: 使用關鍵字 left [outer] join … on
      • select * from dept left outer join emp on dept.did = emp.dno;
  • 右外鏈接(看右表,把右表所有的數據全部查詢出來)

    • 前提條件:需要有外鍵的。
    • 語法: 使用關鍵字 right [outer] join … on
      • select * from dept right join emp on dept.did = emp.dno;
  • 外鏈接與內連接的關係


多表查詢—子查詢
  • 在sql語言中,select…from…語爲一個查詢塊,將一個查詢塊嵌套在另一個查詢塊中作爲條件稱爲嵌套查詢,也稱爲子查詢
  • 外層的查詢塊稱爲父查詢內層的查詢塊稱爲子查詢

  • 語法:select * from table where 條件 > (select * from table where 條件)

    • any 任意
    • all 全部
    • >any 大於結果的最小值
    • >all 大於結果的最大值


基礎練習

create table dept(
    did int primary key auto_increment,
    dname varchar(30)
);

create table emp(
    eid int primary key auto_increment,
    ename varchar(20),
    salaly double,
    dno int
);


//查看所有人所屬的部門名稱和員工名稱?
    //方法一:
    select dept.dname,emp.ename from dept,emp where dept.did = emp.dno;

    //方法二:
    select d.dname,e.ename from dept d,emp e where d.did = e.dno;


//統計每個部門的人數(按照部門名稱統計,分組group by  count)
    select d.dname,count(*) from dept d,emp e where d.did = e.dno group by d.dname;


//統計部門的平均工資(按部門名稱統計 ,分組group by  avg)
    select d.dname,avg(salaly) from dept d,emp e where d.did = e.dno group by d.dname;


//統計部門的平均工資大於公司平均工資的部門(子查詢)
    * 公司的平均工資
        select avg(salaly) from emp;
    * 部門的平均工資
        select d.dname,avg(e.salaly) as sa from dept d,emp e where d.did = e.dno group by d.dname having sa > (select avg(salaly) from emp);


應用練習

  • 表結構
DROP TABLE dept;
--部門表
CREATE TABLE dept(
    deptno int  PRIMARY KEY,
    dname VARCHAR(14) , --部門名稱
    loc VARCHAR(13)  ---部門地址
    ) ;

CREATE TABLE dept(
    deptno int  PRIMARY KEY,
    dname VARCHAR(14) , 
    loc VARCHAR(13) 
    ) ;


    INSERT INTO DEPT VALUES (10,'ACCOUNTING','NEW YORK');
    INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
    INSERT INTO DEPT VALUES (30,'SALES','CHICAGO');
    INSERT INTO DEPT VALUES (40,'OPERATIONS','BOSTON');



drop table emp;
--員工表
CREATE TABLE emp(
    empno int  PRIMARY KEY, --員工編號
    ename VARCHAR(10), ---員工姓名
    job VARCHAR(9), --員工工作
    mgr int, ----員工直屬領導編號
    hiredate DATE, ----入職時間
    sal double, ---工資
    comm double, --獎金
    deptno int  REFERENCES dept);  --關聯dept表



CREATE TABLE emp(
    empno int  PRIMARY KEY,
    ename VARCHAR(10),
    job VARCHAR(9),
    mgr int, 
    hiredate DATE, 
    sal double,
    comm double,
    deptno int ,
    foreign key emp(deptno) REFERENCES dept(deptno)
);  


INSERT INTO EMP VALUES(7369,'SMITH','CLERK',7902,"1980-12-17",800,NULL,20);
INSERT INTO EMP VALUES(7499,'ALLEN','SALESMAN',7698,'1981-02-20',1600,300,30);
INSERT INTO EMP VALUES(7521,'WARD','SALESMAN',7698,'1981-02-22',1250,500,30);
INSERT INTO EMP VALUES(7566,'JONES','MANAGER',7839,'1981-04-02',2975,NULL,20);
INSERT INTO EMP VALUES(7654,'MARTIN','SALESMAN',7698,'1981-09-28',1250,1400,30);
INSERT INTO EMP VALUES(7698,'BLAKE','MANAGER',7839,'1981-05-01',2850,NULL,30);
INSERT INTO EMP VALUES(7782,'CLARK','MANAGER',7839,'1981-06-09',2450,NULL,10);
INSERT INTO EMP VALUES(7788,'SCOTT','ANALYST',7566,'1987-07-03',3000,NULL,20);
INSERT INTO EMP VALUES(7839,'KING','PRESIDENT',NULL,'1981-11-17',5000,NULL,10);
INSERT INTO EMP VALUES(7844,'TURNER','SALESMAN',7698,'1981-09-08',1500,0,30);
INSERT INTO EMP VALUES(7876,'ADAMS','CLERK',7788,'1987-07-13',1100,NULL,20);
INSERT INTO EMP VALUES(7900,'JAMES','CLERK',7698,'1981-12-03',950,NULL,30);
INSERT INTO EMP VALUES(7902,'FORD','ANALYST',7566,'1981-12-03',3000,NULL,20);
INSERT INTO EMP VALUES(7934,'MILLER','CLERK',7782,'1981-01-23',1300,NULL,10);


CREATE TABLE salgrade( 
    grade int,--等級
    losal double, --最低工資
    hisal double ); --最高工次


CREATE TABLE salgrade( 
    grade int,
    losal double, 
    hisal double );
INSERT INTO SALGRADE VALUES (1,700,1200);
INSERT INTO SALGRADE VALUES (2,1201,1400);
INSERT INTO SALGRADE VALUES (3,1401,2000);
INSERT INTO SALGRADE VALUES (4,2001,3000);
INSERT INTO SALGRADE VALUES (5,3001,9999);
  • 1、返回擁有員工的部門名、部門號。

    • select d.deptno,d.dname from dept d,emp e where d.deptno = e.deptno group by d.deptno;
  • 2、工資水平多於smith的員工信息。

    • select * from emp e where e.sal > (select em.sal from emp em where em.ename = ‘smith’ );
  • 3、返回員工和所屬經理的姓名。

    • select e.ename,em.ename from emp e,emp em where e.mgr = em.empno and em.job = ‘MANAGER’;
  • 4、返回僱員的僱傭日期早於其經理僱傭日期的員工及其經理姓名。

    • select e.ename,em.ename from emp e,emp em where e.mgr = em.empno and em.job = ‘MANAGER’ and e.hiredate < em.hiredate;
  • 5、返回員工姓名及其所在的部門名稱。

    • select d.dname,e.ename from dept d,emp e where d.deptno = e.deptno;
  • 6、返回從事clerk工作的員工姓名和所在部門名稱。

    • select d.dname,e.ename,e.job from dept d,emp e where d.deptno = e.deptno and job = ‘clerk’;
  • 7、返回部門號及其本部門的最低工資。

    • select d.deptno,min(e.sal) from dept d,emp e where d.deptno = e.deptno group by d.deptno;
  • 8、返回銷售部(sales)所有員工的姓名。

    • select * from dept d,emp e where d.deptno = e.deptno and d.dname = ‘sales’;
  • 9、返回工資水平多於平均工資的員工。

    • select * from emp e where e.sal > (select avg(sal) from emp);
  • 10、返回與SCOTT從事相同工作的員工。

    • select * from emp e where e.job = (select job from emp em where em.ename = ‘SCOTT’);
  • 11、返回與30部門員工工資水平相同的員工姓名與工資。

    • select * from emp e where e.sal in (select e.sal from dept d,emp e where d.deptno = e.deptno and d.deptno = 30);
發佈了91 篇原創文章 · 獲贊 177 · 訪問量 43萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章