关于数据库的操作语句

关于数据库的操作语句

                                                     -----作者:ymkey   
                                                      引用请标明出处
SQL注意点 : 	
	SQL 语言大小写不敏感。 
	SQL 可以写在一行或者多行
	关键字不能被缩写也不能分行
	各子句一般要分行写。
	使用缩进提高语句的可读性。

create 
drop 
alter
以上语句统称DDL语句 -> 数据定义语

-- 查看服务器中有哪些数据库
show databases;
-- 创建新的数据库
create database company;
-- 查看当前数据库中的表
show tables;

-- 导入.sql文件中的数据
source d:/company.sql;

-- 练习 : 创建world数据库, 并切换, 再导入world.sql文件中的数据到world库.
create database world;
use world;
source d:/world.sql;

-- 查看当前数据库中的表
show tables;
-- 丢弃数据库
drop database company;

drop database world;

-- 查看当前工作数据库
select database();

-- 查看当前工作数据库的版本
select version();


- 查看服务器所有参数
show variables;

-- 和字符集设置相关的参数 : 
character_set_client                                     | gbk
character_set_connection                                 | gbk
character_set_database                                   | utf8
character_set_filesystem                                 | binary
character_set_results                                    | gbk
character_set_server                                     | utf8
character_set_system                                     | utf8

-- 如果client,connection和result的设置不是gbk, 必须执行以下语句

-- 修改客户端编码
set names gbk;

数据库结构
	mysqld 服务器
		数据库1(目录形式)
			表1
				数据(记录)1
				数据(记录)2
				数据(记录)3
				....
			表2 
			表3
			....
			
		数据库2
		......
		

关于表的操作


DML 数据操纵语言.
insert C
select R 
update U
delete D



-- 查看表中数据
select * from 表名; 

-- 查看表结构
describe employees;
desc employees;

+----------------+--------------+------+-----+---------+----------------+
| Field          | Type         | Null | Key | Default | Extra          |
+----------------+--------------+------+-----+---------+----------------+
| employee_id    | int(6)       | NO   | PRI | NULL    | auto_increment |
| first_name     | varchar(20)  | YES  |     | NULL    |                |
| last_name      | varchar(25)  | YES  |     | NULL    |                |
| email          | varchar(25)  | YES  |     | NULL    |                |
| phone_number   | varchar(20)  | YES  |     | NULL    |                |
| job_id         | varchar(10)  | YES  | MUL | NULL    |                |
| salary         | double(10,2) | YES  |     | NULL    |                |
| commission_pct | double(4,2)  | YES  |     | NULL    |                |
| manager_id     | int(6)       | YES  |     | NULL    |                |
| department_id  | int(4)       | YES  | MUL | NULL    |                |
+----------------+--------------+------+-----+---------+----------------+
--创建表

create table customer(       create + table +表名(列名 数据类型,列名 数据类型,。。。。。);
	id int,
	name varchar(20),
	age int,
	phone varchar(15),
	birthday date
);

--向表中添加数据
insert into customer (      insert into 表名(列名,列名....)values(数据,数据,.....);
	id,
	name,
	age,
	phone,
	birthday
) values (
	1,
	'张三',
	30,
	'134234234',
	'1992-5-8'
);



-- 更新记录(修改数据)
-- 如果更新时不加where过滤, 会导致所有数据被修改
update customer set    update 表名 set 列名 = '新数据',列名 = '新数据';
	name = '某人',
	age = 10;
	
update customer set      update 表名 set 列名 = '新数据',列名 = '新数据' where 条件控制;
	name = '张三',
	age = 30
where 
	id = 1;


	-- 删除记录
-- 如果没有where过滤, 会全部删除.
delete from customer;      delete from 表名;

delete from customer    delete from 表名 where 条件控制;
where id = 2;
	

查询语句

--查看表中所有数据
SELECT *                       select  * from 表名;
FROM   departments;

跨库操作表 : 只需要在表名上加上库.限定
select * from company.employees;

--查看表中指定列的数据              select 列名 ,列名...from 表名
SELECT department_id, location_id
FROM   departments;

-- AS用于给列起别名, AS关键字可以省略     select 列名 别名 ,列名 别名.... from 表名 别名
SELECT last_name AS name, commission_pct comm   
FROM   employees;

-- 过滤行 where 条件布尔 : 工作流程就是从基本表中测试每行数据, 都经过条件布尔测试一下, 如果结果为真留下, 为假则丢弃. 	
SELECT employee_id, last_name, job_id, department_id
FROM   employees 
WHERE  department_id = 90 ;      select 列名 ,列名...from 表名 where 条件


 

执行顺序 : from => where => select

-查询所有中国城市的人口和名称和id号和国家代码, 给国家代码起别名, 尝试在where中使用别名.
select 
	population,
	name,
	id,
	countrycode code 
from 
	city 
where 
	countrycode = 'chn';
	
	
	
-- between a and b --等效于salary >= a && salary <= 3500	
SELECT last_name, salary
FROM   employees
WHERE  salary BETWEEN 2500 AND 3500;

-- id in(a, b, c) -- 等效于id = a || id = b || id = c 
SELECT employee_id, last_name, salary, manager_id
FROM   employees
WHERE  manager_id IN (100, 101, 201);


--like模糊查询 后面可以加_和%通配符   _下划线代表任意一个字符 %代表任意数量的任意字符

-- 查询国家名称中只要包含ch的都行

select 
	code,
	population,
	name,
	continent 
from 
	country 
where 
	name like '%ch%'
	
	-- 名字中第3个和第4个是in的国家
select 
	code,
	population,
	name,
	continent 
from 
	country 
where 
	name like '__in%'

-- 查询城市表中, 名称的第2个和3个字母是or的城市.
select 
	id,
	name,
	countrycode 
from 
	city 
where 
	name like '_or%';

-- 查看哪些国家没有首都
-- null和任意的比较运算, 结果一定是false, 处理null, 必须使用特殊的is来判断
-- null值在进行统计时会被自动忽略.
select 
	code,
	name,
	continent,
	capital
from 
	country 
where 
	capital = null;
	
	
select 
	code,
	name,
	continent,
	capital
from 
	country 
where 
	capital is null;
	
	
select 
	code,
	name,
	continent,
	capital
from 
	country 
where 
	capital is not null;
	
	

多表查询

-- 多表联接 : 会产生笛卡尔集
-- 为了学习, 创建简单表
create table city2
select * from city where name='london';
+------+--------+-------------+----------+------------+
| ID   | Name   | CountryCode | District | Population |
+------+--------+-------------+----------+------------+
|  456 | London | GBR         | England  |    7285000 |
| 1820 | London | CAN         | Ontario  |     339917 |
+------+--------+-------------+----------+------------+

create table country2
select * from country where code in('gbr', 'can');
+------+----------------+---------------+-----------------+-------------+-----------+------------+----------------+------------+------------+-------------
| Code | Name           | Continent     | Region          | SurfaceArea | IndepYear | Population | LifeExpectancy | GNP        | GNPOld     | LocalName
+------+----------------+---------------+-----------------+-------------+-----------+------------+----------------+------------+------------+-------------
| CAN  | Canada         | North America | North America   |  9970610.00 |      1867 |   31147000 |           79.4 |  598862.00 |  625626.00 | Canada
| GBR  | United Kingdom | Europe        | British Islands |   242900.00 |      1066 |   59623400 |           77.7 | 1378330.00 | 1296830.00 | United Kingd
+------+----------------+---------------+-----------------+-------------+-----------+------------+----------------+------------+------------+-------------

select * from city2, country2; 
结果集中的绝大多数都是垃圾. 必须要过滤掉
+------+--------+-------------+----------+------------+------+----------------+---------------+-----------------+-------------+-----------+------------+--
| ID   | Name   | CountryCode | District | Population | Code | Name           | Continent     | Region          | SurfaceArea | IndepYear | Population | L
+------+--------+-------------+----------+------------+------+----------------+---------------+-----------------+-------------+-----------+------------+--
|  456 | London | GBR         | England  |    7285000 | CAN  | Canada         | North America | North America   |  9970610.00 |      1867 |   31147000 |
| 1820 | London | CAN         | Ontario  |     339917 | CAN  | Canada         | North America | North America   |  9970610.00 |      1867 |   31147000 |
|  456 | London | GBR         | England  |    7285000 | GBR  | United Kingdom | Europe        | British Islands |   242900.00 |      1066 |   59623400 |
| 1820 | London | CAN         | Ontario  |     339917 | GBR  | United Kingdom | Europe        | British Islands |   242900.00 |      1066 |   59623400 |
+------+--------+-------------+----------+------------+------+----------------+---------------+-----------------+-------------+-----------+------------+--
select    无法分辨查询的是哪个表的列
	name,
	population,
	name,
	continent,
	population
from 
	city2, 
	country2
where 
	countrycode = code;
	
--多表查询应该带着表名区分列名	
select 
	city2.name as cityName,
	city2.population cityPop,
	country2.name countryName,
	country2.continent,
	country2.population countryPop
from 
	city2, 
	country2
where 
	city2.countrycode = country2.code;
	
    
 -- 表名一旦指定了别名, 原名就不可以使用了.
		select 
	city2.name as cityName,
	city2.population cityPop,
	country2.name countryName,
	country2.continent,
	country2.population countryPop
from 
	city2 as ci, 
	country2 as co 
where 
	city2.countrycode = country2.code;
	
内联时最好带上jion on  jion 后跟表名 on 后加联接条件
-- 最好的写法是下面的.	inner关键字可以省略
select 
	ci.name as cityName,
	ci.population cityPop,
	co.name countryName,
	co.continent,
	co.population countryPop
from 
	city2 as ci 
join 
	country2 co 
on -- on后面只跟 联接条件 
	ci.countrycode = co.code 
where -- where 后面只跟  普通行过滤
	ci.population > 1000000;
	

-- 外联接可以保证某张表的数据完整, 即使联接条件为假, 也要保留数据
外联有左外联和右外联,前面的表为左后面表为右,左联保证左数据完成,右联保证右表数据完整,outer可以省略
select 
	co.name country,
	ci.name capital,
	ci.district
from 
	country2 co 
left outer join 
	city2 ci 
on 
	co.capital = ci.id;
	
	select 
	co.name country,
	ci.name capital,
	ci.district
from 
	country2 co 
right outer join 
	city2 ci 
on 
	co.capital = ci.id;

// 伪代码
// 内联接
Set leftTable;
Set rightTable;
Set resultSet = new Set();
for (int i = 0; i < leftTable.length; i++) {
	Row leftRow = leftTable[i];
	for (int j = 0; j < rightTable.length; j++) {
		Row rightRow = rightTable[j];
		if (联接条件(leftRow, rightRow)) {
			Row newRow = leftRow + rightRow;
			resultSet.add(newRow);
		}
	}
}

// 外联接 
Set leftTable;
Set rightTable;
Set resultSet = new Set();
for (int i = 0; i < leftTable.length; i++) {
	Row leftRow = leftTable[i];
	boolean flag = false;
	for (int j = 0; j < rightTable.length; j++) {
		Row rightRow = rightTable[j];
		if (联接条件(leftRow, rightRow)) {
			Row newRow = leftRow + rightRow;
			resultSet.add(newRow);
			flag = true; // 表明联接条件为真的记录保存起来
		}
	}
	
	if (!flag) {
		Row newRow = leftRow + 空行(右表);
		resultSet.add(newRow);
	}
}

-- 单行函数, 查询结果中对每一行都单独执行的函数
select
	upper(name),
	lower(continent)
from 
	county;
	
select 
	concat(code, name),
	substr(name, 3, 2)
from 
	country;
	
	-- 把国家的代码和名称及大洲用@符号连接. 如 : CHN@China@asia 
select
	concat(concat(concat(concat(code, '@'), name), '@'), continent)
from 
	country;
	
select
	concat(code, '@', name, '@', continent)
from 
	country;
	

-- 分组函数 : 作用于一组数据. 默认情况下虚表中的所有记录被当作一个组.
分组函数都是统计运算, 特点就是一组数据只能有一个结果. 结果也必须是所有数据处理完后才有的.

max() 最大值 
min() 最小值 
avg() 平均值 
sum() 求和
count() 计数

select 
	max(population),
	min(surfacearea)
from 
	country ;


select 
	-- name, 不可以再把普通的列放在这里
	max(name),
	max(population),
	min(surfacearea)
from 
	country ;
	

--group by 分组语句
-- 解决的问题类似于, 查看 各大洲 的情况.
select 
	continent, -- 群体概念
	max(name),
	avg(surfacearea)
from 
	country 
group by 
	continent;

--having 用来过滤分组结果
-- 对分组的结果进行过滤, 只能使用having	
select 
	countrycode,
	sum(population) sumPop
from 
	city 
group by 
	countrycode 
having
	sumPop > 10000000
order by 
	sumPop;
	
	解决SQL步骤 : 	
1) 最基础的基表, from 
2) 考虑一张表的数据够不够, 如果不够进行连接 join 
3) 再考虑是外还是内, 如果是外还得考虑保证哪张表完整
4) 有join必须要有on 
5) 是否需要对当前的大基表进行基础的行过滤. where 
6) 是否需要分组, 分组依据的列是什么. group by 
7) 如果有分组,第一时间,把分组的列放在 select 后面, 并同时继续分析要选择哪些列或统计运算.
8) 是否要再对分组结果进行进一步过滤, 如果需要使用having
9) 是否需要排序, 如果需要使用order by .

-- 子查询 : 解决一次查询不能解决的问题.
-- 找出哪个城市的人口是最多的.
select 
	countrycode,
	name,
	population
from 
	city  
where 	
	population = (select max(population) from city);
	
	
select 
	name,
	surfacearea,
	continent
from 
	country 
where surfacearea >
					(select 
						avg(surfacearea)
					from 
						country) 

修改数据

-- 修改数据库, 只能修改默认字符集
alter database school charset utf8;


-- 基于子查询建表, 把虚表变成实表
create table country2
as select * from world.country; -- 复制表, 只是机械的把虚表变实, 不能复制约束(主键)

-- 复制表结构建表, 没有数据
create table country3 
like world.country;

- 修改表
alter table 表名 
-- 支持若干子名

-- 添加新列
add column 新列名 数据类型(长度) 其他选项.

alter table student 
add column address varchar(200) not null; -- 新列追加在所有列的最后.

alter table student 
add column email varchar(50) after age; -- 在指定列后面添加新列

alter table student 
add column cardNo char(18) first; -- 在最前面添加新列

-- 修改列, 数据类型, 长度, 其他选项 
modify 列名 新数据类型(新长度) 新其他选项

alter table student 
modify name varchar(10) not null;

-- 重命名列
change 列名 新列名 新数据类型(新长度) 新其他选项;

alter table student 
change phone mobile char(11) unique; -- unique就是唯一.

-- 丢弃列
drop column 列名; -- 会导致删除的列所对应的所有数据全部丢失, 无法找回

alter table student
drop column cardNo;

-- 重新命名表
rename to 新表名

alter table student 
rename to students;

alter table teacher 
rename to teachers;

-- 修改约束
以上都是alter table 的子句, 用于修改表

-- 丢弃表 操作很危险, 如果没有数据备份, 就永远找不回来.
drop table 表名;

-- 丢弃表时可以批量丢弃
drop table country2, country3;

-- 清空表 DDL, 表中数据不能恢复. 效率高
truncate table 表名;

delete 是DML, 是可以后悔的. 效率低.


-- 实现表的完全克隆!!!
create table if not exists country2 like world.country;

-- 基于子查询插入数据, 好处就是一次性插入多条记录.
insert into country2 
select * from world.country;

事务


A Atomic 原子性 			所有操作不可分割.
C Consistence 一致性		数据在事务前和事务后数据是一致的.
I ISOLATION	独立性 			不同事务之间具有隔离性
D Duration	持久性			事务一旦提交, 永久生效.

DCL : 数据控制语言 : commit, rollback, grant, revoke...

显式启动事务 : 
	set autocommit = false;
	set @@autocommit = off;
	
	多条DML语句;
	
	commit; 事务提交, 成功
	rollback; 事务回滚, 失败
	ddl语句执行 : 事务提交
	会话正常结束 提交
	异常结束 : 回滚
	
	
	还原设置
	set autocommit = true;
	set @@autocommit = on;

预编译

执行预编译
execute p1;

sql中的?相当于方法中的形参, ?在SQL中只能替换值的部分.
prepare p2 from '
	insert into classes(
		name,
		room,
		begindate,
		master 
	) values (
		?,
		?,
		?,
		?
	)
';
## 

 - 标题

如果sql中有?, 必须使用用户变量来传值
set @name='BigData0621', @r='306', @b='2020-06-21', @master=2;

执行预编译时使用变量, 用户变量就相当于方法调用时的实参.
execute p2 using @name,@r,@b,@master;

丢弃预编译
drop prepare p1;

-- 如果在sql中也有', 必须要使用''来进行转义.
prepare p2 from '
	insert into classes(
		name,
		room,
		begindate,
		master 
	) values (
		?,
		''301'',
		now(),
		?
	)
';


为了保证数据的一致性和完整性,SQL规范以约束的方式对表数据进行额外的条件限制。

约束

有以下六种约束:
NOT NULL 非空约束,规定某个字段不能为空
UNIQUE  唯一约束,规定某个字段在整个表中是唯一的
PRIMARY KEY  主键(非空且唯一), 一张表只允许有一个主键
FOREIGN KEY  外键
DEFAULT  默认值, 只能写成列级的.

create table if not exists test(
	id int primary key, -- 可以写成表级, 最好写成表级
	name varchar(20) unique, -- 可以写成表级, 最好写成表级
	age int not null, -- 必须是写成列级
	gender enum('男', '女') default '男', -- 必须写成列级
	email varchar(20)
);

insert into test(
	id,
	name,
	age
) values (
	1,
	null,
	20
);

insert into test(
	id,
	name,
	age
) values (
	2,
	null,
	20
);

create table if not exists test2(
	id int,
	name varchar(20), -- 可以写成表级, 最好写成表级
	age int not null, -- 必须是写成列级
	gender enum('男', '女') default '男', -- 必须写成列级
	email varchar(20),
	primary key(id, email), -- 联合主键, 两个列的组合值要 唯一且非空.
	unique(name)
);

insert into test2(
	id,
	name,
	age,
	email
) values (
	1,
	null,
	20,
	'aa'
);

insert into test2(
	id,
	name,
	age,
	email
) values (
	2,
	null,
	20,
	'aa'
);

丢弃主键
alter table test2
drop primary key;

添加主键
alter table test2 
add primary key(id)

-- 查询班级及班主任信息
select 
	c.*,
	t.*
from 
	classes c 
left join 
	teachers t 
on 
	c.master = t.id;
	
create table if not exists teacher(
	id int auto_increment, -- 将来这个列对应的数据可以自动生成. 必须作成主键
	name varchar(20), -- varchar数据类型必须要有长度.
	age int,
	salary double,
	gender enum('男', '女') default '男',
	primary key(id) -- 表级主键
); 

drop table if exists classes;
create table if not exists classes(
	id int auto_increment,
	name varchar(20) not null, -- not null 就是非空
	room char(3),
	begindate date,
	master int, -- 班主任是一个整数, 将来是某个老师的id, 为了强制要求, 必须给它加上外键
	primary key(id),
	-- foreign key(本表的外键的列) references 父表(父表的主键)
	foreign key(master) references teachers(id)
);

set @name='h50727', @master=2;

set @name='bigdata0727', @master=20;

一旦使用了外键约束, 子表插入数据时必须要参考父表的记录, 会导致效率降低.

在删除父表被引用的记录时, 也无法直接删除!!!
delete from teachers where id = 2;

-- 丢弃外键, 必须要提供外键名称.
-- 查看外键名
show create table classes;

alter table classes drop foreign key `classes_ibfk_1`;

-- 添加外键
alter table classes 
-- add constraint fk foreign key(master) references teachers(id) on delete cascade; -- set null(子表中的引用值置空) do nothing(不允许删除父表记录) cascade(级联);
add constraint fk foreign key(master) references teachers(id) on delete set null; -- set null(子表中的引用值置空) do nothing(不允许删除父表记录) cascade(级联);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值