概念:所谓的数据库就是指存储和管理数据的仓库。
扩展内容1:数据库有哪些分类?(了解)
早期: 层次式数据库、网络型数据库(已过时)
现在:关系型数据库、非关系型数据库
总结:数据库比文件直接存数据,更安全,更可靠,大部分还是关系型数据库。
扩展内容2:一些工具的使用注意事项。
pdf 能看不能编辑
.md文件 可以编辑,需要安装typoa软件
扩展内容3:Dos窗口基本注意事项。
外面往Dos窗口粘贴: 先复制 在DOS窗口鼠标右键空白处即可
Dos窗口往外面复制黏贴:
win7 先标记(右键-->标记--然后在空白处右键,在复制的地方ctrl v
win8 win 10 不用标记
在DOS窗口中写错数据不能返回上一行,只能同行返回。建议在外面写出后复制过去。
想用Dos窗口以前的命令:上下箭头进行切换 (只能是同一个窗口)
扩展内容4:typora打开黑屏的解决方式
右键点击typora.exe,“属性”——“兼容性”,勾选“以兼容模式运行这个程序”,
在下拉菜单里选择“Windows Vista (Service Pack 1)”,确定后再重新打开typora。
底层以二维表(有行有列)的形式保存数据的库就是关系型数据库
stu-学生表
学生编号 | 姓名 | 年龄 |
---|---|---|
1001 | 刘沛霞 | 35 |
1002 | 陈子枢 | 18 |
扩展内容2:常见的关系型数据库有哪些?(了解)
Sql Server:微软提供,收费,适用于一些中型或大型的项目中,在java中的使用占比不高(.NET中使用的较多)
Oracle:甲骨文公司提供,收费,适用于一些大型或者超大型的项目中,在java中的使用占比非常高
mysql:瑞典MySQLAB公司提供,免费开源,适用于一些小型或者中型的项目中,在Java中的使用占比较高(小巧轻量) 被Oracle收购后现在变成了收费。
mariadb其实就是MySQL的一个分支,用法和MySQL完全一样。免费
DB2:IBM公司提供,收费,在一些银行、金融等行业中使用较多。在java中的使用占比也不高。
Sqlite:迷你数据库,嵌入式设备中(安卓、苹果手机、pad)
1)、什么是数据库服务器
数据库服务器就是一个软件(比如mysql软件)将数据库软件安装在电脑上,当前电脑就是一个数据库服务器。就可以对外提供存取数据的服务。
在一个数据库服务器中可以创建多个数据库(dataBases),每一个数据库都是一个单独的仓库。
2)、什么是数据库
数据库就是存储和管理数据的仓库,通常情况下,一个网站的中的所有数据会存放在一个数据库中。例如:
jd.com db_jd(数据库)
taobao.com db_taobao(数据库)
...
3)、什么是表
一个数据库中可以创建多张表,每张表用于存储一类信息(数据库),例如:
jd.com中的用户数据 tb_user(表)
jd.com中的商品数据 tb_product(表)
jd.com中的订单数据 tb_order(表)
4)、什么表记录·
一张表中可以包含多行表记录,每一行表记录用于存储某一个具体的数据>
学生编号 | 姓名 | 年龄 |
---|---|---|
1001 | 刘沛霞 | 35 |
1002 | 陈子枢 | 18 |
。。。 | 。。。 | 。。。 |
SQL是一门用于操作关系型数据库的通用的语言(即 使用SQL可以操作所有的关系型数据库)。
使用SQL可以操作数据库、表、表记录:
(1)创建数据库、删除数据库、修改数据库、查询数据库
(2)创建表、删除表、修改表、查询表
(3)新增表记录、删除表记录、修改表记录、查询表记录
使用SQL也可以操作存储过程/视图/索引等:
提示:SQL是一个标准通用的操作关系型数据库的语言(普通话),每个数据库厂商为了增强自己数据库的功能,都提供了支持自己数据库的语言,称之为数据库的方言。方言不通用!
通过命令行工具 或者第三方的工具如:Navicat , SQLyog等,可以登录MySQL客户端,连接MySQL服务器,从而访问服务器中的数据。
1)、连接mysql服务器:
显示密码输入:
mysql -uroot -p密码 -- 注意空格 这个没有分号特殊.其他的sql语句每句话几乎都有分号结尾.
不显示密码输入:
输入密码 可以写 -P +回车 (密码在下一行书写)
-u后面的root是用户名,这里使用的是超级管理员root; (mysql默认的用户名就是root)
-p 后面的root是密码,这是在安装MySQL时就已经指定的密码;
注意 :这里的u和p字母小写。
2)、连接mysql服务器并指定IP和端口:
mysql -uroot -proot -h127.0.0.1 -P3306
-h:后面的127.0.0.1是服务器主机名或ip地址,默认连接的是本机(127.0.0.1),本机可省略。
-P(大写的P)后面的3306是连接端口,默认连接的是3306端口 ,3306端口可以省略;
3)、退出客户端命令:quit或exit或 \q
没有退出:DOS窗口左侧目录显示显示MariaDB.
解决方法:复制mysql安装目录下的bin目录的路径,将bin目录的路径添加到path环境变量中!!
把mysql安装目录放到最前面 用 “ ,”隔开。 win7
win8 win10 没有分号。 编辑后上移即可。
重装 mysql要先停用服务:
计算机—右键管理----服务和应用程序 ,服务----mysql(mariadb)—右键—停止 右键属性—启动类型—手动或禁用. 每次开启计算机它会随着操作系统会自动启动.
1.SQL语句对大小写不敏感。推荐关键字使用大写,自定义的名称(库名,表名,列名等)使用小写。
2. cmd窗口出现 syntax , syntax 语说明法有问题 (语法)
3.在cmd中连接mysql服务器之后,可以使用 #、/**/、-- 等符号添加注释。(注意: --
这个注释后面先要加空格)
4.在cmd中连接mysql服务器之后,在书写SQL语句时,可以通过 \c 取消当前语句的执行。
5.注意在sql语句中写的都是英文符号,java也是不要写成中文.可以再输入法中设置标点符号为英文的格式.在输入法上右键–设置—勾选在中文是使用英文标点—确定.
6.在自定义名称时,针对多个单词不要使用驼峰命名,而是使用下划线连接。(例如:tab_name,而不是 tabName )
7.SQL语句中的值为字符串或日期时,值的两边要加上单引号(有的版本的数据库双引号也可以,但推荐使用单引号)。
8.(针对cmd窗口)在插入数据之前,先设置编码:set names gbk; 因为cmd窗口默认是gbk或者用以下命令连接mysql服务器:
mysql --default-character-set=gbk -uroot -proot
等价于:
mysql -uroot -proot
set names gbk;
注意删数据库不要把它系统自带的数据库删除: mysql,information_schema, performance_schema。
提示:
(1)SQL语句对大小写不敏感。推荐关键字使用大写,自定义的名称(库名,表名,列名等)使用小写。
SHOW DATABASES; -- 查看当前数据库服务器中的所有库 多个s query:查询
CREATE DATABASE mydb1; -- 创建mydb1库 database 数据库
(2)并且在自定义名称时,针对多个单词不要使用驼峰命名,而是使用下划线连接。(例如:tab_name,而不是 tabName )
– 01.查看mysql服务器中所有数据库
show databases; -- 查看服务器所有的数据库
show tables; -- 查询当前库所有表 table表
– 02.进入某一数据库(先进入数据库后,才能操作库中的表和表记录)
– 语法:USE 库名;
use mysql;-- 进入到"mysql"数据库
show tables; -- 查询当前库所有表
– 查看已进入的库(了解)
select database(); -- select选择,选定 这个语法比较特殊
– 03.查看当前数据库中的所有表
-- 先进入某一个库,再查看当前库中的所有表
use test;
show tables;
– 04.删除mydb1库
– 语法:DROP DATABASE 库名;
drop database mydb1;-- 删除mydb1库,但如果删除的库不存在,则会报错。 drop 减少
-- 思考:当删除的库不存在时,如何避免错误产生?
drop database if exists mydb1;
-- 如果mydb1库存在则删除,如果不存在,也就不会执行删除操作。
– 05.重新创建mydb1库,并指定编码为utf8
– 语法:CREATE DATABASE 库名 CHARSET 编码;
– 需要注意的是,mysql中不支持横杠(-),所以utf-8要写成utf8;
create database mydb1 charset utf8;-- 字符集和 charset
– 如果不存在则创建mydb1;
创建数据库需要先判断是否有一个同名的数据库,有需要先进行删除操作(因为不能在创建一个相同名字的数据库),之后再进行创建.
create database if not exists mydb1 charset utf8;
– 06.查看建库时的语句(并验证数据库库使用的编码) 这个主要是验证数据库的编码用的(了解)
– 语法:SHOW CREATE DATABASE 库名; 直接在创建数据库的语句前加个 show
show create database mydb1;
注意:对表进行操作需要先进入到数据库。
总结: 对数据库和表的创建和删除,查看 都是 create drop show,创建和删除都是先进行判断,创建是不存在创建数据库,而表是先删除表在创建.
– 07.进入mydb1库,删除stu学生表(如果存在)
– 语法:DROP TABLE 表名; 注意多条sql语句可以一起执行前提是有分号(;)隔开.
use mydb1;-- 进入到mydb1库
drop table if exists stu;-- 如果存在stu表,则删除
– 08.创建stu学生表(编号[数值类型]、姓名、性别、出生年月、考试成绩[浮点型]),建表的语法:
CREATE TABLE 表名(
列名 数据类型, (逗号分隔)
列名 数据类型,
...
列名 数据类型
);
SQL语句: 主键不一定是数值,也有可能是字符串,只有主键是数字的时候才能设置为自增.
-- 如果存在,则删除stu表
drop table if exists stu;
-- 创建stu学生表
create table stu( -- 先换行(shift+enter,单独的enter键是执行sql命令),在tab缩进一下
-- 如果id是主键并且是数值,可以设置为自增.可以保证每次的id值都不一样.
id int primary key auto_increment, -- 给id添加主键约束,并自增。
name varchar(50), -- 可变长字符串 ,50代表最多只能存50个字符。
gender varchar(10) not null, -- 给gender添加非空的约束。
birthday date,
score double -- 最后不需要逗号。列和列之间用 ,隔开
) ;
– 09.查看stu学生表结构
– 语法:desc 表名;
desc stu;
Null:表示将来给这些列插入值是否允许为空(yes代表允许) Default:表示如果不给值的话默认为null
– 10.往学生表(stu)中插入记录(数据)
– 语法:INSERT INTO 表名(列名1,列名2,列名3…) VALUES(值1,值2,值3…);
-- 如果是在cmd中执行插入记录的语句,先 set names gbk; 再插入记录!
-- 由于id已经设置了主键自增,所以再插入数据,id可以不用给值,但不可以不给,写个null。 在数据库中字符串和日期用单引号,不要写双引号。
insert into stu(id,name,gender,birthday,score) values(null,'tom','male','2000-3-4',89);-- 注意前后顺序一致.
insert into stu values(null,'john','male','2002-5-4',79);-- 同时插入多行数据,从第二行开始前面的那个()的内容可以省略.
insert into stu values(null,'andy','fmale','2004-5-4',69);-- insert 插入 into到...里面
-- 查询学生表中的所有记录
select*from stu; -- *代表所有的
提示:
(1)当为所有列插入值时,可以省写列名(从第二个),但值的个数和顺序必须和声明时列的个数和顺序保持一致!
(2)SQL语句中的值为字符串或日期时,值的两边要加上单引号(有的版本的数据库双引号也可以,但推荐使用单引号)。
(3)(针对cmd窗口)在插入数据之前,先设置编码:set names gbk; -- 因为cmd窗口默认是gbk
或者用以下命令连接mysql服务器:
mysql --default-character-set=gbk -uroot -proot
等价于:
mysql -uroot -proot
set names gbk;
– 11.查询stu表所有学生的信息
– 语法:SELECT 列名 | * FROM 表名
select * from stu; -- *代表所有 select几乎都是对表进行查询操作的,除了查看当前进入的库.
– 12.修改stu表中所有学生的成绩,加10分特长分
– 修改语法: UPDATE 表名 SET 列=值,列=值,列=值…[WHERE子句];
update stu set score=score+10; -- update更新 (不写条件代表更新所有的score)
-- score+=10 mysql中不支持+=
– 13.修改stu表中编号为1的学生成绩,将成绩改为83分。
update stu set score=83 where id=1;-- where一般用于语句中加个条件时,进行过滤用的
-- 修改3号学生的性别为'male',成绩改为99;
update stu set score=99,gender='male' where id=3;
提示:where子句用于对记录进行筛选过滤,保留符合条件的记录,将不符合条件的记录剔除。
– 14.删除stu表中所有的记录 (删除的语法是最简单的) 注意增删改查都是对表的记录进行操作的
– 删除记录语法: DELETE FROM 表名 [where子句]
delete from stu; -- 删除stu表中的所有记录 删除表中的记录用的是delete,那2个用的是drop
– 仅删除符合条件的 (删除是直接删,不像查询样考虑显示的数据,直接删就完了)
delete from stu where id>2; – 删除stu表中id大于2的记录
– 准备数据: 以下练习将使用db10库中的表及表记录,请先进入db10数据库!!!
SELECT 语句用于从表中选取数据。结果被存储在一个结果表中(称为结果集)。
语法:SELECT 列名称 | * FROM 表名
提示:(1) *(星号)为通配符,表示查询所有列。
select * from emp;
(2)但使用 *(星号)有时会把不必要的列也查出来了,并且效率不如直接指定列名
– 15.查询emp表中的所有员工,显示姓名,薪资,奖金
select name,sal,bonus from emp;
– 16.查询emp表中的所有部门和职位
select dept,job from emp;
比如想看 部门dept 和 讲师 job 的种类,每类只需要显示一条就行了。
思考:如果查询的结果中,存在大量重复的记录,如何剔除重复记录,只保留一条? */
剔除一个表中的重复记录
– 在select之后、列名之前,使用DISTINCT 剔除重复的记录
select distinct dept,job from emp; -- distinct 不同种类的
WHERE子句查询语法:SELECT 列名称 | * FROM 表名称 WHERE 列 运算符 值
WHERE子句后面跟的是条件,条件可以有多个,多个条件之间用连接词(or | and)进行连接
下面的运算符可在 WHERE 子句中使用:
– 17.查询emp表中【薪资大于3000】的所有员工,显示员工姓名、薪资
select name,sal from emp where sal>3000;
– 18.查询emp表中【总薪资(薪资+奖金)大于3500】的所有员工,显示员工姓名、总薪资
select name,sal+bonus from emp ; -- 求所有员工的总薪资
select name,sal+bonus from emp
where sal+bonus>3500;
–如果将’韩少云’的奖金更新为null值,在执行上面的SQL语句,会有问题吗?(null+任何值=null)
update emp set bonus=null where name='韩少云';
在进行查询:可以看出韩少云,薪资 sal=5000应该>3500,但是奖金为null,所以相加为null值。显示不出来。
– ifnull(列名, 值)函数: 判断指定的列是否包含null值,如果有null值,用第二个值替换null值
(null一般用0替换)
select name,sal+ifnull(bonus,0) from emp
where sal+ifnull(bonus,0)>3500;
– 注意查看上面查询结果中的表头,如何将表头中的 sal+bonus 修改为 “dec总薪资”
注意列别名不能用在where子句里面
– 使用as
可以为表头指定别名
select name as 姓名,sal+ifnull(bonus,0) as 总薪资 from emp
where sal+ifnull(bonus,0)>3500;
– 另外as可以省略
select name 姓名,sal+ifnull(bonus,0) 总薪资 from emp
where sal+ifnull(bonus,0)>3500;
– 19.查询emp表中【薪资在3000和4500之间】的员工,显示员工姓名和薪资
select name, sal from emp
where sal>=3000 and sal<=4500; -- and
– 提示: between…and… 在…和…之间
select name,sal from emp
where sal between 3000 and 4500; -- 包括3000,也包括4500.如果不包括头和尾不能用between and.
注意:这2者的区别只有一条:上面的写法边界可以控制,是否为>= ,>号。
下面的写法必须包含头和尾。
– 20.查询emp表中【薪资为 1400、1600、1800】的员工,显示员工姓名和薪资
注意:1.where字句里面多个条件要有连接词。
2.如果用and表示你逻辑有错误:用and表示把每个员工的薪资都拿来,看是否同时满足这3个条件,怎么可能有一个员工的薪资同时满足这3个条件.所以应该用or
select name,sal from emp
where sal=1400 or sal=1600 or sal=1800; -- or表示或则
– 或者用另一种写法:in
select name,sal from emp
where sal in(1400,1600,1800); //查询显示所有满足其中()任意一个条件的表里面的记录
– 21.查询薪资不为1400、1600、1800的员工,显示员工姓名和薪资
select name,sal from emp
where not(sal=1400 or sal=1600 or sal=1800);
-- 或
select name,sal from emp
where sal not in(1400,1600,1800);
– 22.(自己完成) 查询emp表中薪资大于4000和薪资小于2000的员工,显示员工姓名、薪资。
注意:不能用and,因为没有薪资是比4000大,比2000还小。
select name,sal from emp
where sal>4000 or sal<2000;
– 23.(自己完成) 查询emp表中薪资大于3000并且奖金小于600的员工,显示员工姓名、薪资、奖金。
select name,sal,bonus from emp
where sal>3000 and bonus<600; -- 结果有误差,少了一行数据 null的哪一行
处理null值(null值和任何值比较都是false)
select name,sal,ifnull(bonus,0) from emp
where sal>3000 and ifnull(bonus,0)<600;
– 24.查询没有部门的员工(即部门列为null值)
select * from emp where dept=null; -- 条件错误,在where条件里不能用某一个列名等于null值作为条件去筛选. 即便是它本身。解决:用is.
select * from emp where dept is null; -- 信息正确
– 思考:如何查询有部门的员工(即部门列不为null值)
select * from emp where dept is not null;
-- 或则
select * from emp where not (dept is null);
LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式。
可以和通配符(%、_)配合使用,其中"%"表示0或多个任意的字符
,"_"表示一个任意的字符
。
语法:SELECT 列 | * FROM 表名 WHERE 列名 LIKE 值
示例:
– 25.查询emp表中姓名中以"刘"字开头的员工,显示员工姓名。
select name from emp where name like '刘%';
– 26.查询emp表中姓名中包含"涛"字的员工,显示员工姓名。
select name from emp where name like '%涛%';
– 27.查询emp表中姓名以"刘"开头,并且姓名为两个字的员工,显示员工姓名。
select name from emp where name like '刘_';
select name from emp where name like '刘_ _';
多行函数也叫做聚合(聚集)函数,根据某一列或所有列进行统计。
常见的多行函数有:
多行函数 | 作用 |
---|---|
COUNT( 列名 | * ) | 统计结果集中指定列的记录的行数。 – 数数,计算 |
MAX( 列名 ) | 统计结果集中某一列值中的最大值 |
MIN( 列名 ) | 统计结果集中某一列值中的最小值 |
SUM( 列名 ) | 统计结果集中某一列所有值的和 |
AVG( 列名 ) | 统计结果集中某一列值的平均值 |
提示:(1**)多行函数不能用在where子句中。
(2)多行函数和是否分组有关,分组与否会直接影响多行函数的执行结果。
(3)多行函数在统计时会对null值进行过滤,直接将null值丢弃,不参与统计。
– 28.统计emp表中薪资大于3000的员工个数(就是把查询的列名,用关键字包起来)
注意:统计所有列有几行,统计某一列有多少行,结果有可能一样也可能不一样。因为比如bonus这一列:有null值,统计结果就由原来的7变为6.
==推荐写 * ==
select count(*)from emp where sal>3000; --count* 对所有列统计行数 7
select count(id)from emp where sal>3000; --countid 对所有id统计行数 7
– 29.求emp表中的最高薪资
select max(sal) from emp; -- 返回最高薪资 5000
select min(sal) from emp;
– 30.统计emp表中所有员工的薪资总和(不包含奖金)
select sum(sal) from emp;-- 薪资总和:39650
select sum(bonus) from emp;--奖金总和:5900 数值正确,多行函数会对null值处理,直接丢弃,不参与统计.
– 31.统计emp表员工的平均薪资(不包含奖金)
select sum(sal)/count(*) from emp;
select avg(sal) from emp;-- 39650/12 一般用这个,底层用的是上面那种方式算的。
多行函数需要注意的问题:
-如果查询结果中的数据经过分组(分的组不止一个),多行函数会根据分的组进行统计,有多少个组,就会统计出多少个结果。
select * from emp;
例如:统计emp表人数
select count(*) from emp; -- 12 没分组按照是默认是同一个组进行统计人数.一个组只会参生一个结果.
结果返回的就是emp表中的所有人数
再例如:根据性别对emp表中的所有员工进行分组,再统计每组的人数,显示性别和对应人数
按性别是分为2组,然后再去统计每组的人数
select count(*) from emp group by gender; --10 2
GROUP BY 语句根据一个或多个列对结果集进行分组。 (类似于where子句,放在查询表后面)
在分组的列上我们可以使用 COUNT,SUM,AVG,MAX,MIN等函数。
语法:SELECT 列 | * FROM 表名 [WHERE子句] GROUP BY 列;(注意如果有where子句则先写where子句在写分组)
培优部,就业部,null. 这3组。
– 32.对emp表,按照部门对员工进行分组,查看分组后效果。
select name,dept from emp group by dept; -- 只显示每组的第一个人 group 组
--统计分组后,每组的人数
select count(*) from emp group by dept;-- 3个组,所以会统计出三个结果
– 33.对emp表按照职位进行分组,并统计每个职位的人数,显示职位和对应人数
-- 根据job进行分组,统计每个组的人数(每个职位的人数)
select job,count(*) from emp group by job;
当然也不是每一个列都适合分组,如按姓名,50个人如果都是不同的名字,分为50组,所以也没啥意义。
– 34.对emp表按照部门进行分组,求每个部门的最高薪资(不包含奖金),显示部门名称和最高薪资
88888888888
-- 如果不分组,直接使用max(sal),这是统计整个emp表中的最高薪资
select max(sal) from emp;-- 5000;
-- 如果根据部门分组,可以分为三个组,在使用max(sal),就是统计每个组的最高薪资.
select dept,max(sal) from emp group by dept;
因为是按照部门分的列,所以可以显示部门,你要是显示名字又不是按照名字分组,2者关系有没有映射没啥意义。
注意: where子句>分组>排序 先写where在写分组,在写排序. (优先顺序)
使用 ORDER BY 子句将结果集中记录根据指定的列排序后再返回
语法:SELECT 列名 FROM 表名 ORDER BY 列名 [ASC|DESC]
写了ORDER BY关键字后,不写升序 降序关键字默认是ASC升序,如果连orderby关键字都不写,默认情况下查询返回的数据是按照添加数据的顺序显示的。
不写ASC(默认)升序,即从低到高;DESC 降序,即从高到低。
– 35.对emp表中所有员工的薪资进行升序(从低到高)排序,显示员工姓名、薪资。
注意:升序指的是重上到下数,由低到高。
select name,sal from emp order by sal ; -- 默认是升序asc可以省略 order 顺序
select name,sal from emp order by sal asc; -- 升序 order by 排序依据 (ascend上升)
– 36.对emp表中所有员工的奖金进行降序(从高到低)排序,显示员工姓名、奖金。
select name,bonus from emp order by bonus desc; -- 降序 不能省略 (descend降序)
先写 where 分组 排序 分页 (优先顺序)即前面where 分组,排序,分页都没有在写分页。
总结: 它们都是放在查询表之后的位置.
在mysql中,通过**limit进行分页查询,**查询公式为:
limit 位置偏移量,每页显示的记录数
limit (当前页码-1)*每页显示记录数, 每页显示记录数
– 37.查询emp表中的所有记录,分页显示:每页显示3条记录,返回所有页的数据。
页码:比如,第一页就是1.
-- 每页显示3条,查询第1页数据 limit 界限,范围
select * from emp limit 0,3; -- 第一页页码是1,(1-1)*3=0 每页记录数;3条记录为:3
-- 每页显示3条,查询第2页数据
select * from emp limit 3,3;
-- 每页显示3条,查询第3页数据
select * from emp limit 6,3;
– 38.求emp表中薪资最高的前3名员工的信息,显示姓名和薪资
-- 现根据薪资降序(从高到低)排序
select name,sal from emp order by sal desc;
-- 在排序的基础上分页查询,只查询第一页
select name,sal from emp order by sal desc limit 0,3;
– 39.查询emp表中所有【在1993和1995年之间出生】的员工,显示姓名、出生日期。
日期可以进行比较,但是在这个表的birthday是一个年-月-日格式的数据,所以把日期1993进行转化为日期格式在进行比较:‘1993-1-1’ 或则用year函数把日期提取出来在进行比较。
-- 将运算符两边的值都转成日期类型,在进行比较
select name,birthday from emp
where birthday>='1993-1-1' and birthday<='1995-12-31';
--或则,将日期中的年份提取出来,用年份和年份进行比较
select name,birthday from emp
where year(birthday)>=1993 and year(birthday)<=1995;
– 40.查询emp表中本月过生日的所有员工
select * from emp
where month(now())=month(birthday);
now():获取当前日期 年 月 日。 month:把当前年份的日期提取出来。然后再把当前表中的年 月 日 中的月份获取出来。最后在进行比较。
补充:获取下个月过生日的所有员工:注意第一种写法如果是12月+1为13月,不等于1月。下面这种写法更好,2边都要取余。
拼接字符串练习即:给查询的值添加单位。
– 41.查询emp表中员工的姓名和薪资(薪资格式为: xxx(元) )
select name,concat(sal,'(元)') from emp; -- concat(s1,s2,s3...)
– 补充练习:查询emp表中员工的姓名和薪资(薪资格式为: xxx/元 )
-- 用concat 函数实现
select name,concat(sal,'/元') from emp;
-- 或则 用concat_ws实现, concat_ws(x,s1,s2,s3...)
select name, concat_ws('/',sal,'元') from emp; -- 即,s1与s2两两拼接会加上一个x
MySQL中支持多种整型,其实很大程度上是相同的,只是存储值的大小范围不同而已。
tinyint:占用1个字节,相对于java中的byte
smallint:占用2个字节,相对于java中的short
int:占用4个字节,相对于java中的int (重点掌握)
bigint:占用8个字节,相对于java中的long
其次是浮点类型即:float和double类型
float:4字节单精度浮点类型,相对于java中的float
double:8字节双精度浮点类型,相对于java中的double (重点掌握)
1、char(n) 定长字符串,最长255个字符。n表示字符数,例如:
– 创建user表,指定用户名为char类型,字符长度不超过10
字符数量: 张三,2个字符. Tom,3个字符.
create table user(
username char(10),
...
);
所谓的定长,是当插入的数据的长度小于指定的长度时,剩余的空间会用空格填充。(缺点:这样可能会浪费空间)
优点是 :效率比varchar更高。
char类型往往用于储存长度固定的数据。(如:身份证号,学生编号)
2、varchar(n) 变长字符串,最长不超过65535个字节,n表示字符数,一般超过255个字符,会使用text类型,例如: various 各种各样的。
iso8859-1码表:一个字符占用1个字节,1*n <65535, n最多等于 65535
utf8码表:一个中文汉字占用3个字节,3*n<65535,n最多等于 65535/3
GBK码表:一个中文汉字占用2个字节,2*n<65535,n最多等于 65535/2
– 创建user表,指定用户名为varchar类型,长度不超过10个字符
create table user(
username varchar(10)
);
所谓的不定长,是当插入的数据的长度小于指定的长度时,剩余的空间可以留给别的数据使用。(节省空间)
总结:长度固定的数据,用char类型,这样既不会浪费空间,效率也比较高。
如果长度不固定,使用varchar类型,这样不会浪费空间。
3、大文本(长文本)类型
最长65535个字节,一般超过255个字符列的会使用text,不超过用char或varchar类型.
– 创建user表:
create table user(
resume text
);
另,text也分多种,其中bigtext存储数据的长度约为4GB。
扩展内容3:(面试题)char(n)、varchar(n)、text都可以表示字符串类型,其区别在于:
(1)char(n)在保存数据时,如果存入的字符串长度小于指定的长度n,后面会用空格补全,因此可能会造成空间浪费,但是char类型的存储速度较varchar和text快。
因此char类型适合存储长度固定的数据,这样就不会有空间浪费,存储效率比后两者还快!
(2)varchar(n)保存数据时,按数据的真实长度存储,剩余的空间可以留给别的数据用,因此varchar不会浪费空间。
因此varchar适合存储长度不固定的数据,这样不会有空间的浪费。
(3)text是大文本类型,一般文本长度超过255个字符,就会使用text类型存储。
date:年月日
time:时分秒
datetime:年月日 时分秒
timestamp:时间戳(实际存储的是一个时间毫秒值),与datetime存储日期格式相同。两者的区别是:
timestamp最大表示1970~2038年,而datetime范围是1000~9999
timestamp在插入数据、修改数据时,可以自动更新成系统当前时间(后面用到时再做讲解)
字段约束/列约束 --> 约束: 即添加一些限制.
主键约束:如果为一个列添加了主键约束,那么这个列就是主键,主键的特点是唯一且不能为空。
主键的作用: 作为一个唯一标识,唯一的表示一条表记录(作用类似于人的身份证号,可以唯一的表示一个人一样。)
添加主键约束,例如将id设置为主键: primary key
create table stu(
id int primary key, -- primary 主要的 key 键
...
);
如果主键是数值类型,为了方便插入主键(并且保证插入数据时,主键不会因为重复而报错),可以设置一个主键自增策略。 – 注意:只有是数值类型才可以设置自增。
主键自增策略是指:设置了自增策略的主键,可以在插入记录时,不给id赋值,只需要设置一个null值,数据库会自动为id分配一个值(AUTO_INCREMENT变量,默认从1开始,后面依次+1),这样既可以保证id是唯一的,也省去了设置id的麻烦。
注意:设置自增 第二个数删除后 在插入一个数直接回变为3
设置自增 也可以从新赋值 如果大于自增的值 则会返回一个+1的数 因为id不能重复
将id主键设置为自增:
create table stu(
id int primary key auto_increment, -- automatic 自动的
... -- increament 增加
);
注意:主键约束不等于非空约束+唯一约束,还作为唯一标示。
非空约束:如果为一个列添加了非空约束,那么这个列的值就不能为空,但可以重复。
添加非空约束,例如为password添加非空约束: not null
create table user(
password varchar(50) not null,
...
);
唯一约束:如果为一个列添加了唯一约束,那么这个列的值就必须是唯一的(即不能重复),但可以为空。
添加唯一约束,例如为username添加唯一约束及非空约束:
unique:代表唯一约束
unique not null:代表 唯一且不为空,它和主键约束有区别(主键约束还有一个标识的作用)
create table user(
username varchar(50) unique not null,
...
);
解释:如果需要查询多张表,多张表中间是需要有关联的。如:在查询部门的同时查询员工,再查询班级的时候查询学生。这个关联就是建立在表和表之间的,这种关联关系就是通过外键约束来实现的。
外键其实就是用于 通知 数据库两张表数据之间对应关系的这样一个列。这样数据库就会帮我们维护两张表中数据之间的关系。
foreign key(dept_id) references dept(id) references:参考
创建表的同时添加外键:
create table emp(
id int,
name varchar(50),
dept_id int,
foreign key(dept_id) references dept(id)
);
(1)如果是要表示两张表的数据之间存在对应关系,只需要在其中的一张表中添加一个列,保存另外一张表的主键,就可以保存两张表数据之间的关系。
但是添加的这个列(dept_id)对于数据库来说就是一个普通列,数据库不会知道两张表存在任何关系,因此数据库也不会帮我们维护这层关系。
(2)如果将dept_id列设置为外键,等同于通知数据库,部门表和员工表之间存在对应关系,dept_id列中的数据要参考部门的主键,数据库一旦知道部门和员工表之间存在关系,就会帮我们维护这层关系。
(可以避免数据的完整性和一致性被破坏,比如你删除销售部,赵四和刘能就找不到部门了会报错,阻止你删除)
那现在就是想删除呢? 可以吧赵四和刘能的id改为别的部门的id如3:update emp dept_id=3 where is=4 or id=5;
注意:正在公司中可以设置外键,也可以不设置外键。区别在于设置外键数据库会帮你维护关系,不设置这个关系你自己维护。而保存这种关系则是在一个表中添加另一个表的主键,一般是在数据多行的一张表添加少的一张。因为再少的一方添加主键保存不完数据,如:在同一行中的一个位置显示2个数据
思考:如果在创建表时没有指定外键,那么后期该如何指定外键?以及如何删除外键? 在下面扩展中。
常见的表关系分为以下三种:
一对多(多对一)、一对一、多对多
解释: 1对应1,说明张飞被王老师教过,1对应2说明刘备被齐老师教过。
对于多对多的关系,设置联合主键就表明各个单独的主键在第三张表中可以重复,但是stuid和teaid加起来不能重复。 然后添加外键数据库底层会帮你自动维护这种关系,不添加外键就需要你自己维护这种关系,比如:删除其中一行是否对另一种表存在影响。参考扩展。
– 准备数据: 以下练习将使用db30库中的表及表记录,请先进入db30数据库!!!
查询部门表
查询员工表
– 42.查询部门和部门对应的员工信息
select *from dept,emp; -- 就是写多张表,之间用逗号隔开。
上面的查询中存在大量错误的数据,一般我们不会直接使用这种查询。
笛卡尔积查询:所谓笛卡尔积查询就是指,查询两张表,其中一张表有m条记录,另一张表有n条记录,查询的结果是m*n条。
虽然笛卡尔积查询中包含大量错误数据,但我们可以通过where子句将错误数据剔除,保留下来的就是正确数据。
-- 员工部门编号=部门的编号
select *from dept,emp -- 因为id在部门表和员工表都有,所以加上列名进行区分
where emp.dept_id=dept.id; -- 因为dept_id只存在于emp表中得列,所以可以直接写 写dept_id 而id则是既存在emp表又存在dept表,所以dept.id(表名.列名) 用于区分, 不然会报错模糊不清的。
那么这个条件是怎么找的:第一行根据表可以看出员工表的id,比如张三的id为1对应的主键depe_id为1,恰好又是部门表的id为1所以查询显示的数据正确。 第二行:员工表的id为1对应的外键是1,但是对应的部门表的id为2所以这是个错误数据。
通过where子句将笛卡尔积查询中的错误数据剔除,保留正确的数据,这就是连接查询!
上面的查询可以换成下面的查询:(,换位inner join where换位on )
select *from dept inner join emp
on emp.dept_id=dept.id; -- 内连接查询,和上面的查询结果一样
和上面的区别就是,上面的连接查询只查询部门对应的员工信息,这个地方的左外连接是部门表所有员工的信息,然后出了显示部门对应的员工信息外还要显示如果没有对应的信息则显示为null. 总结:区别就是出了显示满足对应的关系外还要显示没有关系的数据
– 43.查询【所有部门】及部门对应的员工,如果某个部门下没有员工,员工显示为null
注意:where变为on
select *from dept left join emp
on emp.dept_id=dept.id;
左外连接查询:可以将左边表中的所有记录都查询出来,右边表只显示和左边相对应的数据,如果左边表中某些记录在右边没有对应的数据,右边显示为null即可。
( 如果是想查左边所有表的数据,就用左外连接查询)
连接符号","换成 left join where 换成on
总结:左外连接就是查询左边表所有的的数据,然后右边表显示和左边表对应的数据。
– 44.查询【所有员工】及员工所属部门,如果某个员工没有所属部门,部门显示为null
select *from dept right join emp
on emp.dept_id=dept.id;
右外连接查询:可以将右边表中的所有记录都查询出来,左边表只显示和右边相对应的数据,如果右边表中某些记录在左边没有对应的数据,可以显示为null。
总结:右外连接就是查询右边表所有的的数据,然后左边表显示和右边表对应的数据。
全外连接查询:
扩展:如果想将两张表中的所有数据都查询出来(左外+右外并去除重复记录),可以使用全外连接查询,但是mysql又不支持全外连接查询。
select *from dept left join emp on emp.dept_id=dept.id
union
select *from dept right join emp on emp.dept_id=dept.id;
可以使用union将左外连接查询的结果和右外连接查询的结果合并在一起,并去除重复的记录。例如:
需要注意的是:union可以将两条SQL语句执行的结果合并,但是有前提:
(1**)两条SQL语句查询的结果列数必须一致**
联合查询:把2张表所有的数据显示在一张表中。
== 但是dept有列 emp表有3列,所以报错==
解决:只显示列数相同的个数。*是一个2列,一个3列所以不对。
(2)两条SQL语句查询的结果列名、顺序也必须一致
如果不一致我们可以指定列别名。
并且union默认就会将两个查询中重复的记录去除(如果不希望去除重复记录,可以使用union all)
将一个sql执行的结果作为条件来完成的一个查询叫做子查询。
– 准备数据:以下练习将使用db40库中的表及表记录,请先进入db40数据库!!!
– 45.列出薪资比’王海涛’的薪资高的所有员工,显示姓名、薪资
单表
-- 求出'王海涛'的薪资
select sal from emp where name='王海涛'; -- 2450
-- 求出比'王海涛'薪资高的所有员工信息 这样写没有写死,以后再改工资不用再更改代码 像这样将一条语句作为另一条语句的子句就叫子查询.
select name,sal from emp
where sal>(select sal from emp where name='王海涛');
– 46.列出与’刘沛霞’从事相同职位的所有员工,显示姓名、职位。
单表
-- 求出刘培霞从事的职位
select job from emp where name='刘沛霞';
-- 再求出和刘培霞从事相同职位的员工
select name ,job from emp
where job=(select job from emp where name='刘沛霞');
– 47.列出薪资比’大数据部’部门(已知部门编号为30)所有员工薪资都高的员工信息,显示员工姓名、薪资和部门名称。=这个是查询的2张表:部门表 员工表
如果不考虑没有部门的员工
-- 先连接查询部门表和员工表,显示员工姓名、薪资和部门名称
select emp.name ,sal, dept.name from dept,emp
where emp.dept_id=dept.id;
-- .列出薪资比'大数据部'部门(已知部门编号为30)所有员工薪资都高的员工信息,可以简化为:1.求出'大数据'部门最高的薪资
select max(sal) from emp where dept_id=30;
2.--列出薪资比'大数据'部门最高薪资还高的员工信息
select emp.name ,sal, dept.name from dept,emp
where emp.dept_id=dept.id and
sal>(select max(sal) from emp where dept_id=30);
如果加上没有部门的员工 (考虑韩少云),保证其中一张表的数据都查询出来可以用外连接
-- 使用外连接查询部门表和员工表
select emp.name ,sal, dept.name from dept right join emp
on emp.dept_id=dept.id;
-- 求出'大数据'部门最高的薪资
select max(sal) from emp where dept_id=30;
--列出薪资比'大数据'部门最高薪资还高的员工信息
select emp.name ,sal, dept.name from dept right join emp
on emp.dept_id=dept.id
where sal>(select max(sal) from emp where dept_id=30);
– 48.列出在’培优部’任职的员工,假定不知道’培优部’的部门编号,显示部门名称,员工名称。
分析:部门的名称和员工的名称来自2张表所以用多表查询。
注意:1.可以添加列别名,也可以添加表别名。用法差不多,as可以省略。
-- 连接查询部门表和员工表 多张表查询 先连接查询
select dept.name,emp.name from dept,emp
where emp.dept_id=dept.id;
-- 求出部门名称为'培优部'的员工
select dept.name,emp.name from dept,emp
where emp.dept_id=dept.id and dept.name='培优部';
注意:2.如果你声明了别名又不用,那也是错的。比如:在前面select中from表指定别名时,在后面的where条件中不用e.dept_id 仍用以前的则还是错的。 总之在前面声明后的别名,后面再出现就一定要用别名替换,不然你声明它干啥的。
列别名没有这个用法。前面指定列的别名后,后面的列还是要用原先的。
– 扩展:可以为表明加别名,加了别名后,就需要使用别名替换表名
select d.name,e.name from dept d,emp e
where e.dept_id=d.id and d.name='培优部';
– 49.(自查询)列出所有员工及其直接上级,显示员工姓名、上级编号,上级姓名
把一张表当做2张表来看
/* 将emp同时看做员工表和上级表----起别名当做2张表,其实还是一张表。
* emp e1 看做员工表 emp e2 看做上级表
* 查询的表: emp e1, emp e2
* 查询的列: e1.name,e2.id, e2.name
* 连接条件: 员工所属上级编号=上级编号
* e1.topid=e2.id
*/
select e1.name,e2.id, e2.name -- select一般用于查询表的结构
from emp e1, emp e2 -- from 一般跟来至那个表
where e1.topid=e2.id; -- where 一般用于条件的筛选
– 50.列出最低薪资大于1500的各种职位,显示职位和该职位的最低薪资
-- 根据职位进行分组,在求出每个职位的最低薪资
select job,min(sal) from emp group by job;
-- 求出最低薪资大于1500的职位有哪些
select job,min(sal) from emp group by job
having min(sal) >1500;
(1)相同点: where和having都可以对记录进行筛选过滤。
(2)区别:where是在分组之前,对记录进行筛选过滤,并且where子句中不能使用多行函数以及列别名(但是可以使用表别名)
(3)区别:having是在分组之后,对记录进行筛选过滤,并且having子句中可以使用多行函数以及列别名、表别名。
– 51.列出在每个部门就职的员工数量、平均工资。显示部门编号、员工数量,平均薪资。
-- 根据部门分组,统计每个组(每个部门)的人数,平均薪资
select dept_id,count(*),avg(sal)
from emp
group by dept_id;
– 52.查出至少有一个员工的部门,显示部门编号、部门名称、部门位置、部门人数。
-- 连接查询部门表和员工表
select d.id,d.name,d.loc
from dept d,emp e
where d.id=e.dept_id;
-- 根据部门进行分组
select d.id,d.name,d.loc,count(*)
from dept d,emp e
where d.id=e.dept_id
group by d.name
having count(*)>0; -- 这句话加不加都行,因为上面分组已经满足了这个条件.
– 53.列出受雇日期早于直接上级的所有员工,显示员工编号、员工姓名、部门名称。
/* emp e1 员工表, emp e2 上级表
* 查询的表: emp e1, emp e2, dept d
* 查询的列: e1.id, e1.name, d.name
* 连接条件: e1.topid=e2.id
* e1.dept_id=d.id
* 筛选条件: e1.hdate < e2.hdate
*/
select e1.id, e1.name, d.name
from emp e1, emp e2, dept d
where e1.topid=e2.id
and e1.dept_id=d.id
and e1.hdate < e2.hdate;
– 补充:查询员工表中薪资最高的员工信息 day11pm 223
select name,max(sal) from emp; -- 这个查询的结果是错误的,因为name和sal没有对应关系。
-- 可以按照薪资降序排序,每页显示一条,查询第一页.
select * from emp order by sal desc limit 0,1;
-- 或则 : 也可以使用子查询 效率会偏低一些
select max(sal) from emp;-- 求emp表中的最高薪资
select * from emp where sal=(select max(sal) from emp);
也可以使用工具进行备份Navicat,Sqlyog
在cmd窗口中(未登录的状态下,即:没有连接数据库),可以通过如下命令对指定的数据库进行备份:
mysqldump -u用户名 -p 数据库的名字 > 备份文件的位置
– 注意-p和数据库的名字有空格 文件没有会自动帮你创建
示例1: 对db40
库中的数据(表,表记录)进行备份,备份到 d:/db40.sql
文件中
mysqldump -uroot -p db40 > d:/db40.sql
– 这个没有分号
键入密码,如果没有提示,即表示备份成功!
也可以一次性备份所有库,例如:
对mysql服务器中所有的数据库进行备份,备份到 d:/all.sql文件中
mysqldump -uroot -p --all-database > d:/all.sql
键入密码,如果没有提示错误(警告信息不是错误,可以忽略),即表示备份成功!
1、恢复数据库方式一:
在cmd窗口中(未登录的状态下),可以通过如下命令对指定的数据库进行恢复:
mysql -u用户名 -p 数据库的名字 < 备份文件的位置
示例:将d:/db40.sql文件中的数据恢复到db60库中
– 在cmd窗口中(已登录的状态下),先创建db60库:
create database db60 charset utf8;
– 在cmd窗口中(未登录的状态下)
mysql -uroot -p db60 < d:/db40.sql
2、恢复数据库方式二:
在cmd窗口中(已登录的状态下),可以通过source执行指定位置的SQL文件:
source sql文件的位置
示例:将d:/db40.sql文件中的数据恢复到db80库中
– 在cmd窗口中(已登录的状态下),先创建db80库,进入db80库:
create database db80 charset utf8;
use db80;
– 再通过source执行指定位置下的sql文件:
source d:/db40.sql
Navicat Premium是一套带图形用户界面的数据库管理工具,让你从单一应用程序中同时连接MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite数据库。使用Navicat可以快速、轻松地创建、管理和维护数据库。
1、使用navicat连接mysql服务器(使用cmd连接mysql服务器)
2、查看所有库、进入数据库、创建数据库、删除数据库、修改数据库
3、创建表、查看表、修改表、删除表
4、新增表记录、查询表记录、修改表记录、删除表记录
5、使用navicat书写SQL语句操作数据库、表和表记录
...
哔哩哔哩视频链接:https://www.bilibili.com/video/BV1yA41147Vi/
现创建学生表:
use test; -- 进入test库
drop table if exists stu; -- 删除学生表(如果存在)
create table stu( -- 创建学生表
id int, -- 学生id
name varchar(20), -- 学生姓名
gender char(1), -- 学生性别
birthday date -- 出生年月
);
语法:ALTER TABLE tabname ADD col_name datatype [DEFAULT expr][,ADD col_name datatype…];
1、往stu表中添加score列,double类型
alter table stu add score double;
语法:ALTER TABLE tabname MODIFY (col_name datatype [DEFAULT expr][,MODIFY
col_name datatype]…);
1、修改id列,将id设置为主键
alter table stu modify id int primary key;
2、修改id列,将id主键设置为自动增长
alter table stu modify id int auto_increment;
语法:ALTER TABLE tabname DROP [COLUMN] col_name;
1、删除stu表中的score列
alter table stu drop score;
思考:a) 在建表时,如何为id指定主键约束和自增?
b) 建好的表,如何通过修改添加主键约束和自增?
c) 如何删除表中的主键约束和自增?
1、创建stu学生表,不添加主键自增, 查看表结果
use mydb1; -- 切换到mydb1库
drop table if exists stu; -- 删除stu学生表(如果存在)
create table stu( -- 重建stu学生表,没有主键自增
id int,
name varchar(20),
gender char(1),
birthday date
);
desc stu; -- 查看表结构
表结构如下: 没有主键约束和自增。
2、如果表没有创建,或者要删除重建,在创建时可以指定主键或主键自增
drop table if exists stu; -- 删除stu表
create table stu( -- 重新创建stu表时,指定主键自增
id int primary key auto_increment,
name varchar(20),
gender char(1),
birthday date
);
desc stu; -- 查看表结构
表结构如下: 已经添加了主键约束和自增。
3、如果不想删除重建表,也可以通过修改表添加主键或主键自增
再次执行第1步,创建stu学生表,不添加主键自增,查看表结果
– 例如: 将stu学生表中的id设置为主键和自动增长
alter table stu modify id int primary key auto_increment;
desc stu; -- 查看表结构
如果只添加主键约束,不设置自增
alter table stu modify id int **primary key**;
如果已经添加主键约束,仅仅设置自增,但需注意:
(1)如果没有设置主键,不可添加自增
(2)只有当主键是数值时,才可以添加自增
alter table stu modify id int **auto_increment**;
4、如果想删除主键自增
– 删除主键自增时,要先删除自增
alter table stu modify id int;
– 再删除主键约束
alter table stu drop primary key;
desc stu; -- 查看表结构
1、添加外键方式一:建表时添加外键
现有部门表如下:
– 创建部门表
create table dept(
id int primary key auto_increment, -- 部门编号
name varchar(20) -- 部门名称
);
要求创建员工表,并在员工表中添加外键关联部门主键
– 创建员工表
create table emp(
id int primary key auto_increment, -- 员工编号
name varchar(20), -- 员工姓名
dept_id int, -- 部门编号
foreign key(dept_id) references dept(id) -- 指定dept_id为外键
);
2、添加外键方式二:建表后添加外键
现有部门表和员工表:
– 创建部门表
create table dept(
id int primary key auto_increment, -- 部门编号
name varchar(20) -- 部门名称
);
– 创建员工表
create table emp(
id int primary key auto_increment, -- 员工编号
name varchar(20), -- 员工姓名
dept_id int -- 部门编号
);
– 如果表已存在,可以使用下面这种方式:
alter table emp add constraint fk_dept_id foreign key(dept_id) references dept(id);
其中 fk_dept_id (名字由自己定义),是指外键约束名称,也可以将【constraint fk_dept_id】省略,MySQL会自动分配一个外键名称,将来可以通过该名称删除外键。
foreign key(dept_id)中的dept_id为外键
1、首先通过 “show create table 表名”语法,查询含有外键表的建表语句,例如:
show create table emp;
显示结果如下:
其中,emp_ibfk_1是在创建表时,数据库为外键约束指定的一个名字,删除这个名字即可删除外键关系,例如:
alter table emp drop foreign key emp_ibfk_1;
外键删除成功!
– 现有学生(stu)表和教师(tea)表:
– 创建学生表
create table stu(
stu_id int primary key auto_increment, -- 学生编号
name varchar(20) -- 学生姓名
);
– 创建教师表
create table tea(
tea_id int primary key auto_increment, -- 教师编号
name varchar(20) -- 教师姓名
);
– 添加第三方表(stu_tea)表示学生表和教师表关系
– 创建学生和教师关系表
create table stu_tea(
stu_id int, -- 学生编号
tea_id int, -- 教师编号
primary key(stu_id,tea_id), -- 设置联合主键
foreign key(stu_id) references stu(stu_id), -- 添加外键
foreign key(tea_id) references tea(tea_id) -- 添加外键
);
其中为了防止重复数据,将stu_id和tea_id设置为联合主键。联合主键就是在第三张表中单独的可以重复,但是加起来不能重复。
将stu_id设置为外键,参考stu表中的stu_id列
并将tea_id设置为外键,参考tea表中的tea_id列
– 创建db20库、dept表、emp表并插入记录
– 删除db20库(如果存在),并重新创建db20库
drop database if exists db20;
create database db20 charset utf8;
use db20;
– 创建部门表, 要求id, name字段
create table dept(
id int primary key auto_increment, -- 部门编号
name varchar(20) -- 部门名称
);
– 往部门表中插入记录
insert into dept values(null, '财务部');
insert into dept values(null, '人事部');
insert into dept values(null, '科技部');
insert into dept values(null, '销售部');
– 创建员工表, 要求id, name, dept_id
create table emp(
id int primary key auto_increment, -- 员工编号
name varchar(20), -- 员工姓名
dept_id int, -- 部门编号
foreign key(dept_id) references dept(id) -- 指定外键
on update cascade -- 级联更新
on delete cascade -- 级联删除
);
insert into emp values(null, '张三', 1);
insert into emp values(null, '李四', 2);
insert into emp values(null, '老王', 3);
insert into emp values(null, '赵六', 4);
insert into emp values(null, '刘能', 4);
级联更新:主表(dept表)中的主键发生更新时(例如将销售部的id改为40),从表(emp表)中的记录的外键数据也会跟着该表(即赵六和刘能的部门编号也会更新为40)
级联删除:如果不添加级联删除,当删除部门表中的某一个部门时(例如删除4号部门),若该部门在员工表中有对应的员工(赵六和刘能),删除会失败!
若果添加了级联删除,当删除部门表中的某一个部门时,若该部门在员工表中有对应的员工,会在删除部门的同时,将员工表中对应的员工也删除!
但可以使用表别名,而且是一旦指定了表别名·后面出现表明的要使用表别名替换。
SQL语句的书写顺序:
select * | 列名 -- 确定要查询的列有哪些
from 表名 -- 确定查询哪张表
where 条件 -- 通过筛选过滤,剔除不符合条件的记录
group by 分组的列 -- 指定根据哪一列进行分组
having 条件 -- 通过条件对分组后的数据进行筛选过滤
order by 排序的列 -- 指定根据哪一列进行排序
limit (countPage-1)*rowCount, rowCount -- 指定返回第几页记录以及每页显示多少条
SQL语句的执行顺序:
from 表名 -- 确定查询哪张表
where 条件 -- 通过筛选过滤,剔除不符合条件的记录
select * | 列名 列别名 -- 确定要查询的列有哪些,
group by 分组的列 -- 指定根据哪一列进行分组
having 条件 -- 通过条件对分组后的数据进行筛选过滤
order by 排序的列 -- 指定根据哪一列进行排序
limit (countPage-1)*rowCount, rowCount
**** 关于where中不能使用列别名但是可以使用表别名?**
是因为,表别名是声明在from中,from先于where执行,先声明再使用没有问题,但是列别名是声明在select中,where先于select执行,如果先使用列别名,再声明,这样执行会报错!!
学习目标:
– 因为我们将数据库的最终目的就是用在软件或系统中,比如:做一个京东的网站有很多数据存储,搜索一个手机,同时几百万人搜索,后台人员不可能一个一个的手动查询,都是通过程序执行sql对数据进行增删改查。前面学习只是为了练习,方便在开发时进行一些简单操作。 这个地方为学框架打基础。
JDBC(Java DataBase Connectivity) Java数据库连接 // base:基础
其实就是利用Java语言/程序连接并访问数据库的一门技术
之前我们可以通过CMD或者navicat等工具连接数据库
但在企业开发中,更多的是通过程序(Java程序)连接并访问数据库,通过Java程序访问数据库,就需要用到 JDBC这门技术。
1、提出需求:
创建一个 jt_db 数据库,在库中创建一个account表,并插入三条记录,然后利用Java程序查询出account表中所有的记录,并将查询的结果打印在控制台上。
2、开发步骤:
(1)准备数据, 创建jt_db库, 创建account表
drop database if exists jt_db;
create database jt_db charset utf8;
use jt_db;
create table account(
id int primary key auto_increment,
name varchar(50),
money double
);
insert into account values(null, 'tom', 1000);
insert into account values(null, 'andy', 1000);
insert into account values(null, 'tony', 1000);
如果已经执行过课前资料中的"SQL脚本文件",此步骤可以跳过。
(2)创建JAVA工程:
(3)导入jar包——mysql驱动包:
(4)创建类并实现JDBC程序(六个步骤)
代码实现:
/*
* 实现jdbc的快速入门程序:查询jt_db.account表中的所有记录
* syst: 打印当前类的类名+方法名
*/
public static void main(String[] args) throws Exception {
//1.注册数据库驱动(参数是Driver类的全限定类名) --抛异常
//需要导入一个mysql驱动包,因为java程序不能直接访问别人的数据库(底层代码一概不知),而mysql厂商为了让java开发人员访问这个数据库专门提供了jar包来访问数据库 如:mysql-connector-java.5.1.3.jar,对数据库进行增删改查. 项目右键----Folder(目录:放一些文件,跟src是同级关系)---ctrl+v占到这个目录下.但这一步只是放在项目中,想要使用还需要引用:jar包右键---Build Path---Add to Build Path(会出现一个引用的库 Referenced Libraries) 如果将来需要更新jar包,需要先将引用的库移除(右键--Build Path--Remove ...)
Class.forName("com.mysql.jdbc.Driver");
//2.获取数据库连接(连接数据库的url地址,数据库的用户名,数据库的密码)
//第一个参数解释:jdbc:mysql: 是连接mysql的固定写法,其实是个协议。
// //localhost:3306 本地主机:端口名
// /jt_db? 连接的是哪个库
// characterEncoding=utf-8 指定一个值字符集为utf-8 Encoding:把...编码 ,这个参数是为了预防乱码。
//DriverManager:驱动管理器 Connection :连接 这个方法会返回一个连接对象,导sql包
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8",
"root", "root");
//3.通过连接获取传输器 Statement 说明
Statement stat = conn.createStatement();
//4.通过传输器发送SQL到服务器执行,并返回执行结果
String sql = "select * from account";
ResultSet rs = stat.executeQuery( sql );// executeQuery用于执行查寻类型的sql语句 execute:执行 query:查询 返回的结果即表格,可以用结果集对象来接收
//5.输出结果(将每一行记录输出到控制台上)
//结果集对象的表格中,有一个箭头在表头,boolean next()-- 让箭头往下挪一行,返回布尔值,第一行有数据返回true,没数据返回false.有数据就获取。
while( rs.next() ) {
int id = rs.getInt("id"); //把列名传进去,id是int类型
String name = rs.getString("name"); //name是String类型
double money = rs.getDouble("money");
System.out.println(id+" : "+name+" : "+money);
}
//6.释放资源(越晚获取的越先关闭)
rs.close();
stat.close();
conn.close();
System.out.println("TestJdbc.main()....");
}
3、执行结果:
1、注册数据库驱动
Class.forName(“com.mysql.jdbc.Driver”); //全限定类名:包名+类名 (早期必须要注册驱动,在jdbc4.0之后会自动注册,可以省略这一行,但通常我们加上以防出现错误) 这个全称限定类名在这个引用后的包里,展开引用的包—com.mysql.jdbc—接着展开 Driver驱动类,底层通过反射加载这个类获取字节码对象,这里是加载这个类执行里面的静态代码块,静态代码块里有一行语句才会真正的注册代码. 这个方法本质是让注册驱动的代码执行,本身并不注册.
所谓的注册驱动,就是让JDBC程序加载mysql驱动程序,并管理驱动
驱动程序实现了JDBC API定义的接口以及和数据库服务器交互的功能,加载驱动是为了方便使用这些功能。
2、获取连接之数据库URL //相当于java程序与数据库的连接通道(里面的参数不能写错),这个通道就是Connection
//如果端口是默认的可以省略:3306,连接的是本机主机,主机名(即ip地址)也可以省略, '/'不能省
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8",
"root", "root" );
DriverManager.getConnection() 用于获取数据连接,返回的Connection连接对象是JDBC程序连接数据库至关重要的一个对象。
参数2和参数3分别是所连接数据库的用户名和密码。
参数1:“jdbc:mysql://localhost:3306/jt_db” 是连接数据库的URL,用于指定访问哪一个位置上的数据库服务器及服务器中的哪一个数据库,其写法为:
当连接本地数据库,并且端口为3306,可以简写为如下形式:
jdbc:mysql:///jt_db
3、Statement传输器对象
Statement stat = conn.createStatement();
该方法返回用于向数据库服务器发送sql语句的Statement传输器对象
该对象上提供了发送sql的方法:
executeQuery(String sql) -- 只有查询才返回一个结果集
用于向数据库发送查询类型的sql语句,返回一个ResultSet对象中
executeUpdate(String sql) -- 增删改返回的是数值不是对象
用于向数据库发送更新(增加、删除、修改)类型的sql语句,返回一个int值,表示影响的记录行数
4、ResultSet结果集对象
ResultSet对象用于封装sql语句查询的结果,也是一个非常重要的对象。该对象上提供了遍历数据及获取数据的方法。
(1)遍历数据行的方法
next() – 使指向数据行的箭头向下移动一行,并返回一个布尔类型的结果,true表示箭头指向了一行数据,false表示箭头没有指向任何数据(后面也没有数据了)
(2)获取数据的方法
getInt(int columnIndex) //column index 列指数
getInt(String columnLable)
getString(int columnIndex)
getString(String columnLable)
getDouble(int columnIndex)
getDouble(String columnLable)
getObject(int columnIndex)
getObject(String columnLable)
5、释放资源
rs.close();
stat.close();
conn.close();
此处释放资源必须按照一定的顺序释放,越晚获取的越先关闭。所以先关闭
rs对象,再关闭stat对象,最后关闭conn对象。
另,为了避免上面的程序抛出异常,释放资源的代码不会执行,应该把释放资源的代码放在finally块中.
try{ //学了框架之后会帮你释放
...
}catch(Exception e){
...
}finally{
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
rs = null;
}
}
if (stat != null) {
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
stat = null;
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
conn = null;
}
}
}
1、新增:往account表中添加一个名称为john、money为3500的记录
/* 1、新增:往account表中添加一个名称为john、money为3500的记录 */
@Test
public void testInsert() {
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
//注册驱动并获取连接
conn = JdbcUtil.getConn();
//获取传输器
stat = conn.createStatement();
//发送sql语句到服务器执行,并返回执行结果 id主键自增不用给值,里面不用加分号
String sql = "insert into account values(null, 'john', 3500)";
int rows = stat.executeUpdate( sql ); //返回的是影响函数
//处理结果
System.out.println( "影响行数: "+rows );
} catch (Exception e) {
e.printStackTrace();
} finally {
//通过JdbcUtil工具类中的close方法释放资源,为什么要释放资源,连接是一个通道,配置完后连接是固定的,不断获取连接早晚会用完,后面的连不上. 测试的时候一个一个测试,你直接run as是测试所有的方法,而且顺序也没有按照你写的顺序.
JdbcUtil.close(conn, stat, rs);
}
}
2、修改:将account表中名称为john的记录,money修改为1500
/* 2、修改:将account表中名称为john的记录,money修改为1500 */
//为了减少代码 前2步几乎一样,除了将来主机名和端口可能更改(可以设置参数类型),所以我们可以把它提取到一个工具类.
package com.tedu.util;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* jdbc的工具类
* @author Administrator
*
*/
public class JdbcUtil {
//获取数据库连接对象 是京掏的 默认的用户密码
public static Connection getConn() { //为了方便调用设置为静态公共的
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/jt_db?characterEncoding=utf-8","root","root");
return conn;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();//打印异常的类型
}
return null;//有一个返回值
}
/* 上面写死了,为了方便以后修改把它变为参数类型
* 获取数据库连接对象
* dbName 连接数据库的名字
* user 连接的数据库的用户名
* psw 连接的数据库密码
* Connection连接对象
*/
public static Connection getConn(String dbName,String user,String psw) {
try {
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接 把dbName拼接在里面 "+dbName +",直接拿来是字符串跟变量没关系 后面的2个引号也要去掉
Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/"+dbName+"?characterEncoding=utf-8",user,psw);
return conn;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
}
//测试类
@Test
public void testupdate() throws Exception{
//注册获取连接
Connection conn=JdbcUtil.getConn();
//获取传输器,并执行sql语句,返回执行结果
Statement stat=conn.createStatement();
//john 是个字符串,在sql语句中有单引号,在这把它当成了一个列
String sql="update account set money=1500 where name='john'";
int rows=stat.executeUpdate(sql);
System.out.println("影响行数:"+rows);
stat.close();
conn.close();
}
3、查询:查询account表中名称为john的记录
只有查询返回的才是结果, 增删改返回的都是影响的行数。
/* 3、查询:查询account表中id为1的记录 */
@Test
public void testFindById() {
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
//注册驱动并获取连接
conn = JdbcUtil.getConn();
//获取传输器
stat = conn.createStatement();
//执行sql语句,返回执行结果
String sql = "select * from account where id=1";
rs = stat.executeQuery( sql );
//处理结果
if( rs.next() ) {
int id = rs.getInt("id");
String name = rs.getString("name");
double money = rs.getDouble("money");
System.out.println( id+" : "+name+" : "+money);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(conn, stat, rs);
}
}
4、删除:删除account表中名称为john的记录
/* 4、删除:删除account表中名称为john的记录 */
@Test
public void testdelete() throws Exception{
//注册获取连接 调用工具类的方法
Connection conn=JdbcUtil.getConn();
//获取传输器,并执行sql语句,返回执行结果
Statement stat=conn.createStatement();
String sql="delete from account where name='john'";
int rows=stat.executeUpdate(sql);
System.out.println("影响行数:"+rows);
stat.close();
conn.close();
}
}
报错:上面是错误的信息,下面是定位错误的位置.
单元测试:不用创建新的类,也不用提供main函数,也不用创建类的实例,就可以直接执行一个方法 (为了方便测试)
加了@Test注解的方法,可以通过单元测试(junit)框架测试该方法。底层会创建该方法所在类的实例,通过实例调用该方法。 (第一次需要添加库,第二次只需要导包即可 只需要在Test注解上点击即可)
普通方法运行: 右键run as–java Application
@Test -- 运行:选中(双击选中)方法名,右键run as --junit test 需要添加单元测试的库,junit4,5都行
public void testInsert() {
System.out.println("TestPreparedStatement.testInsert()");
}
能够使用@Test单元测试测试的方法必须满足如下几个条件:
(1)方法必须是公共的
(2)方法必须是非静态的
(3)方法必须是无返回值的
(4)方法必须是无参数的
(5)进行单元测试的方法或类,命名时不要命名为 Test/test
在上面的增删改查的操作中,使用的是Statement传输器对象,而在开发中我们用的更多的传输器对象是PreparedStatement对象,PreparedStatement是Statement的子接口,比Statement更加安全,并且能够提高程序执行的效率。
Statement 父对象
PreparedStatement 子对象
(1)准备数据
use jt_db;
create table user(
id int primary key auto_increment,
username varchar(50),
password varchar(50)
);
insert into user values(null,'张三','123');
insert into user values(null,'李四','234');
(2)创建LoginUser 类,提供 main 方法 和 login 方法。
public class LogininUser {
public static void main(String[] args) throws Exception {
Scanner sc=new Scanner(System.in);
//1.t提示用户登录,提示用户输入用户名,并接受用户名
System.out.println("请登录:");
System.out.println("请输入用户名:");
String user=sc.nextLine();
//2.提示用户登录密码,并接受密码
System.out.println("请输入密码");
String psw=sc.nextLine();
//3.将接受到用户名和密码传递给login方法,实现登录
login(user,psw);
}
/*
* 根据用户名和密码查询user表,进行登录
* user 用户名
* psw 密码
*/
private static void login(String user, String psw) throws Exception {//因为是在本类中使用所以可以设置私有的.
// TODO Auto-generated method stub
//获取驱动并连接
Connection conn=JdbcUtil.getConn();
//获取传输器,并执行SQL,返回执行结果
Statement stat=conn.createStatement();
String sql="select * from user where username='"+user+"' and password='"+psw+"'"; //添加特殊符号使sql语句语意发生了改变,这就是注入攻击. 注意用单引号,如果是双引号改变语义了(都是双引号不知道在哪隔开)
//如:张飞 '#' #是注释,后面的都不会执行
//张飞 'or' 2=2 如果一个sql语句同时又and 和 or, and优先执行
System.out.println(sql);
ResultSet rs=stat.executeQuery(sql);
//处理结果
if(rs.next()) { //true,表明有数据--用户名和密码正确,允许登陆
System.out.println("恭喜您登陆成功");
}else {//false.表明没有数据--用户名或密码错误,登录失败
System.out.println("用户名或密码错误,登陆失败!");
}
rs.close();
stat.close();
conn.close();
}
}
执行时,输入:
请登录:
请输入用户名:
张飞'#'
请输入密码:
select * from user where username='张飞'#'' and password=''
恭喜您登录成功了!
或输入:
请登录:
请输入用户名:
张飞' or '1=1
请输入密码:
select * from user where username='张飞' or '1=1' and password=''
恭喜您登录成功了!
或输入:
请登录:
请输入用户名:
请输入密码:
' or '2=2
select * from user where username='' and password='' or '2=2'
恭喜您登录成功了!
通过上面的案例,我们发现在执行时,不输入密码只输入用户名也可以登陆成功。这就是SQL注入攻击。
SQL注入攻击产生的原因: 由于后台执行的SQL语句是拼接而来的:
select * from user where username='"+user+"' and password='"+pwd+"'
其中的参数是用户提交过来的,如果用户在提交参数时,在参数中掺杂了一些SQL关键字(比如or)或者特殊符号(#、-- 、’ 等),就可能会导致SQL语句语义的变化,从而执行一些意外的操作(用户名或密码不正确也能登录成功)!
如何防止SQL注入攻击?
(1)使用正则表达式对用户提交的参数进行校验。如果参数中有(# – ’ or等)这些符号就直接结束程序,通知用户输入的参数不合法
(2)使用PreparedStatement对象来替代Statement对象。 (prepare:准备好的)
下面通过第二种方式解决SQL注入攻击:添加loginByPreparedSatement方法,在方法中,使用PreparedStatement来代替Statement作为传输器对象使用,代码示例:
//复制文件类: 直接ctrl+c ctrl+v
运行后:红色的不一定是报错信息 eror exception
改文件名 在文件上 f2
package com.tedu.ps;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import com.tedu.util.JdbcUtil;
/**
* 模拟用户登录案例-- 可能会产生SQL注入攻击安全问题
* PreparedStatement对象来替代Statement对象。
* @author Administrator
*
*/
public class LogininUser2 {
public static void main(String[] args) throws Exception {
Scanner sc=new Scanner(System.in);
//1.t提示用户登录,提示用户输入用户名,并接受用户名
System.out.println("请登录:");
System.out.println("请输入用户名:");
String user=sc.nextLine();
//2.提示用户登录密码,并接受密码
System.out.println("请输入密码");
String psw=sc.nextLine();
//3.将接受到用户名和密码传递给login方法,实现登录
login(user,psw);
}
/*
* 根据用户名和密码查询user表,进行登录
* user 用户名
* psw 密码
*/
private static void login(String user, String psw) throws Exception {
// TODO Auto-generated method stub
//获取驱动并连接
Connection conn=JdbcUtil.getConn();
//获取传输器,并执行SQL,返回执行结果
// Statement stat=conn.createStatement();
// String sql="select * from user where username='"+user+"' and password='"+psw+"'"; //添加特殊符号使sql语句语意发生了改变
// System.out.println(sql);
// ResultSet rs=stat.executeQuery(sql);
//这个地方会在传骨架后,如果是字符或日期会自动加上一个单引号,如果是字符串则不会有单引号
String sql="select * from user where username=? and password=?";
//将SQL骨架传给PreparedStatement方法,获取ps传输器
PreparedStatement ps=conn.prepareStatement(sql);//创建这个传输器就带传一个参数,所以需要先声明.(?是占位符,这个地方不能像上面直接拼接,直接拼接有和上面的问题一样产生注入攻击问题.)
//设置SQL中的参数(几个问号,就设置几个参数,第一个参数表示第几个问号设置参数,从1开始)
ps.setString(1, user);//有占位符才可以设置参数
ps.setString(2, psw);//先把骨架传过去(单独一个骨架无法执行),再把参数传过去,骨架确定不会再改变 类型看你需要传入的参数
//执行sql语句
ResultSet rs=ps.executeQuery();//不要在传入sql语句! 会报错把前面的sql覆盖
//处理结果
if(rs.next()) { //true,表明有数据--用户名和密码正确,允许登陆
System.out.println("恭喜您登陆成功");
}else {//false.表明没有数据--用户名或密码错误,登录失败
System.out.println("用户名或密码错误,登陆失败!");
}
//释放资源 将来讲框架的时候会帮你释放
rs.close();
ps.close();
conn.close();
}
}
再次执行程序,按照上面的操作登录。此时,已经成功的防止了SQL注入攻击问题了。
PreparedStatement对象是如何防止SQL注入攻击的:
使用PreparedStatement对象是先将SQL语句的骨架发送给服务器编译并确定下来,编译之后,SQL语句的骨架和语义就不会再被改变了,再将SQL语句中的参数发送给服务器,即使参数中再包含SQL关键字或者特殊符号,也不会导致SQL语句的骨架或语义被改变,只会被当作普通的文本来处理!
String sql = "select * from user where username=? and password=?";
//将SQL骨架传给prepareStatement方法,获取ps传输器
PreparedStatement ps = conn.prepareStatement( sql );
//设置SQL语句中的参数(几个问号,就设置几个参数, 第一参数表示为第几个问号设置参数, 从1开始)
ps.setString( 1 , user );
ps.setString( 2 , psw );
//执行SQL语句
ResultSet rs = ps.executeQuery( );
在执行上面的SQL语句时,服务器会将SQL参数 和 SQL骨架 结合在一起,最终生成一条完整的SQL语句。
在用参数替换占位符时(?),如果参数是字符串或日期类型的值,会在字符串或日期值的两边加上单引号!,如果传得是数值的话当然不会加上单引号.
优点:
使用PreparedStatement对象可以防止SQL注入攻击
而且通过方法设置参数更加的方便且不易出错!
还可以从某些方面提高程序执行的效率!
注意 1.什么时候用Statement 什么时候用PreparedStatement?
如果是 里面的sql语句没有参数时那个都一样,如做查询的时候。
池:指内存中的一片空间(容器,比如数组、集合)
连接池:就是将连接存放在容器中,供整个程序共享,可以实现连接的复用,减少连接创建和关闭的次数,从而提高程序执行的效率!
1、传统方式操作数据库
Connection conn = DriverManager.getConnection( url, user, pwd );
//创建连接对象
conn.close(); //关闭连接, 销毁连接
在传统方式中,每次用户需要连接访问数据库时,都是创建一个连接
对象,基于这个连接对象访问数据库,用完连接后,会将连接关闭
(conn.close)。
由于每次创建连接和关闭连接非常的耗时间而且耗资源,因此会导致程序执行的效率低下。
2、使用连接池操作数据库
可以在程序一启动时,就创建一批连接放在一个连接池中(容器),当用户需要连接时,就从连接池中获取一个连接对象,用完连接后,不要关闭,而是将连接再还回连接池中,这样一来,用来用去都是池中的这一批连接,实现了连接的复用,减少了连接创建和关闭的次数,从而提高了程序执行的效率!
dbcp/c3p0/druid 第3方提供的 ,不是java自带的所以 需要导包,所有的连接池技术在实现的时候都需要实现Sun公司所制定的一个标准即接口.
所有的连接池都要实现一个接口——DataSource(数据源),因此连接池也被叫做数据源!
使用C3P0连接池开发步骤:
1、导入开发包
2、创建数据库连接池(对象)
ComboPooledDataSource cpds = new ComboPooledDataSource();
3、设置连接数据库的基本信息
总测试: 注意红色的信息不一定是错误,一般报错有 Exception Error是错误
syntax 语说明法有问题 (语法) File:文件 Folder:文件夹 修改文件名:选中—右键–Rename(重新命名) 或则在文件上选中 F2
package com.tedu.c3p0;
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.tedu.util.JdbcUtil;
/*
* 测试c3p0连接池的使用 用法和上面的jar包差不多,先复制Folder 在右键引用
* (1)导入c3p0的开发包(jar包)早期在官网上下载,现在用项目管理工具Maven统一管理下载jar包。
* (2)在程序中创建一个连接池对象(容器:里面会存放一批连接)
* (3)设置连接数据的基本信息(驱动类的全路径, 链接库的url地址,链接库的用户名和密码)
* 方式一:直接将参数写死在程序中,如果将来有变化,就需要改变程序,会带来很多不必要的麻烦
* 方式二:将连接数据库的基本信息配置在c3p0.properties 文件放在 src根目录下,将来需要修改信息,直接改这个文件里的东西就行. 名字不能改变,就是这 个.
* 方式三:将连接数据库的基本信息配置在c3po-config.xml文件中,文件放在src目录下,点击--source进入编辑模式.(这个文件老师已经给了)
* 方式二和方式三中的文件名位置都是固定的,不能改变,因为c3p0会自动读取这些问题
方式二 和 三 的文件不需要我们自己读,由c3p0自动到这个src下的目录下读取,只需要把这个写好的文件放到这个src根目录下就行
*
* (4)从连接池中获取一个连接对象进行使用
* ....
* (5)将连接换回到连接池中
*/
public class TestC3p0 {
//创建一个连接池对象 可以放在方法的内部,类的内部 如果导入到包,ComboP+alt /,会有提示.
static ComboPooledDataSource pool =new ComboPooledDataSource(); //静态为了方便调用
//设置连接数据库的基本信息(方式一,不推荐使用!)
// static {//放在静态代码块里是因为可以在整个类中调用,也可以放在方法里但只能在方法里用。
// try { 上面创建对象加上 static是因为在静态代码块里,静态只能调静态
// pool.setDriverClass("com.mysql.jdbc.Driver");
// pool.setJdbcUrl("jdbc:mysql:///jt_db?characterEncoding=utf-8");
// pool.setUser("root");
// pool.setPassword("root");
// } catch (PropertyVetoException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();//显示异常类型
// }
// }
//查询表中的所有用户信息
@Test
public void testFindAll() throws Exception {
//注册驱动,并获取连接(创建一个对象),改为从连接池中获取一个现有的连接对象
//Connection conn=JdbcUtil.getConn();
Connection conn=pool.getConnection();
//获取传输器
PreparedStatement ps=conn.prepareStatement("select*from user");
//执行aql语句,返回执行结果
ResultSet rs=ps.executeQuery(); //执行查询
//输出结果
while(rs.next()) {
int id=rs.getInt(1); //1表示获取当前行中的第一列数据
String username=rs.getString(2); //2表示获取当前行中的第二列数据
String psw=rs.getString(3); //3表示获取当前行中的第三列数据
System.out.println(id+","+username+","+psw);
}
//释放资源
rs.close();
ps.close();
conn.close();
/*
* 如果当前这个连接对象,是我们自己创建的一个连接对象,调用conn.close方法默认就是将连接
* 关闭(也就是释放掉)
* 如果这个连接对象,是从连接池中获取过来的,在连接池返回这个连接对象时,会改造对象的功能(方法)--将conn的close方法改造为还连接到连接池中,而不是将连接关闭.也就是说有原来的关闭连接变为还回到连接池中而不再关闭,它会自动改造.
*/
}
}
方式二文件配置的内容,像键值对但不是:
# key=value //这个地方不能加引号,对应4个方法里的参数 左边是固定写死的
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUr1=jdbc:mysql:///jt_db?characterEncoding=utf-8
c3p0.user=root
c3p0.passworld=root
(1)方式一:(不推荐) 直接将参数通过 pool.setXxx方法设置给c3p0程序
这种方式直接将参数写死在了程序中,后期一旦参数发生变化,就要修改程序,要重新编译项目、重新发布项目,非常麻烦。
//设置连接数据库的基本信息
pool.setDriverClass( "com.mysql.jdbc.Driver" );
pool.setJdbcUrl( "jdbc:mysql:///jt_db?characterEncoding=utf-8" );
pool.setUser( "root" );
pool.setPassword( "root" );
(2)方式二:将连接参数提取到properties文件中(推荐) 创建 File文件
文件必须放在src(源码根目录)目录下 !
文件名必须叫做 c3p0.properties !
在类目录下(开发时可以放在src或者类似的源码目录下),添加一个c3p0.properties文件,配置内容如下: (不能加引号)
左边的key固定不变,右边的value视情况而变。注释:#
#key=value 这是properties文件里面的注释
c3p0.driverClass=com.mysql.jdbc.Driver #设置驱动类的全类名
c3p0.jdbcUrl=jdbc:mysql:///jt_db?characterEncoding=utf-8 #连接数据库的url地址
c3p0.user=root //连接数据库的用户名
c3p0.password=root //连接数据库的密码
这种方式由于是c3p0到指定的位置下寻找指定名称的properties文件,所以文件的位置必须是放在src或其他源码根目录下,文件名必须是c3p0.properties。
(3)方式三:将连接参数提取到xml文件中(推荐)
文件必须放在src(源码根目录)目录下 !
文件名必须叫做 c3p0-config.xml
在类目录下(开发时可以放在src或者类似的源码目录下),添加一个c3p0-config.xml文件,配置内容如下: 点击source进入编辑模式。
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driverproperty>
<property name="jdbcUrl">jdbc:mysql:///jt_db?characterEncoding=utf-8property>
<property name="user">rootproperty>
<property name="password">rootproperty>
default-config>
c3p0-config>
这种方式由于是c3p0到指定的位置下寻找指定名称的xml文件,所以文件的位置必须是放在src或其他源码根目录下,文件名必须是c3p0-config.xml。
4、从连接池中获取一个连接对象并进行使用
Connection conn = pool.getConnection();
5、用完连接后将连接还回连接池中
JdbcUtil.close(conn, ps, rs);
//conn.close()
/* 如果是自己创建的连接对象,这个连接对象没有经过任何的改动,调用
* conn.close方法,是将连接对象关闭
* 如果是从连接池中获取的连接对象,该连接对象在返回时就已经被连接池
* 改造了,将连接对象的close方法改为了还连接到连接池中
*/
(1)切换到新的工作空间目的:若旧的工作空间内容过多,可能会导致eclipse不编译,甚至进入休眠状态。
(2)设置工作空间编码为utf-8,此后在当前工作空间下创建的项目编码也默认是utf-8。
B站视频链接:https://www.bilibili.com/video/BV1ka4y1x7M6
建库建表语句如下:
-- 1、创建数据库jt_db数据库(如果不存在才创建)
create database if not exists jt_db charset utf8;
use jt_db; -- 选择jt_db数据库
-- 2、在 jt_db 库中创建 stu 表(学生表)
drop table if exists stu;
create table stu(
id int,
name varchar(50),
gender char(2),
addr varchar(50),
score double
);
-- 3、往 stu 表中, 插入记录
insert into stu values(1001,'张三','男', '北京', 86);
package com.tedu.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/** JDBC工具类 */
public class JdbcUtil {
/**
* 获取数据库连接对象并返回
* @return Connection对象
* @throws Exception
*/
public static Connection getConn() throws Exception{
//1.注册驱动
Class.forName( "com.mysql.jdbc.Driver" );
//2.获取连接
Connection conn = DriverManager.getConnection(
"jdbc:mysql:///jt_db?characterEncoding=utf-8",
"root",
"root");
return conn;
}
/**
* 释放JDBC程序中的资源
* @param conn 连接对象
* @param stat 传输器对象
* @param rs 结果集对象
*/
public static void close(Connection conn,
Statement stat, ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
rs = null;
}
}
if(stat != null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
stat = null;
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
conn = null;
}
}
}
}
package com.tedu;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;
import com.tedu.util.JdbcUtil;
/**
* 学生信息管理系统
* 运行程序,根据选项,可以对学生信息进行增删改查操作。
*/
public class StudentManager {
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
while (true) {
//1.提示选择操作选项
System.out.print("a:查询学生信息 ");
System.out.print("b:添加学生信息 ");
System.out.print("c:修改学生信息 ");
System.out.println("d:删除学生信息");
System.out.print("请输入操作,abcd任选一项:");
String opt = sc.next();
//2.根据选项执行不同操作
if( "a".equalsIgnoreCase( opt ) ){
findAll(); //查询学生信息
}else if( "b".equalsIgnoreCase( opt ) ){
addStu(); //添加学生信息
}else if( "c".equalsIgnoreCase( opt ) ){
updateStu(); //修改学生信息
}else if( "d".equalsIgnoreCase( opt ) ){
deleteStu(); //删除学生信息
}else{
System.out.println("输入错误,请重新输入!");
}
}
}
/** a. 查询所有学生信息 */
private static void findAll() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConn();
String sql = "select * from stu";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
String gender = rs.getString("gender");
String addr = rs.getString("addr");
double score = rs.getDouble("score");
System.out.println( id+","+name+","+gender
+","+addr+","+score );
}
System.out.println("------------------------------------------------------------------------------");
} catch (Exception e) {
e.printStackTrace();
}
}
/** b. 添加学生信息 */
private static void addStu() {
System.out.println("请输入要添加的学生编号、姓名、性别、地址、成绩(使用空格分隔):");
int id = sc.nextInt();
String name = sc.next();
String gender = sc.next();
String addr = sc.next();
double score = sc.nextDouble();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConn();
String sql = "insert into stu values(?,?,?,?,?)";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.setString(2, name);
ps.setString(3, gender);
ps.setString(4, addr);
ps.setDouble(5, score);
int rows = ps.executeUpdate();
if (rows > 0) {
System.out.println("添加成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/** c. 根据id修改学生信息 */
private static void updateStu() {
System.out.println("请输入要修改的学生编号、姓名、性别、地址、成绩(使用空格分隔):");
int id = sc.nextInt();
String name = sc.next();
String gender = sc.next();
String addr = sc.next();
double score = sc.nextDouble();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConn();
String sql = "update stu set name=?,gender=?"
+ ",addr=?,score=? where id=?";
ps = conn.prepareStatement(sql);
ps.setString(1, name);
ps.setString(2, gender);
ps.setString(3, addr);
ps.setDouble(4, score);
ps.setInt(5, id);
int rows = ps.executeUpdate();
if (rows > 0) {
System.out.println("修改成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/** d. 根据id删除学生信息 */
private static void deleteStu() {
System.out.println("请输入要删除的学生编号:");
int id = sc.nextInt();
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JdbcUtil.getConn();
String sql = "delete from stu where id=?";
ps = conn.prepareStatement(sql);
ps.setInt(1, id);
int rows = ps.executeUpdate();
if (rows > 0) {
System.out.println("删除成功!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行程序控制台提示如下:
输入a:查询所有学生信息
输入b:添加学生信息
输入c:根据id修改学生信息
输入d:根据id删除学生信息
在控制台中输入操作代码"a",效果如下:
在控制台中输入操作代码"b",效果如下:
在控制台中输入操作代码"c",效果如下:
在控制台中输入操作代码"d",效果如下:
HTML: 用于开发网页的一门技术
CSS: 用于修饰、渲染网页的一门技术 (用来美化网页)
HTML+CSS可以开发一个非常美观、非常漂亮的网页
开发网页 盖房子
HTML标签搭建网页的结构 砖块(搭建房子的结构)
CSS属性 石灰、油漆等涂料
HTML:执行顺序,浏览器加载从上到下,从左到右。
HTML(Hyper Text Markup Language): 超文本标记语言
超文本: 超级文本、超过文本(其中可以包含除了文本以外的其它数据,例如图片、音频、视频等各种格式)
标记:也叫标签、元素、节点等,就是用尖括号(<>)括起来的一组内容,例如:
等
HTML是最基础的开发网页的语言。
HTML由W3C组织提供(CSS/xml):该组织为国际中立性组织定义了html,css,DOM,xml,js一些的的规范标准。
万维网网址:W3Cschoole,菜鸟教程,可以再该网址学习前端知识,相当于一个在线文档。
开发工具: 早期:记事本,Dreamweaver。现在:IDEA(后端也集成了前段),WebStorm(前端),这2个软件都是捷克公司的,当然还有其他的软件等。
关于HTML的细节:
(1)使用HTML开发的网页文件通常以 .htm或 .html 为后缀!
(2)使用HTML开发的网页文件由浏览器负责解析并显示(浏览器就是一个html解析器)
(3)HTML是文档的一种(txt/word/ppt/pdf等)
总结: HTML就是用于开发网页的一门语言!
alt+/ 写一部分代码,提示快捷键 。
如果是:html,css,js,就用 Static Web Project
如果是:servlet,jsp就用 Dynamic Web Project
可以暂时用 eclipse工具: new --File–other—搜索web----Static Web Project(是静态项目还是动态项目看要求,里面用到的)—写一个项目名-----Finish --打开视图(opten…),
建好后会有一个默认的根目录(WebCount)----右键—new—HTML File(起一个文件名:如,01-第一个网页.html)
使用浏览器的注意事项:
选中打开的文件----Open With----默认的是HTML Editor-----改为Web Browser,
但是这个浏览器是eclipse自带的(不推荐,可能会发生错误,使用本地自带的)
怎么本地打开:1,选中项目—Show In—System Explorer(打开项目所在的硬盘位置,里面的.metadata是eclipse的工作空间的环境,删了这项会恢复出厂设置)—根据路径找到所建的文件—右键—打开方式(太过麻烦)
2.Wnidow—Web Brower(一般用谷歌,火狐,但最好不用IE,和本地自带的,不够专业),这个时候在 选中打开的文件----Open With----Web Browser,就用的是外部的浏览器。
如果电脑上比如先安装了一个浏览器如何把它加进来呢:
windows—preferences—General—Web Browser(倒数第二个)—第二个选项 external 外浏览器,
Remove(是移除)
加进来:new----(Name:起一个名字,Location:指定浏览器的位置,先可以选中谷歌—右键打开文件位置----点击Browse----点击回车在网址栏上粘贴----在选中浏览器----打开,Ok,就有了)
3.1.2 HTML的结构
1、案例:编写我的第一个HTML网页,并用浏览器打开
新建一个txt文档,将后缀名改为.html,代码实现如下:(保存才生效)
DOCTYPE html>
<html> //第一行下面的内容都会放在,根标签下
<head>
<title>网页的标题title>
head>
<body>
<h1>Hello CGB2003...h1> 网页内部的标题:比如一个新闻的标题,他是一个标题标签
body>
html>
测试:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>我的第一个网页title>
head>
<body>
<h1>重大新闻:马云有没有去过天上人间?h1>
<div>aaadiv>
<div>bbbdiv>
<div>cccdiv>
aaa<br/>
bbb<br/>
ccc<br/>
用户名:<input/> <br/>
密 码:<input/> <br/>
body>
html>
2、HTML结构详解
(1)DOCTYPE HTML> 文档声明, 用来声明HTML文档所遵循的HTML规范和版本
上面是html 5.0的声明, 也是目前最常用的版本 (默认就是5.0),这个版本可以简写。
(2)<html><html> 根标签,用于包裹所有的网页内容(除了文档声明)
(2)<head>head> 头部分, 用来存放HTML文档的基本属性信息, 比如网页的标题, 文档使用的编码等, 这部分信息会被浏览器优先加载.
(3)<body>body> 体部分, 用来存放网页可视化数据. 即真正的网页数据
(4)<title>title> 声明网页的标题
(5)<meta charset="utf-8" > 用来通知浏览器使用哪一个编码来打开HTML文档, 这个编码一定要和文件保存时的编码保持一致, 才不会出现中文乱码问题.
3.1.3 HTML语法(了解)
1、html标签
标签:也叫做标记、元素等,标签分为开始标签,例如:
<head>、<body>
和结束标签,例如: 注意 / 在前面
head>、body>
开始标签和结束标签之间还可以包含其他内容。
<head>
<titile>声明网页的标题title>
<meta charset="utf-8">
head>
有些标签开始标签和结束标签之间没有内容要包裹,通常可以写成自闭标签,例如:5个
<br/> <hr/> <input/> <img/> <link/>等 注意;这个/放在后面
相当与 <img> img> 但是通常不会这样写
2、html属性
在标签上可以声明属性(属性不能独立存在,必须声明在标签上)
<div id="d1" class="c1" style="color:red;">这是一个div元素div>
标签上可以声明多个属性,多个属性之间用空格分隔
标签上的属性的值可以使用单引号或者双引号引起来
<meta charset="UTF-8" id="m1">
<meta charset='UTFzs-8' id='m1'>
3、html注释
格式:
ctrl shift +/
注释的作用:
(1)为代码添加解释说明
(2)将一些暂时不需要执行的代码注释
浏览器对于html注释中的内容不会解析,也不会显示!
4、html空格和换行
在浏览器中,多个连续的空白字符(空格、制表符tab、换行)会被浏览器显示为一个空格。那么:
如何在网页中做一个换行:可以使用
标签做换行
也可以用aaa
标签包裹起来,也是独占一行。
如何在网页中做一个空格:可以使用 (英文的空格);
或
做空格
写几个就有几个空格, &emsp是中文的空格,一个相当于一个汉字的宽度
补充: HTML中是不区分大小写的!
HTML中对语法要求非常不严格!(比如大小写混用,或者标签只有开始没有结束,或者标签的不合理嵌套),但是我们在书写HTML时要按照规范来写。
3.2 HTML标签
3.2.1 标题标签
3.2.2 段落标签
<p>这是一个段落标签p>
3.2.3 换行标签(自闭)
<br/>
3.2.4 水平线标签(自闭)
<hr/>
3.2.5 粗体 斜体
粗体: <Strong>i love youstrong>
斜体: <em>i love youem>
之后的样式用css来做。
3.2.6 特殊符号标签
空格: (直接键盘输入多个空格只会显示一个)
>: >
<: $lt;
©(版权符号):©
3.2.7 图像标签(自闭)相对路径
通过img标签可以在网页中插入一副图像
<img src="./imgs/meinv.jpg" width="50%"/> 自闭标签
<img src="./imgs/lpx.jpg" alt="显示失败" title="悬停文字" width="50%"/>
把包存图片的目录复制到WebContent下
其中src属性用于指定图片的路径(图片的路径不要是带盘符的绝对路径,推荐使用相对路径)
srch:搜索,搜寻
width属性用于指定图片的宽度
height属性用于指定图片的高度
alt属性:图片显示失败时会显示这个属性的内容。
title:鼠标放在图片上显示的文字提示为这个属性设置的值。
3.2.8 超链接标签
超链接就是a标签,通过a标签可以在网页中创建指向另外一个文档的超链接
点击超链接可以跳转到另外一个网页(图片/下载路径等),示例:
<a href="01-第一个网页.html">01-第一个网页.htmla>
<a href="http://www.baidu.com">百度一下,你就不知道a>
<br/>
<a target="_blank" href="http://www.tmooc.cn">
<img alt="tmooc" src="imgs/tmooc.png" />
a>
href 属性:用于指定点击超链接后将要跳转到的URL地址 (跳转的网址)
target属用于:指定以何种方式打开超链接 (target: 目标,对象。 在当前窗口点击超链接,以前的浏览器就看不见了,有2个值。)
_self:默认值, 表示在当前窗口中打开超链接 (不写target属性,默认当前网页)
_blank:表示在新的窗口中打开超链接 (blank:空白)
总测试:
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>图像和超链接标签title>
head>
<body>
<h3>在下面创建一个超链接h3>
<a href="http://www.baidu.com">百度一下,你就不知道!a>
但这个地方打开超链接是当前网页上,在想看之前的网页没法看了,想要打开的是新的一个网页需要设置一个属性值:target,目标,对象
<a href="http://www.tmooc.cn" target="_blank">TMOOC一下,你就知道!a>
<hr/><hr/>
<h3>在下面插入一幅图像h3>
<img src="./imgs/meinv01.jpg" width="45%"/>
<img src="imgs/meinv02.jpg" width="45%"/>
body>
html>
3.2.9 锚链接(就是添加了一些属性的超链接标签)
步骤:1,需要一个锚标记。2,通过#跳转到标记。
<a name="top">顶部a>
<a href="#top">回到顶部a>
3.2.10 功能性连接
<a href="mailto:[email protected]">点击联系我a>
<a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=&site=qq&menu=yes"><img border="0" src="http://wpa.qq.com/pa?p=2::53" alt="你好,加我领取免费电影" title="你好,加我领取免费电影"/>a>
3.2.11 列表
<ol>
<li>javali>
<li>webli>
<li>linuxli>
<li>aaali>
ol>
<ul>
<li>javali>
<li>webli>
<li>linuxli>
<li>aaali>
ul>
<dl>
<dt>学科dt>
<dd>javadd>
<dd>linuxdd>
<dd>cdd>
<dd>pythondd>
dl>
自定义列表显示效果:
3.2.12 媒体元素标签(音频,视频)
<video src="/片头.mp4" controls autoplay>video>
<video src="/片头.mp3" controls autoplay>video>
3.2.13 iframe内联框架
用法一:通过src直接跳转地址显示
<iframe src="https://blog.kuangstudy.com" name="hello" width="1000px" height="500px">
iframe>
用法2:点击超链接,通过超链接向iframe框架添加属性进行跳转
<iframe src="" name="hello" width="1000px" height="500px">
iframe>
<a href="https://blog.kuangstudy.com" target="hello">点击跳转a>
3.2.14 表格标签
作用:主要用于显示,展示数据,因为他可以让数据显示的非常完整,可读性性非常好。特别是后台展示数据的时候,能够熟练的运用表格就显得很重要。一个清爽简约的表格能够把繁琐的的数据表现得很有条理。
即:表格不是用来布局页面的,而是用来展示数据的。
表格基本标签
1.案例:在网页中插入一个3*3的表格
<h1>案例1:在网页中插入一个3*3的表格h1>
<table>
<tr>
<td>11td>
<td>12td>
<td>13td>
tr>
<tr>
<td>21td>
<td>22td>
<td>23td>
tr>
<tr>
<td>31td>
<td>32td>
<td>33td>
tr>
table>
<h1>案例2:在网页中插入一个3*3的表格 跨行,跨列h1>
<table border="1px">
<tr>
<td colspan="3">11td>
tr>
<tr>
<td rowspan="2">21td>
<td>22td>
<td>23td>
tr>
<tr>
<td>31td>
<td>32td>
tr>
table>
<h1>案例3:在网页中插入一个3*3的表格,包含表格头h1>
<table>
<tr>
<th>表头1th>
<th>表头2th>
<th>表头3th>
tr>
<tr>
<td>11td>
<td>12td>
<td>13td>
tr>
<tr>
<td>21td>
<td>22td>
<td>23td>
tr>
<tr>
<td>31td>
<td>32td>
<td>33td>
tr>
table>
在浏览器中显示效果如下:
案例1:
案例2:
案例3:
在head标签内添加如下内容:
<style>
/* style标签内只能书写css注释和css代码 */
table{
border:*2px solid red; /* 为表格添加边框 */
border-collapse: collapse; /* 设置边框合并 */
background-color: pink; /* 为表格设置背景颜色 */
width: 70%; /* 为表格设置宽度 */
/* margin-left: 15%; */
/* 设置表格的左外边距和右外边距自适应(保证两者始终相等) */
margin-left: auto;
margin-right: auto;
}
td,th{
border:2px solid red; /* 为单元格添加边框 */
border-collapse: *collapse*; /* 设置边框合并 */
padding: 5px; /* 设置单元格边框和内容的距离(内边距) */
}
h1{
/* border: 2px solid blue; */
text-align: *center*; /* 设置元素中的内容水平居中 */
}
style>
再次刷新浏览器显示效果为:
2、表格基本标签介绍
table -- 用于在网页中定义一个表格
tr -- 用于定义表格中的行
td -- 用于定义表格中的单元格
th -- 用于定义表头行中的单元格(th中的文本默认居中,并且加粗)
3、练习:使用表格标签在网页中生成一个表格,如下图:
要求如下:
(1) 表格内容如下图, 并设置表格边框
(2) 设置单元格之间没有缝隙, 并设置单元格边框和内容之间的距离为5px
(3) 设置表格的背景颜色为pink, 并设置表格的宽度为70%
(4) 设置表格在网页中居中显示, 并为表格添加表头以及标题
表格结构标签
使用场景:因为表格可能很长,为了更好地表示表格的语义,可以将表格分割成表格头部和表格主题2大部分。
在表格标签中,分别用:< thead >标签表示表格的头部区域,< tbody>表示表格的主题区域。这样可以更好地分清表格结构。
1.< thead>< /thead>:用于定义表格的头部。< thead>内部必须拥有< tr>标签。一般是位于第一行。
2.< tbody>< /tbody>:一般用于定义表格的主题,主要用于放数据本体。
3.以上标签都是放在:< table> table>
<table>
<thead>
<tr>
<td>11td>
<td>12td>
<td>13td>
tr>
thead>
<tbody>
<tr>
<td>21td>
<td>22td>
<td>23td>
tr>
<tr>
<td>31td>
<td>32td>
<td>33td>
tr>
tbody>
table>
3.2.15 表单标签
1、表单的作用: 用于向服务器提交数据
向服务器提交数据的两种方式:
表单中可以包含表单项标签,在表单项中可以填写数据(比如用户名、密码等),填写完成后通过提交表单,可以将表单中的数据提交给相应的服务器。
(2)通过超链接向服务器提交数000000000000据
http://www.baidu.com?username=张三&pwd=123&like=篮球
<a href="http://www.baidu.com?username=张三&pwd=123&like=篮球" target="_blank">百度一下,你就不知道!a>
在地址栏URL地址的后面通过问号(?)可以拼接参数,参数可以有多个,多个参数之间用&
分隔,参数还分为参数名(例如:username/pwd/like)以及参数值(例如:张三/123/篮球),在回车后访问百度服务器的同时,就可以将问号后面拼接的参数一并带给百度服务器。
如果浏览器版本过低有可能会显示的是 url编码格式,不是错误。
2、表单标签
<form action="url地址" method="提交方式">form> 注意单词是form
其中action属性用于指定表单的提交地址,例如,将action指向百度服务器,就意味着将来填写完表单后,提交表单将会把表单中的数据提交给百度服务器。
method=“GET/POST” 属性是用于指定表单的提交方式,常用的就是GET和POST提交。
后面会讲。
3.2.16 表单项标签(自闭)
写在form标签里面可以提交数据的标签,当然也可以用ajax。
1、input
元素: 是什么类型取决于,type的值。
(1)普通文本输入框(比如:用户名/昵称/邮箱/验证码等)
<input type="text" name="username"/>
(2)密码输入框(比如:密码/确认密码等)
<input type="password" name="pwd"/>
(3)单选框(比如:性别/部门等)
<input type="radio" name="gender" value="male"/>男
<input type="radio" name="gender" value="fmale"/>女
(4)复选框/多选框(比如:爱好/岗位等)
<p>爱好:
<input type="checkbox" name="like" value="sleep"/>睡觉
<input type="checkbox" name="like" value="code"/>敲代码
<input type="checkbox" name="like" value="game"/>玩游戏
<input type="checkbox" name="like" value="chat"/>聊天
p>
(5)普通按钮(比如:换一张图片)
<input type="button" value="换一张"/>
普通按钮本身没有功能,但我们可以通过js为按钮添加功能或添加行为,如点击事件。
(6)图片按钮
<input type="image" src="./1.jpg"/>
(7)重置按钮
<input type="reset" value="清空表单"/>
(8)提交按钮(比如:提交/注册/登录)
<input type="submit" value="提交/注册/登录"/>
提交按钮用于提交表单中的数据到服务器中!
(9)上传文件按钮
<form action="aa.html" method="post">
<p>
<input type="file" name="files">
p>
<input type="submit" value="提交/注册/登录"/>
form>
(10)验证按钮
<p>邮箱:
<input type="email" name="email">
p>
<p>URL:
<input type="url" name="url">
p>
<p>数字:
<input type="number" name="num" max="100" min="0" step="1">
p>
(11)滑块按钮
<input type="range" name="num" max="100" min="0" step="2">
(12)搜索框按钮
<input type="search" name="search">
2、select、option
标签:
<select name="city">
<option value="beijing">北京option>
<option value="shanghai">上海option>
<option selected="selected">广州option>
<option>深圳option>
select>
3、textarea
多行文本输入区域:
<textarea name="description" cols="30" rows="5"placeholder="请输入描述信息...">
文本内容
textarea>
3.2.17 表单细节问题
1、提交表单时,表单中的数据为什么没有被提交?
对于表单中的表单项标签,只要是需要向服务器提交数据,该表单项上必须添加name属性;如果表单项标签上没有name属性,在表单提交时,该项将会被忽略。例如:
<input type="text" name="username"/>
<input type="password" name="psw"/>
2、如何让多个单选框只能有一个被选中?
要求多个单选框必须具有相同的name属性值,如果多个单选框name属性值相同,则说明是一个组的内容,一个组中的单选框只能选择其中的一个!
<td>性别:td>
<td>
<input type="radio" name="gender"/>男
<input type="radio" name="gender"/>女
td>
3、为什么单选框、复选框选择某一项后提交的值都是on?
因为单选框、复选框只能选择,不同于用户名、密码输入框,可以输入内容。
因此我们需要通过value属性为单选框或复选框设置提交的值(如果不设置默认值都是on),例如:
如果多个单选框的name值相同,表示同一组,同一组只能选一个。
<input type="radio" name="gender" value="male"/>男
<input type="radio" name="gender" value="female"/>女
4、如何设置单选框或复选框默认选中某一项?
可以在单选框或复选框标签上添加一个checked="checked"属性,就可以让当前单选框或复选框默认被选中。例如:checked:检查
<input type="radio" checked="checked" name="gender" value="male"/>男
<input type="radio" name="gender" value="female"/>女
<input type="checkbox" name="like" value="basketball"/>篮球
<input type="checkbox" checked="checked" name="like" value="football"/>足球
<input type="checkbox" name="like" value="volleyball"/>排球
5、如何设置下拉选框默认选中某一项?
在option标签上添加一个selected="selected"属性,可以让当前option选项默认被选中,例:
<select name="city">
<option>北京option>
<option>上海option>
<option selected="selected">广州option>
<option>深圳option>
select>
6、下拉选框中option选项上的value属性的作用是什么?
<select name="city">
<option value="beijing">北京option>
<option value="shanghai">上海option>
<option selected="selected">广州option>
<option>深圳option>
select>
如果某一个选项被选中,并且该选项上添加了value属性,在提交表单时,将会提交value属性的值。
如果某一个选项被选中,该选项上没有添加value属性,在提交表单时,将会提交标签中的内容(只适合下拉框)
注意:浏览器把数据提交给服务器,会把中文字符进行url编码,不是错误。
3.2.18 表单的应用(隐藏,只读,禁用,可用性增强)
<input type="text" name="username" value="好帅" readonly/>
<input type="radio" name="gender" value="male" checked disabled/>男
<input type="radio" name="gender" value="fmale"/>女
<input type="password" name="pwd" value="124155" hidden/>
<p>
<label for="mark"> 你点击试试label>
<input type="text" id="mark"/>
p>
3.2.19 表单初级验证(查询正则表达式网址)
思考表单为什么要进行验证:
1,减轻服务器的访问压力,比如淘宝每天接收几十万条请求,接收错误的数据也要验证会造成服务器压力变大。
2,保证数据的安全性。
常用方式:
1,自带验证功能的标签(初级)
2,添加验证的属性(初级,查询正则表达式网址:https://www.jb51.net/tools/regexsc.htm)
3,通过js进行验证(高级)
<input type="text" name="username" value="好帅" placeholder="请输入用户名"/>
<input type="text" name="username" placeholder="请输入用户名" required/>
<input type="text" name="mail" pattern="^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$">
3.3 注册表单案例
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>表格和表单标签title>
<style>
h1{ /* 选中所有的h1元素 */
text-align:center; /* 设置元素内容居中显示 */
color:red; /* #FF0000 */
颜色不知道具体数值时:可以使用EverEdit工具中的---工具---取色器,小吸管然后把值粘过来,值前面+个#号 16进制的值。
}
table{ /* 选中的所有的table元素 */
border:2px solid red;
border-collapse: collapse;/* 设置边框合并 */
background:lightgrey; /* 为表格设置背景颜色 */
/* 设置表格左右外边距自适应 */
margin-left: auto;
margin-right: auto;
}
td{ /* 选中所有的td元素 */
/* 为当前元素设置边框为:2像素、实线、红色 */
border:2px solid red;
border-collapse: collapse; /* 设置边框合并 */ (collapase:倒塌)
padding:5px; /* 设置边框和内容之间的距离 */ 内边距
}
style>
head>
<body>
<h1>欢迎注册h1>
<form action="#"> #相当于一个占位符会提交给它自己,相当于没提交.开发网页时可以用这个符号先占位
<table>
<tr>
<td>用户名:td> 每一个需要提交数据的表单都要加name.
<td><input type="text" name="user"/>td>
tr>
<tr>
<td>密码:td> (password 密码 ,这个框密码不会显示)
<td><input type="password" name="psw"/>td>
tr>
<tr>
<td>性别:td>
<td>
<input type="radio" name="gender" value="male" checked="checked"/>男 checked设置默认选中这个框,给用户更好的体验。前后带一致名字。
<input type="radio" name="gender" value="female" />女
td> 设置value是因为单选框默认提供的是on,男女 服务器没法区分,可以设置不同的value的值进行区分,再提交表单时On替换为value值。
tr>
<tr>
<td>爱好:td>
<td>
<input type="checkbox" name="like" value="basketball"/>篮球
<input type="checkbox" name="like" value="football" checked="checked"/>足球
<input type="checkbox" name="like" value="velloball"/>排球
td>
tr>
<tr>
<td>城市:td>
<td>
<select name="city"> select代表定义一个下拉选框,option负责里面的选项 下拉框中的option中的value,是为了如果不想提交里面的值,设置个value就是提交的vauue里的值
<option value="beijing">北京option>
<option value="shanghai">上海option>
<option selected="selected">广州option>
selected:默认选择显示广州这个选项
<option>深圳option>
select>
td>
tr>
<tr>
<td>自我描述:td>
<td>
<textarea name="description" cols="30" rows="5" placeholder="请输入描述信息...">textarea> 而且里面如果由内容哪怕是空格也不会有提示的信息,尖括号里面.输入东西提示信息消失. 多文本输入框(textarea,注意不是自闭标签 ,默认的是2行 列数行数是指,数值越大越长宽 placeholder(占位符) :写一个提示,)
td>
tr>
<tr>
<td colspan="2" style="text-align:center;">
<input type="submit" value="提交"/> (submit:提交按钮 align:校准,使一致 他就是为了提交数据的不需要 name)
td>
tr>
table>
form>
body>
html>
3.4 页面结构分析
通常一个网页包含哪些部分
<header>
<h2>网页头部h2>
header>
<section>
<h2>网页主题h2>
section>
<footer>
<h2>网页脚步h2>
footer>
效果:
3.5 CSS概述(继续学习)
3.5.1 什么是CSS?(了解)
CSS: 层叠样式表,用于修饰、渲染网页的一门技术。
一般美化的功能为:字体,颜色,边距,高度,宽度,背景图片,网页定位,网页浮动…
打开–更多工具----开发者工具或者f12,为web开发人员提供的一个工具。可以用来更好的查看网页源码,样式,调试,等等功能。
右键打开网页源代码:在浏览网页有时需要对网页源代码进行查看学习或者修改。为什么网页都可以查看源代码,不怕抄袭吗? 只能看到前端的html/js等内容,后端的代码你是看不到的。而很多网站重要的都是后端而非前端,前端只是给你个交互界面。给你看了也无妨,难不成你能看到支付宝的网页前端代码,就能复制出来一个全功能的支付宝出来?显然不太现实。
eclipse打开网页编辑模式:选中网页—new—HTML Editor
注意:Open with—HTML Editor(才是打开文件进行编辑) editor编译。
3.5.2 css发展史
css1.0
css2.0 DIV(块)+css,HTML与CSS结构分离的实现,网页变得简单,SEO
css2.1 浮动 定位
css3.0 圆角,阴影,动画… 浏览器兼容性。
注意:css和js文件的创建都是一个普通的文件file。
目录:sts :folder idea:directory
3.5.3 css语法
选择器{
/*css注释*/
声明1;
声明2;
声明3;
}
3.5.4 在HTML中引入CSS
引入优先级:就近原则
方式1:通过style属性引入css(不推荐)
<div style="border:2px solid red;font-size:26px; background:pink;">这是一个div...div>
由于上面这种方式是将css样式代码,直接写在标签上的style属性内部,如果属性太多,容易造成页面结构的混乱,不利于后期的维护。
将样式代码写在标签上,样式代码只对当前标签生效,代码无法复用!
并且使用这种方式无法将html标签和css样式进行分离!
因此不推荐使用这种方式!(这种通过style属性添加的样式,叫做行内样式/内联样式)
方式2:通过style标签引入css(这个在head标签内和script不一样)
在head标签内部可以添加一个style标签,在style标签内部可以直接书写css样式
这种方式是将所有的css样式代码集中在一个style标签内部统一管理,这种方式不会造成页面结构的混乱,并且可以实现代码的复用!
初步的实现了将html标签代码和css样式代码进行了分离!
代码示例 :
<head>
<meta charset="utf-8">
<style type="text/css">
/* ****** CSS样式 ****** */
span{ /* 为当前html中的所有span标签设置样式 */
border:2px solid green;
font-size:30px;
font-weight:bolder; /* bold/bolder */
}
style>
head>
方式3:css3.o 通过link链接引入外部的css文件(推荐)
在head标签内部,通过一个link标签可以引入外部的CSS文件(选中Web项目—new–other—css File)
这种方式是将所有的css代码集中在一个单独的css文件中统一管理,真正的实现了将css代码和html代码的分离,实现了代码的复用。 link:连接;按钮.
代码示例:html中引入demo.css文件
<link rel="stylesheet" href="demo.css" />
demo.css文件:
/*指定编码格式 */
@charset "UTF-8";
p{
border: 2px solid blue;
color: red;
font-family: "华文琥珀";
text-indent: 50px;
}
总测试:
DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
/* ****** CSS样式 ,可以省略不写****** */
span{ /* 选中所有的span元素 */
border:2px solid green;
font-size:30px;
font-weight:bolder;
}
style>
<link rel="stylesheet" href="demo.css"/>
head>
<body>
<div style="border:2px solid red;font-size:26px;background:pink;">
这是一个div...
div>
<br/>
<span>span111span>
<span>span222span>
<span>span333span>
<p>这是一个p标签1p>
<p>这是一个p标签p2p>
<p>这是一个p标签p3p>
body>
html>
demo.css文件:
@charset "UTF-8"; 不能删
p{ /* 选中所有的p元素 */
border:2px solid blue;
color:red;
/* 设置首行缩进50px */
text-indent:50px;
/* 设置字体 */
font-family:"华文琥珀";
}
3.6 CSS选择器(重点)
所谓的选择器就是能够在html中帮助我们选中元素进行修饰的一门技术。
在网页上打开开发者工具, F12。
左上角箭头选中后变蓝色,再点击对应的区域,会显示html 和 style 样式对应的代码。
被删除线标记后说明这行代码没有生效。(被覆盖可能)
3.6.1 标签名选择器(基本选择器)
通过元素名称(或标签名称)选中指定名称的所有标签
格式:
元素名/标签名{
css样式...
}
/* ----- 1.标签名选择器练习 -----
将所有span标签的背景颜色设置为#efbdef, 设置字体大小为22px,字体加粗;*/
span{ /* 选中所有的span元素 */
background-color:#efbdef;
font-size: 22px;
font-weight: bolder;
}
3.6.2 class选择器(跨标签)(基本选择器)
可以为元素添加一个通用的属性 – class,通过class属性为元素设置所属的组,class值相同的元素则为一组。通过class值可以选中这一组的元素,为元素添加样式,可以对标签进行归类。
格式:
.class值{
css样式...
}
/* ----- 2.类选择器练习 -----
(1)将所有的span(但是不包括div和p标签下的span)的背景颜色设置为#faf77b,边框改为2px solid cyan;
(2)将div下的span和内容为"span111"的span,背景颜色设置为#5eff1e、字体颜色设置
#ec0e7e;*/
.s1{ /* 选中所有class值为s1的元素 */
background: #faf77b;
border: 2px solid cyan;
}
.s2{ /* 选中所有class值为s2的元素 */
background: #5eff1e;
color: #ec0e7e;
}
另外,一个元素也可以设置多个class值,多个class值中间用空格分隔,例如:
<span class="s1 s2" >span111span>
表示当前元素同时属于多个分组,多个分组上设置的样式也会同时作用在当前元素上。
如果多个分组设置了相同的样式(但是值不一样),样式会发生冲突,写在后面的样式会覆盖前面的样式!
内容补充:选择器优先级顺序:
(1)如果是同一类选择器,同时给某些元素设置了样式,如果样式冲突了,那么写在后面的样式会覆盖前面的样式。
(2)如果是不同的选择器,设置的样式优先级顺序是:直接写在元素上>id选择器(100) > 类选择器(10) > 元素名选择器(1)
3.6.3 id选择器(基本选择器)
通过标签上通用的属性id,可以为标签设置一个独一无二的(在整个网页)编号(id值应该是唯一的),通过id值可以唯一的选中一个元素。
格式:
#id值{
css样式
}
/* ----- 3.id选择器练习 -----
用id选择器将第一个p标签设置字体大小为24px,字体颜色为#a06649, 首行文本缩进20px。*/
#p1{ /* 选中id值为p1的元素 */
font-size:24px;
color: #a06649;
text-indent: 20px;
}
<p id="p1">这是一个p元素!!!p>
3.6.4 后代选择器(层级选择器)
选中指定元素内部的指定后代元素
格式: 祖先 后代{ css样式… } 注意中间有空格.
/* ----- 4.后代选择器练习 -----
为p元素内部的所有span元素,设置字体大小为18px,字体颜色为红色,背景颜色为pink;*/
/* 匹配所有p元素内部的所有span元素 */
p span{
font-size:18px;
color: red;
background: pink;
}
/* p,span{} 匹配所有的p元素和所有的span元素 */
<p id="p1">
这是一个p元素!!!
<span>这是一个span元素!!!span>
p>
3.6.5 属性选择器(层级选择器)
在选择器选中元素的基础上,根据元素的属性条件筛选/过滤元素
格式:
/* 前面是个选择器,后面是一个中括号,里面写一个完整的属性条件,
如果一个不能区分可以用多个属性。注意这里的条件属性是完整的写。*/
选择器[属性条件]...{
css样式
}
/* ----- 5.属性选择器 -----
为所有的文本输入框,设置背景颜色为#FF7CCC、字体大小22px,首行文本缩进15px;*/
input[type='text']{ /* 匹配所有的input并且type值为text的元素 */
background: #FF7CCC;
font-size: 22px;
text-indent: 15px;
}
input[type='text'][name='email']{
/* 选中所有的input并且type值为text、并且name为email的元素 */
background : yellow;
}
3.6.6 子选择器(层级)
body>p{
background:#3cbda6;
}
3.6.7 相邻兄弟选择器(层级)
.active+p{
background:#a13d3o;
}
3.6.8 同用选择器(层级)
.active~p{
background:#a13d3o;
}
3.6.9 结构伪类选择器(略)
b站地址: https://www.bilibili.com/video/BV1YJ411a7dy?p=7&spm_id_from=pageDriver
选择器测试:
DOCTYPE HTML>
<html>
<head>
<title>CSS选择器title>
<meta charset="UTF-8" />
<style type="text/css" >
/* 为了看着方便给所有标签都加上边框,及设置一些默认的样式 */
body,input{font-size:18px;}
input{border: 2px solid green;}
div,span,p{border: 2px solid red;font-size:18px;}
span{border-color: blue;margin-right:10px;}
div,p{ width:350px;height:80px;padding:5px;}
/* ----- 1.标签名选择器练习 -----
将所有span标签的背景颜色设置为#efbdef, 设置字体大小为22px,字体加粗;*/
span{
background:#efbdef;
font-size:22px;
font-weight:bolder;
}
/* ----- 2.类选择器练习 -----
(1)将所有的span(但是不包括div和p标签下的span)的背景颜色设置为#faf77b,边框改为2px solid cyan;
(2)将div下的span和内容为"span111"的span,背景颜色设置为#5eff1e、字体颜色设置#ec0e7e;*/
.s1{ /* 点(.)后面跟的就是class的值,因此这里是选中所有class值为s1的元素 */
background:#faf77b;
border:2px solid cyan;
}
.s2{
background:#5eff1e;
color:#ec0e7e;
}
/* ----- 3.id选择器练习 -----
用id选择器将第一个p标签设置字体大小为24px,字体颜色为#a06649, 首行文本缩进20px。*/
#p1{ /* 选中id为p1的元素 */
font-size:24px;
color:#a06649;
text-indent:20px;
}
/* ----- 4.后代选择器练习 -----
为p元素内部的所有span元素,设置字体大小为18px,字体颜色为红色,背景颜色为pink;*/
p span{ /* 选中p元素内部的span元素,中间有空格 */
font-size:18px;
color:red;
background:pink;
}
/* ----- 5.属性选择器 -----
为所有的文本输入框(input type='text'),设置背景颜色为#FF7CCC、字体大小22px,首行文本缩进15px;*/
input[type='text']{ /* 选中所有的type值为text的input元素 */
background:#FF7CCC;
font-size:22px;
text-indent:15px;
}
/* */
input[type='text'][name='email']{ /* 匹配所有type为text、并且name为email的input元素 中间没有空格*/ }
style>
head>
<body>
<br/>
<div>
div111
<span class="s2">这是一个spanspan>
这是一个div
div> <br/>
<span class="s1 s2">span111span>
<span class="s1">span222span>
<span class="s1">span333span>
<p id="p1">
ppp111
<span>这是一个spanspan>
这是一个P元素
p>
<p>
ppp222
<span>这是一个spanspan>
这是一个P元素
p>
<input type="text" value="用户名"/>
<input type="button" value="按钮1" />
<input type="button" value="按钮2" />
body>
html>
3.7 常用属性总结
3.7.1 文本属性
1、text-align
:设置元素内的文本水平对齐方式,其常用取值为:
left; 默认值。左对齐
right; 右对齐
center; 居中对齐
justify; 两端对齐
2、text-decoration
:设置文本的下划线样式,其常用取值为:
underline; 有下划线
none; 没有下划线
3、text-indent
:2em ; 设置文本首行缩进,单位: 像素/百分比
4、letter-spacing
:设置字符间隔/间距,其常用取值为:
normal
5、text-shadow
:设置字体阴影,其取值为:
像素值 像素值 像素值 颜色值
第一个值为阴影水平位移,第二个值为阴影垂直位移,第三个值为阴影扩散值,第四个值为阴影颜色
解释:第一个值越大越往右偏移
3.7.2 字体属性
font-size
:设置字体大小
font-weight
:设置字体粗细 normal、bold、bolder 100/200/300…/900
font-family
:设置字体,比如微软雅黑、黑体、楷体等
color
:设置字体颜色
3.7.3 背景属性
background-color
:设置背景颜色
background-image
:设置背景图片,url(‘图片的路径’); //路径可以加引号也可以不加
background-repeat
:设置或检索对象的背景图片是否及如何排列,常用取值:
repeat(默认值,重复排列)
repeat-x(横向重复排列,但纵向不重复)
repeat-y(纵向重复排列,但横向不重复)
no-repeat(不重复)
background-position
:设置或检索对象的背景图片位置
background
: 背景颜色 背景图片 背景图片是否重复 背景图片的位置
3.7.4 边框(border)
border:2px solid red; – 设置元素的边框(可以同时设置边框的宽度、样式、颜色)
复合属性:可以同时设置多个属性
border属性可以拆分为如下设置:
border-width: 2px; -- 设置元素边框的宽度
border-style: solid; -- 设置元素边框的样式
border-color: red; -- 设置元素边框的颜色
其中border-width、border-style(比如,实线 ,虚线)、border-color也可以按照上右下左方向进行拆分,以border-width为例: 这三个属性都可以这样写
border-top-width: 2px; -- 设置上边框的宽度
border-left-width: 2px; -- 设置左边框的宽度
border-right-width: 2px; -- 设置右边框的宽度
border-bottom-width: 2px; -- 设置下边框的宽度
或则: 上 下 右 左
border width: 5px 10px 15px 20px;
border width: 5px 10px 20px; 上 左右 下
border width: 5px 20px; 上下 左右
border width: 5px ; 上下左右都是5px;
3.7.5 其它属性
width:设置元素的宽度
height:设置元素的高
margin: 设置元素的外边距
margin-top: 10px; -- 设置元素的上外边距为10px;
margin-right: 20px; -- 设置元素的右外边距为20px;
margin-bottom: 30px; -- 设置元素的下外边距为30px;
margin-left: 40px; -- 设置元素的左外边距是40px;
---------------------------------------------
margin: 10px 20px 30px 40px; -- 上 右 下 左, 顺时针方向对应
margin: 10px 20px 30px; -- 上 左右 下
margin: 10px 20px; -- 上下 左右
margin: 10px; -- 上下左右都是10px;
padding:内边距, padding 属性接受长度值或百分比值,但不允许使用负值。
h1 {
padding: 10px 0.25em 2ex 20%;
}
3.7.6 补充: 颜色设置
颜色取值方式常见的方式有三种:
方式一:设置颜色名,例如:
red、green、blue、yellow、cyan、pink、white、black等
/*在color属性后可以设置颜色这3种方式。*/
方式二:设置#加上六位的十六进制数值 可以直接使用那个工具中的取色器需要加个#:
工具----取色器—点击小吸管进行取色。
#FF0000(red)、#00FF00(green)、#0000FF(blue)、#FFFF00(yellow)、#00FFFF(cyan)等
方式三:设置rgb颜色值 ctrl +alt+a c 这是得到 rgb的三色值。
实质和方式二一样,十进制表现形式。
rgb(255,0,0) 、rgb(0,255,0) 、rgb(0,0,255) 、rgb(255,255,0) 、rgb(0,255,255) 等
(red) ( green) (blue) (yellow) (cyan)
3.8 网页开发实战
测试:完成JT项目中的登录页面!
可以先设置一些样式进行区分
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>欢迎登录title>
<link rel="stylesheet" href="login.css"/>
head>
<body>
<div id="header">
<img src="./imgs/logo.jpg"/>
<span class="line">span>
<span class="wel-login">欢迎登录span>
div>
<div id="middle">
<img src="./imgs/show.jpg"/>
<form action="#"> 为了将内容提交
<h1>登录h1>
<div class="err-msg">
账户名与密码不匹配请重新输入
div>
<input type="text" name="user" placeholder="用户名 / 已验证手机"/>
<input type="password" name="psw" placeholder="密码"/>
<input type="submit" value="登 录"/>
form>
div>
<div id="footer">
<p>
关于我们 | 联系我们 | 人才招聘 | 商家入驻 | 营销中心 | 手机京淘 | 友情连接 | 销售联盟 | 京淘社区 | 京淘公益 | English Site
<br/>
Copyright © 2015 - 2019 京淘jingtao.com 版权所有
p>
div>
body>
html>
.css文件:
@charset "UTF-8";
/* 头部分的样式 */
#header{
/* background:pink; 333 */
height:72px;
width:1200px;
/* 外边距: 上 左右 下 */
margin: 42px auto 0px;
}
#header img{ /* logo图片 */
margin-left:50px;
margin-right:33px;
vertical-align: middle; 设置中线对齐
}
#header .line{ /* 竖线 */ 加个边框设置宽高就是竖线
border:2px solid #676767;
height:68px;
/* span是inline元素,无法设置宽高,将span设置为
行内块元素,就可以设置宽高了 */
display:inline-block;
margin-right: 22px;
vertical-align: middle;
background:#676767; //给背景颜色添加一个和边框一样的颜色,这样就不会出现,里面有空白的情况。
}
#header .wel-login{ /* 欢迎登录 */
font-size:36px;
color:#676767;
vertical-align: middle;
}
/* 体部分的样式 */
#middle{
width:1200px;
margin: 42px auto 0px;
border: 7px solid #f0f0f0;
/* 设置边框的宽度, 上下为9px,左右为7px */
border-width:9px 7px;
/* border-top-width:9px;
border-bottom-width:9px; */
}
#middle form{ /* 主体中的表单 */
/* background:cyan; 333 */
width:385px;
margin-left:110px;
/* 由于form是块元素,无法和其他元素同行显示,所以
将form设置为行内块元素,这样既可以设置宽高,还可以和
其他的行内(块)同行显示 */
display: inline-block;
/* 让form的顶部和当前行内最高元素的顶部对齐 */
vertical-align: top;
}
#middle form h1{ /* 表单中的登录标题 */
font-size:26px;
color:#333; /* #六位十六进制数,AABBCC->ABC 每两位可以简写 */
margin: 87px 0px 20px;
text-align:center;
}
#middle form .err-msg{ /* 登录失败后的错误提示 */
font-size:16px;
color:#f00;
margin-bottom:9px;
text-align:center;
}
#middle form input{ /* 表单中的所有input */
width:381px;
height:49px;
border:2px solid #ededed;
font-size:16px;
color:#999;
text-indent:46px;
margin-bottom:32px;
}
#middle form input[name='user']{ /* 用户名输入框 */
/* background-image:url(./imgs/u_ico.jpg);
background-repeat:no-repeat;
background-position:15px 15px; */
/* background是复合属性,可以同时设置 背景颜色、背景图片、
背景图片是否以及如何重复排列、背景图片的位置 */
background:#fff url(./imgs/u_ico.jpg) no-repeat 14px 14px;
}
#middle form input[name='psw']{ /* 密码输入框 */
background:#fff url(./imgs/p_ico.jpg) no-repeat 14px 14px;
}
#middle form input[type='submit']{ /* 登录按钮 */
width:385px;
height:52px;
background-color:#f00;
font-size:20px;
color:#fff;
/* 覆盖上面设置的首行缩进 */
text-indent:0px;
}
/* 尾部分的样式 */
#footer{
/* background:yellow; 333 */
width:1200px;
margin: 144px auto 0px;
}
#footer p{ /* 友情链接和版权信息 */
text-align:center;
font-size:14px;
color:#999;
line-height:34px;
} 设置完成后可以缩放到同等比例进行比较有什么区别。
完成JT项目中的注册页面!(选作!)
注册页面视频:https://www.bilibili.com/video/BV16K4y1x7wX
3.9 扩展内容
3.9.1 display属性
display用来设置元素的类型,常用取值: display:陈列,展出
block:块级元素的默认值 (block:块)
默认情况下独占一行
可以设置宽高
inline:行内元素的默认值 (inline:一列)
默认情况下多个行内元素可以处在同一行
一般不能设置宽高
inline-block:行内块元素
多个元素既可以显示在同一行, 也可以设置宽和高
none:表示隐藏元素
3.9.2 元素类型(了解)
div/span/p 都是一个容器标签,用于包裹其他内容(这些元素本身不具备太多的样式!)
p: 块级元素,默认独占一行,用于包裹一段文本(段落标签,写文章时用于p标签包裹每一段内容)
div: 块级元素,默认独占一行,用于包裹其他内容,将样式设置在div上,就可以作用在div的内容上。
span:行内元素,默认可以和其他元素显示在同一行。
(1)块级元素(block)
默认情况下,无论多少内容,块级元素独占一行
可以设置宽和高,如果设置了就是用设置的宽和高
如果不设置宽和高,其中宽是默认填满父元素,而高是由内容决定(由内容支撑)
比如: div/p/h1~h6/form/table 等元素都是块级元素
(2)行内元素(inline)
默认情况下,多个行内元素可以处在同一行
不能设置宽和高
比如: span/input/img/i/b/a 等元素都是行内元素
(3)行内块元素(inline-block)
既具备行内元素的特征(可以同行显示),还具备块级元素的特征(可以设置宽和高)
3.10 css盒子模型
css盒模型 内容+padding+border+margin
1.标准盒模型(框模型)
width属性=内容的宽度
2.怪异盒模型 ie6以及ie6以下的浏览器 不写 文档声明的时候
width属性=内容宽度+padding +border
如果写文档声明,即在标准情况下出现怪异盒模型的情况:
box-sizing:border-box; //怪异盒模型
center-box;//标准盒模型
3.11 css定位的方式(5种)
概念:确定标签的位置
postion属性需要与left,right,top,bottom(底部,最下面)连用
属性:postion
取值:
1:relative:相对定位,相对于自身的默认位置进行定位.
2.absolute:绝对定位,相对于整个web页面定位.
3.static:默认的定位方式 (左上角)
4.fixed:固定定位,相对于整个web页面定位,位置不会随着页面的位置变化而变化.
5.黏贴定位:sticky是CSS3新增的一处属性,可以说是相对定位relative与固定定位fixed的结合,它主要用在对scroll事件的监听上,简单来说,在滚动过程中,某个元素距离父元素的距离达到sticky粘性定位的要求时(比如:top: 40px;)position: sticky这时的效果相当于fixed定位,固定到适当的位置(比如:固定在距离屏幕上方40px处)
如:
#pp1{
color: blue;
postion:absolute;
left:100px;
top:100px;
right:50px;
}
4 unit00-第二阶段课程介绍
4.1 讲师自我介绍
张慎政
QQ: 731471199
Tel: 18518923147
4.2 Web课程简介
1、学习数据库(MySQL)的相关知识
2、学习如何利用Java程序访问数据库,实现增删改查操作(JDBC)
3、学习前端页面开发的相关技术(html,css,JavaScript,jQuery)
4、学习Servlet/JSP相关知识,为后面的框架打基础
5、学习会话技术(Cookie和Session)
5、学习企业级开发项目管理工具-Maven,利用Maven构建项目
6、学习Mybatis框架(封装JDBC、简化JDBC)、SpringMVC框架(封装Servlet)、spring框架等三大框架的基础操作
7、学习SSM三大框架整合,使用SSM框架完成永和大王门店系统
关于SSM三大框架,Web阶段只是做一个框架的基础入门,只学习简单的框架使用及整合,框架的高级进阶和底层实现会在第三个阶段(框架阶段)进行学习!!!
4.3 学习方法建议
1、课上以听为主,在听懂知识点的基础上,或者是理解程序的实现思路之后,再去写代码。
2、遇到不懂的、没跟上的先做标记,坚持把课听完整,课下再解决问题或者再补课上遗漏的内容。
3、遇到问题或BUG,自己通过查看错误信息,分析问题出现的原因(自己找5~10min),如果找不出原因,再求助他人。
~求助周围的同学
~求助项目经理
~求助讲师
4、多敲代码:通过多敲代码达到一定的熟练度,做到触类旁通!!!(误区:听懂了就以为自己会了)
~代码量和薪资成正比!!!
5 unit00-MySQL环境检测
5.1 检查MySQL或mariadb环境
mariadb是MySQL的一个分支,是由开发MySQL的团队成员之一,分离后开发的数据库产品,用法和MySQL完全一致,并且mariadb安装起来要比MySQL更不容易出现环境问题。
下面不再出现mariadb,统一用MySQL代替 (即: 可以理解为mariadb就是Mysql)
mysql --version 查看安装MySQL的版本
(1)打开CMD窗口,在cmd中输入:mysql -uroot -proot (window+r , u p 代表的是你安装好数据库设置的用户名和密码)
若提示如下效果:
则说明MySQL环境正常,即当前电脑上安装了MySQL 软件,并且也配置了!!
(2)如果提示“mysql不是内部或外部命令”则说明MySQL环境有问题
有如下两种可能:
a)当前电脑安装了MySQL ,但没有配置环境变量
b)当前电脑既没有安装MySQL ,也没有配置环境变量
下面先来验证第一种情况
5.2 检查电脑上是否安装MySQL
默认情况下,mysql 会安装在:C:\Program Files\ 目录下,
在C:\Program Files\目录下查看是否有MySQL 目录,如果有,并且目录结构如下,则说明当前电脑上安装了数据库软件。
如果当前电脑上安装了数据库软件,则跳转第三步,直接执行第4步,配置mysql 的环境变量;
如果当前电脑上没有安装数据库软件,则执行第三步,先安装数据库软件,再执行第4步;
5.3 安装MySQL/mariadb 数据库
在 ftp://cgb2xxx/02-web/unit00-software/ 已经上传了 mariadb软件,大家可以下载下来进行安装,安装步骤如下。
mysql每次开启计算机,它会随着windows系统的启动而自动启动. 不需要自己开启,
如果是安装过后需要重装,则先把服务停掉(计算机—右键管理—服务和应用程序–服务----找到安装的mysql可以看到正在运行----右键—停止, 接着右键–属性—启动类型—禁用/手动)
找到课前资料中软件中的 MAriaDB双击运行:
(1)在下面窗口中直接点击下一步即可
(2)在下面窗口中勾选复选框,同意协议
(3)下面窗口要求设置软件安装路径,保持默认即可
(4)在下面窗口中设置密码和确认密码,可以统一设置为 root
(5)在下面窗口中设置服务的名称(只要不和系统中存在的服务名称冲突即可) 和
端口(只要不和系统中其他进程占用的端口冲突即可)
一个线程只能占用一个端口
(6)在下面窗口中直接点击下一步
(7)点击instal安装即可
5.4 配置MySQL 环境变量
(1)在 计算机/此电脑 图标上右键找属性—>高级系统设置 —>
环境变量,在弹出的窗口中找到 系统变量,在系统变量窗口中找到
Path变量,如图所示:
(2)找到mysql 安装目录下的bin目录,复制bin目录的路径,例如:(为了保证在任何目录下都能使用这个命令,
(3)将复制的路径,配置到path环境变量中。如果是win7系统,配置如下:
(4)如果是win8或win10系统:
6 unit00-typora软件配置
6.1 设置代码块前的序号
如何在代码块前面设置行号,如下图所示: (打开笔记需要用到课前资料的软键安装后才能打开)
设置步骤如下:在 typora 软件的左上角,找到菜单中的 文件
—> 偏好设置
(或者直接 ctrl+逗号 ),会弹出如下窗口,选择 markdown
,找到右侧中的代码块
,勾选显示行号选项
。
设置完后,关闭偏好设置窗口,重启typora软件即可!
6.2 设置标题前的编号
如何在一级、二级、三级标题前显示编号,效果如下图所示:
设置步骤如下:在 typora 软件的左上角,找到菜单中的 文件
—> 偏好设置
(或者直接 ctrl+逗号 ),会弹出如下窗口,选择 外观
,找到右侧中的打开主题文件夹
,并点击。
点击后,会出现如下文件夹(themes),找到并打开其中的base.user.css
文件(如果没有就创建该文件):
将该文件中的内容覆盖为如下内容即可:
@charset "utf-8";
#write{counter-reset:h1}
h1{counter-reset:h2}
h2{counter-reset:h3}
h3{counter-reset:h4}
h4{counter-reset:h5}
h5{counter-reset:h6}
#write h1:before{counter-increment:h1;content:counter(h1) " "}
#write h2:before{counter-increment:h2;content:counter(h1) "." counter(h2) " "}
#write h3:before,
h3.md-focus.md-heading:before{counter-increment:h3;content:counter(h1) "." counter(h2) "." counter(h3) " "}
#write h4:before,
h4.md-focus.md-heading:before{counter-increment:h4;content:counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) " "}
#write h5:before,
h5.md-focus.md-heading:before{counter-increment:h5;content:counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) " "}
#write h6:before,
h6.md-focus.md-heading:before{counter-increment:h6;content:counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) "." counter(h6) " "}
#write>h3.md-focus:before,
#write>h4.md-focus:before,
#write>h5.md-focus:before,
#write>h6.md-focus:before,
h3.md-focus:before,
h4.md-focus:before,
h5.md-focus:before,
h6.md-focus:before{ color:inherit;border:inherit;border-radius:inherit;position:inherit;left:initial;float:none;top:initial;font-size:inherit;padding-left:inherit;padding-right:inherit;vertical-align:inherit;font-weight:inherit;line-height:inherit}
img{border:2px dashed #333;border-radius:10px;zoom:80%}
或者直接到:C:/用户/{当前系统用户}/AppData/Roaming/Typora/themes/
这个目录下,找到并打开其中的base.user.css
文件(如果没有就创建该文件),并将内容覆盖为如上内容。
设置完后,关闭偏好设置窗口,重启typora软件即可!
你可能感兴趣的:(mysql,数据库)