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) values (1,‘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 AS 名 FROM 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只能處理數字型,max 、min、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 varbinary) 1242 #較長文本 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 #1,while 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 ;