MySQL数据库之SQL的各种操作/Html/Java和XML的关系

MySQL数据库之SQL的各种操作/Html/Java和XML的关系

今天内容:
   (1)数据库的概述
   (2)MySQL数据库的环境搭建
   (3)常用的数据类型
   (4)DDL数据定义语句
   (5)DML数据操纵语句

1.数据库的概述(常识)
1.1 数据库的概念
   数据库主要指存放数据的仓库。

1.2 主流的数据库
   目前主流的数据库有:OracleMySQL、SQL Server...

2.MySQL数据库的环境搭建(重点)
2.1 下载方式
   方式一:直接从官网下载   www.mysql.com
   方式二:从第三方网站下载 www.baidu.com

2.2 安装方式
   对于绿色版来说,则直接解压即可;
   对于安装版来说,则一路点击下一步即可;
   只需要设置 编码方式为utf-8 和 密码123456;   

注意:
   计算机 => 管理 => 服务 =>MySQL服务已启动,则表示数据安装和启动已完成!
  
2.3 卸载方式

2.4 登录方式
(1)远程登录服务器的方式:
   使用windows+r打开运行,输入mstsc命令使用远程桌面登录远程服务器再访问数据库
(2)本地登录数据库的方式:
   a.使用命令行工具进行登录,show databases查看当前已有数据库,exit退出
   b.使用图形化工具进行登录

2.5 数据库的操作
   create database practice; -- 表示创建名字为practice的数据库 
   show databases;           -- 表示查看当前数据库软件中所有数据库
   use practice;             -- 表示使用practice库,以后的增删改查都在该库进行
   select database();        -- 表示查看当前正在使用库名
   select user();            -- 表示查看当前正在登录的用户名
   show tables;              -- 表示查看当前库中的所有表信息
   drop database practice;   -- 表示删除名字为practice的数据库

3.常用的数据类型(重点、记住)Java语言中的常用数据类型有:byteshortintlongfloatdoublebooleancharStringDateCalendar...
   MySQL数据库中常用的数据类型有:
       整数数值类型:若没有特殊要求时,则一律使用int类型
       小数数值类型:若没有特征要求时,则一律使用double类型
                     若希望描述明确位数的小数时,则使用decimal类型
          如:decimal(5,2) 表示该类型描述5位数字,其中小数点后有2位,123.45等
       字符类型:    若描述具有固定长度的字符串时,则一律使用 char类型
                     若描述具有不固定长度的字符串时,则一律使用 varchar类型
       日期类型:    若描述年月日相关的数据时,则一律使用date类型
                     若描述时分秒相关的数据时,则一律使用time类型
                     若描述年月日时分秒相关的数据时,则一律使用datetime类型

4.DDL数据定义语句(重点、练熟)
4.1 基本概念
   DDL数据定义语句主要用于实现对数据库中表格的创建、修改以及删除操作。

4.2 表格的创建
(1)语法格式
   create table 表名 (
       字段名1 数据类型, 
       字段名2 数据类型,
       字段名3 数据类型,
       ... ...
   );  
如:
   -- 创建一个t_person表,字段有:姓名、年龄、性别
   create table t_person (
       name varchar(20),
       age  int(3),
       sex  char(2)
   ); 

练习:
   创建供应商表t_provider,包含以下几列:
     供应商代码:sNo 固定长2位字符
     供应商姓名:sName 可变长8位字符 
     供应商所在城市:city 可变长20位字符
   create table t_provider (
       sNo   char(2),
       sName varchar(8),
       city  varchar(20)
   );


   创建产品表t_product,包含以下几列:
     产品代码:pNo 固定长2位字符
     产品名:pName 可变长8位字符
     产品等级:kind 数值,2位
   create table t_product (
       pNo   char(2),
       pName varchar(8),
       kind  int(2)
   );    

   创建供应情况表t_supply,包含以下几列:
     供应商代码:sNo 固定长2位字符
     产品代码:pNo 固定长2位字符
     供应斤数:qty 数值,2位
   create table t_supply (
       sNo char(2),
       pNo char(2),
       qty decimal(4,2)
   );

4.3 表格的修改
(1)向表格中增加字段
   alter table 表名 add 字段名 数据类型;
如:
   -- 向t_person表中增加一个身高字段
   alter table t_person add height int(3);   

(2)实现表格中字段的改变
   alter table 表名 change 旧字段名 新字段名 数据类型;
如:
   -- 将t_person表中身高字段修改为名字为shenGao类型为3位数字,其中小数点后2位
   alter table t_person change height shenGao decimal(3,2);

(3)实现表格中字段的删除
   alter table 表名 drop 字段名;
如:
   -- 将t_person表中身高字段给删除掉
   alter table t_person drop height;

(4)实现表格名称的重命名
   alter table 表名 rename to 新的表名;
如:
   -- 将t_person表名修改为t_people
   alter table t_person rename to t_people;

练习:
   创建商品表t_commodity,包含以下几列:
     商品编号:pid 可变长8位字符
     商品标题:title 可变长20位字符
     商品单价:price 数值,8位数值,2位小数
     商品分类:gid 数值,2位整型
     库存数量:count 数值,6位整数
     保留字段1,
     保留字段2,
     保留字段3
   create table t_commodity (
       pid    varchar(8),
       title  varchar(20),
       price  decimal(8, 2),
       gid    int(2),
       count  int(6),
       baoliu1 varchar(50),
       baoliu2 varchar(50),
       baoliu3 varchar(50)
   );

4.4 表格的删除
(1)语法格式
   drop table 表名;
如:
   -- 删除t_person表
   drop table t_person;

作业:
   1.重点掌握常用的数据类型、表格的创建和修改以及删除。
   2.创建女孩表,字段有:姓名、年龄、电话号码、是否有男朋友
     实现将女孩表中是否有男朋友的字段删除
     实现向女孩表中增加字段性别
     实现将女孩表中性别字段修改为xingBie
     实现将女孩表的表名修改为男孩表
     实现男孩表的删除
1.简答题
  简述MySQL数据库中常用的数据类型并简要概述。

2.编程题
  创建t_car表,字段有:品牌、价格
  向t_car表中增加字段颜色
  将t_car表中颜色字段修改为color
  将t_car表中颜色字段删除
  再将表名t_car修改为t_che
  删除t_car表

作业:
  -- 创建女孩表,字段有:姓名、年龄、电话号码、是否有男朋友
  create table t_girl (
      name  varchar(20),
      age   int(3),
      phone varchar(20),
      bf    char(2)
  );
  -- 实现将女孩表中是否有男朋友的字段删除
  alter table t_girl drop bf;
  -- 实现向女孩表中增加字段性别
  alter table t_girl add gender char(2);
  -- 实现将女孩表中性别字段修改为xingBie
  alter table t_girl change gender xingBie char(2);
  -- 实现将女孩表的表名修改为男孩表
  alter table t_girl rename to t_boy;
  -- 实现男孩表的删除
  drop table t_boy;
------------------------------------------------------------------------------
今天内容:
   (1)DML数据操纵语句
   (2)Select查询语句

1.DML数据操纵语句(重点、练熟)
1.1 基本概念
   DML数据操纵语句主要用于实现对表格中数据内容的插入、更新(修改)以及删除操作。

1.2 数据内容的插入
(1)语法格式
   insert into 表名 [(字段名1, 字段名2, ...)] values (1,2, ...);
如:
   -- 创建t_person表,字段有:姓名、年龄、性别
   create table t_person (
       name varchar(20),
       age  int(3),
       sex  char(2)
   );
   -- 向t_person表中所有字段插入数据'喻超贤' 18 '男'
   insert into t_person (name, age, sex) values('喻超贤', 18, '男');
   -- 当实现向表格中所有字段插入数据时,通常都省略字段名
   insert into t_person values('喻超贤', 18, '男');
   -- 实现向表格中部分字段插入数据时,不能省略字段名
   insert into t_person (name, age) values ('孙悟空', 66);
   -- 实现批量增加
   insert into t_person values('李赟', 16, '男'), ('娄东岳', 17, '男'), ('赵大凯', 18, '男'); 

1.3 数据内容的更新(修改)
(1)语法格式
   update 表名 set 字段名1 =1 [where 条件];
如:
   -- 实现将t_person表中所有年龄字段的数值修改为18
   -- 当需要实现将指定字段的所有数值进行修改时,省略where条件
   update t_person set age = 18;

   -- 实现将t_person表中'孙悟空'的年龄修改为20
   -- 当需要修改某条记录中的指定字段时,不能省略where条件
   update t_person set age = 20 where name = '孙悟空';

   -- 实现批处理
   update t_person set name = '苍老师', sex = '女';

1.4 数据内容的删除
(1)语法格式
   delete from 表名 [where 条件];
如:
   -- 实现将t_person表中年龄为20的记录删除
   delete from t_person where age = 20;
   -- 实现将t_person表中所有记录删除
   delete from t_person;

2.select查询语句(重中之重)
2.1 回顾已学内容

2.2 查看表结构
   desc 表名;
如:
   desc s_emp;  -- 表示查看s_emp员工表中的结构(字段),具体结果如下:
   
id int(7)  NOT NULL             -- 员工编号
last_name  varchar(25) NULL     -- 员工姓
first_name varchar(25) NULL     -- 员工名字
userid varchar(8) NULL          -- 员工昵称
start_date date NULL            -- 入职日期
comments varchar(255) NULL      -- 备注信息
manager_id int(7) NULL          -- 领导编号
title varchar(25) NULL          -- 职位
dept_id int(7) NULL             -- 部门编号
salary int(11) NULL             -- 薪水
commission_pct double(4,2) NULL -- 奖金

   desc student; -- 表示查看student学生表中的结构,具体结果如下:
StudentNo varchar(50) NOT NULL   -- 学生学号
LoginPwd  varchar(20) NOT NULL   -- 登录密码
StudentName varchar(50) NOT NULL -- 学生姓名
Sex char(3) NOT NULL             -- 学生性别
GradeId int(2) NOT NULL          -- 年级编号
Phone varchar(255) NOT NULL      -- 电话号码
Address varchar(255) NULL        -- 家庭住址
BornDate date NULL               -- 出生日期
Email varchar(50) NULL           -- 邮箱地址

2.3 基本语法格式
   select 字段名1, 字段名2, ... from 表名;
如:
   -- 查询员工表中所有员工的名字, 25个员工
   select first_name from s_emp;
   -- 查询员工表中所有员工的名字和薪水
   select first_name, salary from s_emp;
   -- 查询员工表中所有员工的所有字段
   select * from s_emp;   

2.4 算术运算符的使用
如:
   -- 查询员工表中所有员工加上500元过节费之后的薪水
   select first_name, salary, salary+500 from s_emp;
   -- 查询员工表中所有员工扣除200元后的薪水
   select first_name, salary, salary-200 from s_emp;
   -- 查询员工表中所有员工的年薪,一年至少16薪
   select first_name, salary, salary*16 from s_emp;   
   -- 查询员工表中所有员工的日薪,一月按照21天计算
   select first_name, salary, salary/21 from s_emp;
   -- 查询员工表中所有员工的日薪后的余数
   select first_name, salary, salary%21 from s_emp;
   -- 查询员工表中所有员工涨薪500元后的年薪
   select first_name, salary, (salary + 500)*16 from s_emp;

练习:
   -- 查询员工表中所有员工涨薪500元的日薪
   select first_name, salary, (salary + 500)/21 from s_emp;
   -- 查询员工表中所有员工加上奖金后的年薪   Error
   select first_name, salary, (salary + commission_pct)*16 from s_emp;
   -- 使用ifnull()函数来处理空值的问题
   select first_name, salary, commission_pct, 
      (salary + ifnull(commission_pct, 0))*16 from s_emp;

2.5 列的别名
   select 字段名1 [as] 别名1, 字段名2 [as] 别名2, ... from 表名;
如:
   -- 查询员工表中所有员工的名字,薪水以及年薪
   select first_name as 名字, salary 薪水, salary*16 年薪 from s_emp;
   -- 若别名中有空格时,则使用双引号括起来表示这个整体都是别名
   select first_name as 名字, salary 薪水, salary*16 "年 薪" from s_emp;
   select first_name as name, salary, salary*16 income from s_emp;
   -- 查询常量列并起别名
   select first_name, '兄弟连' 公司名称 from s_emp;
   -- 注意:"666"被连接到一起了,加个as可以作为别名
   select first_name, '兄弟连' as "666" from s_emp;

2.6 where子句
   select 字段名1 [as] 别名1, 字段名2 [as] 别名2, ... from 表名
   [where 条件];

2.7 比较运算符的使用
如:
   -- 查询员工表中薪水为800的员工名字以及员工薪水
   select first_name, salary from s_emp
   where salary = 800; 
   -- 查询员工表中薪水大于等于800的员工名字以及员工薪水
   select first_name, salary from s_emp
   where salary >= 800; 
   -- 查询员工表中薪水不等于800的员工名字以及员工薪水
   select first_name, salary from s_emp
   where salary != 800;
   select first_name, salary from s_emp
   where salary <> 800;

练习:
   -- 查询员工表中奖金为空的员工名字和奖金数值
   -- 代码没错,但是查询不到结果
   select first_name, commission_pct from s_emp
   where commission_pct = null;
   -- 查询员工表中奖金不为空的员工名字以及奖金数值
   select first_name, commission_pct from s_emp
   where commission_pct <> null;

   -- 对于空值数据不能使用 =<> 进行处理,使用 is null 和 is not null
   -- 查询员工表中奖金为空的员工名字和奖金数值
   select first_name, commission_pct from s_emp
   where commission_pct is null;
   -- 查询员工表中奖金不为空的员工名字以及奖金数值
   select first_name, commission_pct from s_emp
   where commission_pct is not null;

2.8 逻辑运算符的使用
如:
   -- 查询员工表中所有薪水在10002000之间的员工名称以及员工薪水
   select first_name, salary from s_emp
   where salary >= 1000 and salary <= 2000;
   select first_name, salary from s_emp
   where salary >= 1000 && salary <= 2000;
   
   -- 查询员工表中所有薪水小于1000或者薪水大于2000的员工名称以及员工薪水
   select first_name, salary from s_emp
   where salary < 1000 or salary > 2000;
   select first_name, salary from s_emp
   where salary < 1000 || salary > 2000;

   -- 查询员工表中所有薪水为1400并且部门编号不是41的员工名字、薪水以及部门编号
   select first_name, salary, dept_id from s_emp
   where salary = 1400 and dept_id <> 41;
   select first_name, salary, dept_id from s_emp
   where salary = 1400 and not dept_id = 41;
   
   -- 查询员工表中薪水为1400并且部门编号为41或者42的员工名字、薪水以及部门编号
   select first_name, salary, dept_id from s_emp
   where salary = 1400 and dept_id = 41 or dept_id = 42;
   -- 上述查询结果不满足需求,此时使用()来修改, and的优先级高于or
   select first_name, salary, dept_id from s_emp
   where salary = 1400 and (dept_id = 41 or dept_id = 42);

   -- 极限条件
   select first_name, salary from s_emp
   where 1 = 1;                                -- 永远为真,查询到所有
   select first_name, salary from s_emp
   where 1 != 1;                               -- 永远为假,啥也查不到

2.9 between... and ...的使用
如:
   -- 查询员工表中所有薪水在10002000之间的员工名称以及员工薪水
   select first_name, salary from s_emp
   where salary >= 1000 and salary <= 2000;
   
   -- 使用新的方式进行查询
   select first_name, salary from s_emp
   where salary between 1000 and 2000;

   -- 查询员工表中所有薪水在11001400之间的员工名称以及员工薪水, 闭区间
   select first_name, salary from s_emp
   where salary between 1100 and 1400;
   -- 与上述方式不等价
   select first_name, salary from s_emp
   where salary > 1100 and salary < 1400;

   -- 笔试考点
   -- 下面的查询语句不会报错,但是查询不到任何数据
   select first_name, salary from s_emp
   where salary between 1400 and 1100;
   
   -- 查询员工表中薪水不在11001400之间的员工名称以及薪水
   select first_name, salary from s_emp
   where salary not between 1100 and 1400; 

2.10 数据的去重处理
   select [distinct] 字段名1 [as] 别名1, 字段名2 [as] 别名2, ... from 表名
   [where 条件];
如:
   -- 查询员工表中部门编号在3040之间的部门编号
   select dept_id from s_emp
   where dept_id between 30 and 40;
   -- 查询员工表中部门编号在3040之间的部门编号,要求体现出部门的数量,去重
   select distinct dept_id from s_emp
   where dept_id between 30 and 40;
   
   -- 查询员工表中所有员工的薪水和部门编号,要求薪水范围在10002000之间
   select salary, dept_id from s_emp
   where salary between 1000 and 2000;
   -- 查询员工表中所有员工的薪水和部门编号,要求薪水范围在10002000之间
   -- 当查询多个字段时,只有多个字段的数值都完全相同时才认为该条记录是重复的
   select distinct salary, dept_id from s_emp
   where salary between 1000 and 2000;

2.11 按照指定的列表进行查询
如:
   -- 查询员工表中部门编号在3040之间的员工名字、部门编号
   select first_name, dept_id from s_emp
   where dept_id >= 30 and dept_id <= 40;
   select first_name, dept_id from s_emp
   where dept_id between 30 and 40;

   -- 查询员工表中部门编号在4142的员工名字、部门编号   7条
   select first_name, dept_id from s_emp
   where dept_id >= 41 and dept_id <= 42;
   select first_name, dept_id from s_emp
   where dept_id = 41 or dept_id = 42;
   select first_name, dept_id from s_emp
   where dept_id between 41 and 42;
   select first_name, dept_id from s_emp
   where dept_id in (41, 42);
    
   -- 查询员工表中部门编号不在4142的员工名字、部门编号
   select first_name, dept_id from s_emp
   where dept_id not in (41, 42);

2.12 按照条件进行模糊查询
如:
   -- 查询员工表中以'拉'开头后面跟任意多个字符的员工名字以及员工薪水
   select first_name, salary from s_emp
   where first_name like '拉%';     
   -- 查询员工表中以'拉'开头后面跟一个字符的员工名字以及员工薪水
   select first_name, salary from s_emp
   where first_name like '拉_';
   -- 查询员工表中名字带有'拉'的员工名字以及员工薪水
   select first_name, salary from s_emp
   where first_name like '%拉%';  
   -- 查询员工表中名字以'拉'结尾的员工名字以及员工薪水
   select first_name, salary from s_emp
   where first_name like '%拉';
   -- 查询员工表中名字以'拉'结尾前面只有一个字符的员工名字以及员工薪水
   select first_name, salary from s_emp
   where first_name like '_拉';

   -- 特殊情况
   -- 向员工表中添加一个名字以_开头的员工信息
   insert into s_emp (id, first_name) values(26, '_田喆');
   -- 查询员工表中名字以'_'开头的员工名字以及员工薪水
   -- 下面的写法虽然没有错误但不满足需求
   select first_name, salary from s_emp
   where first_name like '_%';
   -- 使用转义字符进行转义,让_不再代表通配符而是_字符自身
   select first_name, salary from s_emp
   where first_name like '\_%'; 
   -- 使用'#'作为转义字符来转义_的含义
   select first_name, salary from s_emp
   where first_name like '#_%' escape '#';

练习:   
   -- 查询“山东”的学生姓名、电话、住址
   select studentname, phone, address from student
   where address like '山东%';

   -- 查询名称中含有“p”字母的科目信息
   select subjectname from subject
   where subjectname like '%p%';

   -- 查询电话中以“1387”开头的学生信息
   select studentname, phone from student
   where phone like '1387%';

   -- 查询姓姜的,单名的学生信息
   select studentname from student
   where studentname like '姜_';

   -- 查询学号为S1101004的指定123科目考试成绩
   select studentno, subjectid, studentresult from result
   where studentno = 'S1101004' and  subjectid in (1, 2, 3);
   
作业:
   1.将笔记中所有的SQL语句练习3遍。
   2.创建t_person表,字段有:姓名、年龄、电话号码、是否有男朋友
     向该表中插入'貂蝉''西施''王昭君'的个人信息
     更新该表中'貂蝉'的电话号码为119
     更新该表中所有人的年龄为18
     删除名字为'王昭君'的记录
     删除所有记录
     删除女孩表
   3.实现以下需求:
     --查看表结构s_dept表,并且从s_dept表中,查询id、name字段对应的内容
     --查看员工表中所有员工的每个月涨薪300元后的年薪
     --查询员工信息:员工编号、员工姓名以及员工的领导编号,没领导就设置为-1    
     --查询员工表中部门在313233的员工编号、员工姓名以及部门编号信息
   
---------------------------------------------------------------------------------------------------------------------------
1.编程题
  -- (1)创建t_person表,字段有:姓名、年龄
  -- (2)向t_person表中增加字段 性别
  -- (3)将左右同桌的信息插入到t_person表中
  -- (4)将左同桌的年龄修改为15
  -- (5)将所有人的年龄都修改为18
  -- (6)将右同桌的个人信息删除
  -- (7)将t_person表中所有数据删除
  -- (8)将t_person表删除
  -- (9)查询员工表中所有员工的名字、薪水
  -- (10)查询员工表中所有员工的名字以及日薪
  -- (11)查询员工表中所有员工的名字以及加上奖金后的年薪,要求起别名为"年 薪"
  -- (12)查询员工表中所有薪水大于等于1000的员工名字和薪水
  -- (13)查询员工表中所有薪水小于等于2000并且部门编号为4142的员工名字、薪水
  -- (14)查询员工表中薪水在8001400之间并且部门编号为3132的员工名字、薪水
  -- (15)查询员工表名字带有'德'的员工名字
  -- (16)查询员工表中所有没有奖金的员工名字
  -- (17)查询员工表中部门编号小于等于40的数据且进行去重处理

作业:
   -- 创建t_person表,字段有:姓名、年龄、电话号码、是否有男朋友
   drop table t_person;
   create table t_person (
       name varchar(20),
       age  int(3),
       phone varchar(20),
       bf   char(2)
   ); 
   -- 向该表中插入'貂蝉''西施''王昭君'的个人信息
   insert into t_person values('貂蝉', 18, 110, '有'),('西施', 17, 112, '无'),('王昭君', 20, 120, '有');
   -- 更新该表中'貂蝉'的电话号码为119
   update t_person set phone = 119 where name = '貂蝉';
   -- 更新该表中所有人的年龄为18
   update t_person set age = 18;
   -- 删除名字为'王昭君'的记录
   delete from t_person where name = '王昭君';
   -- 删除所有记录
   delete from t_person;
   -- 删除表
   drop table t_person;


   -- 查看表结构s_dept表,并且从s_dept表中,查询id、name字段对应的内容
   desc s_dept;
   select id, name from s_dept;

   -- 查看员工表中所有员工的每个月涨薪300元后的年薪
   select first_name, salary, (salary+300)*16 "年 薪"from s_emp; 
   -- 查询员工信息:员工编号、员工名字以及员工的领导编号,没领导就设置为-1 
   select id, first_name, ifnull(manager_id,-1) from s_emp;    
   -- 查询员工表中部门在313233的员工编号、员工名字以及部门编号信息
   select id, first_name, dept_id from s_emp
   where dept_id in (31, 32, 33);
------------------------------------------------------------------------------
今天内容:
   (1)select查询语句

1.select查询语句(重中之重)
1.1 字段的排序
   select [distinct] 字段名1 [as 别名1], 字段名2 [as 别名2], ... from 表名
   [where 查询条件]
   [order by 字段名1 asc或desc, 字段名2 asc或desc, ...]; 
如:
   -- 查询员工表中所有薪水超过1000元的名字和薪水
   select first_name, salary from s_emp
   where salary > 1000;
   -- 查询员工表中所有薪水超过1000元的名字和薪水,并按照薪水进行升序排序
   select first_name, salary from s_emp
   where salary > 1000
   order by salary asc;
   -- asc关键字表示升序排序,可以省略,默认就是升序排列
   select first_name, salary from s_emp
   where salary > 1000
   order by salary;
   -- desc关键字可以实现降序排列
   select first_name, salary from s_emp
   where salary > 1000
   order by salary desc;

   -- 查询员工表中所有部门的所有员工的薪水,要求按照部门进行升序,按照薪水升序
   select first_name, dept_id, salary from s_emp
   order by dept_id asc, salary asc; 
   -- 查询员工表中所有部门的所有员工的薪水,要求按照部门进行升序,按照薪水降序
   select first_name, dept_id, salary from s_emp
   order by dept_id asc, salary desc; 
   -- 查询员工表中所有部门的所有员工的薪水,要求按照部门进行降序,按照薪水降序
   select first_name, dept_id, salary from s_emp
   order by dept_id desc, salary desc; 
   -- 查询员工表中所有部门的所有员工的薪水,要求按照部门进行降序,按照薪水升序
   select first_name, dept_id, salary from s_emp
   order by dept_id desc, salary asc; 

   -- 实现三个字段的排序,按照部门编号降序,薪水降序,名字降序
   select dept_id, salary, first_name from s_emp
   order by dept_id desc, salary desc, first_name desc;
   
1.2 常用的字符串函数
如:
   -- 使用查询实现获取字符串'hello世界'的长度,获取字符串的字节个数,汉字占3个
   select length('hello世界') 获取字符串长度;
   -- 使用查询实现字符串'hello世界'的字符长度,获取字符的个数,汉字是一个字符
   select char_length('hello世界') 获取字符长度;
   -- 使用查询实现将字符串'hello'转换为大写
   select upper('hello') 转为大写;
   -- 使用查询实现将字符串'HELLO'转换为小写
   select lower('HELLO') 转为小写;
   -- 使用查询实现将字符串'helloworld'中的world获取出来
   -- 默认下标从1开始,下面的sql是表示从下标6开始获取5个字符
   select substr('helloworld', 6, 5) 获取子串;
   -- 使用查询实现字符串的拼接
   select concat('hello', 'world') 拼接字符串;

   -- 使用查询实现字符串内容的替换
   --'e'替换为'E'
   select replace('hello', 'e', 'E') 替换字符串;
   -- 当出现重复字符时,则全部进行替换
   select replace('hehe', 'e', 'E') 替换字符串;
   -- 使用查询实现指定字符串出现的首位置
   -- 表示查找字符串'hello''e'第一次出现的索引位置,下标默认从1开始
   select instr('hello', 'e') 查找第一次出现位置;
   -- 使用查询实现去除字符串两端的空白字符
   select trim('     hello     ') 去除两端空白字符;
   select length(trim('     hello     ')) 去除两端空白字符后的长度;

1.3 常用的数值函数
如:
   -- 使用查询将数值19.3584进行四舍五入保留3位小数
   select round(19.3584, 3) 保留3位小数;            -- 19.358
   -- 使用查询将数值19.3584进行四舍五入保留2位小数
   select round(19.3584, 2) 保留2位小数;            -- 19.36
   -- 使用查询将数值19.3584进行四舍五入保留1位小数
   select round(19.3584, 1) 保留1位小数;            -- 19.4
   -- 使用查询将数值19.3584进行四舍五入保留0位小数
   select round(19.3584, 0) 保留0位小数;            -- 19
   -- 使用查询将数值19.3584进行四舍五入保留-1位小数,别名有-号要加""
   select round(19.3584, -1) "保留-1位小数";        -- 20
   -- 使用查询将数值19.3584进行四舍五入保留-2位小数
   select round(19.3584, -2) "保留-2位小数";        -- 0

   -- 使用查询将数值19.3584进行截取保留3位小数
   select truncate(19.3584, 3) 保留3位小数;            -- 19.358
   -- 使用查询将数值19.3584进行截取保留2位小数
   select truncate(19.3584, 2) 保留2位小数;            -- 19.35
   -- 使用查询将数值19.3584进行截取保留1位小数
   select truncate(19.3584, 1) 保留1位小数;            -- 19.3
   -- 使用查询将数值19.3584进行截取保留0位小数
   select truncate(19.3584, 0) 保留0位小数;            -- 19
   -- 使用查询将数值19.3584进行截取保留-1位小数,别名有-号要加""
   select truncate(19.3584, -1) "保留-1位小数";        -- 10
   -- 使用查询将数值19.3584进行截取保留-2位小数
   select truncate(19.3584, -2) "保留-2位小数";        -- 0

1.4 常用的日期函数
如:
   -- 使用查询来获取当前系统日期
   select curdate() 当前系统日期;   
   -- 使用查询来获取当前系统时间
   select curtime() 当前系统时间;
   -- 使用查询来获取日期中的月份
   select month(curdate()) 获取当前日期中的月份;

   -- 使用查询来获取当前系统日期的昨天
   select curdate()-1 昨天;
   -- 使用查询来获取当前系统日期的明天
   select curdate()+1 明天;

   -- 向员工表中插入员工信息27'云峰', curdate(), 200
   insert into s_emp (id, first_name, start_date, salary) values(27, '云峰', curdate(), 200);
   insert into s_emp (id, first_name, start_date, salary) values(28, '晓奎', curdate()+2, 300);
   insert into s_emp (id, first_name, start_date, salary) values(29, '宇鉴', '20191111', 300);
   insert into s_emp (id, first_name, start_date, salary) values(30, '宇鉴', 
'2019-12-12', 3);
   -- 查询员工表中所有员工的名字和入职日期
   select first_name, start_date from s_emp;

1.5 常用的聚合(多行、分组)函数
   单行函数 - 主要指将一条数据交给该函数处理之后的结果还是一条数据。
   多行函数 - 主要指将多条数据交给该函数处理之后的结果是一条数据。

   sum() - 主要用于实现总和的计算,如:计算总分。
   avg() - 主要用于实现平均值的计算,如:平均分。
   max() - 主要用于查找最大值,如:最高分。
   count() - 主要用于统计个数,通常使用方式为:count(*),如:学生人数 
如:
   -- 查询员工表中所有员工的总薪水
   select sum(salary) 总薪水 from s_emp;
   -- 查询员工表中所有员工的平均薪水
   select avg(salary) 平均薪水 from s_emp;
   select round(avg(salary), 2) 平均薪水 from s_emp;
   -- 查询员工表中的最高薪
   select max(salary) 最高薪水 from s_emp;
   -- 查询员工表中的最低薪,不考虑空值
   select min(salary) 最低薪水 from s_emp;
   -- 查询员工表中的总人数
   select count(*) 总人数 from s_emp;

练习:
   -- 查询成绩表中所有学生的总成绩
   select sum(studentresult) 总成绩 from result;
   -- 查询成绩表中所有学生的平均成绩
   select avg(studentresult) 平均成绩 from result;
   select round(avg(studentresult),2) 平均成绩 from result;
   -- 查询成绩表中所有学生的最高分 
   select max(studentresult) 最高分 from result;
   -- 查询成绩表中所有学生的最低分
   select min(studentresult) 最低分 from result;
   -- 查询成绩表中所有记录的个数
   select count(*) 个数 from result;
   -- 查询学生表中岁数最大的学生姓名和出生日期
   -- date类型也可以使用min函数计算最小值
   select min(borndate) 岁数最大 from student;
   -- 查询学生表中岁数最小的学生姓名和出生日期
   select max(borndate) 岁数最小 from student;

1.6 分组查询的实现
   select [distinct] 字段名1 [as 别名1], 字段名2 [as 别名2], ... from 表名
   [where 查询条件]
   [group by 字段名]
   [order by 字段名1 asc或desc]; 
如:
   -- 查询学生表中每个年级的学生人数,每...就表示按照...分组
   select gradeid, count(*) from student
   group by gradeid;
   -- 查询学生表中每种性别的学生人数
   select sex, count(*) from student
   group by sex;
   -- 查询学生表中每种性别的学生人数并按照人数进行降序排列
   select sex, count(*) from student
   group by sex
   order by count(*) desc;
   -- 注意:下面的代码虽然没有报错,但与实际情况不符,多个学生应该有多个学号
   select studentno, sex, count(*) from student
   group by sex
   order by count(*) desc;

案例讲解:
   -- 查询成绩表中每门课程的平均分
   select subjectid, avg(studentresult) from result
   group by subjectid;
   -- 查询成绩表中每门课程的平均分,并按照平均分进行降序排列
   select subjectid 课程编号, avg(studentresult) 平均分 from result
   group by subjectid
   order by 平均分 desc;
   -- 查询每个年级中每种性别的学生人数
   select gradeid 年级编号, sex 性别, count(*) 学生人数 from student
   group by gradeid, sex;
   -- 先按照年级升序,在按照人数降序
   select gradeid 年级编号, sex 性别, count(*) 学生人数 from student
   group by gradeid, sex
   order by gradeid asc, count(*) desc;

1.7 分组后的过滤
   select [distinct] 字段名1 [as 别名1], 字段名2 [as 别名2], ... from 表名
   [where 查询条件]
   [group by 字段名]
   [having 条件]
   [order by 字段名1 asc或desc]; 
如:
   -- 查询总人数超过18人的所有年级
   -- 也就是先计算每个年级的总人数,再按照18进行过滤
   -- 下面的写法直接报错:where子句不许使用分组函数,因为此时还没有分组
   select gradeid, count(*) from student
   where count(*) > 18
   group by gradeid;
   -- 正确的写法
   select gradeid, count(*) from student
   group by gradeid
   having count(*) > 18;

执行流程:
   from子句 => where子句 => group by子句 => having子句 => select子句 
=> order by子句

练习:
   -- 查询每个年级的总课时,并升序排列 (subject表)
   select gradeid, sum(classhour) from subject
   group by gradeid
   order by sum(classhour) asc;
 
   -- 查询每个学员的平均分(result表)
   select studentno, avg(studentresult) from result
   group by studentno;

   -- 查询每门课程的平均分,并降序排列(result表)
   select subjectid, avg(studentresult) from result
   group by subjectid
   order by avg(studentresult) desc;

   -- 查询每个学生的总分,并降序排列(result表)
   select studentno, sum(studentresult) from result
   group by studentno
   order by sum(studentresult) desc;
 
1.8 子查询
   子查询就是指将一个查询语句的结果作为条件进行下一次查询的机制,也叫作多次/多重查询,也就是在查询语句中嵌套查询语句。

如:
   -- 查询学生表中比'崔今生'小的学生姓名和出生日期
   -- 第一步:先查询'崔今生'的生日信息   '1990-01-05'
   select borndate from student
   where studentname = '崔今生';
   -- 第二步:根据'崔今生'的生日信息来查询比该生日信息大的学生信息  23个
   select studentname, borndate from student
   where borndate > '1990-01-05'; 

   -- 实现真正的子查询
   select studentname, borndate from student
   where borndate > ( select borndate from student
   	where studentname = '崔今生'); 

练习:
   -- 查询学生表中与'崔今生'在同一个年级的学生姓名和年级编号
   -- 第一步:查询学生表中'崔今生'所在的年级编号  1
   select gradeid from student
   where studentname = '崔今生';
   -- 第二步:根据查询到的年级编号再查同一个年级的学生姓名和年级编号
   select studentname, gradeid from student
   where gradeid = 1;
   -- 合并起来
   select studentname, gradeid from student
   where gradeid = ( select gradeid from student
       where studentname = '崔今生');

案例讲解:
   -- 查询'JavaSE'课程中考了100分的学生名字 
   -- 第一步:根据课程名称'JavaSE'来查询对应的课程编号   1
   select subjectid from subject
   where subjectname = 'JavaSE';

   -- 第二步:根据课程编号和100分的成绩来查询对应的学生学号  S1101019
   select studentno from result
   where subjectid = 1 and studentresult = 100;

   -- 第三步:根据学生的学号来查询对应的学生名字
   select studentname from student
   where studentno = 'S1101019';

   -- 合并上述结果
   select studentname from student
   where studentno = ( select studentno from result
   	where subjectid = ( select subjectid from subject
   		where subjectname = 'JavaSE') and studentresult = 100);
练习:
   -- 查询“青铜”阶段开设的课程
   -- 第一步:从年级表中根据根据年级的名称来查询对应的年级编号  1
   select gradeid from grade
   where gradename = '青铜';
   -- 第二步:从课程表中根据年级编号来查询对应的课程名称
   select subjectname, gradeid from subject
   where gradeid = 1;
   -- 合并上述查询语句
   select subjectname, gradeid from subject
   where gradeid = ( select gradeid from grade
   	where gradename = '青铜' );

   -- 查询参加最近一次“HTML和CSS网页技术”考试成绩的学生的最高分和最低分
   -- 第一步:从课程表中通过课程名称查询课程编号  2
   select subjectid from subject
   where subjectname = 'HTML和CSS网页技术';
   -- 第二步:从成绩表中通过课程编号查询最近一次考试的日期,也就是最大日期
   -- 2010-03-01
   select max(examdate) from result
   where subjectid = 2;
   -- 第三步:从成绩表中通过课程编号和最近一次考试的日期来查询考试成绩,
   --         使用聚合函数找到最高分和最低分
   select max(studentresult),min(studentresult) from result
   where subjectid = 2 and examdate = '2010-03-01';
   -- 合并上述查询语句
   select max(studentresult),min(studentresult) from result
   where subjectid = ( select subjectid from subject
   	where subjectname = 'HTML和CSS网页技术') and 
        examdate = ( select max(examdate) from result
   		where subjectid = (select subjectid from subject
   			where subjectname = 'HTML和CSS网页技术') );

案例:
   -- 查询“JavaSE”课程考试成绩不及格的学生名单
   -- 第一步:从课程表中根据课程的名称查询课程的编号  1
   select subjectid from subject
   where subjectname = 'JavaSE';
   -- 第二步:从成绩表中根据课程的编号和不及格的考试成绩来查询对应的学号
   -- S1200902002 
S1101004 
S1101010
 S1101013
   select studentno from result
   where subjectid = 1 and studentresult < 60;
   -- 第三步:从学生表中通过学生的学号来查询学生的名称
   select studentname from student
   where studentno in ('S1200902002', 'S1101004', 'S1101010', 'S1101013');
   -- 合并上述查询语句
   select studentname from student
   where studentno in ( select studentno from result
   	where subjectid = ( select subjectid from subject
   		where subjectname = 'JavaSE') and studentresult < 60);
   -- 使用any关键字
   select studentname from student
   where studentno = any ( select studentno from result
   	where subjectid = ( select subjectid from subject
   		where subjectname = 'JavaSE') and studentresult < 60); 

案例讲解:
    -- 查询参加“JavaSE”课程最近一次考试的在读学生名单
    -- 第一步:从课程表中根据课程名称查询课程的编号  1
    select subjectid from subject
    where subjectname = 'JavaSE';
    -- 第二步:从成绩表中根据课程编号来查询最近一次考试的日期 '2010-02-01'
    select max(examdate) from result
    where subjectid = 1;
    -- 第三步:从成绩表中根据课程编号和考试日期来查询对应的学生学号 'S1101011'
    select studentno from result
    where subjectid = 1 and examdate = '2010-02-01';
    -- 第四步:从学生表中根据学号来查询对应的学生名单
    select studentname from student
    where studentno = 'S1101011';
    -- 合并上述查询语句
    select studentname from student
    where studentno = ( select studentno from result
    	where subjectid = ( select subjectid from subject
    		where subjectname = 'JavaSE') 
                and examdate = ( select max(examdate) from result
    			where subjectid = ( select subjectid from subject
   				where subjectname = 'JavaSE')));

作业:
   -- 查询成绩表中学生编号、课程编号以及学生成绩信息,要求按照学生编号
      进行降序排列,若学生编号一样按照课程编号降序,若课程编号一样按照
      成绩升序排序
   -- 查询s_emp表中所有first_name包含b或B员工,显示id、first_name、salary信息
   -- 显示s_emp表中first_name中4个字符以后的内容
   -- 查询今天过生日的员工信息,假设入职日期就是出生日期   
   -- 查询和Ben一个部门的员工的id,first_name,dept_id,salary信息
   -- 显示所有工资超过Ben的员工的信息,包括:id,first_name,salary
   -- 显示工资高于全公司平均工资的员工信息,包括id,first_name,salary
   -- 显示工资高于部门id=43的平均工资 的员工信息,包括id,first_name,salary
   -- 显示所有工资等于 部门43的所有员工 的信息,包括id,first_name,salary
   -- 返回管理者的信息,id,first_name,salary,也就是id号和manager_id相同
   -- 显示所有工资大于 部门43的任意员工 的信息,包括id,first_name,salary
   -- 显示平均工资 比部门id=33高的 部门id和平均工资
 -------------------------------------------------------------------------------------- 
1.编程题
  -- (1)查询员工表中所有员工的薪水并按照降序排列
  -- (2)查询员工表中所有员工的部门编号和薪水,按照部门编号升序,再按照薪水降序
  -- (3)使用查询将字符串'hello'转换为大写
  -- (4)使用查询将字符串'HELLO'转换为小写
  -- (5)使用查询计算字符串'Hello'的长度
  -- (6)使用查询替换字符串'hehe'中所有的'e''E'
  -- (7)使用查询将数值123.456采用四舍五入保留2位小数
  -- (8)使用查询将数值123.456采用四舍五入保留0位小数
  -- (9)使用查询将数值123.456采用截取方式保留2位小数
  -- (10)使用查询将数值123.456采用截取方式保留0位小数
  -- (11)使用查询获取当前系统日期
  -- (12)使用查询获取当前系统时间
  -- (13)查询员工表所有员工的总薪水、平均薪水、最高薪水、最低薪水以及员工数量
  -- (14)查询学生表中每个年级的学生人数
  -- (15)查询学生表中每个年级总人数超过18人的学生人数
  -- (16)查询学生表中每个年级每种性别的学生人数并按照年级编号降序排列
  -- (17)查询比'崔今生'大的学生姓名和出生日期
  -- (18)查询'JavaSE'课程不及格的学生姓名

作业:
  -- 查询成绩表中学生编号、课程编号以及学生成绩信息,要求按照学生编号
     进行降序排列,若学生编号一样按照课程编号降序,若课程编号一样按照
     成绩升序排序
  select studentno, subjectid, studentresult from result
  order by studentno desc, subjectid desc, studentresult asc;

   -- 查询s_emp表中所有first_name包含b或B员工,显示id、first_name、salary信息
   select id, first_name, salary from s_emp
   where first_name like '%b%';
   select id, first_name, salary from s_emp
   where lower(first_name) like '%b%';

   -- 显示s_emp表中first_name中4个字符以后的内容,下标默认从1开始
   select substr(first_name, 5, length(first_name)-4) from s_emp;
 
   -- 查询今天过生日的员工信息,假设入职日期就是出生日期 
   select first_name, start_date from s_emp
   where start_date = curdate();
  
   -- 查询和Ben一个部门的员工的id,first_name,dept_id,salary信息
   select id, first_name, dept_id, salary from s_emp
   where dept_id = ( select dept_id from s_emp 
   	where first_name = 'Ben');

   -- 显示所有工资超过Ben的员工的信息,包括:id,first_name,salary
   select id, first_name, salary from s_emp
   where salary > ( select salary from s_emp
	where first_name = 'Ben');

   -- 显示工资高于全公司平均工资的员工信息,包括id,first_name,salary
   select id, first_name, salary from s_emp
   where salary > ( select avg(salary) from s_emp );

   -- 显示工资高于部门id=43的平均工资 的员工信息,包括id,first_name,salary
   select id, first_name, salary from s_emp
   where salary > ( select avg(salary) from s_emp
      where dept_id = 43 );

   -- 显示所有工资等于 部门43的任意员工 的信息,包括id,first_name,salary
   select id, first_name, salary from s_emp
   where salary = any (select salary from s_emp
   	where dept_id = 43);

   -- 返回管理者的信息,id,first_name,salary,也就是id号和manager_id相同
   select id, first_name, salary from s_emp
   where id = any ( select distinct manager_id from s_emp );

   -- 显示所有工资大于 部门43的所有员工 的信息,包括id,first_name,salary 
   select id, first_name, salary from s_emp
   where salary > ( select max(salary) from s_emp
	where dept_id = 43);
   select id, first_name, salary from s_emp
   where salary > all ( select salary from s_emp
	where dept_id = 43);

   -- 显示平均工资 比部门id=33高的 部门id和平均工资
   select dept_id, avg(salary) from s_emp
   group by dept_id
   having avg(salary) > ( select avg(salary) from s_emp
	where dept_id = 33 );
-----------------------------------------------------------------------------
今天内容:
   (1)select查询语句
   (2)常用的约束

1.select查询语句(重中之重)
1.1 复习语法格式
   select [distinct] 字段名1 [as 别名1], ... from 表名
   [where 条件]
   [group by 字段名]
   [having 条件]
   [order by 字段名 asc或desc];

1.2 多表查询
   单表查询 - 主要指查询的所有字段都是来自于同一张表中的数据。
   多表查询 - 主要指查询的所有字段同时来自于多张表中的数据。 
  
   多表查询主要分为:
     内连接(inner join)、左外连接(left outer join)、右外连接(right outer join)

1.3 内连接(inner join)
   内连接主要指将满足匹配条件并且每张表中都有的数据内容进行查询的连接机制。
   内连接的语法格式是:
      select [表名1.]字段名1, [表名2.]字段名2, ... from 表名1 inner join 表名2
      on 连接条件;
如:
   -- 从学生表和成绩表中查询学生姓名、课程编号以及考试成绩
   select studentname, subjectid, studentresult from student
   inner join result on student.studentno = result.studentno;
   
练习:
   -- 从部门表和员工表中查询部门名称、员工名称,使用内连接
   select name, first_name from s_dept
   inner join s_emp on s_dept.id = s_emp.dept_id;

   -- 查询员工编号,姓名以及所在部门名称
   select s_emp.id 员工编号, concat(last_name, first_name) 员工姓名, name 部门名称 from s_emp inner join s_dept on s_emp.dept_id = s_dept.id;
 
   -- 查询部门编号,部门名称以及该部门负责的区域名称
   select s_dept.id 部门编号, s_dept.name 部门名称, s_region.name 区域名称
   from s_dept inner join s_region on s_dept.region_id = s_region.id;

案例讲解:
   -- 查询学生姓名、课程名称以及考试成绩,  涉及到三表连接
   select studentname 学生姓名, subjectname 课程名称, studentresult 考试成绩
   from student inner join result on student.studentno = result.studentno
   inner join subject on result.subjectid = subject.subjectid; 

练习:
   -- 查询年级编号为1的年级名称、科目名称及学时
   select gradename 年级名称, subjectname 课程名称, classhour 学时
   from grade inner join subject on grade.gradeid = subject.gradeid
   and subject.gradeid = 1;

   -- 查询学生学号、姓名、考试科目名称及成绩
   select student.studentno 学生学号, studentname 学生姓名, subjectname 科目名称, studentresult 学生成绩 from student inner join result 
   on student.studentno = result.studentno 
   inner join subject on subject.subjectid = result.subjectid;

   -- 查询参加“JavaSE”考试的学生姓名、成绩、考试日期
   select studentname 学生姓名, studentresult 学生成绩, examdate 考试日期
   from student inner join result on student.studentno = result.studentno
   and subjectid = ( select subjectid from subject 
	where subjectname = 'JavaSE');

1.4 左外连接
   左外连接主要指将满足匹配条件多张表都有的数据查询出来之后,还要将左表中拥有但右表中没有的数据查询出来的连接机制。
   语法格式:
      select [表名1.]字段名1, [表名2.]字段名2, ... from 表名1 left outer join        表名2 on 连接条件;
如:
   -- 从学生表和成绩表中查询学生姓名、课程编号以及考试成绩,  使用内连接
   select studentname, subjectid, studentresult from student
   inner join result on student.studentno = result.studentno;
   -- 从学生表和成绩表中查询学生姓名、课程编号以及考试成绩,  使用左外连接
   select studentname, subjectid, studentresult from student
   left outer join result on student.studentno = result.studentno;
   
   -- 从员工表和部门表中查询员工名字和部门的名称, 使用内连接
   select first_name, name from s_emp inner join s_dept
   on s_emp.dept_id = s_dept.id;
   -- 从员工表和部门表中查询员工名字和部门的名称, 使用左外连接
   select first_name, name from s_emp left outer join s_dept
   on s_emp.dept_id = s_dept.id;

1.5 右外连接
   右外连接主要指将满足匹配条件多张表都有的数据查询出来之后,还要将右表中拥有但左表中没有的数据查询出来的连接机制。
   语法格式:
      select [表名1.]字段名1, [表名2.]字段名2, ... from 表名1 right outer join       表名2 on 连接条件;
如:
   -- 从员工表和部门表中查询员工名字和部门的名称, 使用内连接
   select first_name, name from s_emp inner join s_dept
   on s_emp.dept_id = s_dept.id;
   -- 从员工表和部门表中查询员工名字和部门的名称, 使用左外连接
   select first_name, name from s_emp left outer join s_dept
   on s_emp.dept_id = s_dept.id; 

   -- 向部门表中插入一个新的部门,此时该部门就没有员工
   insert into s_dept values(55, '吹牛', 5);
   -- 从员工表和部门表中查询员工名字和部门的名称, 使用右外连接
   select first_name, name from s_emp right outer join s_dept
   on s_emp.dept_id = s_dept.id; 

   -- 使用左外连接来取代右外连接
   select first_name, name from s_dept left outer join s_emp
   on s_dept.id = s_emp.dept_id;

练习:
   -- 查询所有科目的考试信息   使用左外连接,让课程表作为左表 成绩表作为右表
   select subjectname 课程名称, examdate 考试日期, studentresult 考试成绩
   from subject left outer join result 
   on subject.subjectid = result.subjectid; 
   
   -- 查询所有考试的科目信息  使用右外连接,让课程表作为左表,成绩表作为右表
   select subjectname 课程名称, examdate 考试日期, studentresult 考试成绩
   from subject right outer join result 
   on subject.subjectid = result.subjectid;
   
   -- 查询从未考试的科目信息  也就是查询成绩表中没有的科目信息
   select subjectid 课程编号, subjectname 课程名称 from subject
   	where subjectid not in(select distinct subjectid from result); 
   
   -- 查询所有年级对应的学生信息 使用左外连接 年级表作为左表  学生表作为右表
   select gradename 年级名称, studentname 学生名称 from grade
       left outer join student on grade.gradeid = student.gradeid;
   
1.6 分页查询
   select 字段名1 [as 别名1], 字段名2 [as 别名2], ... from 表名 
   limit 初始位置(下标默认从0开始), 记录的条数;
如:
   -- 查询员工表中所有员工的名字和薪水
   select first_name, salary from s_emp;
   -- 采用分页技术来实现每10个员工信息显示为一页
   -- 查询到第一页信息
   select id, first_name, salary from s_emp limit 0, 10;
   -- 查询到第二页信息
   select id, first_name, salary from s_emp limit 10, 10;
   -- 查询到第三页信息
   select id, first_name, salary from s_emp limit 20, 10;
   -- 当删除完毕数据后也不会影响分页显示
   delete from s_emp where id = 2;

2.常用的约束(重点)
2.1 基本概念
   数据完整性约束主要用于防止错误数据的输入以及错误格式数据的输入等问题。
   数据完整性约束主要有:域完整性、实体完整性、引用完整性、自定义完整性.

2.2 主键约束
   主键约束要求该字段的数据必须唯一,并且不能为空,primary key。
如:
   -- 创建一张工人表,字段:工号
   create table t_worker (
       id int
   );
   -- 向工人表中插入数据内容
   insert into t_worker values(1);
   insert into t_worker values(2);
   -- 此时再次插入数据1不会报错,为了确保工号的唯一性就可以增加主键约束
   insert into t_worker values(1);
   -- 删除这张表
   drop table t_worker;

   -- 创建一张工人表,字段:工号
   create table t_worker (
       id int primary key
   );
   -- 向工人表中插入数据内容
   insert into t_worker values(1);
   insert into t_worker values(2);
   -- 当增加主键约束后,则插入相同工号时报错
   insert into t_worker values(1);
   -- 当增加主键约束后,则不允许插入空值
   insert into t_worker values(null);

2.3 唯一约束
   唯一约束主要用于要求该列的数据必须唯一,也就是不能重复但可以为空。
如:
   -- 创建t_worker表,字段有:工号,姓名,要求姓名唯一
   create table t_worker (
       id int primary key,
       name varchar(20) unique
   );
   
   -- 向表中插入数据
   insert into t_worker values(1, '张一');
   -- 当加入唯一性约束后,则下面的插入会报错
   insert into t_worker values(2, '张一');
   -- 当加入唯一性约束后,下面的插入不会报错
   insert into t_worker values(3, null);

   -- 删除表
   drop table t_worker;

2.4 非空约束
   非空约束主要用于要求该列的数据不能为空。
如:
   -- 创建t_worker表,字段有:工号,姓名,性别,要求性别不能为空
   create table t_worker (
       id int primary key,
       name varchar(20) unique,
       sex char(3) not null
   );
   
   -- 向表中插入数据
   insert into t_worker values(1, '张一', '男');
   -- 当加入非空约束后,则下面的代码会报错
   insert into t_worker values(2, '李敬强', null);
  
   -- 删除表
   drop table t_worker;

   -- 使用表级约束创建上述表格
   create table t_worker (
       id int,
       name varchar(20),
       constraint t_worker_id_pk primary key(id),
       constraint t_worker_name_uq unique(name)
   );

2.5 外键约束
   若当前表中的数据依赖于另外一张表中主键的数值时,就需要使用外键约束。
如:
   -- 创建一个用户表,字段有:用户编号,用户姓名
   create table t_user (
       id int primary key,
       name varchar(20) not null
   );
   
   -- 向表中插入数据
   insert into t_user values(1, '薛宇宸');
   insert into t_user values(2, '武志伟');
   
   -- 删除表格
   drop table t_user;

   -- 创建一个订单表,字段有:订单编号,订单描述, 用户编号
   create table t_order (
       oid int primary key,
       oname varchar(50) not null,
       uid int,
       -- 外键约束,在MySQL中只能使用表级约束
       constraint t_order_uid_fk foreign key(uid) references t_user(id)
   );
   
   -- 插入数据
   insert into t_order values(101, '一支笔', 1);
   insert into t_order values(102, '一本书', 2);
   insert into t_order values(103, '一个水杯', 3);

   -- 删除表
   drop table t_order;

   -- 直接删除t_user表中的数据报错,因为t_order表中的数据依赖于该表数据 
   delete from t_user where id = 2;   
   
   -- 先将从表t_order中的数据删除或置为空,然后再删除主表t_user中的数据
   delete from t_order where uid = 2;
   delete from t_user where id = 2;

   -- 直接将从表t_order删除,再删除主表t_user也可以,慎用!
   drop table t_order;
   drop table t_user;

     
----------------------------------------------------------------------------------------------------------


### MYSQL 05

2019/10/15 10:37:00 

----

###微信公众号的申请.

		步骤:
			1.	打开微信公众号官网:	https://mp.weixin.qq.com/	
			2.	点击立即注册
			3.	选择订阅号
			4.	填写信息:
				1 基本信息  2 选择类型  3 信息登记  4 公众号信息
	
				注意: 注册过个人微信的邮箱, 在注册公众号时不能使用. 



##JDBC * 

	Java DataBase Connectivity  Java数据库连接

	我们学习的技术是JDBC  不是 MYSQLJDBC  也不是 OJDBC

	JDBC是一套标准 ,Java与各大数据库厂商共同定制的一套接口. 这套接口由各大数据库厂商进行了实现.

###Jar文件的使用方式
	0.	在项目中, 创建一个文件夹 (lib)
	1.	在lib文件夹中粘贴jar文件
	2.	右键单击jar文件
	3.	选择build-path
	4.	选择add to build path
	

###使用步骤: *****
	
	1.	引入jar文件.
	2.	加载数据库驱动 (JavaSE项目中可以省略 , JavaWeb项目必须编写此步骤)
		Class.forName("com.mysql.jdbc.Driver");
	3.	通过驱动管理器, 获取JDBC连接对象.
		Connection conn = DriverManager.getConnection("数据库连接地址","帐号","密码");
		//	数据库连接地址格式:	主协议:子协议://ip地址:端口号/数据库名称
		//	mysql的连接地址:	jdbc:mysql://localhost:3306/java35
		//	oracle的连接地址: jdbc:oracle:thin:@localhost:1521:xe
	4.	通过连接对象, 创建SQL执行对象 (SQL执行环境)
		Statement state = conn.createStatement();

	5.	通过SQL执行对象 ,执行SQL语句.
		state.execute(String sql语句);

	6.	释放资源
		state.close();
		conn.close();


###JDBC中常用的类型与方法

	1.	DriverManager	:	驱动管理器
			常用方法:
				-	获取数据库连接:
					static Connection getConnection(String 数据库地址,String user ,String password)

	2.	Connection	:	数据库连接对象
			常用方法:
				-	创建SQL执行对象:	Statement createStatement();


	3.	Statement	:	SQL执行对象
			常用方法:
				-	执行SQL语句(查询语句返回true, 其它语句返回false)
						boolean execute(String sql);

				-	执行DML语句(INSERT UPDATE DELETE) 和 DDL语句(create alter drop) 
						(返回int, 表示语句对数据库表格的影响行数 !)
						(通常我们认为 返回值>0 表示执行成功.)
						int executeUpdate(String sql);
	
				-	执行DQL语句 (select) 
						ResultSet executeQuery(String sql);

	4.	ResultSet	:	结果集对象 (指的是一个select语句的查询结果)
			常用方法:
				1.	控制游标移动的常用方法:
						-	boolean next()	****
								作用:	控制游标向下一行移动.
								返回值:	移动成功返回true , 下一行不存在移动失败, 返回false
					
						-	boolean privious() 了解
								作用:	控制游标向上一行移动.
								返回值:	移动成功返回true , 上一行不存在移动失败, 返回false
					
						-	boolean absolute(int 行号) 了解
								作用:	控制游标向指定行移动
								返回值:	移动成功返回true , 行不存在移动失败, 返回false

						-	boolean beforeFirst()	了解
								作用:	控制游标移动到第一行
								返回值: 移动成功返回true, 没有第一行数据返回false

						-	boolean afterLast()	了解
								作用:	控制游标移动到最后一行
								返回值: 移动成功返回true, 没有最后一行数据返回false

					

				2.	获取游标指向行的 字段值的常用方法:
						-	XXX getXXX(String 列名) ***
								根据字段名, 得到此字段的值
			
						-	XXX getXXX(int 字段的索引) *
								根据字段的索引, 得到字段的值 , 索引从1开始


###SQL注入问题 * 

	进行用户登录时, 输入不存在的帐号 和 如下的密码:
		1' or '1'='1

	结果显示登录成功.

	因为用户输入的密码, 与我们的查询语句拼接后, 使得我们的查询语句产生了歧义:

	原查询语句:
		select id from user35 where username='帐号' and password='密码'
	拼接后:
		select id from user35 where username='帐号' and password='1' or '1'='1'

###解决sql注入问题 *

	我们可以将代码与参数分离:
	
		将未拼接参数的SQL语句, 作为SQL指令, 先传递给数据库 进行编译.
		再将需要传递的参数, 不作为指令 , 传递给数据库.

	需要使用到PreparedStatement执行环境类

###PreparedStatement 预编译的SQL执行环境

	内部实现原理:
		1.	将未拼接参数的SQL语句, 作为SQL指令, 先传递给数据库 进行编译.
		2.	再将参数传递给数据库, 此时传递的参数不会再作为指令执行, 只会被当作文本存在.

	操作流程与Statement基本一致:

		1.	如何得到一个PreparedStatement 对象
				PreparedStatement state = conn.prepareStatement("预编译的SQL语句");

		2.	预编译的SQL语句如何编写
				需要填充参数的位置, 使用?代替即可! 例如:
				select id from user35 where username=? and password=?

		3.	参数如何填充
				state.setXXX(int index,XXX value);
					setXXX中XXX指的是数据类型,
					参数1:	index	:	SQL语句中?的索引值 ,1开始
					参数2:	value	:	填充的参数值.

		4.	如何执行填充完毕参数的SQL
				-	boolean execute();
				-	int executeUpdate();
				-	ResultSet executeQuery();

###作业:

	通过控制台 , 完成学生信息管理系统 !

----------------------------------------------------------------------------------------------------------------------------
#JDBC 02 

2019/10/16 9:05:03 

----


###1.	JDBC高级技术 

####事务 熟悉

	概述:	将多条SQL语句, 看作一个整体. 要么一起成功, 要么一起失败.

	事务在mysql中, 是默认自动提交的 . 

#####操作方式1:	命令行
	
	-	开启事务:	start transaction;
	-	回滚	   :	rollback;	--此次事务中所有的sql操作, 放弃.
	-	提交	   :	commit;	--此次事务中所有的sql操作, 作为一个整体, 提交.

#####操作方式2:	Java
	
	JDBC事务通过连接对象开启, 回滚 ,提交. 只针对当前连接对象生效.

	-	开启事务:	conn.setAutoCommit(false);
	-	回滚事务:	conn.rollback();
	-	提交事务:	conn.commit();


#####面试题: *****
	
	1.	请描述事务的四大特征 : 
			<1>.	原子性:	事务是一个整体 , 不可分割 , 要么同时成功, 要么同时失败.
			<2>.	持久性:	当事务提交或回滚后, 数据库会持久化的保存数据.
			<3>.	隔离性:	多个事务之间, 隔离开, 相互独立.
			<4>.	一致性:	事务操作的前后 , 数据总量不变 (例如: 转账时: 孟亮给帅兵转账是一个事务, 转账完毕后. 两人余额的和不变.)

	2.	请描述什么是脏读, 幻读, 不可重复读 ?
			-	脏读:	读取到了一个事务 未提交的数据.
			-	不可重复读:	一个事务, 两次连续的读取 ,结果不一致.	
			-	幻读:	一个事务在执行DML语句时, 另一个事务也在执行DML语句 ,他们一起修改了同一个表格的数据.
		
	3.	请描述事务的隔离级别
			1.	读未提交	:	read uncommitted; (可能产生:脏读, 不可重复读, 幻读)
			2.	读已提交	:	read committed; (可能产生: 不可重复度, 幻读)
			3.	可重复读	:	repeatable read;(mysql默认值) (可能产生: 幻读)
			4.	串行化	:	serializable;

			-	查看数据库当前的隔离级别:	select @@tx_isolation; (了解)
			-	数据库设置隔离级别:	set global transaction isolation level 级别字符串; (了解)

####URL类 了解

	统一资源定位符, 简单理解为 网址.

####批处理 熟悉
	
	将多条语句, 放到一起批量处理 .
	批处理的原理:	将多条SQL语句, 转换为一个SQL指令.  显著的提高大量SQL语句执行时的数据库性能. 

	
	使用流程:
		1.	得到Statement对象
			Statement state = conn.createStatement();
		
		2.	将一条SQL语句, 加入到批处理中.
			state.addBatch(String sql);

		3.	执行批处理
			state.executeBatch();

####Properties 类 与 文件 了解

	Properties类 是Java中的Map集合的实现类.
	.properties文件 用于通过文件描述一组键值对!
	.properties文件 ,可以快速的转换为Properties类的对象.
	
	文件中内容的格式:
	    文件内容都是字符串 , 键与值之间通过等号连接 , 多个键值对之间换行分割.
	    例如:
	    url=xxx
	    user=xxx
	    password=xxx
	
	如何将文件 转换为 集合: 
	    步骤:
	        1.  创建Properties对象
	                Properties ppt = new Properties();
	        2.  创建一个字节输入流 , 指向.properties文件
	                InputStream is = new FileInputStream("文件地址");
	        3.  将字节输入流, 传递给properties对象, 进行加载.
	                ppt.load(is);
 
###2.	连接池(DataSource)的使用 *

	连接池用于缓存连接!

	当我们需要使用连接时, 可以不用再创建连接 ! 可以直接从连接池中获取连接.
	当连接池中存在空闲连接时, 会将空闲连接给到程序使用.
	当连接池中不存在空闲连接时, 且连接池未满时 , 则创建连接提供给程序使用 ,并在程序使用完毕后, 缓存连接.
	当连接池中不存在空闲连接时, 且连接池已满时 , 则排队等候空闲连接的出现.

	注意:
		使用连接池中的连接对象操作数据库时, 操作完毕依然需要释放连接(close()).
		连接池中的连接在设计时, 使用了动态代理设计模式+装饰者设计模式 . 我们调用它的close方法, 代理没有关闭这个连接, 而是将连接重新放入了池中.

####DBCP连接池的使用步骤 *

	1.	引入相关的jar文件
			-	dbcp.jar
			-	poll.jar

	2.	将配置文件引入
	3.	将配置文件, 转换为Properties对象
			Properties ppt = new Properties();
			ppt.load(配置文件的输入流);
	
	4.	通过连接池的工厂类(BasicDataSourceFactory)的创建连接池的方法(createDataSource())
			DataSource ds = BasicDataSourceFactory.createDataSource(ppt);

	5.	从连接池中 获取连接对象
			Connection conn = ds.getConnection();


####德鲁伊连接池的使用步骤 * 

	1.	引入相关的jar文件
			-	druid-1.0.9.jar
	2.	将配置文件引入
	3.	将配置文件, 转换为Properties对象
			Properties ppt = new Properties();
			ppt.load(配置文件的输入流);
	
	4.	通过连接池的工厂类(DruidDataSourceFactory)的创建连接池的方法(createDataSource())
			DataSource ds = DruidDataSourceFactory.createDataSource(ppt);

	5.	从连接池中 获取连接对象
			Connection conn = ds.getConnection();

----------------------------------------------------------------------------------------------------------------------------
#XML

2019/10/17 9:35:46 

----

##数据库连接池工具类:

###DBCP连接池:

	public class DBCPUtil{
		private static DataSource data = null;
		static {
			InputStream is = DBCPUtil.class.getClassLoader().getResourceAsStream("dbcp.properties");
			Properties ppt = new Properties();
			try {
				ppt.load(is);
				data = BasicDataSourceFactory.createDataSource(ppt);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		/**
		 * 用于从DBCP连接池中 获取一个连接
		 * @return DBCP连接池中的一个连接对象.
		 */
		public static Connection getConnection() {
			try {
				return data.getConnection();
			} catch (SQLException e) {
				e.printStackTrace();
				return null;
			}
		}
		
		/**
		 * 用于释放连接  , 执行环境 , 结果集 等资源
		 * @param conn 要释放的连接资源
		 * @param state	要释放的执行环境资源
		 * @param result 要释放的结果集资源
		 */
		public static void close(Connection conn,Statement state,ResultSet result) {
				if(result != null) {
					try {
						result.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(state != null) {
					try {
						state.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(conn != null) {
					try {
						conn.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
		}
	}


####Druid连接池工具类(德鲁伊连接池)

	public class DruidUtil{
		private static DataSource data = null;
		static {
			InputStream is = DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties");
			Properties ppt = new Properties();
			try {
				ppt.load(is);
				data = DruidDataSourceFactory.createDataSource(ppt);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		/**
		 * 用于从DBCP连接池中 获取一个连接
		 * @return DBCP连接池中的一个连接对象.
		 */
		public static Connection getConnection() {
			try {
				return data.getConnection();
			} catch (SQLException e) {
				e.printStackTrace();
				return null;
			}
		}
		
		/**
		 * 用于释放连接  , 执行环境 , 结果集 等资源
		 * @param conn 要释放的连接资源
		 * @param state	要释放的执行环境资源
		 * @param result 要释放的结果集资源
		 */
		public static void close(Connection conn,Statement state,ResultSet result) {
				if(result != null) {
					try {
						result.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(state != null) {
					try {
						state.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				if(conn != null) {
					try {
						conn.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
		}
	}

##Java 与 XML

	可扩展标记语言.

	特性:
		1.	xml具有平台无关性, 是一门独立的标记语言.
		2.	xml具有自我描述性

	用途:
		1.	网络数据传输. 
		2.	数据存储
		3.	配置文件		*


###XML语法格式 ***

	XML文档通常存储在.xml文件中.

	1.	XML文档声明
		<?xml version="1.0" encoding="UTF-8"?>

	2.	标记 ( 元素 / 标签 / 节点)  
			XML文档,由一个个的标记组成.
			语法:
				开始标记(开放标记):	<标记名称>
				结束标记(闭合标记):	</标记名称>

				标记名称:	自定义名称, 命名规则参考 Java的标识符命名规则.
				标记内容:	开始标记与结束标记之间 ,是标记的内容.

			例如 ,我们通过标记, 描述一个人名:
				<name>马帅兵</name>
	
	3.	一个XML文档中, 必须有且且仅允许有一个根标记.
			正例:
				<names>
					<name>帅兵</name>
					<name>孟亮</name>
				</names>
			反例:
				<name>帅兵</name>
				<name>孟亮</name>

	4.	标记可以嵌套, 但是不允许交叉.
			正例:
				<person>
					<name>帅兵</name>
					<age>18</age>
				</person>
			反例:
				<person>
					<name>帅兵<age></name>
					18</age>
				</person>

	5.	标记的层级称呼 (子标记, 父标记 , 兄弟标记, 后代标记 ,祖先标记)
			例如:
				<persons>
					<person>
						<name>帅兵</name>
						<length>180cm</length>
					</person>
					<person>
						<name>孟亮</name>
						<length>200cm</length>
					</person>
				</persons>

			name是person的子标记.也是person的后代标记
			name是persons的后代标记.
			name是length的兄弟标记.
			person是name的父标记.
			persons是name的祖先标记.
			
	6.	标记名称 允许重复
	7.	标记除了开始和结束 , 还有属性.
			标记中的属性, 在标记开始时 描述, 由属性名和属性值 组成.
			格式:
				在开始标记中, 描述属性.
				可以包含0-n个属性, 每一个属性是一个键值对!
				属性名不允许重复 , 键与值之间使用等号连接, 多个属性之间使用空格分割.
				属性值 必须被引号引住.

			案例:
				<persons>
					<person id="10001" age="18">
						<name>帅兵</name>
						<length>180cm</length>
					</person>
					<person id="10001" age="19">
						<name>孟亮</name>
						<length>200cm</length>
					</person>
				</persons>

	8.	注释
			多行注释:
				注释开始:	<!--
				注释结束:	-->

####案例 , 描述一组学生, 存储到students.xml中

	<?xml version="1.0" encoding="UTF-8"?>
<students>
	<student id="1">
		<name>小泽马老师</name>
		<age>18</age>
	</student>
	<student id="2">
		<name>武藤马老师</name>
		<age>18</age>
	</student>
	<student id="3">
		<name>php马老师</name>
		<age>18</age>
	</student>
</students>

####练习:	
	
	描述一组图书books, 至少包含3本书
			图书book包含 
				图书名称name 
				图书简介info , 
				以及属性id 	

	<?xml version="1.0" encoding="UTF-8"?>
	<books>
		<book id="1">
			<name>金苹果</name>
			<info>讲述了果农种植苹果的艰辛历程.</info>
		</book>
		<book id="2">
			<name>银苹果</name>
			<info>讲述了果农种植苹果的艰辛历程2.</info>
		</book>
		<book id="3">
			<name>铜苹果</name>
			<info>讲述了果农种植苹果的艰辛历程3</info>
		</book>
	</books>

###Java解析XML 掌握


####面试题 *****: Java中有几种XML解析方式 ? 分别是什么 ? 有什么样的优缺点 ?:
	
		方式可以回答:	两种或四种.
	
		1.	SAX解析
				解析方式是事件驱动机制 !
				SAX解析器, 逐行读取XML文件解析 , 每当解析到一个标签的开始/结束/内容/属性时,触发事件.
				我们可以编写程序在这些事件发生时, 进行相应的处理.
				
				优点:
					在读取大文件时, 节省内存.

				缺点:
					1.	因为逐行解析, 当解析第n行是, 第n-1行已经被释放了, 无法在进行操作了.
					2.	因为事件驱动机制 , 我们无法得知事件发生时元素的层次, 只能自己添加标记来感知.
					3.	SAX解析的方式, 是只读解析方式, 无法修改XML文档的内容.

		2.	DOM解析
				直接将整个文档 , 加载到内存, 在内存中建立文档树模型.
				程序员可以通过操作文档树, 来完成数据的获取 修改 删除等.
	
				优点:
					文档在内存中加载, 可以任意的读取, 修改和删除.

				缺点:
					文档全部加载在内存中 , 浪费我们大量的内存, 无法解析大文件.
	

		3.	JDOM解析
				是DOM解析的扩展 ,与DOM解析优缺点完全一致;

		4.	DOM4J解析
				是DOM解析的扩展 ,与DOM解析优缺点完全一致;


####DOM4J解析XML 掌握

	步骤:

		1.	引入jar文件 dom4j.jar
		2.	创建一个指向XML文件的输入流
				FileInputStream fis = new FileInputStream("xml文件的地址");
		3.	创建一个XML读取工具对象
				SAXReader sr = new SAXReader();
		4.	使用读取工具对象, 读取XML文档的输入流 , 并得到文档对象
				Document doc = sr.read(fis);	
		5.	通过文档对象, 获取XML文档中的根元素对象
				Element root = doc.getRootElement();


####文档对象 Document
	
	指的是加载到内存的 整个XML文档.

	常用方法:
		1.	通过文档对象, 获取XML文档中的根元素对象
				Element root = doc.getRootElement();

		2.	添加根节点
				Element root = doc.addElement("根节点名称");

####元素对象 Element

	指的是XML文档中的单个节点.

	常用方法:
		1.	获取节点名称
				String getName();
		2.	获取节点内容
				String getText();
		3.	设置节点内容
				String setText();
		4.	根据子节点的名称 , 获取匹配名称的第一个子节点对象.
				Element element(String 子节点名称);
		5.	获取所有的子节点对象
				List<Element> elements();
		6.	获取节点的属性值
				String attributeValue(String 属性名称);
		7.	获取子节点的内容
				String elementText(String 子节点名称);
		8.	添加子节点
				Element addElement(String 子节点名称);
		9.	添加属性
				void addAttribute(String 属性名,String 属性值);

####解析本地文件案例:

		//1.	获取文件的输入流
		FileInputStream fis = new FileInputStream("C:\\code\\35\\code1\\day03_XML\\src\\books.xml");
		//2.	创建XML读取工具对象
		SAXReader sr = new SAXReader();
		//3.	通过读取工具, 读取XML文档的输入流 , 并得到文档对象
		Document doc = sr.read(fis);
		//4.	通过文档对象 , 获取文档的根节点对象
		Element root = doc.getRootElement();
		//5.	通过根节点, 获取所有子节点
		List<Element> es = root.elements();
		//6.	循环遍历三个book
		for (Element e : es) {
			//1.	获取id属性值
			String id = e.attributeValue("id");
			//2.	获取子节点name , 并获取它的内容
			String name = e.element("name").getText();
			//3.	获取子节点info , 并获取它的内容
			String info = e.element("info").getText();
			System.out.println("id="+id+",name="+name+",info="+info);
		}

####解析网络文件案例:

		Scanner input = new Scanner(System.in);
		System.out.println("欢迎使用xxx手机号码查询系统");
		System.out.println("请输入你要查询的手机号:");
		String phone = input.nextLine();
		// 1. 得到指向XML文件的输入流
		URL url = new URL(
				"http://apis.juhe.cn/mobile/get?phone=" + phone + "&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253");
		URLConnection conn = url.openConnection();
		InputStream is = conn.getInputStream();
		//2.	创建XML读取工具对象
		SAXReader sr = new SAXReader();
		//3.	通过XML读取工具对象, 读取输入流 ,得到文档对象
		Document doc = sr.read(is);
		//4.	获取文档的根节点
		Element root = doc.getRootElement();
		//5.	获取子节点error_code , 判断是否出错.
		String errorCode = root.elementText("error_code"); 
		if("0".equals(errorCode)) {
			//服务器回复的数据是查询成功
			Element result = root.element("result");
			System.out.println("查询结果如下:");
			String province = result.elementText("province");
			String city = result.elementText("city");
			if(!province.equals(city))
				System.out.println("\t省份:"+province);
			System.out.println("\t城市:"+city);
			System.out.println("\t区号:"+result.elementText("areacode"));
			System.out.println("\t邮编:"+result.elementText("zip"));
			System.out.println("\t运营商:"+result.elementText("company"));
		}else {
			System.out.println("请检查手机号码格式是否正确!");
		}


####DOM4J - XPATH解析XML  了解

	通过路径快速的查找一个或一组元素

	路径表达式:
		1.	/	:	从根节点开始查找
		2.	//	:	从发起查找的节点位置 查找后代节点  ***
		3.	.	:	查找当前节点
		4.	..	:	查找父节点
		5.	@	:	选择属性. *   
					属性使用方式:
					[@属性名='值']
					[@属性名>'值']
					[@属性名<'值']
					[@属性名!='值']

####XPATH使用
	
	通过Node类的两个方法, 来完成查找:
	(NodeDocumentElement 的父接口)

	方法1.	
		//根据路径表达式, 查找匹配的单个节点
		Element e = selectSingleNode("路径表达式");

	方法2.
		List<Element> es = selectNodes("路径表达式");


	案例:

		//1.	获取文件的输入流
		FileInputStream fis = new FileInputStream("C:\\code\\35\\code1\\day03_XML\\src\\books.xml");
		//2.	创建XML读取工具对象
		SAXReader sr = new SAXReader();
		//3.	通过读取工具, 读取XML文档的输入流 , 并得到文档对象
		Document doc = sr.read(fis);
		//4.	通过路径, 快速获取第一个name值
		Element name = (Element) doc.selectSingleNode("//name");
		System.out.println(name.getText());
		
		Element name2 = (Element) doc.selectSingleNode("//book[@id='3']//name");
		System.out.println(name2.getText());
		
		List<Element> es = doc.selectNodes("//info");
		for (Element e : es) {
			System.out.println(e.getText());
		}

###Java生成XML 熟悉

	步骤:
		1.	通过文档帮助器 (DocumentHelper) , 创建空的文档对象
				Document doc = DocumentHelper.createDocument();

		2.	通过文档对象, 向其中添加根节点
				Element root = doc.addElement("根节点名称");
	
		3.	通过根节点对象root , 丰富我们的子节点
				Element e = root.addElement("元素名称");

		4.	创建一个文件输出流 ,用于存储XML文件
				FileOutputStream fos = new FileOutputStream("要存储的位置");
		
		5.	将文件输出流, 转换为XML文档输出流
				XMLWriter xw = new XMLWriter(fos);	

		6.	写出文档
				xw.write(doc);

		7.	释放资源
				xw.close();

	案例:
			//1.	通过文档帮助器, 创建空的文档对象
			Document doc = DocumentHelper.createDocument();
			//2.	向文档对象中, 加入根节点对象
			Element books = doc.addElement("books");
			//3.	向根节点中 丰富子节点
			for(int i=0;i<1000;i++) {
				//向根节点中加入1000个book节点.
				Element book = books.addElement("book");
				//向book节点, 加入id属性
				book.addAttribute("id", 1+i+"");
				//向book节点中加入name和info节点
				Element name = book.addElement("name");
				Element info = book.addElement("info");
				name.setText("苹果"+i);
				info.setText("哈哈哈"+i);
			}
			//4.	创建文件的输出流
			FileOutputStream fos = new FileOutputStream("c:\\books.xml");
			//5.	将文件输出流 , 转换为XML文档输出流
			XMLWriter xw = new XMLWriter(fos);
			//6.	写出XML文档
			xw.write(doc);
			//7.	释放资源
			xw.close();
			System.out.println("代码执行完毕");

###XStream 的使用  了解

	快速的将Java中的对象, 转换为 XML字符串.

	使用步骤:
		1.	创建XStream 对象
			XStream x = new XStream();

		[2].修改类生成的节点名称 (默认节点名称为 包名.类名)
			x.alias("节点名称",类名.class);

		3.	传入对象 , 生成XML字符串
			String xml字符串 = x.toXML(对象);

	案例:
		Person p = new Person(1001, "小泽马老师", "不详");
		XStream x = new XStream();
		x.alias("haha", Person.class);
		String xml = x.toXML(p);
		System.out.println(xml);
-------------------------------------------------------------------------------------------------------------------------
=============================================================================
前端Html
=============================================================================


#前端01 - HTML 

2019/10/18 8:52:05 

----

### 课程安排
	
	1- html
	2- css
	2- JavaScript

	2- Jquery
	2- bootstrap+vue

### HTML简介

	超文本 标记语言 . 	由W3C组织维护的一门标记语言 , 是用于描述网页的标记语言.

### HTML 发展史


	互联网泡沫的破裂. 

	97年推出 HTML4.0版本
	99年推出 HTML4.0.1版本

	201410月 推出HTML5.0

### HTML语法格式 ***

	语法格式 与 XML基本一致的.
	HTML文档通常存储在.html 文件中 或 htm文件中.

	基础网页模板:

		由三部分组成.
			1.	HTML文档声明
				<!DOCTYPE html>
				<html>
			2.	网页标签 - 头部 : 用于描述网页
					<head>
						<title>我们的第一个网页</title>
					</head>
			3.	网页标签 - 主体 : 网页显示的内容
					<body>Hello HTML</body>
				</html>

### head 中的常用子标签

	-	title	:	网页的标题 , 在浏览器的标签位置显示..
	-	meta	:	描述网页的编码, 移动设备优先 , 也常用于通知搜索引擎蜘蛛 搜索关键字.
	-	style	:	用于描述样式表 , style标签中的语法格式 按照CSS格式编写.
	-	script	:	用于描述脚本 , script标签中的语法格式, 按照JavaScript语法编写.
	-	link	:	用于引入外部的样式表.

### 网页中描述颜色值:

	两种方式, 来描述网页中的颜色:
		1.	不推荐:	通过颜色的单词,来描述颜色, 例如: 红色 red
		2.	推荐:	通过三原色调色板, 来设置颜色:
				格式1:	#RGB (R表示红色  G表示绿色  B表示蓝色)
						(每一个R/G/B的值都是116进制的数字0-f , 表示的是颜色的亮度, 例如:#f00 正红色, #060 暗绿色)
				格式2:	#RRGGBB (R表示红色  G表示绿色  B表示蓝色)
						(每一个RR/GG/BB的值都是216进制的数字00-ff , 表示的是颜色的亮度, 例如:#ff0000 正红色, #006600 暗绿色)	
				格式3:	rgb(r值,g值,b值)  (R表示红色  G表示绿色  B表示蓝色)
						(每一个R/G/B的值都是110进制的数字0-255 , 表示的是颜色的亮度, 例如:rgb(255,0,0) 正红色, rgb(255,255,255) 白色)
				格式4:	rgba(r值,g值,b值,a值)  (R表示红色  G表示绿色  B表示蓝色 a表示透明度)
						(每一个R/G/B的值都是110进制的数字0-255 , 表示的是颜色的亮度, 例如:rgb(255,0,0) 正红色, rgb(255,255,255) 白色)	
						(a的值表示透明度, 是一个0-1的浮点型数字. 0表示完全透明,0.5表示半透明 1表示完全不透明.)

### HTML中 如何引入文件 
	
	通过文件的路径, 来引入文件.
		路径的使用方式:
			1.	本地相对路径:
					指的是相对当前代码所在位置, 描述路径.
					例如: 在c:\x\y\demo.html 中出现了相对路径: 美女与野兽.jpg
						  图片的真实路径是:	c:\x\y\美女与野兽.jpg
					例如: 在c:\x\y\demo.html 中出现了相对路径: ../美女与野兽.jpg
						  图片的真实路径是:	c:\x\美女与野兽.jpg
					例如: 在c:\x\y\demo.html 中出现了相对路径: images/shuaibingphp.mp4
						  图片的真实路径是:	c:\x\y\images\shuaibingphp.mp4
			2.	本地绝对路径 (不建议使用, web项目中,用户没有权限访问.)
					指的是从盘符开始描述的路径:
					例如:	在c:\x\y\demo.html 中出现了绝对路径: d:\a.mp3
						  	真实路径是:	d:\a.mp3
			3.	网络路径 : 就是网址;


###网页中的长度单位

	常见:
		-	px	:	像素
		-	em	:	常用于设置文字.  1em表示默认的1个文字大小, 1.5em 表示文字大小的1.5-	x%	:	占用父元素的百分比


	不常见:	
		-	pc	:	派卡
		-	in	:	英寸
		-	mm	:	毫米
		-	cm	:	厘米
		-	m	:...

### body标签的常用属性.

		-	bgcolor	:	用于设置背景颜色.
		-	background : 用于设置背景图片.
		-	text	:	用于设置网页中的文本颜色

### body 常用子标签 * 

	注意: 标签是可以嵌套的.

	1.	标题标签
			<h1></h1>	一级标题	(建议一个网页只有一个一级标题.)
			<h2></h2>	二级标题
			...
			<h6></h6>	六级标题

	2.	文字格式化标签  (HTML5版本 大多被废弃了.)
			<b>文本加粗</b>
			<i>文本斜体</i>
			<del>文本添加删除线</del>
			<u>下划线</u>
			<center>内容居中</center>
	
	3.	空格 / 换行 / 段落
			
			&nbsp;	空格
			<br>	换行
			<hr>	换行并添加分割线
			<p></p>	文章的一个段落 (上下换行并设置默认间隔)

	4.	原样显示标签:
			按照编写的代码格式, 原样显示.
			<pre></pre>

	5.	超链接标签 a 
			常用使用方式:
				1.	用于网页跳转:
						<a href="跳转的地址">显示的内容</a>
				2.	用于新窗口打开:
						<a href="打开的地址" target="_blank">显示的内容</a>

			不常用使用方式 (了解):
				1.	调用邮件客户端 发送邮件 (需要安装邮箱软件)
						<a href="mailto:邮件地址">显示的内容</a>
				2.	用于拨打电话 (需要安装电话软件, 常见于手机网页)
						<a href="tel:电话号">显示的内容</a>
				3.	发起QQ临时会话 (QQ需要设置允许临时会话)
						<a href="https://wpa.qq.com/msgrd?v=3&uin=QQ号码&site=qq&menu=yes"></a>
				4.	锚点的使用
						网页内容过于多时,  可以通过在网页中加入锚点的方式, 让用户快速的到达网页的某个位置;
						1.	建立锚点
								编写a标签 , 给a标签设置name属性值 , name属性值就是锚点的名称
						2.	使用锚点
								使用本页的锚点:	<a href="#锚点名称"></a>
								使用其他页面的锚点: <a href="网页地址#锚点名称"></a>

###title属性

	所有标签都可以加入title属性, 效果是: 在鼠标悬停时, 弹出文字描述.


###多媒体标签 掌握

	-	图片标签 img  ***
			属性:
				-	src	:	图片地址 (可支持常见的大多图片格式)
				-	alt	:	当图片地址出错, 加载失败时, 显示的文字内容.
				-	width :	宽度
				-	height: 高度
				注意:	宽度和高度不建议同时设置,  会导致图片拉伸, 
						图片的宽度和高度在设置任意一个时,  另外一个会自动按比例缩放 .

	-	音乐标签 audio
			属性:
				-	src	:	音乐资源地址 , 通常指的是mp3 .
				-	autoplay : 是否自动播放 , HTML5版本的boolean属性 , 属性一旦出现就是true.
				-	controls : 是否显示控制器 , HTML5版本的boolean属性 , 属性一旦出现就是true.

	-	视频标签 video
			属性:
				-	src	:	视频资源地址 , 通常指的是mp4 .
				-	autoplay : 是否自动播放 , HTML5版本的boolean属性 , 属性一旦出现就是true.
				-	controls : 是否显示控制器 , HTML5版本的boolean属性 , 属性一旦出现就是true.
				-	width	:	视频播放窗口的宽度
				-	height	:	视频播放窗口的高度

	-	动画标签 embed
			属性:
				-	src	:	动画资源地址 , 通常指的是swf .
				-	width	:	动画播放窗口的宽度
				-	height	:	动画播放窗口的高度

###组合标签

####列表标签

	-	有序列表 ol
			
	-	无序列表 ul

	在上述的两个列表标签中, li标签表示列表中的一行数据.

	案例:
		<h3>有序列表</h3>
		<ol>
			<li>床前明月光 , </li>
			<li>地上鞋一堆 !</li>
			<li>床上马帅兵 ,</li>
			<li>喊十块一双 !</li>
		</ol>
		<h3>无序列表</h3>
		<ul>
			<li>床前明月光 , </li>
			<li>地上鞋一堆 !</li>
			<li>床上马帅兵 ,</li>
			<li>喊十块一双 !</li>
		</ul>

表格标签
	在网页中编写表格标签, 通过三个标签来完成:

		1.	表格本身:	table
		2.	表格中的行:	tr
		3.	行中的列:	td (表头列为th)

	属性:
		-	width:	设置table/td的宽度 ,设置td宽度时, 会导致所有行的当前列的宽度变化
		-	height: 设置table/td的高度 ,设置td高度时, 会导致当前行的行高发生改变.
		-	border:	数字值 , 边框的宽度,默认值为0, 单位是px
		-	bordercolor: 边框颜色
		-	bgcolor: 设置table/td的背景颜色
		-	background:设置table/td的背景图片.

	代码案例:

		<h3>表格标签 - 用户表格</h3>
		<table border="1" width="100%" height="300px">
			<tr><th>编号</th><th>帐号</th><th>密码</th><th>昵称</th><th>注册时间</th></tr>
			<tr><td>1</td><td>hahaha1</td><td>******</td><td>dsb帅兵</td><td>2019-10-18</td></tr>
			<tr><td>2</td><td>hahaha2</td><td>******</td><td>dsg帅兵</td><td>2019-10-18</td></tr>
			<tr><td>3</td><td>hahaha3</td><td>******</td><td>xsb帅兵</td><td>2019-10-18</td></tr>
			<tr><td>4</td><td>hahaha4</td><td>******</td><td>xsg帅兵</td><td>2019-10-18</td></tr>
			<tr><td>5</td><td>hahaha5</td><td>******</td><td>heiheihei帅兵</td><td>2019-10-18</td></tr>
		</table>
 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
评论

打赏作者

枝头小寨

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值