MySQL - 基本語法

1. MySQL 語法分類

1.sql92 (這個能夠淘汰)

2.sql99(學習這個)

3.區別 下面來個練習

1. sql92的
SELECT ename,dname  FROM ept AS e , dept AS d WHERE e.dept_id=d.id
其中","就是笛卡爾積在sql92中

2. sql99的 須要 一個關鍵字 "join"  來實現笛卡爾積  (內鏈接 的 等值鏈接)
SELECT
	e.ename,
	d.dname
FROM
	ept e
JOIN dept d ON e.dept_id = d.id

只是省略了 inner 這個關鍵字

SELECT
	e.ename,
	d.dname
FROM
	ept e
INNER JOIN dept d ON e.dept_id = d.id
複製代碼
  • 區別1 實現笛卡爾積的方式不一樣 一個是 ", 和 where條件" 一個是 "join 和 on 條件"

2. MySQL 查詢語句執行循序

3. Join 表的鏈接

1. 內鏈接(jion/inner jion)

  • 等值鏈接(鏈接條件是 a.filed=b.filed)前端

    1. 需求 : 根據員工表的部門名稱id查詢出部門表中部門名稱
    
    2.查詢出 員工表的員工名稱和部門id
    mysql> select ename,dept_id from ept;
    +-------+---------+
    | ename | dept_id |
    +-------+---------+
    | 小明  |       1 |
    | 小王  |       2 |
    | 小李  |       3 |
    | 小錢  |       2 |
    +-------+---------
    
    3. 查詢出了 部門表中部門名稱和部門id
    mysql> select id , dname from dept;
    +----+-------+
    | id | dname |
    +----+-------+
    |  1 | 運維  |
    |  2 | 開發  |
    |  3 | 產品  |
    |  4 | 前端  |
    +----+-------+
    
    4. 咱們能夠將兩個錶鏈接起來 而後 第一章標的dept_id=B表的id 就行了,這就是等值鏈接
    SELECT
    	e.ename,
    	d.dname
    FROM
    	ept e
    INNER JOIN dept d ON e.dept_id = d.id
    
    +-------+-------+
    | ename | dname |
    +-------+-------+
    | 小明  | 運維  |
    | 小王  | 開發  |
    | 小李  | 產品  |
    | 小錢  | 開發  |
    +-------+-------+
    複製代碼
  • 非等值鏈接 (鏈接條件不是等值)mysql

    SELECT
    	e.ename,e.salary,s.level
    FROM
    	ept e
    INNER JOIN
    	salary_level s
    ON
    	e.salary BETWEEN s.salary-449 AND s.salary
    複製代碼
  • 自鏈接(本身連本身) 把兩次查詢的結果當作單獨的表sql

    mysql> select ename,p_id from ept;
    +-------+------+
    | ename | p_id |
    +-------+------+
    | 小明  | NULL |
    | 小王  |    1 |
    | 小李  |    2 |
    | 小錢  |    1 |
    +-------+------+
    
    mysql> select id , ename from ept;
    +----+-------+
    | id | ename |
    +----+-------+
    |  1 | 小明  |
    |  2 | 小王  |
    |  3 | 小李  |
    |  4 | 小錢  |
    +----+-------+
    
    咱們能夠當作  第一個表爲 A表 ;第二個表爲B表;只要A表的 p_id 等於 B 表的 id  就能夠實現了
    
    
    SELECT
    	a.ename,
    	b.ename as leader_name
    FROM
    	ept a
    INNER JOIN ept b ON a.p_id = b.id
    
    +-------+-------------+
    | ename | leader_name |
    +-------+-------------+
    | 小王  | 小明        |
    | 小錢  | 小明        |
    | 小李  | 小王        |
    +-------+-------------+
    複製代碼

2. 外鏈接(left join / right outer join)

  • 什麼是外鏈接?shell

    ​ 咱們不難發現 咱們在等值鏈接中只會取到A和B表都符合條件的內容;這就是內鏈接數據庫

    有的時候咱們須要 咱們也要查詢出B表中應該有的數據可是沒匹配的數據api

    因此區分 內外鏈接的關鍵字是 left 和 rightbash

  • 左外鏈接(LEFT JOIN/LEFT OUTER JOIN)oracle

    同上面 內鏈接那個需求,咱們須要顯示出沒有領導的員工
    
    SELECT
    	a.ename,
    	b.ename AS leader_name
    FROM
    	ept a
    LEFT JOIN ept b ON a.p_id = b.id
    
    +-------+-------------+
    | ename | leader_name |
    +-------+-------------+
    | 小王  | 小明        |
    | 小錢  | 小明        |
    | 小李  | 小王        |
    | 小明  | NULL        |
    +-------+-------------+
    複製代碼
  • 右外鏈接(right JOIN/right OUTER JOIN)app

    1. 需求: 查詢出部門對應的員工姓名,沒有的也要顯示
    
    2.查詢出 員工表的員工名稱和部門id
    mysql> select ename,dept_id from ept;
    +-------+---------+
    | ename | dept_id |
    +-------+---------+
    | 小明  |       1 |
    | 小王  |       2 |
    | 小李  |       3 |
    | 小錢  |       2 |
    +-------+---------
    
    3. 查詢出了 部門表中部門名稱和部門id
    mysql> select id , dname from dept;
    +----+-------+
    | id | dname |
    +----+-------+
    |  1 | 運維  |
    |  2 | 開發  |
    |  3 | 產品  |
    |  4 | 前端  |
    +----+-------+
    
    4. 咱們就須要 B表所有顯示;就算不匹配的
    
    SELECT
    	d.dname,
    	e.ename
    FROM
    	dept d
    LEFT JOIN ept e ON d.id = e.dept_id
    
    +-------+-------+
    | dname | ename |
    +-------+-------+
    | 運維  | 小明  |
    | 開發  | 小王  |
    | 產品  | 小李  |
    | 開發  | 小錢  |
    | 前端  | NULL  |
    +-------+-------+
    
    因此 不難看出來 咱們的需求實現了;就算是前端麼有人,可是他也所有顯示了;
    
    5. 其中關於左和右 是創建在 join 這個詞 左邊仍是右邊的 你的表在join這個詞左邊就是左鏈接
    複製代碼

    3. 全鏈接

    1. 需求 咱們須要 查詢出每一個員工對應的領導名稱,以及每一個員工對應的部門名稱,以及每一個員工對應的薪水等級
    2. 三張表結構
    mysql> select * from ept ;
    +----+-------+---------+---------+------+
    | id | ename | salary  | dept_id | p_id |
    +----+-------+---------+---------+------+
    |  1 | 小明  | 1800.00 |       1 | NULL |
    |  2 | 小王  | 1200.00 |       2 |    1 |
    |  3 | 小李  | 2500.00 |       3 |    2 |
    |  4 | 小錢  | 2000.00 |       2 |    1 |
    +----+-------+---------+---------+------+
    
    mysql> select * from dept ;
    +----+-------+
    | id | dname |
    +----+-------+
    |  1 | 運維  |
    |  2 | 開發  |
    |  3 | 產品  |
    |  4 | 前端  |
    +----+-------+
    
    mysql> select * from salary_level;
    +----+--------+-------+
    | id | salary | level |
    +----+--------+-------+
    |  1 |   2500 |     1 |
    |  2 |   2000 |     2 |
    |  3 |   1500 |     3 |
    |  4 |   1000 |     4 |
    +----+--------+-------+
    
    
    3. 咱們須要 a錶鏈接a表  a錶鏈接b表  a錶鏈接c表 
    
    select 
    a.ename,b.ename as leader_name,c.dname as dept,d.level as level
    from ept a
    left join ept b
    on a.p_id=b.id
    join dept c
    on a.dept_id=c.id
    join salary_level d
    on a.salary between d.salary and d.salary+499;
    
    +-------+-------------+------+-------+
    | ename | leader_name | dept | level |
    +-------+-------------+------+-------+
    | 小李  | 小王        | 產品 |     1 |
    | 小錢  | 小明        | 開發 |     2 |
    | 小明  | NULL        | 運維 |     3 |
    | 小王  | 小明        | 開發 |     4 |
    +-------+-------------+------+-------+
    
    複製代碼

4. 子查詢

1. 其實 就是把 子查詢當作 一個 條件參數

1. 需求 查詢出員工表中薪水大於平均薪水的員工的姓名和薪水
2. 查詢emp 表 狀況
mysql> select * from emp;
+-------+--------+-----------+------+------------+---------+---------+--------+
| EMPNO | ENAME  | JOB       | MGR  | HIREDATE   | SAL     | COMM    | DEPTNO |
+-------+--------+-----------+------+------------+---------+---------+--------+
|  7396 | SMITH  | CLERK     | 7902 | 1980-12-17 |  800.00 |    NULL |     20 |
|  7499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN  | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7566 | JONES  | MANAGER   | 7839 | 1981-04-02 | 2975.00 |    NULL |     20 |
|  7654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7782 | CLARK  | MANAGER   | 7839 | 1981-06-09 | 2450.00 |    NULL |     20 |
|  7788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 | 3000.00 |    NULL |     20 |
|  7839 | KING   | PRESIDENT | NULL | 1981-11-17 | 5000.00 |    NULL |     10 |
|  7844 | TURNER | SALESMAN  | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7876 | ADAMS  | CLERK     | 7788 | 1987-05-23 | 1100.00 |    NULL |     20 |
|  7900 | JAMES  | CLERK     | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
|  7902 | FORD   | ANALYST   | 7566 | 1981-12-03 | 3000.00 |    NULL |     20 |
|  7934 | MILLER | CLERK     | 7782 | 1982-01-23 | 1300.00 |    NULL |     10 |
+-------+--------+-----------+------+------------+---------+---------+--------+

3. 就是嵌套查詢

SELECT
	a.ENAME,
	a.SAL
FROM
	emp a
WHERE
	a.SAL > (
		SELECT
			AVG(emp.SAL) AS avgsal
		FROM
			emp
	)

+-------+---------+
| ENAME | SAL     |
+-------+---------+
| JONES | 2975.00 |
| BLAKE | 2850.00 |
| CLARK | 2450.00 |
| SCOTT | 3000.00 |
| KING  | 5000.00 |
| FORD  | 3000.00 |
+-------+---------+
	
複製代碼

2. 就是把子查詢 當作 一個 臨時表

1. 需求  找出每一個部門的平均薪水,而且顯示出每一個部門的薪水等級

2. 分析 找出每一個部門的平均薪水 就須要 先按部門分組,而後求出每一個部門的平均薪水

SELECT
	e.DEPTNO as DEPTNO,
	AVG(e.SAL) AS avgsal
FROM
	emp e
GROUP BY
	e.DEPTNO
+--------+-------------+
| DEPTNO | avgsal      |
+--------+-------------+
|     10 | 3150.000000 |
|     20 | 2220.833333 |
|     30 | 1566.666667 |
+--------+-------------+

3.查看薪水錶
mysql> select * from salgrade;
+-------+-------+-------+
| GRADE | LOSAL | HISAL |
+-------+-------+-------+
|     1 |   700 |  1200 |
|     2 |  1201 |  1400 |
|     3 |  1401 |  2000 |
|     4 |  2001 |  3000 |
|     5 |  3001 |  9999 |
+-------+-------+-------+
4. 咱們應該把 表1當作 a表  表二當作 b表 此時作鏈接
select  a.DEPTNO,b.GRADE
from a
join b
on a.avgsal between b.LOSAL and b.HISAL

此時咱們是否是 能夠改寫一下 

SELECT
	a.DEPTNO,
	a.avgsal,
	b.GRADE
FROM
	(
		SELECT
			e.DEPTNO AS DEPTNO,
			AVG(e.SAL) AS avgsal
		FROM
			emp e
		GROUP BY
			e.DEPTNO
	) a
JOIN salgrade b 
ON a.avgsal BETWEEN b.LOSAL AND b.HISAL;

+--------+-------------+-------+
| DEPTNO | avgsal      | GRADE |
+--------+-------------+-------+
|     10 | 3150.000000 |     5 |
|     20 | 2220.833333 |     4 |
|     30 | 1566.666667 |     3 |
+--------+-------------+-------+
複製代碼

5. union 表的鏈接

1.使用場景 : 鏈接兩個同樣的表;運維

1. 查詢出工做爲 "CLERK" 和 "SALESMAN"的 員工姓名

2. 第一種實現結果 
SELECT
	ename,
	job
FROM
	emp
WHERE
	JOB = "CLERK"
OR JOB = "ANALYST"

3. 第二種實現
SELECT
	ename,
	job
FROM
	emp
WHERE
	job IN ('CLERK', 'ANALYST')

4. 第三種實現

SELECT
	ename,
	job
FROM
	emp
WHERE
	job = "CLERK"
UNION
	SELECT
		ename,
		job
	FROM
		emp
	WHERE
		job = "ANALYST"

+--------+---------+
| ename  | job     |
+--------+---------+
| SMITH  | CLERK   |
| ADAMS  | CLERK   |
| JAMES  | CLERK   |
| MILLER | CLERK   |
| SCOTT  | ANALYST |
| FORD   | ANALYST |
+--------+---------+

顯然 union  必須 要求兩個組合的 表 必須 字段長度相同 ;並且 有意義點的就是 兩個表 字段含義同樣
複製代碼

6. constraint 表的約束

非空約束 not null

惟一性約束 , 不可重複 unique

給約束起別名 constraint name

聯合約束主鍵約束 primary key 與 not no unique 的效果相同 ,

還能夠添加索引 ,每張表必須有主鍵,否則就是無效表

主鍵值不能修改的單一主鍵聯合主鍵(可是 一張表只能有一個主鍵,,只有兩個同樣時纔會出現主鍵不一樣)天然主鍵業務主鍵自增主鍵值 auto_increment 只要你一旦使用過 , 就不能重複使用外鍵約束 foreign key 外簡約束外鍵字段外鍵值

drop table if exists t_user;

create table t_user(
	id int(2) not null,
    name varchar(10) unique,
    email varchar(20),
    phone varchar(15),
    cd_card char(18) not no unique,
    constraint t_user_email_phone_unique unique(email,phone),
    primary key(id,name) 
)



constraint  英文單詞 翻譯叫  約束   通常寫法就是 constraint + 一個字段名 +條件

若是咱們給一個表添加外鍵約束
子 ----- 父
constraint t_student_classes_fk foreign key(classno)  references t_class(cno)

子表的數據也就是 外鍵值能夠爲空 ,稱爲孤兒數據
父表中的引用字段必須具備惟一性
建立表要先建立父表再建立子表
複製代碼

7. cascade 級聯操做

1.級聯刪除 on delete cascade  (當我刪除 父表(引用表)中的數據時,子表中的相關數據也要被刪除   )
cascade 意思是 級聯 ,瀑布

2.給學生表添加一個級聯刪除 
alter table student drop foreign key t_student_classes_fk;

alter table stadent add constraint t_student_classes_fk foreign key(classno) 
reference t_class(cno) on delete cascade; 


3.級聯更新  on update cascade (更新父表,子表中引用的字段也要被更新)

alter table student add constraint t_class_student_fk foreign key(classno)
reference t_class(cno) on update cascade


* 注意就是 更新和刪除創建在外鍵之上

複製代碼

8. transaction 事務

mysql數據庫中 在操做數據庫時 是 設置的自動提交事務

你能夠 根據 show variables like '%commit%'; 看到

mysql> show variables like '%commit%';
+-----------------------------------------+-------+
| Variable_name                           | Value |
+-----------------------------------------+-------+
| autocommit                              | ON    |
| binlog_group_commit_sync_delay          | 0     |
| binlog_group_commit_sync_no_delay_count | 0     |
| binlog_order_commits                    | ON    |
| innodb_api_bk_commit_interval           | 5     |
| innodb_commit_concurrency               | 0     |
| innodb_flush_log_at_trx_commit          | 1     |
| slave_preserve_commit_order             | OFF   |
+-----------------------------------------+-------+
8 rows in set, 1 warning (0.00 sec)
複製代碼
  1. 開啓事務

    1.手動開啓事務
    start transaction ;
    2. 執行 DML語句
    inset into student (name) values ('小王');
    3.手動提交
    commit;
    
    
    
    
    4.若是咱們關閉事務  set autocommit=off
    執行 DML語句
    
    而後 commit;
    
    
    
    
    複製代碼
  2. mysql的四種 隔離級別

    1. 查看當前會話的隔離級別  
    mysql> select @@tx_isolation;
    +-----------------+
    | @@tx_isolation  |
    +-----------------+
    | REPEATABLE-READ |
    +-----------------+
    1 row in set, 1 warning (0.00 sec)
    
    2. 查看當前 全局的隔離級別
    mysql> select @@global.tx_isolation;
    +-----------------------+
    | @@global.tx_isolation |
    +-----------------------+
    | REPEATABLE-READ       |
    +-----------------------+
    1 row in set, 1 warning (0.00 sec)
    
    
    修改全局的隔離級別
    set global transaction isolation level read committed
    
    
    3. 讀未提交(read uncommitted) : 就是當A選擇開啓事務,執行了一條DML語句,此時未提交;而後B也開起了事務去讀取數據,結果讀取到了A修改後的數據,這條數據 爲 髒讀;
    
    4. 讀已提交(read committed) : 就是A選擇開起了事務,而後執行了一條DML語句,此時開着事務的B沒法看到A執行後的結果,當A提交後,此時開着事務的B 就能看到 commit後的數據; 此時出現的現象叫作 不可重複讀;
    
    5. 可重複讀(repeatable read) : 就是A,B開啓着事務,A提交的數據,B沒法獲取到 ;此時這種現象叫作幻象讀;保證了B的數據開啓事務時刻數據的一致性
    
    6. 串行化(serializable): 同一時刻操做數據庫的只有一我的;可是能夠多人開啓事務;只能等待第一我的提交事務或者回滾事務,另一我的才能執行數據庫操做;
    
    
    複製代碼

9. index 索引

  1. 主鍵索引 ,添加主鍵會自動添加主鍵索引

  2. 外鍵索引,

  3. 索引檢索方式

    • 全表掃描
    • 索引檢索
  4. 不多使用 dml操做時,適合添加索引

  5. 常常出如今where語句中

  6. 建立索引

    create index tudent_name_index on student(name);
    
    
    查看索引
    show index from table_name
    
    
    刪除索引
    drop index  tudent_name_index on student;
    複製代碼
  7. 索引也要被存儲在文件中

10. view 視圖

  1. 建立視圖

    1. create view student_view as select * from student
    
    2. 當咱們 show create view student_view時
    
    mysql> show create view dept_view;
    
    | View      | Create View                                                                                                                                           
    | dept_view | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `dept_view` AS select `dept`.`DEPTNO` AS `DEPTNO`,`dept`.`DNAME` AS `DNAME`,`dept`.`LOC` AS `LOC` from `dept` | gbk                  | gbk_chinese_ci 
    
    
    咱們能夠發現 他只是 在原有的表上建立了一個 select 語句
    
    
    3. 刪除視圖
    drop view dept_view;
    或
    drop view if exists dept_view;
    複製代碼
  2. 索引 視圖 和 原表中的數據 是個影子關係

  3. 視圖的做用

    • 隱藏表的細節 好比 create view dept_view as select depton as a ,dname as b from dept 咱們會發現 咱們拿到的表 只有 a , b 字段 只能考 字段操做

    • 相似與 建立臨時表,提升查詢效率,以及可用性,

      create  view  emp_dept as
      select a.ename,b.dname
      from emp a
      join dept b
      on a.deptno=b.deptno
      
      
      而後直接 
      select* from emp_dept;
      
      這個能夠提升檢索效率和重複利用率
      複製代碼

11. MySQL 存儲引擎

1.mysql有9種存儲引擎

mysql> show engines ;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES          | YES  | YES        |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                          | NO           | NO   | NO         |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables      | NO           | NO   | NO         |
| BLACKHOLE          | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO   | NO         |
| MyISAM             | YES     | MyISAM storage engine                                          | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                             | NO           | NO   | NO         |
| ARCHIVE            | YES     | Archive storage engine                                         | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                             | NO           | NO   | NO         |
| FEDERATED          | NO      | Federated MySQL storage engine                                 | NULL         | NULL | NULL       |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
9 rows in set (0.01 sec)


1. 默認是 innodb 
2. 能夠修改 my.ini 設置默認存儲引擎 以及一些默認配置
3. 修改表的存儲引擎  alter table table_name engine=MyISAM


複製代碼

2. InnoDB

​ 1.主要記住 innodb 支持事務操做

2. 使用**外鍵** 以及  級聯刪除和級聯更新也須要使用 innodb engine
複製代碼
3. 行及鎖定
4. mysql數據庫崩潰 後 提供自動恢復
5. 表空間的概念
6. 提供 acid 的兼容
複製代碼

3. MyISAM

1. 表存儲格式
 - 表結構 .frm
 - 表數據  .myd
 - 表索引  .myi
2. 能夠壓縮文件,節省空間
複製代碼

4. MEMORY

  1. 存儲的數據在 內存中 ,因此 很快
  2. 索引也被存儲在內存中
  3. 字段屬性不能包含text,blob等大的地段

12. 數據庫設計的三範式

  1. 第一範式 : 要求有主鍵 , 且每一個字段保證其原子性,且不重複
  2. 第二範式 : 數據庫中的非主鍵字段嚴格和主鍵字段有關聯 ,其自身不能產生部分依賴 (儘可能不要使用聯合主鍵)
    • 多對多 時 ;創建 中間表
  3. 第三範式:非主鍵字段不能產生傳遞依賴 ;

13. MySql 鎖的問題

1.表鎖(互斥鎖)

  • 讀鎖 :lock table clazz read; 此時只能讀數據,沒法修改數據;只有當 unlock tables; 才能夠執行修改操做
  • 寫鎖:lock table clazz write; 此時只能寫數據,沒法進行讀取數據;只有當 unlock tables; 才能夠執行修改操做
  • 這種使用場景通常是 鎖表 ;作大的維護操做時;能夠鎖表 ; 讀寫互斥

2.行鎖

  • 他不鎖住整個數據庫,開啓事務,只會鎖住操做的同一張表(好比 A B 兩我的同時開啓事務,A對錶a操做,B對錶b操做,此時兩個行爲均可以執行,不須要等待一方commit,當B表嘗試修改A表時;此時就會等待,必須等待A提交才能執行)

  • 其實就是上面的四種事務;這裏不作解釋了;

3. 悲觀鎖

1. 就是mysql默認的事務等級 
他能保證 每一時刻只能有一我的操做數據庫,除非你提交了;否則沒法更新
好比 兩我的 A和B 
每次執行操做 都要開啓事務 默認事務是 可重複讀(repeatable read)  這個級別;
count=2
當 A 執行 update oreders set count=count-1 where id=1 and count>=1;
此時 B也去執行 update oreders set count=count-2 where id=1 and count>=2;
因爲A先執行 ;因此此時B 是卡住的;只有 A提交了;B才能修改;此時 B中查到的count數據已經修改過了;因此返回結果爲false;



可是 在事務中 若是使用了 這個 select * from oreders for update; 他能夠防止讀取到的數據發生不可重複讀現象;其實能夠理解爲 帶着 updateselect語句; 你執行了 update 自己就鎖住了;他其實一句帶着兩句;他是個 互斥鎖;你就算你是讀,可是你執行了這個操做,別人也沒法寫執行;



可是 就算是咱們在 開啓事務中 使用select * from oreders 讀到的是假數據 仍然不影響咱們執行 update操做時;數據的讀取問題 ;好比上面那個問題


複製代碼

4.樂觀鎖

1. 好比說 咱們在 查詢的時候 帶上一個 version ,更新的時候 須要帶上這個version

SELECT  count,version FROM orders WHERE id =1   把查詢到version數據加給第二行,

每次更新都須要這樣子,若是一我的更新成功,那麼version數據就變化了,那麼另一我的拿到的鎖,他打不開,找不到數據就沒法更新

UPDATE orders SET count=count-5 , version=version+5 WHERE id=1 AND version=2 AND count>=5

這樣能夠防止超賣和加鎖
複製代碼

QA

  1. between range_1 and range_2 是 左閉右閉

  2. SELECT
    	AVG(emp.SAL) AS avgsal,ENAME,SAL
    FROM
    	emp
    WHERE SAL>avgsal
    切記 where 語句中不能直接套用非表格字段 ;這個須要子查詢
    複製代碼
  3. limit 用法 limit a , b (a是從0開始的,b指的是長度) 當 只有一個參數時 ;指的 是長度; 好比說 找出 第五個到第八個,咱們 5 , 6 , 7 ,8 一共長度是4 ,則 limit 4 , 4, 其中limit是mysql 特有的

  4. mysql 的 varcart類型 長度 爲 1 能夠輸入 一個漢字 也是一個英文 一個數字 ;其實 一個varchar 就是一個字符;存儲空間等於實際數據長度

  5. char 是固定長度 通常填寫 固定長度的信息好 ;存儲空間是死的;無論你是1 23 4 5 我規定了10 你就給你分配10

  6. int類型 佔用4個字節 長度 好像無論寫多少 數字 都麼限制

  7. bigint類型 佔用8個字節 長度 好像無論寫多少 數字 都麼限制

  8. tinyint 類型 長度 選擇 1 可是能夠到達 127 [0,128)

  9. double 和 float

  10. date 佔用8個字節

1.技巧

  1. 備份表 : create table emp_bak as select * from emp

  2. 查看建立表的語句: show create table emp_bak

  3. DML 是什麼 Data Manipulation Language(數據操縱語言) ; 很顯然是 delete , insert , update

    1. delete from table_name where field=a
    2. delete from table_name
    3. update table_name set gender=1,emp=2 where id=1
    4. insert into table_name(filed1,field2) values ('','','')
  4. str_to_date('1949-10-01','%Y-%m-%d') 這個是日期 插入日期 ;; 其中mysql 默認的日期格式 是 1994-10-01 輸入這個不會報錯

  5. show variables like '%char%';

    +--------------------------+---------------------------------------------------------+
    | Variable_name            | Value                                                   |
    +--------------------------+---------------------------------------------------------+
    | character_set_client     | gbk                                                     |
    | character_set_connection | gbk                                                     |
    | character_set_database   | latin1                                                  |
    | character_set_filesystem | binary                                                  |
    | character_set_results    | gbk                                                     |
    | character_set_server     | latin1                                                  |
    | character_set_system     | utf8                                                    |
    | character_sets_dir       | C:\Program Files\MySQL\MySQL Server 5.7\share\charsets\ |
    +--------------------------+---------------------------------------------------------+
    
     character_set_results   字符結果集
    character_set_database   數據庫的字符集
    
    
    修改很簡單 直接  set character_set_results = utf8  就能夠了
     
    
    複製代碼
  6. 兩個表之間備份插入 ,上面提到了 所有插入 ,如今改爲條件插入insert into emp_bak select * from emp where job="manager"

  7. 數據庫模式定義語言DDL(Data Definition Language),是用於描述數據庫中要存儲的現實世界實體的語言。

    添加 alter table table_name add  email varchar(128) ;
    
    修改 alter table table_name modify no int(8);
    
    刪除 alter table table_name  drop email ;
    
    修改表結構 alter table table_name change name  username varchar(32)
    
    
    複製代碼
  8. 解決 1對 1 表的問題 :

    • 就是在一張表的外鍵字段上添加惟一約束
    • 中間表 外鍵 + 惟一
  9. 查看數據庫的version SHOW VARIABLES WHERE Variable_name = 'version';

13. mysql的執行順序

14. Oracle 新語法 start with...connect by

  1. start with 條件1
  2. connect by 條件2
  3. prior表示上一條記錄 好比 CONNECT BY PRIOR org_id = parent_id;就是說上一條記錄的org_id 是本條記錄的parent_id

給一張圖 解釋

修改字符集

su - oracle  
sqlplus /nolog  
connect /as sysdba  
 
--查看數據庫字符編碼集
select userenv('language') from dual;
 
shutdown immediate  
startup restrict  
alter database character set INTERNAL_USE ZHS16GBK;  
shutdown immediate  
startup
複製代碼

15.數據庫操做練習

1. 取得每一個部門中最高薪水的人員名稱

SELECT
	f.DEPTNO,
	f.DNAME,
	f.ENAME,
	MAX(f.SAL) AS maxsal
FROM
	(
		SELECT
			d.DEPTNO,
			d.DNAME,
			e.ENAME,
			e.SAL
		FROM
			dept d
		JOIN emp e ON e.DEPTNO = d.DEPTNO
	) f
GROUP BY
	f.DNAME
	
+--------+------------+-------+---------+
| DEPTNO | DNAME      | ENAME | maxsal  |
+--------+------------+-------+---------+
|     10 | ACCOUNTING | KING  | 5000.00 |
|     20 | RESEARCH   | SMITH | 3000.00 |
|     30 | SALES      | ALLEN | 2850.00 |
+--------+------------+-------+---------+





2. 查詢出哪些人的薪水在平均薪水之上
分析: 1.咱們要先找出每一個部門的平均薪水,而後跟咱們的emp表進行鏈接誒,比較薪水大於平均薪水的

SELECT
	d.ename,
	d.sal,
	d.deptno,
	f.avgsal
FROM
	emp d
JOIN (
	SELECT
		e.DEPTNO,
		AVG(e.sal) AS avgsal
	FROM
		emp e
	GROUP BY
		e.DEPTNO
) f ON f.DEPTNO = d.deptno
WHERE
	d.sal > f.avgsal

+-------+---------+--------+-------------+
| ename | sal     | deptno | avgsal      |
+-------+---------+--------+-------------+
| ALLEN | 1600.00 |     30 | 1566.666667 |
| JONES | 2975.00 |     20 | 2220.833333 |
| BLAKE | 2850.00 |     30 | 1566.666667 |
| CLARK | 2450.00 |     20 | 2220.833333 |
| SCOTT | 3000.00 |     20 | 2220.833333 |
| KING  | 5000.00 |     10 | 3150.000000 |
| FORD  | 3000.00 |     20 | 2220.833333 |
+-------+---------+--------+-------------+


3. 取出部門中的人的平均薪水等級

思路先求出每一個人的薪水等級,而後根據此表分組,計算出平均值, 而後根據dept表查詢出部門



SELECT
	h.deptno,
	d.dname,
	h.avggra
FROM
	dept d
JOIN (
	SELECT
		f.deptno,
		AVG(f.grade) AS avggra
	FROM
		(
			SELECT
				e.ename,
				e.deptno,
				s.grade
			FROM
				emp e
			JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal
		) f
	GROUP BY
		f.deptno
) h
ON
	h.deptno = d.deptno
		
或者

SELECT
	f.deptno,
	d.dname,
	AVG(f.grade) AS avggra	
FROM
	(
		SELECT
			e.ename,
			e.deptno,
			s.grade
		FROM
			emp e
		JOIN salgrade s ON e.sal BETWEEN s.losal AND s.hisal
	) f
JOIN dept d ON d.deptno = f.deptno
GROUP BY
	f.deptno
	
+--------+------------+--------+
| deptno | dname      | avggra |
+--------+------------+--------+
|     10 | ACCOUNTING | 3.5000 |
|     20 | RESEARCH   | 3.0000 |
|     30 | SALES      | 2.5000 |
+--------+------------+--------+ 


或者 是 查詢出平均薪水 而後根據 平均薪水找對應等級 

SELECT
	f.deptno,
	d.dname,
	s.grade,
	f.avgsal
FROM
	salgrade s
JOIN (
	SELECT
		e.ename,
		e.deptno,
		AVG(e.sal) AS avgsal
	FROM
		emp e
	GROUP BY
		e.deptno
) f ON f.avgsal BETWEEN s.losal AND s.hisal
JOIN dept d ON f.deptno = d.deptno
	
+--------+------------+-------+
| deptno | dname      | grade |
+--------+------------+-------+
|     30 | SALES      |     3 |
|     20 | RESEARCH   |     4 |
|     10 | ACCOUNTING |     5 |
+--------+------------+-------+ 
	
	
	
	
4. 不許用max聚合函數,取得最高薪水等級 給出兩種方案

SELECT
	sal
FROM
	emp
ORDER BY
	sal DESC
LIMIT 1

+---------+
| sal     |
+---------+
| 5000.00 |
+---------+

第二種方案 就是 兩個同樣的表比較  好比 (1,2,3,4),(1,2,3,4) 我要找出a表中小於b表中的數(1,2,3) 因此此時空掉的是 4 這個數字

SELECT
	sal
FROM
	emp
WHERE
	sal NOT IN (
		SELECT DISTINCT
			a.sal
		FROM
			emp a
		JOIN emp b ON a.sal < b.sal
	)
+---------+
| sal     |
+---------+
| 5000.00 |
+---------+


5.取出平均薪水最高的部門編號

SELECT
	deptno,
	avg(sal) AS avgsal
FROM
	emp
GROUP BY
	deptno
HAVING
	avgsal = (
		SELECT
			max(a.avgsal) AS maxavg
		FROM
			(
				SELECT
					deptno,
					avg(sal) AS avgsal
				FROM
					emp
				GROUP BY
					deptno
			) a
	)



6.找出平均薪水最高的部門所對應的部門名稱

SELECT
	e.deptno,
	d.dname,
	avg(e.sal) AS avgsal
FROM
	emp e
JOIN dept d
ON e.deptno=d.deptno
GROUP BY
	e.deptno
HAVING
	avgsal = (
		SELECT
			max(a.avgsal) AS maxavg
		FROM
			(
				SELECT
					deptno,
					avg(sal) AS avgsal
				FROM
					emp
				GROUP BY
					deptno
			) a
	)

複製代碼

16. 建表語句

DROP TABLE IF EXISTS EMP;
DROP TABLE IF EXISTS DEPT;
DROP TABLE IF EXISTS SALGRADE;
 
CREATE TABLE DEPT
	(DEPTNO int(2) not null ,
	DNAME VARCHAR(14) ,
	LOC VARCHAR(13) ,
	primary key (DEPTNO)
	);
CREATE TABLE EMP
	(EMPNO int(4) not null ,
	ENAME VARCHAR(10) ,
	JOB VARCHAR(9) ,
	MGR INT(4) ,
	HIREDATE DATE DEFAULT NULL ,
	SAL DOUBLE(7,2) ,
	COMM DOUBLE(7,2) ,
	primary key (EMPNO) ,
	DEPTNO INT(2)
	);
CREATE TABLE SALGRADE
	(GRADE INT ,
	LOSAL INT ,
	HISAL INT 
	);
	
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
10, 'ACCOUNTING', 'NEW YOURK');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT ( DEPTNO, DNAME, LOC ) VALUES (
30, 'SALES', 'CHICAGO');
INSERT INTO DEPT( DEPTNO, DNAME, LOC ) VALUES (
40, 'OPERATIONS', 'BOSTON');
commit;
 
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7396, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300,30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, NULL, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7839, 'KING', 'PRESIDENT', NULL, '1981-11-17', 5000, NULL, 10);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500, 0, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, NULL, 30);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, NULL, 20);
INSERT INTO EMP (EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO) VALUES (
7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, NULL, 10);
commit;
 
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
1, 700, 1200);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
2, 1201, 1400);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
3, 1401, 2000);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
4, 2001, 3000);
INSERT INTO SALGRADE (GRADE, LOSAL, HISAL) VALUES (
5, 3001, 9999);
commit;
複製代碼
相關文章
相關標籤/搜索