b站尚硅谷MySQL筆記(婷姐初級,周陽高級)


   1 #開啟關閉服務
   2 #管理員啟動cmd,,net start/stop mysql,,
   3 #登錄數據庫,,mysql 【-h localhost -P 端口號】 -u 用戶名  -p,,
   4 #退出數據庫,,exit,, / #ctrl+c
   5 #查看版本號,,mysql -V,,
   6 ##常見語句
   7 #查看當前所有數據庫
   8 SHOW DATABASES;
   9 #打開指定的庫,,use 庫名;
  10 #查看某庫所有的表,,show tables; // show tables from 庫名;
  11  /*創建表,, create table(
  12     字段名稱 字段類型,
  13     字段名稱 字段類型
  14     );*/
  15 #查看表結構,,desc 表名;
  16 #修改字符集 set names gbk;
  17 #查看表內容,,select * from 表名;
  18 #插入內容,,insert into 表名 (id , name) values1,‘yangbo’);
  19 #更新修改內容,,update  表名 set name='yb' where id=1;
  20 #刪除內容,,delete from 表名  where id=1;
  21 ##不區分大小寫
  22 ##單行注釋   #注釋    -- 注釋 
  23 ##多行注釋  /* 注釋 */
  24  ###data query language/ data manipulation lan/
  25 ### data define lan/transcation control lan/
  26 ###DQL數據查詢語言
  27 ##進階1 基礎查詢-----------------------------------------
  28 # select  (字段、常量、表達式、函數) from  表名;
  29 USE myemployees;
  30  SELECT
  31   job_id          #F12變規范
  32 FROM
  33   jobs;
  34   
  35 SELECT
  36   `manager_id`,  #`` 區分系統sql關鍵字和字段名
  37   `first_name`,
  38   #逗號自己加
  39    `email`
  40 FROM
  41   `employees`;
  42 
  43 SELECT * FROM employees;  
  44 
  45 SELECT    1+4;
  46 
  47 #查詢函數
  48 SELECT VERSION();
  49 
  50 #起別名alias  便於理解 ,防止重名
  51 SELECT last_name AS 姓 , first_name ASFROM employees;
  52 SELECT last_name 姓 FROM employees ;  # 無AS
  53 SELECT last_name 'x  #i ng' FROM employees;
  54 
  55 #去重
  56 SELECT  DISTINCT department_id FROM employees;
  57 
  58 # + 號的作用
  59 SELECT 10+10;   #==20
  60 SELECT "10"+10; #==20
  61 SELECT '1o'+10; #==11
  62 SELECT 'oo'+10; #==10
  63 SELECT NULL+10; #==null
  64 
  65 #拼接文本,判斷是否為null
  66 SELECT CONCAT(last_name,first_name)  AS 姓名 FROM employees;
  67 SELECT CONCAT(`first_name`,`job_id`,IFNULL(`commission_pct`,0)) AS infor 
  68 FROM employees;
  69 
  70 ##進階2 條件查詢--------------------------------------------
  71  /*
  72 select 查詢列表  #3
  73 from 表名        #1
  74 where 條件       #2
  75 
  76 條件表達 <  >  =  !=  <>  <=  >=
  77 #邏輯表達  &&  ||  !   連接多條件表達
  78 #          and  or  not 
  79 #模糊查詢  
  80     like   
  81     between  and
  82     in 
  83     is null  
  84 */
  85 USE `myemployees`;
  86 
  87 SELECT
  88   *
  89 FROM
  90   employees
  91 WHERE salary > 12000;
  92 
  93  
  94 
  95 SELECT
  96   last_name,
  97   `department_id`
  98 FROM
  99   `employees`
 100 WHERE `department_id` <> 90;
 101 
 102 
 103 SELECT 
 104     last_name,
 105     salary
 106 FROM 
 107     employees
 108 WHERE
 109     salary>=10000 AND salary<=20000;
 110 
 111 #查詢部門編號不是在90-120,或者工資大於15000的員工信息
 112 SELECT *
 113 FROM  employees
 114 #where not(`department_id`>=90 and `department_id`<=120) or salary>15000;
 115 #where department_id not between 90 and 15000 or salary>15000;
 116 WHERE NOT(department_id BETWEEN 90 AND 15000) OR salary>15000;
 117 
 118 
 119 #模糊查詢 通配符
 120 # % 表示任意多個字符  _ 表示1個字符 , %%不能代表null!!!!!!!!!!
 121 SELECT *
 122 FROM employees
 123 WHERE last_name LIKE '%a%';  #姓包含a
 124 SELECT *
 125 FROM employees
 126 WHERE last_name LIKE '_i%'; #查詢第二個字符為i,注意%的使用
 127 SELECT *
 128 FROM `employees`
 129 WHERE last_name LIKE '_\_%'; #查詢第二個字符為下划線。\為轉義符
 130 SELECT *
 131 FROM employees
 132 WHERE last_name LIKE '_$_%' ESCAPE '$'; #escape指定轉義符為$
 133 
 134 #between A and B ===  >=A and <=B,所以 A<=B
 135 SELECT * 
 136 FROM employees
 137 WHERE `employee_id` BETWEEN 100 AND 120; 
 138 
 139 #in
 140 /*
 141 in === multiple or , 不支持通配符,因為or是=,不是like
 142 */
 143 SELECT * 
 144 FROM employees
 145 WHERE `job_id` IN ('AD_VP','IT_PROG');
 146 # where `job_id`='AD_VP' OR `job_id`='IT_PROG';
 147 
 148 
 149 #is null  /  is not null
 150 SELECT * 
 151 FROM  employees
 152 WHERE commission_pct IS NULL;
 153 
 154 SELECT ISNULL(`commission_pct`),commission_pct  #判斷為null=1,notnull=0
 155 FROM `employees`;
 156 
 157 #安全等於 <=>
 158 SELECT * 
 159 FROM employees
 160 WHERE `job_id` <=> 'AD_VP';
 161 
 162 SELECT * 
 163 FROM employees
 164 WHERE salary <=> 12000;
 165 
 166 SELECT * 
 167 FROM employees
 168 WHERE commission_pct <=> NULL;
 169 
 170 
 171 ##進階3 排序---------------------------------------------
 172 
 173 #ORDER BY 默認asc ,降序,放在查詢最后(除limit之外)
 174 #工資從高到低
 175 SELECT * FROM `employees` ORDER BY salary DESC;
 176 
 177 #加篩選條件
 178 #按表達式排序
 179 #ifnull(字段,0),字段值為null,賦值為0,不為null,為原值
 180 SELECT salary, salary*12*(1+IFNULL(`commission_pct`,0)) AS 年薪
 181 FROM  employees
 182 ORDER BY salary*12*(1+IFNULL(`commission_pct`,0));
 183 
 184 #按照別名排序
 185 SELECT salary, salary*12*(1+IFNULL(`commission_pct`,0)) AS 年薪
 186 FROM  employees
 187 ORDER BY 年薪 DESC;  #說明order by 最后一步執行
 188 
 189 #按函數排序
 190 SELECT `last_name`,LENGTH(`last_name`)
 191 FROM `employees`
 192 ORDER BY LENGTH(`last_name`) DESC;
 193 
 194 #多條件排序 員工信息 先按工資升序,后按 員工編號降序
 195 SELECT *
 196 FROM employees
 197 ORDER BY salary ASC,`employee_id` DESC;
 198 
 199 
 200 ##進階4 常見函數-------------------------------------------------
 201 
 202 /*
 203 函數分為單行和多行函數
 204 單行比如length(),肯定有返回值
 205     1.字符函數(處理字符串)
 206 多行函數,又稱組函數,統計用
 207 */
 208 
 209 #一、 字符函數##########################
 210 
 211 #1.length,獲取字符長度
 212 SELECT LENGTH('莫默123aaa');
 213 #UTF8中文為3個字節,GBK中文2個字節
 214 SHOW VARIABLES LIKE '%char%';
 215 
 216 #2.concat
 217 SELECT CONCAT(`last_name`,'_',`first_name`) AS 姓名 FROM employees;
 218 
 219 #3.upper lower 
 220 
 221 SELECT CONCAT(UPPER(last_name),LOWER(first_name)) 姓名 FROM employees;
 222 
 223 #4.substr / substring
 224 SELECT SUBSTR('李莫愁愛上了陸展元',7) AS output; #從第7個位置開始
 225 SELECT SUBSTR('李莫愁愛上了陸展元',1,3) AS output; #從第1個位置開始的三個字符
 226 
 227 #大寫首字母
 228 SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),LOWER(SUBSTR(last_name,2)))
 229 FROM employees;
 230 
 231 #5 instr
 232 #返回substr在str中第一次出現的索引,若不匹配,返回0
 233 SELECT INSTR('楊不悔愛上了殷六俠','殷六俠') AS output;
 234 #substr和instr連用,取郵箱用戶名
 235 SELECT SUBSTR(email,1,INSTR(email,'@')-1) FROM ..;
 236 #6. trim 
 237 #去掉首位空格或指定str
 238  SELECT TRIM('  莫默  ') AS output;
 239 SELECT TRIM('a' FROM 'aa默aa') AS output;
 240 
 241 #7. lpad
 242 #左填充str為10個字符長,用padstr填充
 243 SELECT LPAD('莫默',10,'*') AS output;
 244 
 245 #8. rpad
 246 SELECT RPAD('y',5,'-') AS output; 
 247 
 248 #9 replace
 249 # 在str中,from_str被to_str替代
 250 SELECT REPLACE('張無忌愛上了周芷若','周芷若','趙敏') AS output;
 251 
 252 #二、數學函數############################
 253 
 254 SELECT ROUND(1.4);
 255 SELECT ROUND(1.459,2);
 256 
 257 SELECT CEIL(1.01); # 取右  取≥該參數的最小整數
 258 
 259 SELECT FLOOR(-1.09); #往數軸 取左
 260 
 261 SELECT TRUNCATE(1.123456,4); #取小數點前4位
 262 
 263 #取余
 264 SELECT MOD(10,3);
 265 SELECT MOD(-10,3);  #結果和被除數正負一致
 266 SELECT 10%3; 
 267 
 268 #出一個隨機數,范圍0-1
 269 SELECT RAND(0123456);
 270 #三、日期函數##############################
 271 SELECT NOW();
 272 
 273 SELECT CURDATE();
 274 
 275 
 276 SELECT CURTIME();
 277 #獲得指定的部分 year年 month月 date日 hour小時 minute分 second秒
 278 SELECT YEAR(NOW());
 279 SELECT YEAR('1994-09-10');
 280 SELECT YEAR(hiredate) FROM employees;
 281 SELECT MONTH(NOW());
 282 SELECT MONTHNAME(NOW()); #返回英文月
 283 
 284 #日期格式的字符  轉換成指定的格式
 285 #%Y1994 %y94 %m01 %c1 %d30 %H24 %h12 %i00 59 %s00 59
 286 SELECT MONTHNAME( STR_TO_DATE('1994-4-2','%Y-%c-%d') )output ;
 287 #           日期型字符    該字符的格式
 288 /*
 289 #查詢入職日期為1992-4-3的員工信息
 290 select * from employees where hiredate = '1992-4-3'; 
 291 若日期型字符格式為04-03 92
 292 select * from employees where hiredate = str_to_date('04-03 1992','%m-%d %Y');
 293 */
 294 #時間格式的轉換為特定格式的字符串
 295 SELECT DATE_FORMAT(NOW(),'%Y年%m月%d日') 日期;
 296 #查詢有獎金的員工的員工名和入職日期,要求該日期格式輸出為xx月/xx日 xxxx年
 297  SELECT
 298   last_name 姓名,
 299   DATE_FORMAT (hiredate, '%m月/%d日 %Y年') 入職日期
 300 FROM
 301   employees
 302 WHERE commission_pct IS NOT NULL;
 303 
 304 #求日期之差
 305 SELECT DATEDIFF(CURDATE(),'1994-01-21');
 306 
 307 
 308 #四、 其他函數###################################
 309 SELECT VERSION();
 310 SELECT DATABASE();
 311 SELECT USER();
 312 SELECT PASSWORD('yb'); #加密
 313 SELECT MD5('yb');    #加密
 314 #五、流程控制函數###################################
 315 #if
 316 SELECT IF(10>5,1,0); #和excel的if一樣
 317 SELECT IF(salary<20000,IF(salary<10000,'small','media'),'high') 
 318     grade #nesting 嵌套
 319 FROM employees;
 320 
 321 SELECT last_name, commission_pct,
 322  IF(commission_pct IS NULL,'呵呵','哈哈')   備注
 323 FROM employees;
 324 
 325 #case多條件判斷,可以和select搭配,也可單獨使用
 326 /*
 327 case 常量
 328 when 值1 then 顯示的值1
 329 when 值2 then 顯示的值2
 330 。。。
 331 else 要顯示的值n
 332 end
 333 */
 334 #在部門30的,工資×1.1
 335 #在部門40的,工資×1.2
 336 #在部門50的,工資×1.3
 337 #其他部門,原工資
 338 SELECT `department_id`, salary, 
 339 CASE `department_id`
 340 WHEN 30 THEN salary*1.1
 341 WHEN 40 THEN salary*1.2
 342 WHEN 50 THEN salary*1.3
 343 ELSE salary
 344 END 
 345 AS 新工資
 346 FROM employees; 
 347 #excel嵌套大法
 348 SELECT department_id,salary,
 349 IF(department_id=30,salary*1.1,
 350 IF(department_id=40,salary*1.2,
 351 IF(department_id=50,salary*1.3,salary)))AS 新工資 
 352 FROM employees;
 353 
 354 /* 多重if
 355 case 
 356 when 條件1 then 顯示的值1
 357 when 條件2 then 顯示的值2
 358 。。。
 359 else 要顯示的值n
 360 end
 361 */
 362 #工資<10000,small;10000<=工資<20000,media;20000<工資,high
 363 SELECT salary,
 364 CASE
 365 WHEN salary>20000 THEN 'high'
 366 WHEN salary>10000 THEN 'media'
 367 ELSE 'small'
 368 END
 369 AS grade 
 370 FROM employees;
 371 #excel嵌套大法
 372 SELECT salary,IF(salary<20000,IF(salary<10000,'small','media'),'high') 
 373                     grade #nesting 嵌套
 374 FROM employees;
 375 
 376 ##二、統計函數
 377 
 378 #sum avg max min count
 379 #sum avg只能處理數字型,maxmin、count可以字符型
 380 #全部忽略null值
 381 #可以搭配distinct,去重
 382 #和統計函數一同使用的時group by 后的字段。☆☆☆☆☆
 383 
 384 SELECT SUM(salary),AVG(salary),MAX(salary),MIN(salary),COUNT(salary)
 385 FROM employees;
 386 
 387 SELECT SUM(salary),ROUND(AVG(salary),2),MAX(salary),MIN(salary),COUNT(salary)
 388 FROM employees;
 389 
 390 SELECT SUM(`commission_pct`),MAX(hiredate)
 391 FROM employees;
 392 
 393 SELECT SUM(DISTINCT salary), COUNT(DISTINCT `commission_pct`),
 394     SUM(salary),COUNT(`commission_pct`)
 395 FROM `employees`;
 396 
 397 #count單獨使用
 398 SELECT COUNT(*) FROM `employees`;#☆☆☆
 399 SELECT COUNT(1) FROM `employees`;
 400 
 401 #進階5 分組查詢 ------------------------------------------------
 402 /*
 403 select 統計函數,字段
 404 from 表名
 405 【where 包含表名字段的條件】  #不可使用別名
 406 group by 字段   #可使用別名
 407 【having 包含統計函數的字段】  #可使用別名
 408 【order by 字段】 #可使用別名
 409 
 410 */
 411 #簡單分組查詢:每個部門平均工資
 412 SELECT AVG(salary),`department_id`
 413 FROM employees
 414 GROUP BY `department_id`;
 415 #前篩選--分組查詢:郵箱中包含a字符的,每個部門平均工資,
 416 #where要跟在from 后面一行
 417 SELECT AVG(salary),department_id,email
 418 FROM employees
 419 WHERE email LIKE '%a%'
 420 GROUP BY department_id;
 421 #有獎金的每個領導手下的員工最高工資
 422 SELECT MAX(salary),manager_id
 423 FROM employees
 424 WHERE commission_pct IS NOT NULL
 425 GROUP BY manager_id;
 426 #后篩選--分組查詢:領導編號>102的每個領導手下員工的最低工資>5000的領導編號
 427 #,以及其最低工資
 428 SELECT MIN(salary),manager_id
 429 FROM employees
 430 WHERE manager_id>102           #優先考慮前篩選☆☆☆☆☆
 431 GROUP BY manager_id
 432 HAVING MIN(salary)>5000;
 433 #按函數--分組查詢:按員工姓名長度分組,查詢每組個數,篩選員工個數>5的有哪些
 434 SELECT COUNT(*),LENGTH(last_name)
 435 FROM employees
 436 GROUP BY LENGTH(last_name)
 437 HAVING COUNT(*)>5;
 438 #多字段--分組查詢
 439 #每個部門每個工種的平均員工工資
 440 SELECT AVG(salary),department_id,job_id
 441 FROM employees
 442 GROUP BY department_id,job_id;
 443 #排序--分組查詢
 444 #每個部門每個工種的員工平均工資,按照平均工資大小降序
 445 SELECT AVG(salary),department_id,job_id
 446 FROM employees
 447 GROUP BY department_id,job_id
 448 ORDER BY AVG(salary) DESC;
 449 
 450 #進階6 多表連接查詢-----------------------------------------------
 451 #當查詢的字段來自多個表
 452 #分類:內連接:等值連接、非等值連接、自連接
 453 #      外連接:左外連接、右外連接、全外連接
 454 #      交叉連接
 455 
 456 ##92版 內連接    
 457 USE girls;
 458 SELECT NAME,boyName FROM beauty ,boys
 459 WHERE beauty.`boyfriend_id`=boys.`id`;
 460 
 461 #查詢員工名和對應的部門名
 462 SELECT last_name,department_name
 463 FROM employees , departments
 464 WHERE employees.`department_id`=departments.`department_id`;
 465 #為表名起別名,且from先執行,所以select 里面的job.id有歧義,只能用別名去標明
 466 #查詢員工名、工種號、工種名 #
 467 #SELECT last_name,employees.job_id,job_title
 468 SELECT last_name,e.job_id,job_title
 469 FROM employees e, jobs j
 470 WHERE e.`job_id`=j.`job_id`;
 471 
 472 
 473 #篩選--內連接
 474 #有獎金的員工名、部門名
 475 SELECT last_name,department_name
 476 FROM employees e,departments d
 477 WHERE e.`department_id`=d.`department_id`
 478 AND e.`commission_pct` IS NOT NULL;
 479 #查詢城市名中第二個字符為o的部門名和城市名
 480 EXPLAIN SELECT department_name,city
 481 FROM departments d,locations l
 482 WHERE d.`location_id`=l.`location_id`
 483 AND l.`city` LIKE '_o%';
 484 
 485 #分組-內連接
 486 #查詢每個城市的部門個數
 487 SELECT COUNT(*), city
 488 FROM departments d,locations l
 489 WHERE d.`location_id`=l.`location_id`
 490 GROUP BY l.`city`;
 491 #查詢有獎金的每個部門的部門名和部門領導編號,以及該部門最低工資
 492 SELECT department_name,e.manager_id,MIN(salary)
 493 FROM departments d,employees e
 494 WHERE d.`department_id`=e.`department_id`
 495 AND e.`commission_pct` IS NOT NULL;
 496 
 497 #三表連接
 498 #查詢員工名、部門名、所在城市
 499 SELECT last_name,department_name,city
 500 FROM employees e,departments d,locations l
 501 WHERE e.`department_id`=d.`department_id`
 502 AND d.`location_id`=l.`location_id`;
 503 
 504 #非等值連接
 505 #查詢員工工資和工資級別
 506 SELECT salary, grade_level
 507 FROM employees e,job_grades g
 508 WHERE e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`;
 509 
 510 #自連接
 511 #查詢員工名和上級名稱
 512 SELECT a.last_name,b.last_name
 513 FROM employees a,employees b
 514 WHERE a.`manager_id`=b.`employee_id`;
 515 
 516 #99版內連接
 517 #查詢員工名和對應的部門名
 518 SELECT last_name,department_name
 519 FROM employees e 
 520 JOIN departments d
 521 ON e.`department_id`=d.`department_id`;
 522 
 523 #為表名起別名,且from先執行,所以select 里面的job.id有歧義,只能用別名去標明
 524 #查詢員工名、工種號、工種名 #
 525 SELECT last_name,e.job_id,job_title
 526 FROM employees e
 527 JOIN jobs j
 528 ON e.`job_id`=j.`job_id`;
 529 
 530 #篩選--內連接
 531 #有獎金的員工名、部門名
 532 SELECT last_name,department_name
 533 FROM employees e
 534 JOIN departments d
 535 ON e.`department_id`=d.`department_id`
 536 WHERE e.`commission_pct` IS NOT NULL;
 537 
 538 
 539 #查詢城市名中第二個字符為o的部門名和城市名
 540 SELECT department_name,city
 541 FROM departments d
 542 JOIN locations l
 543 ON d.`location_id`=l.`location_id`
 544 WHERE l.`city` LIKE '%o%';
 545 
 546 #分組-內連接
 547 #查詢每個城市的部門個數
 548 SELECT COUNT(*),city
 549 FROM departments d
 550 JOIN locations l
 551 ON d.`location_id`=l.`location_id`
 552 GROUP BY l.`city`;
 553 
 554 #查詢有獎金的每個部門的部門名和部門領導編號,以及該部門最低工資
 555 SELECT department_name,d.manager_id,MIN(salary)
 556 FROM employees e
 557 JOIN departments d
 558 ON e.`department_id`=d.`department_id`
 559 GROUP BY d.`department_name`;
 560 
 561 
 562 
 563 #三表連接
 564 #查詢員工名、部門名、所在城市
 565 SELECT last_name,department_name,city
 566 FROM departments d
 567 JOIN  employees e ON e.`department_id`=d.`department_id`
 568 JOIN locations l ON d.`location_id`=l.`location_id`;
 569 
 570 #非等值連接
 571 #查詢員工工資和工資級別
 572 SELECT salary, grade_level
 573 FROM employees e
 574 JOIN job_grades j 
 575 ON e.`salary` BETWEEN j.`lowest_sal` AND j.`highest_sal`;
 576 
 577 #自連接
 578 #查詢員工名和上級名稱
 579 SELECT a.last_name,b.last_name
 580 FROM employees a
 581 JOIN employees b ON  a.`manager_id`=b.`employee_id`;
 582 
 583 SELECT department_name,COUNT(*) 員工個數
 584 FROM departments d INNER 
 585 JOIN employees e
 586 ON d.`department_id`=e.`department_id`
 587 GROUP BY d.`department_name`
 588 HAVING COUNT(*)>3
 589 ORDER BY  員工個數 DESC;
 590 
 591 #左外連接#查詢非交集(內連接查詢的即為交集)
 592 SELECT b.*, bo.boyName
 593 FROM beauty b       #主表
 594 LEFT JOIN boys bo
 595 ON b.`boyfriend_id`=bo.`id`
 596 WHERE bo.`boyName` IS  NULL;
 597 #右外連接
 598 SELECT bo.boyName,b.*
 599 FROM boys bo
 600 RIGHT JOIN beauty b
 601 ON bo.`id`=b.`boyfriend_id`
 602 WHERE bo.`boyName` IS  NULL;
 603 #-----
 604 SELECT bo.*,b.name
 605 FROM boys bo
 606 LEFT JOIN beauty b
 607 ON bo.`id`=b.`boyfriend_id`;
 608 
 609 #交叉連接(笛卡爾乘積)
 610 SELECT * FROM beauty;
 611 SELECT * FROM boys;
 612 SELECT b.*,bo.*
 613 FROM beauty b
 614 CROSS JOIN boys bo;
 615 SELECT b.*,bo.*
 616 FROM beauty b,boys bo;
 617 ####7種join大法
 618 #左拼
 619 SELECT * FROM a LEFT JOIN b ON a.id=b.id;
 620 #左拼左獨有
 621 SELECT * FROM a LEFT JOIN b ON a.id=b.id WHERE b.id IS NULL;
 622 
 623 #右拼
 624 SELECT * FROM a RIGHT JOIN b ON a.id=b.id;
 625 #右拼右獨有
 626 SELECT * FROM a RIGHT JOIN b ON a.id=b.id WHERE b.id IS NULL;
 627 
 628 #內連接
 629 SELECT * FROM a INNER JOIN b ON a.id=b.id ;
 630 
 631 ##全外連接(mysql不支持全外,使用union連接去重的特性,實現full join)
 632 SELECT * FROM a LEFT  JOIN b ON a.id=b.id
 633 UNION 
 634 SELECT * FROM a RIGHT JOIN b ON a.id=b.id;
 635 
 636 ##左獨有  拼  右獨有
 637 SELECT * FROM a LEFT JOIN b ON a.id=b.id WHERE b.id IS NULL;
 638 UNION
 639 SELECT * FROM a RIGHT JOIN b ON a.id=b.id WHERE b.id IS NULL;
 640 
 641 
 642 #習題 那個城市沒有部門
 643 SELECT l.city ,d.department_name
 644 FROM locations l
 645 LEFT JOIN departments d
 646 ON l.`location_id`=d.`location_id`
 647 WHERE d.`department_name` IS NULL;
 648 
 649 #習題 查詢部門名為SAL/IT的員工信息
 650 SELECT d.department_name,e.*
 651 FROM departments d
 652 LEFT JOIN employees e  #注意主表不同,結果不同(把lfet換成right,39行)
 653 ON e.`department_id`=d.`department_id`
 654 WHERE d.`department_name` IN( 'SAL' ,'IT');
 655 
 656 ##進階7 子查詢---------------------------------------
 657 #出現在其他語句的select查詢語句為子查詢
 658 #子查詢出現的位置:    select后面
 659 #               僅支持標量子查詢
 660 #            from后面
 661 #               僅支持表子查詢(多行多列)
 662 #            where后面(**/having后面(** 663 #               標量子查詢(一行一列)√
 664 #               列子查詢(多行一列)  √
 665 #               行子查詢(一行多列)
 666 #            exists后面
 667 #               表子查詢
 668 /*
 669 #where和having后面:標量、列、行子查詢
 670 特點: 子查詢放在小括號內
 671     一般放在條件的右側
 672     標量子查詢一般搭配單行操作符使用:> < >= <= = <>
 673     列子查詢一般搭配多行操作符使用 in any/some all
 674     查詢過程中,子查詢優先執行
 675 */
 676 ##標量子查詢
 677 #案例1 誰的工資比Abel高?
 678 SELECT *
 679 FROM employees
 680 WHERE salary>( SELECT salary FROM employees WHERE last_name='Abel');
 681 #案例2 返回job_id和141號員工相同,salary比143號員工高的員工信息
 682 SELECT * 
 683 FROM employees
 684 WHERE job_id = 
 685     (SELECT job_id FROM employees WHERE employee_id=141)
 686 AND   salary>
 687     (SELECT salary FROM employees WHERE employee_id = 143);
 688 #案例3 返回工資最少的員工的信息
 689 SELECT * 
 690 FROM employees
 691 WHERE salary = (SELECT MIN(salary) FROM employees );
 692 #案例4 查詢最低工資大於50號部門的最低工資的部門name和其最低工資(外加多表查詢)
 693 SELECT MIN (salary), d.department_name
 694 FROM employees e
 695 JOIN departments d
 696 ON e.`department_id` = d.`department_id`
 697 GROUP BY d.department_name
 698 HAVING MIN (salary) >
 699   (SELECT
 700     MIN (salary)
 701   FROM
 702     employees
 703   WHERE department_id = 50);
 704 ##列子查詢
 705 #案例1 返回location_id是1400或者1700的部門中所有員工姓名
 706 SELECT *
 707 FROM employees
 708 WHERE department_id IN (
 709  SELECT DISTINCT department_id 
 710  FROM departments
 711  WHERE location_id IN(1400,1700)
 712 );
 713 SELECT *
 714 FROM employees
 715 WHERE department_id =ANY (
 716  SELECT DISTINCT department_id 
 717  FROM departments
 718  WHERE location_id IN(1400,1700)
 719 );
 720 # is not in == <>all
 721 # is in == =any
 722 #返回其他工種中比job_id為'IT-PROG'工種任一工資低的員工號、姓名、jobid、salary
 723 SELECT employee_id,last_name,job_id,salary
 724 FROM employees
 725 WHERE salary < ANY(
 726     SELECT DISTINCT salary FROM employees WHERE job_id='IT_PROG'
 727 ) AND job_id <> 'IT_PROG';
 728 SELECT employee_id,last_name,job_id,salary
 729 FROM employees
 730 WHERE salary < (
 731     SELECT DISTINCT MAX(salary) FROM employees WHERE job_id='IT_PROG'
 732 ) AND job_id <> 'IT_PROG';
 733 #返回其他工種中比job_id為'IT-PROG'工種*所有*工資低的員工號、姓名、jobid、salary
 734 SELECT employee_id,last_name,job_id,salary
 735 FROM employees
 736 WHERE salary < ALL(
 737     SELECT DISTINCT salary FROM employees WHERE job_id='IT_PROG'
 738 ) AND job_id <> 'IT_PROG';
 739 SELECT employee_id,last_name,job_id,salary
 740 FROM employees
 741 WHERE salary < (
 742     SELECT DISTINCT MIN(salary) FROM employees WHERE job_id='IT_PROG'
 743 ) AND job_id <> 'IT_PROG';
 744 ##3、行子查詢
 745 #查詢員工編號最小,工資最高的員工信息
 746 
 747 SELECT * FROM employees
 748 WHERE employee_id = (SELECT MIN(employee_id) FROM employees)
 749 AND  salary = (SELECT MAX(salary) FROM employees);
 750 
 751 SELECT * FROM employees e
 752 WHERE (e.`employee_id` , e.`salary`) =(
 753     SELECT MIN(employee_id) ,MAX(salary) FROM employees);
 754 
 755 
 756 #二、select后面子查詢,**僅支持標量子查詢
 757 #每個部門的員工個數
 758 SELECT d.*,(
 759     SELECT COUNT(*)
 760     FROM employees e
 761     WHERE e.department_id = d.`department_id`) N
 762 FROM departments d;
 763 SELECT d.* ,COUNT(*) N
 764 FROM employees e,departments d
 765 WHERE e.`department_id`=d.`department_id`
 766 GROUP BY e.`department_id`;
 767 #員工號102的部門名
 768 SELECT (SELECT d.department_name
 769     FROM employees e,departments d
 770     WHERE e.department_id=d.department_id
 771     AND e.employee_id=102) N
 772 ;
 773 ##from 后面跟表子查詢,表子查詢必須要起別名
 774 #案例:每個部門的平均工資的工資等級
 775 SELECT a.avge,a.department_id, j.`grade_level`
 776 FROM (
 777     SELECT AVG(salary) avge,department_id
 778     FROM employees
 779     GROUP BY department_id
 780 ) a
 781 , job_grades j
 782 WHERE a.avge BETWEEN j.`lowest_sal` AND j.`highest_sal`;
 783 SELECT a.*, j.`grade_level`
 784 FROM (
 785     SELECT AVG(salary) avge,department_id
 786     FROM employees
 787     GROUP BY department_id
 788 ) a
 789 JOIN job_grades j
 790 ON a.avge BETWEEN j.`lowest_sal` AND j.`highest_sal`;
 791 
 792 ##exists (相關子查詢)
 793 SELECT EXISTS(
 794     SELECT salary FROM employees WHERE salary = 23000
 795 );
 796 #返回布爾向量,0或1
 797 #有員工的部門名
 798 SELECT d.department_name
 799 FROM departments d
 800 WHERE d.department_id IN (SELECT e.department_id FROM employees e);
 801 
 802 SELECT d.department_name
 803 FROM departments d
 804 WHERE EXISTS 
 805 (SELECT * FROM employees e WHERE e.`department_id`=d.`department_id`);
 806 
 807 (SELECT
 808   e.*
 809 FROM
 810   employees e ,departments d
 811 WHERE e.`department_id` = d.`department_id`);
 812 #案例2 沒有女朋友的男神信息
 813 USE girls;
 814 SELECT bo.*
 815 FROM boys bo
 816 WHERE NOT EXISTS (
 817     SELECT * FROM beauty b WHERE b.`boyfriend_id`=bo.`id`
 818 );
 819 ##習題:查詢各部門中工資比本部門平均工資高的員工信息
 820 SELECT e.* 
 821 FROM employees e,(
 822     SELECT AVG(salary) av,department_id 
 823     FROM employees 
 824     GROUP BY department_id
 825 )a
 826 WHERE e.`department_id`=a.department_id
 827 AND e.`salary`>a.av;
 828 
 829 
 830 SELECT e.* ,e.`department_id` FROM employees e 
 831 JOIN (
 832     SELECT AVG(salary) av,department_id 
 833     FROM employees 
 834     GROUP BY department_id
 835 )a
 836 ON e.`department_id`=a.department_id
 837 WHERE e.`salary`>a.av;
 838 
 839 ##進階8 分頁查詢--------------------------------------------
 840 #偽代碼
 841 #    select 查詢列表
 842 #    from 表名
 843 #    【join type
 844 #      where group by  having  order by 845 #    limit 【起始頁=0】,size
 846 #公式:******limit (page-1)*size,size*********
 847 #*******************查詢虛擬表的極值order by xx desc limit 1*******************
 848 #案例1 查詢前5條員工信息
 849 SELECT * FROM employees LIMIT 0,5; #從0開始!!!!!!,substr是1開始
 850 SELECT * FROM employees LIMIT 5;
 851 #案例2 有獎金的員工信息,工資較高的前10名
 852 SELECT * 
 853 FROM employees
 854 WHERE commission_pct IS NOT NULL
 855 ORDER BY salary DESC
 856 LIMIT 0,10;
 857 #執行順序
 858 /*
 859 select 查詢列表        7
 860 from 表名        1
 861 連接類型 join 表2    2 #產生一個笛卡爾乘積
 862 on 連接條件        3 #根據連接條件篩選
 863 where 篩選條件        4
 864 group by 分組列表    5
 865 having 分組后篩選    6
 866 order by 排序列表    8
 867 limit 偏移,條目數    9
 868 */
 869 
 870 #子查詢經典習題
 871 #案例1 查詢平均工資最低的部門信息
 872 SELECT d.*
 873 FROM departments d
 874 JOIN (
 875     SELECT AVG(salary) ag ,e.department_id 
 876     FROM employees e
 877     GROUP BY e.`department_id`
 878     ORDER BY a.ag
 879     LIMIT 0,1
 880 ) a
 881 ON d.`department_id`=a.department_id
 882 ;
 883 #平均工資最高的job信息
 884 SELECT j.* 
 885 FROM jobs j,(
 886     SELECT AVG(salary) av,job_id
 887     FROM employees 
 888     GROUP BY job_id
 889     ORDER BY av DESC
 890     LIMIT 1
 891 ) a
 892 WHERE  j.`job_id`=a.job_id;
 893 
 894 #查詢平均工資高於公司平均工資的部門
 895 SELECT a.department_id,a.av
 896 FROM (
 897     SELECT AVG(salary) av,department_id
 898     FROM employees
 899     GROUP BY department_id
 900 ) a 
 901 WHERE a.av>(
 902     SELECT AVG(salary) FROM employees
 903 );
 904 #查詢公司中所有manager的詳細信息
 905 SELECT b.*
 906 FROM employees a
 907 JOIN employees b
 908 ON  a.`manager_id`=b.`employee_id`
 909 GROUP BY b.`employee_id`;
 910 
 911 SELECT *
 912 FROM employees
 913 WHERE employee_id = ANY(
 914     SELECT DISTINCT manager_id
 915     FROM employees
 916     GROUP BY manager_id
 917 );
 918 #各部門中,最高工資最低的那個部門 的最低工資為
 919 SELECT MIN(salary)
 920 FROM employees 
 921 WHERE department_id =(
 922     SELECT department_id
 923     FROM employees a 
 924     GROUP BY department_id
 925     ORDER BY MAX(salary) 
 926     LIMIT 1)
 927 ;
 928 #查詢平均工資最高的部門的manager信息
 929 #where 標量子查詢結果為null時,如何判斷
 930 SELECT *
 931 FROM employees e
 932 RIGHT JOIN (
 933     SELECT manager_id
 934     FROM employees
 935     GROUP BY department_id
 936     ORDER BY AVG(salary) DESC
 937     LIMIT 1
 938 ) a
 939 ON IFNULL(e.manager_id,1) = IFNULL(a.manager_id,1) ;
 940 
 941 SELECT
 942   *
 943 FROM
 944   employees e
 945 WHERE IFNULL (e.manager_id, 1) = IFNULL (
 946     (SELECT
 947       manager_id
 948     FROM
 949       employees
 950     GROUP BY department_id
 951     ORDER BY AVG (salary) DESC
 952     LIMIT 1),1
 953   );
 954 
 955 #查詢生日在1988-1-1后的學生姓名和專業名稱
 956 USE student;
 957 SELECT  s.`studentname`,m.`majorname`
 958 FROM student s
 959 JOIN major m
 960 ON s.`majorid`=m.`majorid`
 961 WHERE DATEDIFF(s.`borndate`,'1988-1-1')>0;
 962 #每個專業的男生女生人數
 963 SELECT m.`majorname`, sex,COUNT(*)
 964 FROM student s,major m
 965 WHERE s.`majorid`=m.`majorid`
 966 GROUP BY s.majorid , sex;
 967 #變橫行
 968 SELECT majorid ,
 969 (SELECT COUNT(*) FROM student WHERE sex="男" AND majorid=s.`majorid`) 男,
 970 (SELECT COUNT(*) FROM student WHERE sex="女" AND majorid=s.`majorid`) 女
 971 FROM student s
 972 GROUP BY majorid;
 973 #查詢專業和張翠山一樣的學生的最低分
 974 SELECT MIN(score)
 975 FROM student s
 976 JOIN result r
 977 ON s.`studentno`=r.`studentno`
 978 WHERE majorid=(
 979     SELECT  majorid
 980     FROM student
 981     WHERE studentname = '張翠山'
 982 );
 983 #查詢哪個專業沒有學生,分別左連接,右連接
 984 SELECT m.*
 985 FROM major m
 986 LEFT JOIN (
 987     SELECT COUNT(*) AS a, majorid
 988     FROM student
 989     GROUP BY majorid
 990 ) n
 991 ON m.`majorid`=n.majorid
 992 WHERE n.a IS NULL;
 993 
 994 #沒有成績的學生人數
 995 SELECT COUNT(*)
 996 FROM result r
 997 RIGHT JOIN student s
 998 ON r.`studentno`=s.`studentno`
 999 WHERE r.`id` IS NULL;
1000 
1001 ##進階9 聯合查詢-----------------------------------------------
1002 /* 語法:查詢語句1
1003     union 【all】
1004     查詢語句2
1005 特點:
1006 查詢結果來自多個表,且各表之間無關鍵列索引
1007 1、查詢列數一致
1008 2、每個查詢語句的列的排列一致
1009 3、union會去重,顯示全部為union all
1010 */
1011 SELECT c.id ,c.name FROM  china c
1012 UNION ALL
1013 SELECT s.id ,s.name FROM stuinfo s;
1014 
1015 ###DML語言 database manipulate language
1016 #    插入insert
1017 #    修改update
1018 #    刪除delete
1019 
1020 #插入語句
1021 #方式一:insert into 表名(列名) values(值,'')
1022 
1023 USE girls;
1024 INSERT INTO beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
1025 VALUES(13,'安妮·海瑟薇','','1980-1-1','188888888',NULL,NULL);
1026 
1027 #變量nullable,用null作為該字段值,或者不寫該字段
1028 INSERT INTO beauty(id,NAME,sex,borndate,phone)
1029 VALUES(14,'三上悠亞','','1988-1-1','288888888');
1030 
1031 #列的順序可以調換
1032 #字段個數和字段值必須一一對應
1033 #可以省略列名,默認為所有字段,且按照表中順序排列
1034 INSERT INTO beauty
1035 VALUES(15,'妲露拉·萊莉','','1982-1-1','388888888',NULL,NULL);
1036 
1037 #方式二:insert into 表名 set 字段名=值...
1038 INSERT INTO beauty 
1039 SET id=16,NAME='劉濤',phone='12345678';
1040 
1041 #兩種方式 PK
1042 
1043 #方式一可以插入多行
1044 INSERT INTO beauty(id,NAME,sex,borndate,phone)
1045 VALUES(17,'高圓圓','','1988-10-10','488888888'),
1046 (18,'白百何','','1989-01-10','588888888');
1047 
1048 INSERT INTO beauty #效率高**********
1049 SELECT 17,'高圓圓','','1988-10-10','488888888' UNION#*****
1050 SELECT 18,'白百何','','1989-01-10','588888888';
1051 
1052 #方式一支持子查詢#行子查詢的結果為beauty的新值
1053 INSERT INTO beauty(id,NAME,phone)
1054 SELECT 19,'唐藝昕','688888888'; 
1055 
1056 #修改單表記錄
1057 #語法 update 表名 set 字段名=值.... where 篩選條件
1058 UPDATE beauty 
1059 SET NAME='唐嫣'
1060 WHERE id=15;
1061 
1062 #修改多表記錄
1063 #修改張無忌的女朋友電話為18866669999
1064 UPDATE beauty b JOIN boys bo
1065 ON b.`boyfriend_id`=bo.`id`
1066 SET phone = '18866669999'
1067 WHERE bo.`boyName`='張無忌';
1068 #沒有男朋友的女神的男朋友都為id=2
1069 UPDATE beauty b LEFT JOIN boys bo 
1070 ON b.`boyfriend_id`=bo.`id`
1071 SET b.`boyfriend_id`=2
1072 WHERE bo.`id` IS NULL;
1073 
1074 #刪除語句
1075 #方式一
1076 #單表刪除 ,LIMIT 2 b表示刪除兩條記錄
1077 DELETE FROM beauty WHERE id=19 LIMIT 2;
1078 
1079 #多表刪除
1080 #刪除黃曉明的信息以及他女朋友的信息
1081 DELETE bo,b
1082 FROM boys bo JOIN beauty b
1083 ON b.`boyfriend_id`=bo.`id`
1084 WHERE bo.`boyName`='黃曉明';
1085 
1086 #方式二
1087 TRUNCATE TABLE boys;
1088 
1089 #兩種方式PK 篩 率 斷 返 滾
1090 /*
1091 1.delete可以加where,truncate不能
1092 2.truncate效率高
1093 3.對於自增列,delete刪除后在插入,從斷點處記錄,
1094   truncate刪除后從1 開始記錄
1095 4.truncate無返回值,delete顯示刪除了多少行(多少行受影響)
1096 5.truncate刪除不能回滾,delete刪除可以回滾
1097 */
1098 SELECT * FROM boys;
1099 
1100 DELETE FROM boys;
1101 TRUNCATE TABLE boys;
1102 INSERT INTO boys(boyName,userCP)
1103 VALUES('張無忌',100),
1104 ('鹿晗',800),
1105 ('段譽',300);
1106 
1107 
1108 ###DDL數據定義語言
1109 #庫的管理,表的管理
1110 #庫、表的創建create、修改alter,管理drop
1111 #位置 programdata/mysql/data
1112 
1113 ##庫的管理
1114 #庫的創建
1115 CREATE DATABASE IF NOT EXISTS books;
1116 #庫的修改
1117 RENAME DATABASE books TO  newbooks;#不穩定
1118 #修改字符集
1119 ALTER DATABASE books CHARACTER SET gbk;
1120 #庫的刪除
1121 DROP DATABASE IF EXISTS books;
1122 
1123 ##表的管理
1124 #表的創建
1125 #create table 表名(
1126 #    列名 類型 【長度,約束】,
1127 #    列名 類型 【長度,約束】
1128 #    );
1129 CREATE DATABASE IF NOT EXISTS books;
1130 
1131 CREATE TABLE  IF NOT EXISTS book (
1132     id INT,
1133     bookname VARCHAR(20), #(20)為必須
1134     booauthorid INT,
1135     publishtime DATETIME
1136 );
1137 CREATE TABLE author(
1138     id INT,
1139     b_name VARCHAR(20),
1140     nation VARCHAR(20)
1141 )
1142 DESC author;
1143 DESCRIBE author;
1144 
1145 #表的修改
1146 DESCRIBE book;
1147 #修改列名
1148 ALTER TABLE book CHANGE COLUMN publishtime pubdate DATETIME;
1149 #修改類型或約束
1150 ALTER TABLE book MODIFY COLUMN pubdate TIMESTAMP;
1151 #添加新列
1152 ALTER TABLE book ADD COLUMN annual DOUBLE ;
1153 ALTER TABLE stuinfo ADD COLUMN sex CHAR AFTER id;
1154 ALTER TABLE stuinfo ADD COLUMN fam_id INT FIRST;
1155 #刪除列
1156 ALTER TABLE book DROP COLUMN annual;
1157 #修改表名
1158 ALTER TABLE author RENAME bookauthor;
1159 
1160 ##表的刪除
1161 DROP TABLE IF EXISTS bookauthor;
1162 SHOW TABLES;
1163 
1164 ##表的復制
1165 CREATE TABLE author(
1166     id INT,
1167     b_name VARCHAR(20),
1168     nation VARCHAR(20)
1169 );
1170 INSERT INTO author
1171 VALUES
1172     (1,'村上春樹','日本'),
1173     (2,'路遙','中國'),
1174     (3,'王小波','中國');
1175 
1176 #僅復制表的結構,跨庫:庫名.表名
1177 CREATE TABLE copy LIKE author;
1178 #復制表的內容+結構
1179 CREATE TABLE copy1 
1180 SELECT * FROM author; 
1181 #只復制部分數據
1182 CREATE TABLE copy2
1183 SELECT id ,nation
1184 FROM author WHERE nation='中國';
1185 #僅復制某些字段的結構
1186 CREATE TABLE copy3 
1187 SELECT id ,nation
1188 FROM author
1189 WHERE 0; #where 1=2;
1190 
1191 ###常見數值類型
1192 /*
1193 數值型:整數、小數(定點數、浮點數)
1194 字符型:較短文本char、varchar,
1195     較長文本text、blob(較長二進制)
1196 日期型:
1197 */
1198 ##數值型:
1199 /*整數:tinyint(3)、smallint(5)、mediumint(7)、int(10)、bigint
1200     int有符號為正負最大10位,27********,無符號為最大正10位,49********
1201 特點:  1。默認為有符號(-),unsgined關鍵字表示無符號
1202     2。數字超過界值,警告,且用界值填充
1203     3。有默認長度,長度表示顯示的最大寬度,位數不夠用0填補,但必須搭配zerofill
1204     4。zerofill只能為無符號
1205 */
1206 USE test;
1207 DROP TABLE  tab_int;
1208 CREATE TABLE tab_int(
1209     integer1 INT,
1210     integer2 INT UNSIGNED,
1211     integer3 INT(10) ZEROFILL
1212 ); 
1213 
1214 INSERT INTO tab_int VALUES (-1234567890,1234567890,123);
1215 INSERT INTO tab_int VALUES (-1234567890,12345678901,123);
1216 DESC tab_int;
1217 SELECT * FROM tab_int;
1218 /*小數:
1219 浮點型float(M,D)、double(M,D)
1220 定點型dec(M,D)/decimal(M,D)
1221 通用的情況下,優先float>double>decimal
1222 特點: 1。M表示整數+小數位數
1223     2.D表示小數位數
1224     3.如果數值位數超過范圍,則插入臨界值
1225     4.M D都可以省略,float和double隨數據長度變化,但默認decimal(10,0)
1226     5.decimal精度高,用於如貨幣運算
1227 */
1228 CREATE TABLE tab_dem(
1229     d1 FLOAT(5,2),
1230     d2 DOUBLE(5,3),
1231     d3 DECIMAL
1232 );
1233 DROP TABLE tab_dem;
1234 INSERT INTO tab_dem(d1) VALUES(123.12);
1235 INSERT INTO tab_dem(d2) VALUES(123.1);
1236 
1237 SELECT * FROM tab_dem;
1238 DESC tab_dem;
1239 
1240 ##文本類型
1241 #較短文本 char varchar (二進制binary varbinary1242 #較長文本 text blob(二進制)
1243 
1244 #特點
1245 /*
1246     寫法        M                特點        
1247 char    char(M)        最大字符數,可以省略,默認1    固定長度    
1248 varchar varchar(M)    最大字符數,不接省略        可變長度
1249 
1250             空間的耗費    效率
1251             比較耗費    較高
1252             比較節省    較低
1253 
1254 
1255 */
1256 #枚舉 enum
1257 CREATE TABLE tab_enum(
1258     e1 ENUM('a','b','c')
1259 );
1260 DESC tab_enum;
1261 INSERT INTO tab_enum VALUES
1262     ('a'),    #不區分大小寫
1263     ('c');  #不在列舉范圍,則插入值為空
1264 SELECT * FROM tab_enum;
1265 
1266 #集合 set 
1267 CREATE TABLE tab_set(
1268     s1 SET('a','b','c')
1269 );
1270 INSERT INTO tab_set VALUES
1271     ('a'),   #不區分大小寫
1272     ('a,c'); #可加兩個
1273 SELECT * FROM tab_set;
1274 
1275 ##日期類型
1276 /*分類:
1277 date日期
1278 time時間
1279 year年
1280         字節    范圍        時區
1281 datetime    8    1000-9999    不受時區影響
1282 timestamp    4    1970-2038    受影響
1283 
1284 */
1285 #datetime和timestamp(受時區,語法模式、版本影響,但更能反映當前時區的真實時間)
1286 CREATE TABLE tab_date(
1287     d1 DATETIME,
1288     d2 TIMESTAMP
1289 );
1290 INSERT INTO tab_date 
1291 VALUES    (NOW(),NOW());
1292 SELECT * FROM tab_date;
1293 #system時間為+8:00東八區
1294 SHOW VARIABLES LIKE 'time_zone';
1295 
1296 SET time_zone = '+9:00';
1297 SELECT DATE(NOW());
1298 ##常見約束
1299 /*
1300 分類:六大約束
1301     1,not null 保證該字段不為空
1302         如ID、姓名
1303     2,default默認 保證該字段有默認值
1304 1305     3,primary key主鍵 用於保證該字段有唯一性,且非空
1306         比如學號、編號
1307     4,unique唯一鍵 用於保證該字段具有唯一性,可以為空
1308         比如座位號
1309     5,check【mysql不支持】 
1310         比如0<年齡<99
1311     6,foreign key外鍵 用於限制兩表關聯列在主表中該列的值
1312         比如:employees.department_id in departments.department_id
1313         
1314 在創建表和修改表時,添加約束
1315 
1316 分類:    列級約束 :(除外鍵)六大常見約束都支持,但是check無效果、foreign key無效果
1317     表級約束 :(三鍵)除了非空、默認都支持    
1318     
1319 主鍵和唯一鍵的PK
1320         唯一性    是否允許為空    一個表有幾個    是否允許組合
1321     主鍵    √    ×        最多一個    √,但是不推薦
1322       唯一鍵    √    √(只能有一個空)    可以有多個    √,但是不推薦
1323       
1324   組合的意思是,讓ID和name的組合如:ID_name唯一且不為空    
1325   
1326   外鍵:1,要求在從表(stinf)設置外鍵
1327     2,從表(stinf)的外鍵列要求和主表(major)的類型一致或兼容
1328     3,主表(major)的關聯列必須是一個key (一般為主鍵)
1329     4,插入數據時,先插主表(major),后從表(stinf)
1330     5,刪除數據時,先刪從表(stinf),后主表(major)***級聯刪除和級聯置空
1331 
1332 */
1333 
1334 #列級約束
1335 
1336 CREATE DATABASE constrain;
1337 CREATE TABLE stinf(
1338     id INT PRIMARY KEY, #主鍵
1339     stuname VARCHAR(20) NOT NULL UNIQUE,#非空 & 唯一鍵
1340     gender CHAR(1) CHECK(gender='' OR  gender=''),#核查
1341     seat INT UNIQUE,#唯一鍵
1342     age INT DEFAULT 18,#默認
1343     majorid INT REFERENCES major(id)#外鍵
1344 );
1345 
1346 CREATE TABLE major(
1347     id INT PRIMARY KEY,
1348     mname VARCHAR(20) 
1349 );
1350 DESC stinf;
1351 SHOW INDEX FROM stinf; #查看主鍵、外鍵、唯一鍵
1352 
1353 #表級約束
1354 DROP TABLE IF EXISTS stinf;
1355 CREATE TABLE IF NOT EXISTS stinf(
1356     id INT,
1357     stuname VARCHAR(20),
1358     gender CHAR(1),
1359     seat INT,
1360     age INT,
1361     majorid INT,
1362     CONSTRAINT pk PRIMARY KEY(id),#主鍵
1363     CONSTRAINT uq UNIQUE(seat),#唯一鍵
1364     CONSTRAINT ck CHECK(gender IN ('','')),#核查
1365     CONSTRAINT fk_stinf_major FOREIGN KEY(majorID) 
1366                     REFERENCES major(id)#外鍵
1367     #constriant用來給鍵起名字
1368 );
1369 SHOW INDEX FROM stinf; #查看主鍵、外鍵、唯一鍵
1370 DROP TABLE IF EXISTS stinf;
1371 
1372 CREATE TABLE IF NOT EXISTS stinf(
1373     id INT,
1374     stuname VARCHAR(20),
1375     gender CHAR(1),
1376     seat INT,
1377     age INT,
1378     majorid INT,
1379      PRIMARY KEY(id),#主鍵
1380      UNIQUE(seat),#唯一鍵
1381      CHECK(gender IN ('','')),#核查
1382      FOREIGN KEY(majorID) REFERENCES major(id)#外鍵
1383     
1384 );
1385 SHOW INDEX FROM stinf; #查看主鍵、外鍵、唯一鍵
1386 #通用
1387 DROP TABLE IF EXISTS stinf;
1388 
1389 CREATE TABLE IF NOT EXISTS stinf(
1390     id INT PRIMARY KEY, #主鍵
1391     stuname VARCHAR(20) NOT NULL,#非空
1392     gender CHAR(1) CHECK(gender='' OR  gender=''),#核查
1393     seat INT UNIQUE,#唯一鍵
1394     age INT DEFAULT 18,#默認
1395     majorid INT,
1396     CONSTRAINT fk_stinf_major FOREIGN KEY(majorid) 
1397                 REFERENCES major(id)#外鍵
1398 );
1399 SHOW INDEX FROM stinf; #查看主鍵、外鍵、唯一鍵
1400 
1401 ##修改約束
1402 /*
1403 
1404 
1405 */
1406 DROP TABLE IF EXISTS stinf;
1407 
1408 CREATE TABLE IF NOT EXISTS stinf(
1409     id INT,
1410     stuname VARCHAR(20),
1411     gender CHAR(1) NOT NULL,
1412     seat INT,
1413     age INT,
1414     majorid INT
1415 );
1416 #列級約束修改
1417 ALTER TABLE stinf MODIFY COLUMN id INT PRIMARY KEY ;
1418 ALTER TABLE stinf MODIFY COLUMN age INT DEFAULT 18;
1419 DESC stinf;
1420 SHOW INDEX FROM stinf;
1421 #表級約束修改
1422 #主鍵也可以這樣去添加,但是不能添加constraint 限制名    
1423 ALTER TABLE stinf ADD CONSTRAINT u_seat UNIQUE(seat);
1424 ALTER TABLE stinf
1425   ADD CONSTRAINT fk_major_stinf FOREIGN KEY (majorid) REFERENCES major (id);
1426 DESC stinf;
1427 SHOW INDEX FROM stinf;
1428 
1429 ##修改表時刪除約束
1430 #1刪非空約束
1431 ALTER TABLE stinf MODIFY COLUMN gender CHAR(1);
1432 #2刪默認約束
1433 ALTER TABLE stinf MODIFY COLUMN age INT;
1434 #3刪主鍵
1435 ALTER TABLE stinf DROP PRIMARY KEY;
1436 #4刪唯一鍵
1437 ALTER TABLE stinf DROP INDEX seat;
1438 #5刪除外鍵
1439 ALTER TABLE stinf DROP FOREIGN KEY fk_major_stinf;
1440 SHOW INDEX FROM FROM stinf;
1441 
1442 ##級聯刪除:關於從表有外鍵時,刪除數據biubiu先刪主表,級聯可以先刪從表
1443 #級聯刪除
1444 ALTER TABLE student ADD CONSTRAINT fk_stu_maj 
1445     FOREIGN KEY(majorid) REFERENCES major(majorid) ON DELETE CASCADE;
1446 DELETE FROM major WHERE majorid=3;
1447 #級聯置空
1448 ALTER TABLE student DROP FOREIGN KEY fk_stu_maj;
1449 ##無法設置成功!!??
1450 ALTER TABLE student ADD CONSTRAINT fk_stu_maj 
1451     FOREIGN KEY(majorid) REFERENCES major(majorid) ON DELETE SET NULL;
1452 DELETE FROM major WHERE majorid=2;
1453 
1454 
1455 
1456 #標識列
1457 /*
1458 1 必須搭配  鍵(只限mysql)
1459 2 至多一個標識列
1460 3 標識列類型只能是數值
1461 4 步長設置通過SET auto_increment_increment = 2;
1462 5 標識列初始值可通過手動添加
1463 
1464 */
1465 DROP TABLE tab_auto;
1466 CREATE TABLE tab_auto(
1467     id INT PRIMARY KEY AUTO_INCREMENT,
1468     NAME VARCHAR(20) 
1469 );
1470 
1471 INSERT INTO tab_auto(id,NAME) VALUES(NULL,'john');
1472 INSERT INTO tab_auto(NAME) VALUES('john');
1473 INSERT INTO tab_auto VALUES(NULL,'john');
1474 INSERT INTO tab_auto VALUES(5,'lily'); #相當於設置了起始值
1475 INSERT INTO tab_auto VALUES(NULL,'john');
1476 
1477 TRUNCATE TABLE tab_auto;
1478 
1479 SELECT * FROM tab_auto;
1480 SHOW VARIABLES LIKE '%auto_increment%';
1481 SET auto_increment_increment = 2; #設置步長
1482 SET auto_increment_offset = 3; #mysql無作用
1483 #修改表時 添加刪標識列
1484 DROP TABLE tab_auto;
1485 CREATE TABLE tab_auto(
1486     id INT,
1487     NAME VARCHAR(20) 
1488 );
1489 ALTER TABLE tab_auto MODIFY id INT PRIMARY KEY AUTO_INCREMENT;
1490 ALTER TABLE tab_auto MODIFY id INT;
1491 
1492 ##事務
1493 /*分類:
1494     隱式事務:insert update delete
1495     顯式事務:set autocommit=0;
1496           strat transaction;
1497           select insert update delete;
1498           ***** 無create alter drop ******
1499           commit;    /    rollback;
1500 ACID
1501 1 原子性atomicity:一個事務不可再分割,要么都執行要么都不執行
1502 2 一致性consistency:一個事務執行會使數據從一個狀態切換到另一個狀態
1503 3 隔離性isolation:一個事務的執行不受其他事務的影響
1504 3 持久性durability:一個事務的提交會永久改變數據庫的數據
1505 
1506 三種數據問題:
1507     1臟讀:T1 T2 ,T2更新沒提交,T1讀取,讀取了臨時無效的信息,若T2回滾
1508     2不可重復度:T1讀取,T2更新,T1再讀取則信息變化
1509     3幻讀:T1讀取,T2更新某些行,T1再讀取,出現多行數據
1510 
1511 事務隔離級別:
1512             臟讀    不可重復讀    幻讀
1513 read uncommitted    √    √        √
1514 read committed        ×    √        √
1515 repeatable read        ×    ×        √
1516 serializable        ×    ×        ×
1517 
1518 mysql默認repeatable read
1519 Oracle默認read committed
1520 */
1521 #查看當前隔離級別
1522 SELECT @@tx_isolation;
1523 #設置隔離級別
1524 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
1525 SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
1526 
1527 SELECT @@tx_isolation;
1528 #事務中delete 和truncate 的區別
1529 
1530 SET autocommit=0;
1531 START TRANSACTION;
1532 DELETE FROM stuinfo;
1533 ROLLBACK;
1534 SELECT * FROM stuinfo;
1535 
1536 SET autocommit=0;
1537 START TRANSACTION;
1538 TRUNCATE stuinfo;
1539 ROLLBACK;
1540 SELECT * FROM stuinfo;
1541 COMMIT;
1542 
1543 #演示savepoint的使用
1544 INSERT INTO stuinfo VALUES(1,1,'s','yb');
1545 INSERT INTO stuinfo VALUES(2,2,'x','lz');
1546 SELECT * FROM stuinfo;
1547 COMMIT;
1548 
1549 SET autocommit=0;
1550 START TRANSACTION;
1551 DELETE FROM stuinfo WHERE id=1;
1552 SAVEPOINT a;
1553 DELETE FROM stuinfo WHERE id=2;
1554 ROLLBACK TO a;
1555 SELECT * FROM stuinfo;
1556 COMMIT;
1557 ##視圖
1558 /*
1559 含義:虛擬表,和普通表一樣
1560 mysql5.1出現的新特性,是通過表動態生成的數據
1561 
1562 比如:一個班里面 分化出一個舞蹈班,有需要時,舞蹈班就可以直接出現
1563 
1564 視圖和表的PK:
1565 1 創建語法不通 view  table
1566 2 視圖只占sql語句的字節,表占空間
1567 3 視圖一般不能增刪改
1568 
1569 
1570 */
1571 
1572 #查詢各部門平均工資級別
1573 USE myemployees;
1574 CREATE VIEW myv1
1575 AS
1576 SELECT AVG(salary) ag,department_id
1577 FROM employees
1578 GROUP BY department_id;
1579 
1580 SELECT v.ag ,j.`grade_level` FROM myv1 v
1581 JOIN job_grades j
1582 ON v.`ag` BETWEEN j.`lowest_sal` AND j.`highest_sal`;
1583 
1584 #查詢平均工資最低的部門信息
1585 SELECT d.department_name, m.department_id, m.ag 
1586 FROM myv1 m JOIN departments d
1587 ON d.`department_id`=m.`department_id`;
1588 
1589 #視圖的修改
1590 CREATE OR REPLACE VIEW myv1
1591 AS
1592 SELECT AVG(salary) AS average_salary,department_id
1593 FROM employees
1594 GROUP BY department_id;
1595 
1596 ALTER VIEW myv1 
1597 AS 
1598 SELECT AVG(salary) ag,department_id
1599 FROM employees
1600 GROUP BY department_id;
1601 
1602 #視圖的刪除
1603 CREATE  VIEW myv2
1604 AS
1605 SELECT department_id
1606 FROM employees
1607 GROUP BY department_id;
1608 
1609 DROP VIEW myv1, myv2;
1610 #視圖的查看
1611 DESC myv2;
1612 SHOW CREATE VIEW myv2;
1613 SHOW CREATE VIEW myv2\G; #在 DOS中使用
1614 
1615 #通過視圖增刪改原始表
1616 /*
1617 在視圖包含以下情況不能insert update delete包含以下sql語句:
1618 1 分組函數、instinct、group by 、having 、union、union all
1619 2 常量視圖
1620 3 select包含子查詢
1621 4 join
1622 5 from一個不能更新的視圖
1623 6 where子句的子查詢引用了from子句的表
1624 
1625 */
1626 ##變量
1627 /*
1628 系統變量:全局變量、會話變量
1629 自定義變量:用戶變量、局部變量
1630 */
1631 
1632 #一、系統變量、會話變量(一個查詢編輯器一個會話)
1633 /*
1634 變量由系統提供,不是用戶定義,屬於服務器層面
1635 
1636 注意:如果是全局變量,則需要加global,如果是會話級別,則需要加session,默認session
1637 
1638 使用語法:
1639 1,查看所有變量:
1640 show global|session variables;
1641 
1642 2,查看滿足條件的部分系統變量
1643 show global|session variable like '%char%';
1644 
1645 3,查看某個指定變量的值
1646 select @@global|session.變量名;
1647 select @@global.flush;
1648 
1649 4,為某個變量賦值(跨連接有效,不能跨重啟)
1650 set @@global|session 變量名=值;
1651 set   global|session 變量名=值;
1652 
1653 */
1654 #自定義變量
1655 /*
1656 聲明、賦值、使用(查看、比較、運算)
1657 
1658         作用域        定義和使用的位置         語法
1659 用戶變量    當前會話    會話的任何地方            必須加@,不限制類型
1660 局部變量    begin end中    只能在begin end中的第一句話    不加@,限定類型
1661 */
1662 #1,用戶變量 :  作用域:當前會話
1663 
1664 #1 聲明並初始化
1665 SET @用戶變量名=值;
1666 SET @用戶變量名:=值;
1667 SELECT  @用戶變量名:=值;
1668 
1669 #2 賦值(更新用戶變量的值)
1670 #方式一
1671 SET @用戶變量名=值;
1672 SET @用戶變量名:=值;
1673 SELECT  @用戶變量名:=值;
1674 
1675 #方式二
1676 SELECT 字段 INTO @用戶變量名
1677 FROM 表名;
1678 
1679 #使用
1680 SELECT @用戶變量名;
1681 
1682 #案例
1683 SET @count:=1;
1684 SELECT COUNT(*) INTO @count FROM employees;
1685 SELECT @count;
1686 
1687 #2,局部變量
1688 /*
1689 作用域:只在定義它的begin 和 end 中有效
1690 
1691 */
1692 
1693 #聲明 ---------必須放在begin后面第一句----------------------
1694 DECLARE 變量名 類型;
1695 DECLARE 變量名 類型 【DEFAULT 值】;
1696 
1697 #賦值
1698     #方式一
1699     SET 用戶變量名=值;
1700     SET 用戶變量名:=值;
1701     SELECT  @用戶變量名:=值;
1702 
1703     #方式二
1704     SELECT 字段 INTO 用戶變量名 FROM 表名;
1705     
1706 #使用
1707 SELECT 局部變量;
1708 
1709 ##存儲過程和函數
1710 /*
1711 好處:提高代碼的重用性、簡化操作
1712 */
1713 
1714 #存儲過程
1715 /*
1716 定義:一組預先編譯好的SQL語句集合
1717 
1718 
1719 一、創建語法
1720 create procedure 存儲過程名(參數列表)
1721 begin 
1722     存儲過程體(一組合法的SQL語句)
1723 end
1724 
1725 注意:
1726 1,參數列表包含三部分:
1727 參數模式  參數名  參數類型 
1728 in         id       int
1729 
1730 參數模式:
1731 in :改參數可以作為輸入,也就是該參數需要調用方 傳入值
1732 out  : 該參數可以作為輸出,也就是該參數可以作為返回值
1733 inout : 該參數既可以作為輸出,又可以作為輸入,即既需要傳入值,也能返回值
1734 
1735 2,如果存儲過程體只有一句話, begin 和 end 可以省略
1736  存儲過程體每條sql均需要結尾加;
1737  存儲過程的結尾可以使用 delimiter 重新設置
1738  *********delimiter在新連接中要去dos重新設置*************
1739  語法: delimiter 結束標記
1740  案例: delimiter $
1741  
1742  二、調用語法
1743  Call 存儲過程名(實參列表);
1744  */
1745  ##空參列表
1746  #案例:給girls.admin添加5條數據
1747  
1748 DELIMITER $
1749 CREATE PROCEDURE myp1()
1750 BEGIN 
1751     INSERT INTO admin(username,PASSWORD)
1752     VALUES('yb1',123),('yb2',123),('yb3',123),('yb4',123),('yb5',23);
1753 END $
1754 
1755 CALL myp1()$
1756 SELECT * FROM admin$
1757 
1758 ##in列表
1759 #案例1:創建存儲過程實現:根據女神名查詢對應的男生信息
1760 
1761 CREATE PROCEDURE myp2(IN beautyname VARCHAR(20))
1762 BEGIN
1763     SELECT bo.*
1764     FROM boys bo 
1765     LEFT JOIN beauty b ON b.boyfriend_id=bo.id
1766     WHERE b.name=beautyname ;
1767 END $
1768 
1769 CALL myp2('熱巴')$
1770 
1771 #出現 Incorrect string value: '\xC8\xC8\xB0\xCD' for column,表示字符集不匹配
1772 SET NAMES gbk$ #(sqlyog默認utf8, dos默認gbk)
1773 
1774 #案例2:創建存儲過程實現,用戶是否登錄成功
1775 
1776 CREATE PROCEDURE myp3(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
1777 BEGIN
1778     DECLARE result INT DEFAULT 0; #聲明
1779     SELECT COUNT(*) INTO result   #賦值
1780     FROM admin ad
1781     WHERE ad.username=username AND ad.password = PASSWORD;
1782     
1783     SELECT IF(result=0,'失敗','成功') "結果";  #使用
1784 
1785 END $
1786 
1787 ##out列表
1788 #案例:創建存儲過程實現:根據女神名返回對應的男生名
1789 CREATE PROCEDURE myp4(IN beautyname VARCHAR(20),OUT boyname VARCHAR(20))
1790 BEGIN
1791     SELECT bo.boyname INTO boyname
1792     FROM boys bo  JOIN beauty b
1793     ON bo.id = b.boyfriend_id
1794     WHERE b.name=beautyname;
1795 END $
1796 
1797 CALL myp4('柳岩',@bname)$
1798 SELECT @bname$
1799 
1800 #案例:創建存儲過程實現:根據女神名返回對應的男生名和魅力值
1801 CREATE PROCEDURE myp5(IN beautyname VARCHAR(20),OUT boyname VARCHAR(20),
1802             OUT userCP VARCHAR(20))
1803 BEGIN
1804     SELECT bo.boyname ,bo.usercp INTO boyname ,usercp  #賦值
1805     FROM boys bo  JOIN beauty b
1806     ON bo.id = b.boyfriend_id
1807     WHERE b.name=beautyname;
1808 END $
1809 /*
1810 set @name='a'$
1811 set @charm='b'$                           省略了聲明
1812 */
1813 CALL myp5('柳岩',@name,@charm)$                   #相當於省去了聲明
1814 SELECT @name,@charm$                       #調用
1815 
1816 ##inout列表
1817 #案例:返回a,b值的二倍
1818 CREATE PROCEDURE myp6(INOUT a INT,INOUT b INT)
1819 BEGIN
1820     SET a=a*2;  #賦值
1821     SET b=b*2;
1822 END $
1823 SET @aa=1$          #聲明
1824 SET @bb=2$
1825 CALL myp6(@aa,@bb)$
1826 SELECT @aa,@bb$     #調用
1827 
1828 ##課后案例
1829 #存儲過程實現傳入用戶名密碼,插入admin
1830 CREATE PROCEDURE p_insert(IN username VARCHAR(20), IN PASSWORD VARCHAR(20))
1831 BEGIN
1832     INSERT INTO admin(username,PASSWORD) VALUES(username,PASSWORD);
1833 END $
1834 CALL p_insert('yb','122103')$
1835 SELECT * FROM admin$
1836 #傳入女神標號,返回姓名電話
1837 CREATE PROCEDURE p_inf(IN id INT,OUT NAME VARCHAR(50), OUT phone VARCHAR(11))
1838 BEGIN
1839     SELECT b.name,b.phone INTO NAME,phone  #注意要賦值
1840     FROM beauty b
1841     WHERE b.id=id;
1842 END $
1843 CALL p_inf(2,@bname,@bphone)$   #省去聲明
1844 SELECT @bname ,@bphone$        #調用
1845 
1846 #傳入兩個女生生日日期,然后返回大小
1847 CREATE PROCEDURE myp7(IN date1 DATE,IN date2 DATE,OUT result INT)
1848 BEGIN 
1849     SELECT DATEDIFF(date1,date2) INTO result;
1850 END $
1851 CALL myp7('1994-09-10',DATE(NOW()),@result)$
1852 SELECT @result$
1853 
1854 #傳入一個日期類型的日期,輸出為******日格式
1855 CREATE PROCEDURE myp8(IN nor_date DATETIME,OUT for_date VARCHAR(20))
1856 BEGIN
1857     SELECT DATE_FORMAT(nor_date,'%Y年%m月%d日') INTO for_date;
1858 END $
1859 CALL myp8(DATE(NOW()),@fd)$
1860 SELECT @fd$
1861 
1862 #輸入 小昭,返回 小昭 and 張無忌
1863 CREATE PROCEDURE myp9(IN beautyname VARCHAR(20),OUT information VARCHAR(50))
1864 BEGIN 
1865     SELECT CONCAT(beautyname,'and',IFNULL(bo.boyname,'null'))  INTO information
1866     FROM boys bo ,beauty b
1867     WHERE b.boyfriend_id=bo.id
1868     AND b.name=beautyname;
1869 END $
1870 CALL myp9('柳岩',@inf)$
1871 SELECT @inf$
1872 
1873 #傳入條目數和起始索引,查詢beauty表記錄,
1874 CREATE PROCEDURE myp10(IN offsett INT,IN increment INT)
1875 BEGIN 
1876     SELECT * FROM beauty
1877     LIMIT offsett,increment;
1878 END$
1879 
1880 CALL myp10(3,5)$#從第3條記錄開始,顯示5條
1881 
1882 
1883 #刪除儲存過程
1884 DROP PROCEDURE myp7; #只能一個一個的刪
1885 #查看儲存過程
1886 SHOW CREATE PROCEDURE myp6\G;#在dos執行 
1887 
1888 
1889 ##函數
1890 /*
1891 定義:一組預先編譯好的SQL語句集合
1892 
1893 區別:存儲過程:可以有0個返回,也可以有多個返回,適合做批量插入、更新
1894       函數:有且僅有1個返回值,適合做處理數據后返回一個結果
1895 */
1896 /*
1897 一、創建語法:
1898 create function 函數名(參數列表) returns 返回類型
1899 begin
1900     函數體;
1901     return ;
1902 end $
1903 
1904 注意:1參數列表 包含  (無參數模式) 參數名  參數類型
1905       2函數體肯定有return語句,如果沒有會報錯
1906       3函數體中僅有一句話,則可以省略begin和end
1907       4使用delimiter語句設置結束標記
1908 
1909 二、調用語法
1910 
1911 select 函數名(參數列表)
1912 */
1913 
1914 #--------------------------函數案例演示------------------------
1915 #1 無參有返回  案例 :返回公司的員工個數
1916 USE myemployees;
1917 CREATE FUNCTION myf1() RETURNS INT
1918 BEGIN
1919     DECLARE c INT ; #聲明
1920     SELECT COUNT(*) INTO c #賦值
1921     FROM employees;
1922     RETURN c; #調用
1923 END $
1924 SELECT myf1()$
1925 
1926 #2有參有返回   
1927 #案例:根據員工名返回工資
1928 CREATE FUNCTION myf2( ename VARCHAR(20)) RETURNS INT
1929 BEGIN 
1930     DECLARE s INT;
1931     SELECT salary INTO s
1932     FROM employees e
1933     WHERE e.last_name=ename;
1934     RETURN s;
1935 END $
1936 SELECT myf2('chen')$
1937 
1938 #根據部門名返回該部門平均工資
1939 CREATE FUNCTION myf3( dname VARCHAR(20)) RETURNS INT
1940 BEGIN 
1941     SET @s=0;
1942     SELECT AVG(e.salary) INTO @s
1943     FROM employees e JOIN departments d
1944     ON e.department_id = d.department_id
1945     WHERE d.department_name = dname;
1946     RETURN @s; 
1947 END $
1948 SELECT myf3('IT')$
1949 
1950 #案例 :傳入兩個float ,返回二者之和
1951 CREATE FUNCTION mysum(a FLOAT ,b FLOAT) RETURNS FLOAT
1952 BEGIN
1953     DECLARE absum FLOAT;
1954     SELECT a+b INTO absum;
1955     RETURN absum;
1956 END $
1957 #查看、刪除函數
1958 SHOW CREATE FUNCTION myf3\G; #dos
1959 DROP FUNCTION myf3;
1960 
1961 ##流程控制 ——----------------------------------------------
1962 /*
1963 順序、分支、循環
1964 */
1965 #一、 分支
1966 #if(條件,ture,false)
1967 #case
1968 /*
1969 1、等值判斷
1970     
1971     case 字段  
1972     when 值1  then 返回值1
1973     when 值2  then 返回值2
1974     ...
1975     else 返回值3
1976     end 
1977 
1978 2、 條件判斷
1979     case
1980     when 條件1  then  返回值1
1981     when 條件2  then  返回值2
1982     ...
1983     else 返回值3
1984     end
1985 -----可以和select 、update 搭配,case返回的是 返回值1、返回值2...,位置不限------------
1986 
1987 
1988 3、case可以單獨使用,只能放在begin end中
1989     case 字段  
1990     when 判斷條件1  then 語句1;
1991     when 判斷條件2  then 語句2;
1992     ...
1993     else 語句3;
1994     end case;
1995 */
1996 
1997 #案例
1998 CREATE PROCEDURE grade_level(IN grade INT)
1999 BEGIN
2000     CASE 
2001     WHEN  90< grade AND grade <= 100 THEN SELECT 'A' ;
2002     WHEN  80< grade AND grade <=90   THEN SELECT 'B' ;
2003     WHEN  70< grade AND grade <=80   THEN SELECT 'C' ;
2004     ELSE  SELECT 'D' ;
2005     END CASE;
2006 END $
2007 CALL grade_level(98)$
2008 
2009 #if 多重分支,只能用在begin end中
2010 /*
2011    if      條件1  then 語句1;
2012    elseif  條件2  then 語句2;
2013    ...
2014    ELSE 語句n;
2015    end if;
2016 */
2017 #傳入成績,顯示等級
2018 CREATE FUNCTION grade_level( grade INT) RETURNS CHAR
2019 BEGIN 
2020     IF grade>90 AND grade <= 100 THEN RETURN 'A';
2021     ELSEIF grade >80 THEN RETURN 'B';
2022     ELSE RETURN 'c';
2023     END IF;
2024 END$
2025 
2026 ##循環結構
2027 /*
2028 分類:while 、 loop 、 repeat
2029 
2030 循環控制 :
2031 
2032 iterate ,結束本次循環,繼續進行下一次
2033 leave  ,跳出,結束當前循環
2034 出現循環控制時,必須給循環結構添加名稱
2035 */
2036 
2037 #1while
2038 /*
2039 【標簽】while 循環條件 do 
2040     循環體
2041 end while 【標簽】;
2042 */
2043 
2044 #2,loop
2045 /*
2046 【標簽】loop 
2047     循環體
2048 end loop 【標簽】;
2049 
2050 可以模擬簡單的死循環
2051 
2052 */
2053 
2054 #3,repeat 
2055 /*
2056 【標簽】repreat 
2057     循環體
2058 until 結束循環體的條件
2059 end repeat 【標簽】;
2060 */
2061 
2062 /*
2063 loop一般實現簡單死循環
2064 while先判斷后執行
2065 repeat先執行后判斷,無條件至少執行一次
2066 */
2067 #案例,根據次數插入到admin表中多條記錄
2068 CREATE PROCEDURE p_while1(IN insertcount INT)
2069 BEGIN 
2070     DECLARE i INT DEFAULT 1;
2071     WHILE i<insertcount DO 
2072         INSERT INTO admin(`username`,`password`) 
2073             VALUES(CONCAT('rose',i),'123');
2074         SET i=i+1;
2075     END WHILE ;
2076 END$
2077 CALL p_while1(50)$
2078 
2079 #案例,根據次數插入到admin表中多條記錄,到20次就停止
2080 CREATE PROCEDURE p_while2(IN insertcount INT)
2081 BEGIN
2082     SET @i=1;
2083     a:WHILE @i<insertcount DO 
2084         INSERT INTO admin(`username`,`password`)
2085             VALUES(CONCAT('xiaohu',@i),'0000');
2086         IF @i>=20  THEN LEAVE a;
2087         END IF ;
2088         SET @i=@i+1;
2089     END WHILE a;
2090 END$
2091 #案例,根據次數插入到admin表中多條記錄,結尾為偶數
2092 
2093 CREATE PROCEDURE p_while3(IN insertcount INT)
2094 BEGIN
2095     SET @i=0;
2096     a:WHILE @i<insertcount DO 
2097         INSERT INTO admin(`username`,`password`)
2098             VALUES(CONCAT('xiaohu',@i),'0000');
2099         SET @i=@i+2;
2100     END WHILE a;
2101 END$
2102 
2103 CREATE PROCEDURE p_while4(IN insertcount INT)
2104 BEGIN 
2105     SET @i=1;
2106     a :WHILE @i<insertcount DO 
2107         SET @i=@i+1;
2108         IF MOD(@i,2) !=0 THEN  ITERATE a;
2109         END IF;
2110         INSERT INTO admin(`username`,`password`) 
2111             VALUES(CONCAT('ts',@i),'6666');
2112     END WHILE a ;
2113 END $
2114 
2115 ####高級sql
2116 /*GA generally available;
2117 
2118 ##字符集
2119 delimiter ;
2120 show variables like '%char%';
2121 
2122 #插件式的存儲引擎,將查詢處理和其他的系統任務以及數據的存儲提取相分離
2123 
2124 mysql 分四層
2125     1連接層:與其他語言的鏈接,如Perl、Python
2126     2服務層:mysql查詢,內部優化
2127     3引擎層:可拔插的引擎,innoDB、myISAM
2128     4存儲層:硬件
2129 
2130 #查看引擎
2131 show engines;
2132 show variables like '%engine%';
2133 
2134 #sql性能下降的原因
2135     1查詢語句寫的爛
2136     2索引失效(單值、復合)
2137     3關聯查詢join太多
2138     4服務器調優及各個參數設置(緩沖、線程數)
2139 
2140 
2141 */    
2142 ##索引 :是幫助提高mysql高效獲取數據的【【 數據結構】】  
2143  /*
2144 *********排好序的快速查找數據結構*************
2145 
2146 數據本身之外,數據庫還維護着一個滿足特定查找算法的【數據結構】
2147 這些數據結構以某種方式指向數據,這樣就可以在這些數據的基礎上實現
2148 高級查找算法,這種數據結構就是索引。
2149 
2150 索引往往以索引文件的形式存儲在磁盤上
2151 
2152 索引往往指的是B數(多路搜索樹)結構組織的索引
2153 
2154 聚集索引、全文索引、復合索引、前綴索引、唯一索引默認都是使用B+樹索引,統稱索引。
2155 
2156 出了B+樹類型,還有哈希索引(hash index)
2157 
2158 索引的優劣
2159 優勢:    提高數據檢索的效率,降低數據庫IO的成本(input and output)
2160     降低數據排序成本,降低了CPU的消耗
2161 劣勢:    提高查詢速度的同時,降低了更新表的速度(增刪改時,索引也會發生變化)
2162     數據量較大,需要花時間研究建立最優秀的索引
2163     
2164 索引分類:
2165 單值索引:一個索引只包含單個列,一個表可以有多個單列索引(銀行查卡號,ID卡等)
2166       一個表最好不超5個單列索引
2167 唯一索引:索引列的值必須唯一,但允許有空值
2168 復合索引:一個索引包含多個列
2169 全文索引:
2170 
2171 
2172 ##索引的結構:類似於二叉樹一樣
2173 樹的寬度又數據量決定,查詢的速度由樹的高度決定。
2174 判斷次數(IO次數)==樹的高度
2175 
2176 ##什么情況適合建索引
2177 1主鍵自動建立唯一索引
2178 2頻繁作為查詢條件的字段
2179 3與其他表關聯字段,如外鍵 應該建立索引
2180 4頻繁更新的字段不適合建索引
2181 5where中用不到的字段不建索引
2182 6盡量組合索引
2183 7查詢中排序的字段(若排序的字段多個,復合索引按照排序中的多個字段順序建立)
2184 8統計或分組字段(group by和索引有關)
2185 ##什么情況不適合建索引
2186 1表字段太少(3百萬以下)
2187 2經常增刪改的表
2188 3數據列包含太多重復數據(國籍)
2189 
2190 
2191 ##性能查詢
2192 用法 :explain sql語句;
2193 作用 : 1表的讀取順序            id
2194     2數據讀取操作的操作類型        select_type
2195     3哪些索引可以使用
2196     4是哪索引被實際使用
2197     5表之間的引用
2198     6每張表有多少行被優化器查詢
2199     
2200     id、select_type、table、type、possible_key、key_len、ref、rows、extra
2201 
2202 id :id相同時,table從上往下執行;存在子查詢時,id不同,id值越大,越先執行。
2203     表子查詢的select_type值為derived;
2204 select_type:SIMPLE \ PRIMARY \ SUBQUERY \ DERIVED \ UNION \ UNION RESULT
2205     SIMPLE : 不包含子查詢和union
2206     PRIMARY:主查詢,最外層 ,最后執行
2207     SUBQUERY:子查詢
2208     DERIVED:表子查詢
2209     UNION:union后面的表的s_t為union
2210     UNION RESULT:從union表獲取結果的select
2211 table:    顯示這一張行數據是關於哪張表的
2212 type: All \ index \ range \ ref \ eq_ref \ const,system \ Null
2213     顯示查詢使用了何種類型,由好到壞依次為:
2214     system>const>eq_ref>ref>range>index>All****************
2215     -----------------------------------------------------------------
2216     system:系統表,只有一行數據,const的特例,忽視掉
2217     const:表示通過索引一次就找到了,用於比較primary和unique索引
2218         因為只匹配一行數據,如where查主鍵的一個值
2219     eq_ref:唯一性索引掃描,對於每一個索引鍵,表中只有一條記錄與之匹配
2220         explain select * from e ,d where e.id=d.id;
2221         #e.id的每個值在d.id中只出現一次
2222 ???ref:非唯一性索引掃描,返回匹配某個單獨值的所有行(符合條件的多行)
2223         explain select * from employees where job_id='AD_VP';
2224     range:只檢索給定范圍的行使用一個索引來選擇行,可以列顯示使用哪個索引
2225         between and >  <  in
2226         explain select * from employees where `employee_id` between 100 and 105;
2227     index:full index scan.與all的區別在於index只遍歷索引數
2228         explain select `employee_id` from employees;
2229     full:遍歷全表
2230     
2231 ********一般要求出現All以后的百萬級查詢,必須優化。一般到range,更好為ref
2232 
2233 possible_keys:顯示可能應用在這張表的索引,一個或者多個(但不一定被查詢實際使用)
2234 key:實際使用的索引 【查詢中若使用了覆蓋索引,則該索引僅出現在key列表中】
2235     【覆蓋索引:用c1、c2建索引,查詢為select c1,c2 from ..;】
2236 key_len:索引中使用的字節數,可通過該值計算  查詢中使用的索引的長度。在不損失精度
2237      的情況下,【長度越短越好】。該值為索引字段的最大可能長度,【並非實際使用長度】
2238 ???     即key_len是根據表計算而得,不是通過表內檢索出來的
2239 ref:顯示索引的哪一列被使用了,如果可能的話,【是一個常數】
2240 rows:根據 表統計信息 及索引選用情況,大致估算出找到所需記錄要讀取的行數,越小越好
2241 extract:包含不合適在其他列中顯示但十分重要的額外信息;
2242        #using filesort:沒有用索引進行排序,使用了一個外部索引【九死一生】
2243      假設假設索引為ind_t_a_c_b。
2244      select * from table t where t.a='*' order by t.c;則為using filesort
2245      select * from table t where t.a='*' order by t.b;則不為using filesort
2246      select * from table t where t.a='*' order by t.b,t.c;也不為using filesort
2247        #using temporary 使用了臨時表保存中間結果,MYsql對查詢結果排序時使用臨時表
2248         常見於order by 和 group by【十死無生】
2249        #using index 查詢中使用了覆蓋索引,【效率不錯】 
2250       同時出現了using where 表明索引被用來執行索引鍵值的查找(where 后面的列被用於建索引)
2251           沒出現using where表明索引中的列只用來select,沒進行where
2252        #using where 使用了where
2253        #using join buffer 使用了連接緩存,配置文件里的using buffer調大
2254        #impossible  where :where子句的值總是false,不能用來獲取任何元組
2255        #selec table optimized away:在沒有group by子句的情況下,基於索引優化min/max
2256        #distinct:優化distinct操作,在找到第一匹配的元組后即停止找同樣的動作
2257        
2258     
2259  */    
2260 EXPLAIN 
2261 SELECT id FROM(
2262 SELECT a.id FROM admin a
2263  UNION
2264  SELECT b.id FROM beauty b) c ;
2265  EXPLAIN
2266  SELECT a.id FROM admin a
2267  UNION
2268  SELECT b.id FROM beauty b;
2269  EXPLAIN SELECT * FROM admin ORDER BY PASSWORD;
2270  
2271 /*
2272 索引優化
2273 
2274 */
2275 ##案例1 單表索引優化
2276 #category為1,comments>1,views最多的article_id
2277 USE test;
2278 CREATE TABLE IF NOT EXISTS article(
2279     id INT(10)         UNSIGNED   NOT NULL    PRIMARY KEY    AUTO_INCREMENT,
2280     author_id INT(10)       UNSIGNED   NOT NULL,
2281     categoryid INT(10)     UNSIGNED   NOT NULL,
2282     views INT(10)          UNSIGNED   NOT NULL,
2283     comments INT(10)     UNSIGNED   NOT NULL,
2284     title  VARBINARY(255)            NOT NULL,
2285     content TEXT                NOT NULL 
2286 );
2287 
2288 INSERT INTO article(`author_id`,`categoryid`,`views`,`comments`,`title`,`content`) 
2289 VALUES
2290     (1,1,1,1,'1','1'),
2291     (2,2,2,2,'2','2'),
2292     (3,3,3,3,'3','3'),
2293     (4,4,4,4,'4','4');
2294 #情況一:無索引。!type為all,extra提示using filesort
2295 EXPLAIN  SELECT * FROM article WHERE categoryid =1 AND comments >1 
2296                    ORDER BY views DESC LIMIT 1;
2297 #情況二:按序建索引ccv.用到了索引,type為range,但是仍使用了文件內排序
2298 #原因為comments為范圍查詢,sql無法利用索引再對后面的views進行檢索。
2299 #即range類型查詢字段后面的索引無效
2300 CREATE INDEX inx_article_ccv ON article(categoryid,comments,views);
2301 EXPLAIN  SELECT * FROM article WHERE categoryid =1 AND comments >1 
2302                    ORDER BY views DESC LIMIT 1;
2303 #情況三:符合索引ca_v,type為ref,無文件內排序
2304 DROP INDEX inx_article_ccv ON article;
2305 CREATE INDEX inx_article_cv ON article(categoryid,views);
2306 EXPLAIN  SELECT * FROM article WHERE categoryid =1 AND comments >1 
2307                    ORDER BY views DESC LIMIT 1;
2308 ##案例2:兩表索引優化,左拼給右表加索引。
2309 USE myemployees;
2310 EXPLAIN SELECT * FROM employees e LEFT JOIN departments d 
2311 ON e.`department_id`=d.`department_id`;
2312 SHOW INDEX FROM `departments`;
2313 ##案例3:三表連接,用小表驅動大表,索引建立在left 或 right 后面的
2314 
2315 
2316 ##索引失效的原因:
2317 /*
2318 1全職匹配我的最愛
2319 
2320 2最佳左前綴法則********
2321     復合索引要遵守該法則,查詢應該從索引的最左前列開始,並且不跳過索引的列
2322     create index stu_1_2_3 on student(`studentno`,`studentname`,`loginpwd`);
2323     explain select * from student where studentno='S001' and studentname = '張三封' and `loginpwd`='8888';
2324     explain select * from student where studentno='S001' and loginpwd = '8888';
2325     explain select * from student where  loginpwd = '8888';##第一個字段不能丟失
2326 
2327 3不在索引列上做任何操作(計算、函數、(自動或者手動)的類型轉換),導致索引失效,全表掃描
2328 
2329 4儲存引擎不能使用索引中范圍條件右邊的列
2330 create index table.a_b_c on table(a,b,c)
2331 select * from table where a='' and b>X and c=''; #用不到c,但是
2332 select * from table where a='' and b like 'xx%' and c='';#能用到c
2333 
2334 5盡量使用覆蓋索引
2335 
2336 6mysql在使用非等於時(> < !=),無法使用索引,全表掃描
2337 
2338 7is null ,is not null 也無法使用索引
2339 
2340 8like以通配符開始,mysql無法使用索引,全表掃描,
2341     比如select * ...like '%xx'不推薦,而like 'xx%'則使用了索引,type為range
2342     若使用like '%xx%',需要使用覆蓋索引,
2343     即索引包含name時,select name ... like '%xx%';
2344     #select使用*或者非索引列字段也不行
2345 
2346     like 'kk%',雖然也是range,但是與>x 不同,
2347     like后面的等值條件還能用(顯示在len上), >x后面的則通通失效
2348 
2349 9字符串不加單引號,mysql無法使用索引,全表掃描
2350 
2351 10少用or,用or連接時索引會失效
2352 
2353 總結:
2354 
2355 列只和建索引的書寫順序有關:比如index 123,where 1='' and 2='' and 3=''
2356                     ===where 2='' and 3='' and 1=''
2357                 where 1='' and 2> and 3=
2358                 ==where 1='' and 3= and 2>
2359 where有order,group時  :where 1= and 3= order by 2
2360             ==where 1= and order by 2
2361             ≈where 1= order by 2,3
2362             但是 where 1= order by 3,2 (出現內排序,group出現temporary)
2363             但是where 1= and 2= order by 3,2無內排序,因為2定值了
2364             
2365             但是 where 1= and 2= order by 3
2366             !==where 1= order by 3(出現內排序using filesort)
2367 
2368 范圍查詢與order by結合
2369 index 12
2370 where 1> order by 1 優
2371 where 1> order by 1,2 優
2372 where 1= order by 2 優
2373 where 1> order by 2  內排序 (理解索引的內涵)
2374 where 1> order by 2,1 內排序 (排好序  的快速查找數據結構)
2375 order by a acs,b desc,內排序(order by 默認升序,同升同降無內排序)
2376 
2377 group by :同order by,但能用where就不用having
2378 
2379 提高order by 的方法:
2380 1 使用order by大忌使用select * ,應該只查詢需要的字段
2381   1.1當查詢的字段的大小總和<max_length_for_sort_data而且排序字段不是
2382     text/BLOB時,會使用改進算法--單路排序,否則使用對路排序,速度慢
2383   1.2單路多路都可能超過sort_buffer的容量(單路可能性更大),超出后會創建temporary,導致慢速
2384 
2385 2嘗試提高sort_buffer_size
2386 3嘗試提高max_length_for_sort_data,但是設置太高,容易超過sort_buffer_size
2387 
2388 
2389 
2390 口訣:
2391 全職匹配我最愛,最左點綴要遵守
2392 帶頭大哥不能死,中間兄弟不能斷
2393 索引列上少計算,范圍之后全失效
2394 like百分寫最右,覆蓋索引不寫星
2395 不等空值還有or,索引失效要少用
2396 var引號不可丟 ,SQL高級也不難
2397 */
2398 
2399 /*查詢截取分析
2400 
2401 1至少跑一天,觀察,看看生產的慢sql情況
2402 
2403 2開啟慢查詢日志,設置閾值:比如超過5秒的就是慢sql,並將其抓取出來
2404 
2405 3explain+慢sql分析
2406 
2407 4show profile
2408 
2409 5運維經理或DBA進行數據庫服務器的參數調優
2410 
2411 總結:     1慢查詢的開啟並捕獲
2412     2explain+慢sql分析
2413     3show profile查詢sql在MySQL服務器里面的執行細節和生命周期情況
2414     4sql數據服務器的參數調優
2415     
2416 理解小表驅動大表:
2417 
2418 A表數量>>B表
2419 當:【select * from a where a.id in (select id from b)】as WAYIN
2420     的執行順序為:
2421     1 select id from b
2422     2 select * from a where a.id=b.id
2423 此時的執行效率 in> exists
2424 
2425 A表數量<<B表
2426 當:【select * from a where exists (select 1 from b where a.id =b.id)】as WAYEX
2427     的執行順序為
2428     1 select * from a
2429     2 select id from a.id=b.id
2430 此時的執行效率 exists>in
2431 
2432 【exists語法為:
2433 exists子查詢中會忽略的select后面的查詢列表,所以可以寫1 ,'x'等常量值
2434 
2435     1 先查出主查詢的全部數據(小表),
2436     2 然后根據子查詢(大表)得到的布爾向量決定小表數據的去留】
2437 
2438 ***總結:小表驅動大表時,即A表<<B表,使用WAYEX。
2439 
2440 */
2441 
2442 /*慢查詢日志
2443 show variables like '%slow_query%';
2444 
2445 set global slow_query_log =1 ;#開啟慢查詢日志
2446     
2447 show variables like '%long_query_time%';#默認時間>10s為慢sql
2448 
2449 set global long_query_time=3;#設置閾值為3,查看該值需在新會話查看,非新查詢編輯器
2450 set global slow_query_log_file = 'slow.log';#設置慢查日志的文件位置
2451 
2452 select sleep(4); #若執行超過閾值的sql會在慢查詢中顯示
2453 
2454 show global status like '%show_queries%';#顯示當前系統中較慢的sql 條數
2455 
2456 */
2457 
2458 /*show profile
2459 show variables like '%profiling%';
2460 
2461 set profiling = on;
2462 
2463 show profiles;
2464 
2465 show profile cpu, block io for query 17;#一條sql內部執行的完整生命周期
2466 
2467 #如果status出現以下條目,降低速度
2468 1 coverting HEAP to MyISAM :查詢結果太大,內存不夠,往磁盤上搬了
2469 2 creating tpm table :創建臨時表,[拷貝數據到臨時表][用完再刪除]
2470 3 cooying to tmp table on disk :把內存中臨時表復制到磁盤。危險!! 
2471 4 locked
2472 */
2473 
2474 /*全局查詢日志:#不要在生產環境開啟該功能
2475 
2476 set global general_log ;
2477 set global log_output='TABLE';
2478 select * from  my.general_log;
2479 
2480 */
2481 
2482 /*數據庫鎖理論
2483 鎖是計算機協調多個進程或線程並發訪問某一資源的機制
2484 
2485 在數據庫鎖中,除傳統的計算資源(CPU,RAM,IO)的征用以外,數據也是一種供許多用戶共享的資源。
2486 如何保證數據並發訪問的一致性、有效性是所有數據庫必須解決的一個問題,鎖沖突也是影響數據庫
2487 並發訪問性能的一個重要因素。從這個角度來說,鎖對數據庫而言顯得尤其重要,也更加復雜。
2488 
2489 表鎖分類:
2490 #從對數據操作的類型:
2491         1讀鎖(共享鎖):針對同一份數據,多個讀操作可以同時進行,不會互相影響
2492             (會話1給表1上讀鎖,能讀表1,不能改表1,不能讀表2)
2493             (會話2         能讀表1,改表1阻塞,能讀表2)    
2494         2寫鎖(排它鎖):當前寫鎖沒有完成之前,它會阻斷其他寫鎖和讀鎖
2495             (會話1給表1上寫鎖,能讀表1, 能改表1, 不能讀表2)
2496             (會話2能讀表2,讀表1發生阻塞,改表1更慢)
2497         總結:讀鎖阻塞改表,寫鎖阻塞讀寫
2498 show open tables; #顯示沒上鎖的表
2499 lock table 表1 read, 表2 write; #表1讀鎖,表2寫鎖
2500 unlock tables; #解鎖所有的表
2501 show status like 'table%';
2502 
2503 行鎖:只在事務中,對行增刪改時,導致某一行鎖定,另一會話阻塞增刪改
2504 行鎖變表鎖:varchar類型的 值為數字的 字段,沒加引號,導致該列都被行鎖,變成表鎖
2505 
2506 set autocommit=0;
2507 select * from table where id=x for update;#強制鎖定一行
2508 commit;#直到會話1結束,會話2才能讀、寫
2509 */
2510 DELIMITER ;

 


免責聲明!

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



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