約束條件 ,表與表之間的關系 和多表聯合查詢***


一.約束條件
    為了確保數據的完整性 可以給列加上約束條件
    完整性的分類:
        1.實體完整性
        2.域完整性
        3.引用完整性
    1.實體完整性
        實體:即表中的一行(一條)記錄 代表一個實體 entity
        實體完整性的作用:標識每一行數據不重復
        約束類型:
            1.1 主鍵約束(primary key)
            1.2 唯一約束(unique)
            1.3 自動增長列(auto_increment)
        1.1 主鍵約束
            每一個表中要有一個主鍵(可以是一列 也可以是多列組成)
            特點: 數據唯一 且不能為null

            第一種添加方式 在創建表的同時 直接添加主鍵約束
            create table 表名(
                列名1 列值1 primary key,
                列名2 列值2,
                ....
                列名n 列值n
            )
            第二種添加方式 后期補充主鍵約束
            create table 表名(
                列名1 列值1,
                列名2 列值2,
                ....
                列名n 列值n
            )
            alter table 表名 add primary key(列名1);

            聯合主鍵 (由多個列組成的主鍵)
            create table 表名(
                列名1 列值1,
                列名2 列值2,
                ....
                列名n 列值n,
                primary key(列名1,列名2);
            )
            刪除主鍵約束
            alter table 表名 drop primary key;
        1.2 唯一約束
            特點:數據不能重復 值可以為null
            第一種添加方式 在建表的時候添加
            create table 表名(
                列名1 列值1 約束條件,
                列名2 列值2 unique,
                ....
            )
            第二種創建方式 后期追加
            alter table 表名 add unique(列名);
        1.3 自動增長列
            mysql --> auto_increment
            sqlserver --> idenitiy
            oracle --> sequence
            特點:
                1.設置自動增長的時候 列只能是整型
                2.當有行被刪除 自增會繼續自增 在刪除行的基礎上+1
    2.域完整性
        域完整性的作用:限制此單元格的數據正確 不對照此列的其他單元格
        域代表當前單元格
        域完整性約束:
            數據類型 非空約束(not null) 默認值約束(default)
            2.1 數據類型約束
            2.2 非空約束
                not null
                alter table 表名 modify 字段名 字段類型 not null;
            2.3 默認值約束
                default
                第一種添加方式 創建表時添加
                create table 表名(
                    列名1 列值1 約束,
                    列名2 列值2 約束 default 默認值,
                    ....
                    列名n 列值n
                )
                第二種添加方式 后期追加
                alter table 表名 alter 列名 set default 默認值;
    3.引用完整性
        外鍵約束 foreign key
        用來約束 表與表之間的關系
            建立外鍵關系 首先 明確 主從關系
            外鍵一定是在從表中創建 從而找到與主表之間的關系
例:
            主表 : 部門表 學生表
            從表 : 員工表 分數表
        外鍵必須要滿足的條件:
            1.至少涉及到兩張表
            2.建立外鍵關系 對應列具有相似的數據類型
            3.必須建立索引 主鍵 和 外鍵
        注意:外鍵是可以有重復的 也可以有空值
        創建外鍵的兩種方式
            第一種 在創建表的時候 添加外鍵
            constraint 外鍵關系名 foreign key(從表的字段) references 主表名(主表的字段)

            constraint 外鍵關系名 可以不寫 就是一個外鍵約束的名字 如果不寫 系統會自動給
            foreign key(從表的字段) 將 從表中的字段作為外鍵
            references 主表名(主表的字段) 映射到主表的字段

            CREATE TABLE student(
                sid INT PRIMARY KEY AUTO_INCREMENT,//默認自動增加
                sname VARCHAR(10) NOT NULL,//值不能為空
                gender VARCHAR(10) DEFAULT "男"
            )
            CREATE TABLE score(
                id INT PRIMARY KEY,
                score INT,
                fsid INT,
                CONSTRAINT fk_student_score FOREIGN KEY(fsid) REFERENCES student(sid)//這里不加分號也不加逗號
            )
            第二種 表已經創建 后期追加
            alter table 主表 add primary key(主表列名)
            alter table 從表 add foreign key(從表列名) references 主表(主表列名)
            注意:
                1.在從表中添加數據時 外鍵關聯列中存儲的數據 必須是主表中存在的數據
                2.想要刪除主表中 正在被從表使用的行 必須先刪除從表 再刪除主表
            刪除外鍵關聯:
                alter table 表名 drop foreign key 外鍵關系名//就是你起得名字fk_student_score
二.表與表之間的關系
    三種關系
     1.一對一 1 vs 1
        person 表 card 表 人表 和 身份證表
        人是主表 身份證表是從表

     2.一對多 1 vs N
     3.多對多 N vs N
三.多表聯合查詢***
    在關系型數據庫中 一個查詢往往會涉及到多張表 多張表如何進行聯合查詢 就成為了學習sql查詢的關鍵
    如果單純的只將數據放在一張表中 那么這個表存在大量的數據冗余 這種數據庫的設計是不合理的(一般不用)
    1.合並結果集
        union
        union all
        作用 合並結果集 把兩個select語句的查詢結果合並到一起

        CREATE TABLE g(
            gname VARCHAR(10),
            gage INT
        )
        CREATE TABLE h(
            hname VARCHAR(10),
            hage INT
        )
        INSERT INTO g VALUES("a",1),("b",2),("c",3);
        INSERT INTO h VALUES("d",1),("e",2),("c",3);
        /*union 去除重復數據 合並*/
        SELECT * FROM g UNION SELECT * FROM h;
        /*union all 不去除重復數據 合並*/
        SELECT * FROM g UNION ALL SELECT * FROM h;

        要求:被合並的兩個結果集 列數/列類型 必須相同


    2.連接查詢
        連接查詢 就是求多個表的乘積
        例如 a表 連接 b表 那么查詢結果就是 a表*b表
        連接查詢 產生 笛卡爾積(在sql中 實現方式 交叉連接 cross join)
        所有的連接方式 都會先產生笛卡爾積 然后 加上限制條件 才會有實際查詢意義
        select * from emp,dept;
        join 就是把多個表連接成一個表的手段
        多表查詢 分為 內/外連接

        SELECT emp.ename,dept.dname,emp.job FROM emp,dept WHERE emp.deptno = dept.deptno;
        SELECT e.ename,d.dname,e.job FROM emp AS e,dept AS d WHERE e.deptno = d.deptno;
        
        AS關鍵字 可以給表 起別名 as可省略

        內連接 [INNER]join...on INNER可省略
        [隱式]
        SELECT e.ename,d.dname,e.job FROM emp AS e,dept AS d WHERE e.deptno = d.deptno;
        [顯示]
        SELECT e.ename,d.dname,e.job FROM emp e INNER join dept d ON e.deptno = d.deptno;
        特點: 查詢結果必須是滿足條件的

        外連接 [OUTER]join...on OUTER可省略
            左外連接 Left [OUTER]join
            右外連接 right [OUTER]join
            全外連接 full join (Mysql不支持)

            左外連接
                以左表為主
                SELECT * FROM emp e LEFT OUTER JOIN dept d ON e.deptno = d.deptno;
                左連接 是先查詢出左表(以左表為主)
                然后查詢右表 右表中滿足條件的顯示 不滿足條件的顯示為null
            右外連接
                以右表為主
                SELECT * FROM emp e RIGHT OUTER JOIN dept d ON e.deptno = d.deptno;
                右連接 是先查詢出右表(以右表為主)
                然后查詢左表 做表中滿足條件的顯示 不滿足條件的顯示為null
            /*練習 查詢出 員工姓名 工作 部門 部門所在地 當部門為 RESEARCH 的 不顯示 */
            SELECT * FROM emp LEFT JOIN dept ON emp.deptno = dept.deptno WHERE dept.dname!="RESEARCH";
            SELECT * FROM emp LEFT JOIN dept ON emp.deptno = dept.deptno AND dept.dname!="RESEARCH" WHERE emp.ename !="SMITH";

            /* 步驟
                1.生成笛卡爾積 select * from emp cross join dept
                2.應用 on 篩選器 emp.deptno = dept.deptno
                3.看外連接 是 Left join 還是 right join
                    如果是 left join 會以左表為主 作為保留表
                4.where過濾器 過濾的是 left join 之后的數據
            */
            總結:
                1.如果sql 用的是Left join
                    on 后面條件 對left表沒作用 只是對right表起過濾作用
                    where語句可以對生成臨時表后起到過濾 相當於過濾了 left表
                2.如果sql 用的是right join
                    on 后面條件 對right表沒作用 只是對left表起過濾作用
                    where語句可以對生成臨時表后起到過濾 相當於過濾了 right表
            on 和 where 的區別:
                在使用left join時 on 和 where 區別如下:
                    1.on條件是在 生成臨時表 時 使用的條件
                        不管on的條件是否為真 都會返回左邊表的數據
                    2.where條件在 生成臨時表 后 再對臨時表進行過濾
                        如果條件不為真 就會全部過濾
        自然連接 Natural join
            自然連接 無需你去給出外鍵關聯等式 它會自動找到這一等式
            兩張連接表中 名稱 和 類型 完全一致的列 作為條件

            /*自然連接*/
            SELECT * FROM emp NATURAL JOIN dept;
            SELECT * FROM emp NATURAL LEFT JOIN dept;
            SELECT * FROM emp NATURAL RIGHT JOIN dept;
    總結:
        連接查詢時 sql查詢的核心 按照實際需求來選擇對應的類型
        如果選擇不當 非但不能提高效率 反而會帶來一系列的邏輯錯誤 或者性能下降
        選擇依據:
            1.查兩張表關聯列相等的數據 用內連接
            2.right表是left表的子集 用左外連接
            3.left表是right表的子集 用右外連接
            4.right 和 left 彼此之間有交集 但是互不為子集 使用全外連接
    3.子查詢
        一個select語句中 包含另一個完整的select語句
        子查詢 就是 嵌套查詢
        子查詢出現的位置:
            where 后: 作為查詢條件的一部分
            from 后:作為表出現
        當子查詢出現在where后 作為條件時 還可以使用如下關鍵字
            any 任意一個 ---> min
            all 所有 ---> max
        子查詢結果集的形式:
            1.單行單列 (用於條件)
            2.單行多列 (用於條件)
            3.多行單列 (用於條件)
            4.多行多列 (表)
        1.單行單列 (用於條件)
            例如 :員工表中 工資高於CLARK的員工都有誰
            分析 :
                1.查詢CLARK的工資
                    select sal from emp where ename="CLARK"
                2.查詢高於CLARK的員工
                    select * from emp where sal > 第一步的結果
                3.結論
                    select * from emp where sal > (select sal from emp where ename="CLARK")

        2.單行多列 (用於條件)
            例如 :查詢員工表中 工作 和 工資 與 MARTIN完全相同的員工信息
            分析 :
                1.查詢MARTIN的工作和工資
                    select job,sal from emp where ename="MARTIN";
                2.查詢與MARTIN工作和工資相同的人
                    select * from emp where (job,sal) in 第一步的結果
                3.結論
                    select * from emp where (job,sal) in (select job,sal from emp where ename="MARTIN")
        3.多行單列 (用於條件)
            多行子查詢 返回多行數據
            在where 使用多行子查詢時 要用 all any in

            例如 :查找工資高於30號部門所有人的 員工
            分析 :
                1.查找30號部門所有人的工資
                    select sal from emp where deptno=30;
                2.查找高於30號部門所有人工資的員工信息
                    select * from emp where sal > all 第一步的結果
                3.結論
                    SELECT * FROM emp WHERE sal > ALL (SELECT sal FROM emp WHERE deptno=30);

                    SELECT * FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno=30);

                /*練習 部門編號為20的員工工資 並且 大於部門編號為30的所有人工資的 員工列表*/
                SELECT * FROM emp WHERE deptno=20 AND sal> ALL(SELECT sal FROM emp WHERE deptno=30)
        4.多行多列 (表)
            例如 :查詢員工編號為7788的員工 姓名 工資 部門名稱 部門地址
            分析 :涉及到 emp dept兩張表
                1.查詢 姓名 和 工資
                    select ename,sal from emp where empno=7788
                2.查詢 部門名稱 和 部門地址
                    select e.ename,e.sal,d.dname,d.loc
                    from emp e,dept d
                    where e.deptno = d.deptno and e.empno=7788
                改版:
                    select e.ename,e.sal,d.dname,d.loc
                    from emp e,(select dname,loc,deptno from dept) d
                    where e.deptno = d.deptno and e.empno=7788

                /*練習 求7369員工 姓名 經理姓名 經理編號 自己連接自己*/
                    SELECT e1.ename,e2.ename,e2.empno
                    FROM emp e1,(SELECT empno,ename FROM emp) e2
                    WHERE e1.mgr = e2.empno AND e1.empno = 7369


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM