(MySQL学习) 35.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 ;
复制代码

 

Valar morghulis
标签: sql
<div id="blog_post_info">
0
0
<div class="clear"></div>
<div id="post_next_prev">

<a class="p_n_p_prefix" href="https://www.cnblogs.com/super-yb/p/12337767.html">« </a> 上一篇:    <a title="发布于 2020-02-20 22:16" href="https://www.cnblogs.com/super-yb/p/12337767.html">word--公式添加编号</a>
<br>
<a class="p_n_p_prefix" href="https://www.cnblogs.com/super-yb/p/12703672.html">» </a> 下一篇:    <a title="发布于 2020-04-15 10:37" href="https://www.cnblogs.com/super-yb/p/12703672.html">R语言--倾向性评分matchit</a>
posted on 2020-04-14 17:32  be·freedom  阅读(120)  评论(0编辑  收藏
<!--done-->
posted @ 2020-05-05 16:37  退後。  阅读(1406)  评论(0编辑  收藏  举报