一、sql入门
1、数据库的概念
2、关系型数据库(市面上还是这个用的多)
3、常见数据库
(1)、商业数据库
Oracle、SQLServer、DB2、Sybase
(2)、开源数据库
MySQL、SQLLite
4、使用命令行窗口连接MYSQL数据库:
mysql –u用户名 –p,回车,之后输出密码
5、MySQL数据库服务器、数据库和表的关系
(1)、所谓安装数据库服务器,只是在机器上装了一个数据库管理程序,这个管理程序可以管理多个数据库,一般开发人员会针对每一个应用创建一个数据库。
(2)、为保存应用中实体的数据,一般会在数据库创建多个表,以保存程序中实体的数据。
(3)、数据库服务器、数据库和表的关系如图所示:
(4)、数据在数据库中的存储方式
6、SQL语言:
(1)、Structured Query Language, 结构化查询语言
(2)、非过程性语言(行与行之间无关系)
(3)、美国国家标准局(ANSI)与国际标准化组织(ISO)已经制定了SQL标准
(4)、为加强SQL的语言能力,各厂商增强了过程性语言的特征
如Oracle的PL/SQL 过程性处理能力
SQL Server、Sybase的T-SQL
(5)、SQL是用来存取关系数据库的语言,具有查询、操纵、定义和控制关系型数据库的四方面功能。
二、sql语句
创建的数据库存在:C:ProgramData(隐藏)MySQLMySQL Server 5.6data中 ,配置C:ProgramDataMySQLMySQL Server 5.6下的my.ini:
# Path to the database root
datadir=F:webexampleSQL
1.操作数据库
(1)创建数据库
CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...]
create_specification:
[DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name
~创建一个名称为mydb1的数据库。
CREATE DATABASE IF NOT EXISTS mydb1;(不存在创建,存在不创建)
~创建一个使用gbk字符集的mydb2数据库。
create database mydb2 character set gbk;
~创建一个使用utf8字符集,并带校对规则的mydb3数据库。
create database mydb3 character set utf8 collate utf8_bin;
(2)查看数据库
显示数据库语句:
SHOW DATABASES
显示数据库创建语句:
SHOW CREATE DATABASE db_name
~查看当前数据库服务器中的所有数据库 :
show databases;
~查看前面创建的mydb2数据库的定义信息:
show create database mydb3;
(3)修改数据库
ALTER DATABASE [IF NOT EXISTS] db_name [alter_specification [, alter_specification] ...]
alter_specification:
[DEFAULT] CHARACTER SET charset_name | [DEFAULT] COLLATE collation_name
~查看服务器中的数据库,并把其中mydb2字符集修改为utf8
alter database mydb2 character set utf8;
(4)删除数据库
DROP DATABASE [IF EXISTS] db_name
~删除前面创建的mydb1数据库 drop database mydb1;
drop database mydb1;
(5)选择数据库
进入数据库:use db_name;
查看当前所选的数据库: select database();
2.操作表
常用数据类型:
字符串型 :VARCHAR(变长,有最长限制)、CHAR
大数据类型:BLOB、TEXT
数值型:TINYINT 1字节、SMALLINT 2字节、INT 4字节、BIGINT 8字节、FLOAT 4字节、DOUBLE 8
字节逻辑型 :BIT 位类型,对应boolean(0,1)
日期型:DATE、TIME、DATETIME、TIMESTAMP
定义单表字段的约束:
定义主键约束
primary key:不允许为空,不允许重复
删除主键:alter table tablename drop primary key ;
主键自动增长 :auto_increment
定义唯一约束
unique
例如:name varchar(20) unique
定义非空约束
not null
例如:salary double not null
外键约束
(1)创建表
CREATE TABLE table_name
(
field1 datatype,
field2 datatype,
field3 datatype,
)[character set 字符集] [collate 校对规则]
field:指定列名 datatype:指定列类型
~创建一个员工表employee
create table employee(
id int primary key auto_increment,
name varchar(20) unique,
gender bit not null,
birthday date,
entry_date date,
job varchar(40),
salary double,
resume text
);
(2)查看表
查看表结构:desc tabName
查看当前数据库中所有表:show tables
查看当前数据库表建表语句 show create table tabName;
(3)修改表
ALTER TABLE table ADD/MODIFY/DROP/CHARACTER SET/CHANGE
(column datatype [DEFAULT expr][, column datatype]...);
*修改表的名称:rename table 表名 to 新表名;
~在上面员工表的基本上增加一个image列。
alter table employee add image blob; (blod二进制类型)
~修改job列,使其长度为60。
alter table employee modify job varchar(60);
~删除gender列。
alter table employee drop gender;
~表名改为user。
rename table employee to user;
~修改表的字符集为gbk
alter table user character set gbk;
~列名name修改为username
alter table user change name username varchar(20);
(4)删除表
DROP TABLE tab_name;
~删除user表
drop table user;
3.操作表记录CRUD
(1)INSERT
INSERT INTO table [(column [, column...])] VALUES (value [, value...]);
插入的数据应与字段的数据类型相同。
数据的大小应在列的规定范围内,例如:不能将一个长度为80的字符串加入到长度为40的列中。
在values中列出的数据位置必须与被加入的列的排列位置相对应。
字符和日期型数据应包含在单引号中。
插入空值:不指定或insert into table value(null)
如果要插入所有字段可以省写列列表,直接按表中字段顺序写值列表
~使用insert语句向表中插入三个员工的信息
insert into employee (id,name,gender,birthday,entry_date,job,salary,resume)values (null,'张飞',1,'1999-09-09','1999-10-01','打手',998.0,'老大的三弟,真的很能打');
insert into employee values (null,'关羽',1,'1998-08-08','1998-10-01','财神爷',9999999.00,'老大的二弟,公司挣钱都指着他了');
insert into employee values (null,'刘备',0,'1990-01-01','1991-01-01','ceo',100000.0,'公司的老大'),(null,'赵云',1,'2000-01-01','2001-01-01','保镖',1000.0,'老大贴身人');
mysql中文乱码:
mysql有六处使用了字符集,分别为:client 、connection、database、results、server 、system。
client是客户端使用的字符集。
connection是连接数据库的字符集设置类型,如果程序没有指明连接数据库使用的字符集类型就按照服务器端默认的字符集设置。
database是数据库服务器中某个库使用的字符集设定,如果建库时没有指明,将使用服务器安装时指定的字符集设置。
results是数据库给客户端返回时使用的字符集设定,如果没有指明,使用服务器默认的字符集。
server是服务器安装时指定的默认字符集设定。
system是数据库系统使用的字符集设定。(utf-8不可修改)
show variables like'character%';(查看表中使用的编码集)
set names gbk; 指定当前窗口所使用的编码集
通过修改my.ini 修改字符集编码
- 编码:将字符编为二进制 就叫做编码;
- 解码:将二进制解析为字符叫做解码;
- 转码:将一个字符从a字符集表示的二进制转为b字符集表示的二进制过程叫做转码。
未设置数据库的编码时,其默认值如下: 或者将设置过的数据库:set names gbk; 也可变为如下
若想默认使用GBK,可以设置C:ProgramDataMySQLMySQL Server 5.6下的my.ini:
# The default character set that will be used when a new schema or table is
# created and no character set is defined
character-set-server=utf8
(2)UPDATE
UPDATE tbl_name SET col_name1=expr1 [, col_name2=expr2 ...] [WHERE where_definition]
UPDATE语法可以用新值更新原有表行中的各列。
SET子句指示要修改哪些列和要给予哪些值。
WHERE子句指定应更新哪些行。如没有WHERE子句,则更新所有的行
~将所有员工薪水修改为5000元。
update employee set salary = 5000;
~将姓名为’张飞’的员工薪水修改为3000元。
update employee set salary = 3000 where name='张飞';
~将姓名为’关羽’的员工薪水修改为4000元,job改为ccc。
update employee set salary=4000,job='ccc' where name='关羽';
~将刘备的薪水在原有基础上增加1000元。
update employee set salary=salary+1000 where name='刘备';
(3)DELETE
如果不使用where子句,将删除表中所有数据。
Delete语句不能删除某一列的值(可使用update)
使用delete语句仅删除记录,不删除表本身。如要删除表,使用drop table语句。
同insert和update一样,从一个表中删除记录将引起其它表的参照完整性问题,在修改数据库数据时,头脑中应该始终不要忘记这个潜在的问题。
外键约束
删除表中数据也可使用TRUNCATE TABLE 语句,它和delete有所不同,参看mysql文档。
delete from tbl_name [WHERE where_definition]
~删除表中名称为’张飞’的记录。
delete from employee where name='张飞';
~删除表中所有记录。
delete from employee;
~使用truncate删除表中记录。
truncate table employee;
对于其它存储引擎,在MySQL 5.1中,TRUNCATE TABLE与DELETE FROM有以下几处不同:
· 删减操作会取消并重新创建表,这比一行一行的删除行要快很多。
· 删减操作不能保证对事务是安全的;在进行事务处理和表锁定的过程中尝试进行删减,会发生错误。
· 被删除的行的数目没有被返回。
· 只要表定义文件tbl_name.frm是合法的,则可以使用TRUNCATE TABLE把表重新创建为一个空表,
即使数据或索引文件已经被破坏。
· 表管理程序不记得最后被使用的AUTO_INCREMENT值,但是会从头开始计数。
即使对于MyISAM和InnoDB也是如此。MyISAM和InnoDB通常不再次使用序列值。
· 当被用于带分区的表时,TRUNCATE TABLE会保留分区;即,数据和索引文件被取消并重新创建,
同时分区定义(.par)文件不受影响。
TRUNCATE TABLE是在MySQL中采用的一个Oracle SQL扩展。
(4)SELECT
~1.基本查询
SELECT [DISTINCT] *|{column1, column2. column3..} FROM table;
create table exam(
id int primary key auto_increment,
name varchar(20) not null,
chinese double,
math double,
english double
);
~查询表中所有学生的信息。
select * from exam;
~查询表中所有学生的姓名和对应的英语成绩。
select name,english from exam;
~过滤表中重复数据
select distinct english from exam;
~在所有学生分数上加10分特长分显示。
select name , math+10,english+10,chinese+10 from exam;
~统计每个学生的总分。
select name ,english+math+chinese from exam;
使用别名表示学生总分。
select name as 姓名 ,english+math+chinese as 总成绩 from exam;
select name 姓名 ,english+math+chinese 总成绩 from exam;
select name english from exam;(忘记,号,变成别名)
~2.使用where子句进行过滤查询
~查询姓名为张飞的学生成绩
select * from exam where name='张飞';
~查询英语成绩大于90分的同学
select * from exam where english > 90;
~查询总分大于230分的所有同学
select name 姓名,math+english+chinese 总分 from exam where math+english+chinese>230;
~查询英语分数在 80-100之间的同学。
select * from exam where english between 80 and 100;
~查询数学分数为75,76,77的同学。
select * from exam where math in(75,76,77);
~查询所有姓张的学生成绩。
select * from exam where name like '张%';
select * from exam where name like '张__';(两个_)
~查询数学分>70,语文分>80的同学。
select * from exam where math>70 and chinese>80;
比较运算符 | > < <= >= = <> | 大于、小于、大于(小于)等于、不等于 |
between ...and... | 显示在某一区间的值 | |
in(set) | 显示在in列表中的值,例:in(100,200) | |
like ‘张pattern’ | 模糊查询%_ | |
Is null | 判断是否为空 | |
逻辑运算符 | and | 多个条件同时成立 |
or | 多个条件任一成立 | |
not | 不成立,例:where not(salary>100); |
通配符 描述
% 替代一个或多个字符
_ 仅替代一个字符
[charlist] 字符列中的任何单一字符
[^charlist]或[!charlist] 不在字符列中的任何单一字符
~3.使用order by关键字对查询结果进行排序操作
SELECT column1, column2. column3.. FROM table where... order by column asc|desc;
asc 升序 -- 默认就是升序
desc 降序
lORDER
BY 子句应位于SELECT语句的结尾。
~对语文成绩排序后输出。
select name,chinese from exam order by chinese desc;
~对总分排序按从高到低的顺序输出
select name 姓名,chinese+math+english 总成绩 from exam order by 总成绩 desc;
~对姓张的学生成绩排序输出
select name 姓名,chinese+math+english 总成绩 from exam where name like '张%' order by 总成绩 desc;
~4.聚合函数
(1)Count -- 用来统计符合条件的行的个数
~统计一个班级共有多少学生?
select count(*) from exam;
~统计数学成绩大于90的学生有多少个?
select count(*) from exam where math>70;
~统计总分大于230的人数有多少?
select count(*)from exam where math+english+chinese > 230;
(2)SUM -- 用来将符合条件的记录的指定列进行求和操作
~统计一个班级数学总成绩?
select sum(math) from exam;
~统计一个班级语文、英语、数学各科的总成绩
select sum(math),sum(english),sum(chinese) from exam;
~统计一个班级语文、英语、数学的成绩总和
select sum(ifnull(chinese,0)+ifnull(english,0)+ifnull(math,0)) from exam;
在执行计算时,只要有null参与计算,整个计算的结构都是null
此时可以用ifnull函数进行处理
~统计一个班级语文成绩平均分
select sum(chinese)/count(*) 语文平均分 from exam;
(3)AVG -- 用来计算符合条件的记录的指定列的值的平均值
~求一个班级数学平均分?
select avg(math) from exam;
~求一个班级总分平均分?
select avg(ifnull(chinese,0)+ifnull(english,0)+ifnull(math,0)) from exam;
(4)MAX/MIN -- 用来获取符合条件的所有记录指定列的最大值和最小值
~求班级最高分和最低分
select max(ifnull(chinese,0)+ifnull(english,0)+ifnull(math,0)) from exam;
select min(ifnull(chinese,0)+ifnull(english,0)+ifnull(math,0)) from exam;
~5.分组查询 使用group by 子句对列进行分组
CREATE TABLE orders(
id int,
product varchar(20),
price float
);
~对订单表中商品归类后,显示每一类商品的总价
select product,sum(price) from orders group by product;
~询购买了几类商品,并且每类总价大于100的商品
select product 商品名,sum(price)商品总价 from orders group by product having sum(price)>100;
where子句和having子句的区别:
where子句在分组之前进行过滤,having子句在分组之后进行过滤
having子句中可以使用聚合函数,where子句中不能使用
很多情况下使用where子句的地方可以使用having子句进行替代
~查询单价小于100而总价大于150的商品的名称
select product from orders where price<100 group by product having sum(price)>150;
~~sql语句书写顺序:
select——from—— where—— group by—— having ——order by
~~sql语句执行顺序:
from ——where—— select ——group by—— having—— order by
~~备份恢复数据库
备份: cmd> mysqldump -u 用户名 -p 数据库名 > 文件名.sql
在cmd窗口下 mysqldump -u root -p dbName>c:/1.sql
恢复: source 文件名.sql // 在mysql内部使用
mysql –u 用户名 -p 数据库名 < 文件名.sql // 在cmd下使用
方式1:在cmd窗口下 mysql -u root -p dbName<c:/1.sql
方式2:在mysql命令下, source c:/1.sql
要注意恢复数据只能恢复数据本身,数据库没法恢复,需要先自己创建出数据后才能进行恢复.
二、多表设计多表查询
1.外键约束
表是用来保存显示生活中的数据的,而现实生活中数据和数据之间往往具有一定的关系,我们在使用表来存储数据时,可以明确的声明表和表之前的依赖关系,命令数据库来帮我们维护这种关系,向这种约束就叫做外键约束
定义外键约束:
foreign key
foreign key(ordersid) references orders(id)
create table dept(
id int primary key auto_increment,
name varchar(20)
);
insert into dept values(null,'财务部'),(null,'人事部'),(null,'销售部'),(null,'行政部');
create table emp(
id int primary key auto_increment,
name varchar(20),
dept_id int,
foreign key(dept_id) references dept(id)
);
insert into emp values(null,'奥巴马',1),(null,'哈利波特',2),(null,'本拉登',3),(null,'朴乾',3);
emp表中插入dept表中无id=5的部门的人,报错;
删除dept表id=4的部门,emp表中有依赖,无法删除。
2.多表设计
一对多:在多的一方保存一的一方的主键做为外键。
一对一:在任意一方保存另一方的主键作为外键。
多对多:创建第三方关系表保存两张表的主键作为外键,保存他们对应关系。
3.多表查询
笛卡尔积查询:
将两张表的记录进行一个相乘的操作查询出来的结果就是笛卡尔积查询,如果左表有n条记录,右表有m条记录,笛卡尔积查询出有n*m条记录,其中往往包含了很多错误的数据,所以这种查询方式并不常用
+----+--------+
| id | name |
+----+--------+
| 1 | 财务部 |
| 2 | 人事部 |
| 3 | 销售部 |
| 4 | 行政部 |
+----+--------+
4 rows in set
+----+----------+---------+
| id | name | dept_id |
+----+----------+---------+
| 1 | 奥巴马 | 1 |
| 2 | 哈利波特 | 2 |
| 3 | 本拉登 | 3 |
| 4 | 朴乾 | 3 |
+----+----------+---------+
select * from dept,emp;
+----+--------+----+----------+---------+
| id | name | id | name | dept_id |
+----+--------+----+----------+---------+
| 1 | 财务部 | 1 | 奥巴马 | 1 |
| 2 | 人事部 | 1 | 奥巴马 | 1 |
| 3 | 销售部 | 1 | 奥巴马 | 1 |
| 4 | 行政部 | 1 | 奥巴马 | 1 |
| 1 | 财务部 | 2 | 哈利波特 | 2 |
| 2 | 人事部 | 2 | 哈利波特 | 2 |
| 3 | 销售部 | 2 | 哈利波特 | 2 |
| 4 | 行政部 | 2 | 哈利波特 | 2 |
| 1 | 财务部 | 3 | 本拉登 | 3 |
| 2 | 人事部 | 3 | 本拉登 | 3 |
| 3 | 销售部 | 3 | 本拉登 | 3 |
| 4 | 行政部 | 3 | 本拉登 | 3 |
| 1 | 财务部 | 4 | 朴乾 | 3 |
| 2 | 人事部 | 4 | 朴乾 | 3 |
| 3 | 销售部 | 4 | 朴乾 | 3 |
| 4 | 行政部 | 4 | 朴乾 | 3 |
+----+--------+----+----------+---------+
内连接查询:查询的是左边表和右边表都能找到对应记录的记录
select * from dept,emp where dept.id = emp.dept_id;
select * from dept inner join emp on dept.id=emp.dept_id;
+----+--------+----+----------+---------+
| id | name | id | name | dept_id |
+----+--------+----+----------+---------+
| 1 | 财务部 | 1 | 奥巴马 | 1 |
| 2 | 人事部 | 2 | 哈利波特 | 2 |
| 3 | 销售部 | 3 | 本拉登 | 3 |
| 3 | 销售部 | 4 | 朴乾 | 3 |
+----+--------+----+----------+---------+
外连接查询:
左外连接查询:在内连接的基础上增加左边表有而右边表没有的记录
select * from dept left join emp on dept.id=emp.dept_id;
+----+--------+------+----------+---------+
| id | name | id | name | dept_id |
+----+--------+------+----------+---------+
| 1 | 财务部 | 1 | 奥巴马 | 1 |
| 2 | 人事部 | 2 | 哈利波特 | 2 |
| 3 | 销售部 | 3 | 本拉登 | 3 |
| 3 | 销售部 | 4 | 朴乾 | 3 |
| 4 | 行政部 | NULL | NULL | NULL |
+----+--------+------+----------+---------+
右外连接查询:在内连接的基础上增加右边表有而左边表没有的记录
select * from dept right join emp on dept.id=emp.dept_id;
全外连接查询:在内连接的基础上增加左边表有而右边表没有的记录和右边表有而左表表没有的记录
select * from dept full join emp on dept.id=emp.dept_id; -- mysql不支持全外连接
可以使用union关键字模拟全外连接:
select * from dept left join emp on dept.id = emp.dept_id
union
select * from dept right join emp on dept.id = emp.dept_id;
+----+--------+------+----------+---------+
| id | name | id | name | dept_id |
+----+--------+------+----------+---------+
| 1 | 财务部 | 1 | 奥巴马 | 1 |
| 2 | 人事部 | 2 | 哈利波特 | 2 |
| 3 | 销售部 | 3 | 本拉登 | 3 |
| 3 | 销售部 | 4 | 朴乾 | 3 |
| 4 | 行政部 | NULL | NULL | NULL |
+----+--------+------+----------+---------+