数据库-SQL

一 : 数据库

1.数据库是一种软件

2.数据库是专门用来存储数据

3.数据库可以多用户共享访问


1: MYSQL

  • 介绍:瑞典MySQL AB公司开发,

    • 2008 Sun -> 2009甲骨文宣布

    • MySQL是一种关联数据库管理系统由于其体积小、速度快、总体拥有成本低,一般中小型网站的开发都选择 MySQL 作为网站数据库

    • MySQL数据库版本相对比较繁杂。常见的有:Community社区版、Enterprise企业版

      • Community版是开源免费的, 常用 <MySQL Community Server 社区版本>
      • Enterprise版,官方指出提供30天免费试用期
      • 集群, 高级集群版本定制。
  • 下载mysql时注意区分版本细节及所应用的系统平台:linux(32/64) 、win(32/64)


  • mysql表名称区分大小写, 对列名不区分大小写

  • 对数据库进行增(Create)、改(Update)、查(Retrieve)、删(Delete)操作


1.1: 基本操作

  • 登录数据库 mysql -u用户名 -p密码
    • 修改用户的密码 alter user 用户名 identified ``by 新密码
  • 创建数据库
    • 创建一个名称为mydb1的数据库 create database mydb1
      • 修改mydb1的字符集为utf8(不能修改数据库名) alter database mydb1 character set utf8;
    • 创建一个使用utf-8字符集的mydb2数据库 create database mydb2 character set utf8;
    • 创建一个使用utf-8字符集,并带校对规则的mydb3数据库。会对存入的数据进行检查 create database mydb3 character set utf8 collate utf8_general_ci
  • 查看数据库中的用户
    • 显示所有数据库 show databases;
    • 使用 用户use 用户名
    • 查看当前数据库的名字: select database();
    • 显示创建数据库的语句信息 show create database mydb2
  • 删除数据库 mydb3
    • drop database mydb3
  • 退出数据库 : exit
  • mysql账号体系比oracle要多一层,要操作方案(数据库)
    • 其中root是用户名,该用户跟linux中的root不是同一个用户
      mysql有自己的账号体系,其中的数据库管理员也叫root
    • oracle 账号体系, 管理员是: sysdba 一个用户对应一个方案,用户名就是方案名; 在mysql中一个用户是可以拥有多个方案

1.2 用户下的表

  • 创建表 create table t1 (id int, name varchar(20))
  • 查看当前选择的数据库中的表 show tables
  • 查看创建表的语法 show create table t1
  • 查看表结构 desc 表名;

1.3 修改表 – alter

  • 更改表名 rename table 旧表名 to 新表名
  • 增加一个字段(列 ) alter table 表名 add column height double add
  • 修改一个字段的类型 alter table 表名 modify column height float; modify
  • 删除一个字段 alter table 表名 drop column height drop
  • 修改表的字符集 alter table 表名 character set gbk

1.4 删除表

  • drop table 表名 (MySQL中不能使用purge,添加会出现语法错误)

1.5 updata 数据

  • update employee set salary=salary+500
  • update employee set salary=10000, resume='也是一个中牛' where name='王五';

1.6 delete 数据

  • 删除表中姓名为王五的记录 delete from employee where name='王五';
  • 删除表中所有记录 delete from employee
  • 使用truncate删除表中记录 truncate table employee; 无条件效率高

1.7 insert 数据


首先创建表emp
 create table emp(
     id int,
     name varchar(20),
     sex int,
     birthday date,
     salary double,
     entry_date date,
     resume text
 );
 
添加数据
 insert into emp values(1,'张三',1,'1983-04-27',15000,'2012-06-24','一个大牛');
 insert into emp(id,name,sex,birthday,salary,entry_date,resume) values(2,'李四',1,'1984-02-22',10000,'2012-07-24','一个中牛');
 insert into emp(id,name,sex,birthday,salary,entry_date,resume) values(3,'王五',0,'1985-08-28',7000,'2012-08-24','一个小虾');

 
 1 将所有员工薪水都增加500元。
    update emp set salary=salary+500;
 
 2 将王五的员工薪水修改为10000元,resume改为也是一个中牛
    update emp set salary=10000,resume='一个中牛' where name='王五';
 
 3 查询员工的月薪以及年薪
     select salary,salary*12 from emp;
 
 4 删除表中姓名为王五的记录
   delete from emp where name='王五';
 
 5 删除表中所有记录
  delete from emp;
 
 6 使用truncate删除表中记录
     truncate table emp;

1.8 一些常用查询

  • 查询表中所有的信息 select * from 表名
// 案例:
查询表中所有学生的信息。
select * from student;

查询表中所有学生的姓名和对应的英语成绩。
select name,english from student;

过滤表中重复数据。
select english from student;
select DISTINCT english from student;
select DISTINCT english,name from student;
select english+chinese+math from student;
select english+chinese+math as 总分 from student;
select name,english+chinese+math as 总分 from student;

在所有学生英语分数上加10分特长分。
select name,english+10 from student;

统计每个学生的总分。
select english+chinese+math from student;

使用别名表示学生分数
select name,english+chinese+math as 总分 from student;
select name,english+chinese+math 总分 from student;

查询姓名为何东的学生成绩
select * from student where name='何东';

查询英语成绩大于90分的同学
select * from student where english>90;

查询总分大于250分的所有同学
select * from student where english+chinese+math>250;

查询英语分数在 8595之间的同学。
select * from student where english>=85 and english<=95;
select * from student where english between 85 and 95;

查询数学分数为84,90,91的同学。
select * from student where math=84 or math=90 or math=91;
select * from student where math in(84,90,91);

查询所有姓何的学生成绩。
select * from student where name like '何%';

查询数学分>85,语文分>90的同学。
select * from student where math>85 and chinese>90;

对数学成绩排序后输出。
select * from student order by math;

对总分排序后输出,然后再按从高到低的顺序输出
select * from student order by math+chinese+english desc;

对姓何的学生成绩排序输出
select * from student where name like '何%' order by math+chinese+english desc;
select name, math+chinese+english from student where name like '何%' order by math+chinese+english desc;

统计一个班级共有多少学生?
select count(*) from student;

统计数学成绩大于90的学生有多少个?
select count(*) from student where math>90;

统计总分大于250的人数有多少?
select count(*) from student where math+chinese+english>250;

统计一个班级数学总成绩?
select sum(math) from student;

统计一个班级语文、英语、数学各科的总成绩
select sum(math), sum(chinese), sum(english) from student;

统计一个班级语文、英语、数学的成绩总和
select sum(math+chinese+english)from student;
select sum(math)+sum(chinese)+sum(english) from student;

求一个班级数学平均分?
select avg(math) from student;

求一个班级总分平均分
select avg(math+chinese+english)from student;
select avg(math)+avg(chinese)+avg(english) from student;

求班级最高分和最低分
select max(math+chinese+english),min(math+chinese+english) from student;

// 分组数据
为学生表,增加一个班级列,练习分组查询。		
	alter table student add column class_id int;		
		注意语法:Oracle中不能有“column”关键字,MySQL中有没有“column”都可以执行。
		更新表:
			update student set class_id=1 where id<=5;
			update student set class_id=2 where id>5;
			(update student set class_id=2 where id between 6 and 10;)
		查出各个班的总分,最高分。
		求各个班级英语的平均分:
			select classid, avg(english) 
			from student
			group by class_id

1.9: 其他相关操作

拷贝表(重点)

拷贝表其实是另一种创建表的方式
 
     创建一张表emp2,数据跟emp表一样
		create table emp2 as select *from emp;
     
     创建一张表emp3,只有emp表结构,没有数据
		方式一:
			1.create table emp3 as select *from emp;
			2.delete from emp3;
		方式二:
			create table emp3 as select *from emp where 1=2;

清空表(了解)

		delete from 表名
     delete from emp2;

     truncate table 表名 
     truncate table emp2;

        1.  delete 逐条删除表“内容”,truncate 先摧毁表再重建。 
        (由于delete使用频繁,Oracle对delete优化后delete快于truncate)
        2.  delete 是DML语句,truncate 是DDL语句。DML语句可以闪回(flashback)和回滚rollback,DDL语句不可以回滚。
        (闪回: 做错了一个操作并且commit了,对应的撤销行为。了解)
        3.  由于delete是逐条操作数据,所以delete会产生碎片,truncate不会产生碎片。
        (同样是由于Oracle对delete进行了优化,让delete不产生碎片)。两个数据之间的数据被删除,删除的数据——碎片,整理碎片,数据连续,行移动。
        4.  delete不会释放空间,truncate 会释放空间。用delete删除一张10M的表,空间不会释放。而truncate会。所以当确定表不再使用,应使用truncate

删除表(重点)

		drop table 表名
		
           oracle提供了回收站机制,删表的时候先移动到回收站

        purge table 表名
            从回收站中彻底删除某张表

        drop table 表名 purge
            彻底删除表,不移动到回收站

        oracle 提供一个闪回的技术,能够将表还原到以前的某个时间点
            flashback table 表名 to before drop

        show recyclebin
        purge recyclebin 
            清空回收站
            
闪回资料网址:
https://www.jb51.net/article/130703.htm

1.10: 表的约束(重点)

		1 非空
         not null
     2 唯一
         unique

     3 检查
         check
     4 主键
         primary key

         隐含了 not null + unique


     5 外键
         foreign key
         一张表的某一列(或多列)参照另一张表的某一列(或多列)
         在这张表填入的数据必须要在另一张表中能够找到,或者为null
         涉及的问题
             父表的数据删除(更新)了子表数据怎么办
                 1 不允许父表执行删除
                 2 父表删除数据之后,子表对应的数据全部设置为null
                 3 父表删除数据之后,子表对应的数据也跟着删除,级联删除
创建表时,约束,格式如下:
     create table 表名
     (
         列名1 类型1 [constraint 约束名1] 约束类型2  constraint 约束名2 约束类型2,
         列名2 类型2 [constraint 约束名3] 约束类型3  ,
         ....
     )

     create table student 
     (
         sid number constraint pk_student primary key, --学生Id主键约束
         sname varchar2(20) constraint nn_student_name not null,--学生姓名非空约束
         email varchar2(20) constraint un_student_email unique --学生邮件唯一约束
             constraint nn_student_email not null,   --同时邮件可再设非空,没有“,”
         age number constraint chk_student_age_min check(age > 10),  --学生年龄设置check约束
         gender varchar2(6) constraint chk_student_gender check(gender in ('男', '女')),
         deptno number constraint fk_student references dept (deptno) ON DELETE SET NULL
     )
     //外键约束可以定义多个字段
     字段1 类型,
     字段2 类型,
     constraint fk_student foreign key (字段1,字段2) references dept(字段1,字段2)
测试:
	SQL>  insert into student values(1, 'Tom', 'tom@126.com', 20, '男', 10)  	正确插入表数据。
	
SQL>  insert into student values(2, 'Tom', 'tom@126.com', 15, '男', 10)   
		违反un_student_email约束。
		
SQL>  insert into student values(3, 'Tom3', 'tom3@126.com', 14, '男',100 )   				违反完整约束条件 (SCOTT.FK_STUDENT) - 未找到父项关键字

可以查看指定表(如student)的约束,注意表名必须大写。
SQL> select constraint_name, constraint_Type, search_condition  
	  from user_constraints where table_name='STUDENT' 


1.11 : 视图、序列、索引、同义词

视图的概念(了解)

什么是视图:从表中抽出的逻辑上相关的数据集合。是虚拟的表,只是一个查询语句的结果
本质上就封装sql语句
视图的作用:便于查询数据
创建视图的格式:
	create view 视图名称
 as
     子查询


 要注意,创建视图需要权限,需要oracle管理员对scott赋予权限
 
     1.在centos 上 使用 sqlplus / as sysdba

     2.grant create view to scott //赋予创建视图的权限

 创一个视图,用来观看10号部门的员工信息
 	创建视图:
     create view v_emp_10
     as
     	select *from emp where deptno=10;
		创建表:
     create table t_emp_10
         as select * from emp where deptno = 10
		视图和表的区别:
		
		区别:
     视图是不存在数据,只是一个查询语句的结果
     表是真实的存储数据的
     每次执行 select 去查看视图的时候,都会执行视图的sql语句
     视图其实也是一条查询sql语句的封装


 删除视图
     drop view 视图名
 视图的优点:
    1.	简化复杂查询:	原来分组、多表、子查询等可以用一条select * from xxxview代替。
					视图可以看做是表的复杂的SQL一种封装。


	2.	限制数据访问:	只看视图的结构和数据是无法清楚视图是怎样得来的。可以限制数据的访问
	
视图的细节:
总结一句话:不通过视图做insertupdatedelete操作。因为视图提供的目的就是为了简化查询。

序列(了解)

1.序列是什么
	是类似于数组,里面存储的是从1开始的数值,是公有对象
2.序列有什么用
	序列常用于主键的自动增长
	假如:
	创建一张表
    create table t1
    (
        id number primary key,
        name varchar2(30) not null
    )

    insert into t1 values(1,'name-1')
    insert into t1 values(2,'name-2')
    人工去记住这个id,不靠谱,让计算机自身去记住这个id,每次自增

3.序列的使用
	1.创建序列
	create sequence myseq(序列名)
	2.序列的属性
		currval
            当前的序列的值
            select myseq.currval from dual
            第 1 行出现错误:
            ORA-08002: 序列 MYSEQ.CURRVAL 尚未在此会话中定义
            //为什么出错,等下讲
            注意:获取currval 不能早于第一次获取nextval
            因为一开始游标指向的是数组的首元素的前面,前面是空
        nextval
        	从序列获取下一个值
            select myseq.nextval from dual 
            
			注意:每次sql执行,nextval只会获取一次值
			演示:
			1.创建表
            	create table t1
    			(
        			id number primary key,
        			name varchar2(30) not null
    			)
    		2.插入数据:
    			//从前面用了几个值,从最后一个值的后一个值成为主键
    			insert into t1 values(myseq.nextval,'name-'||myseq.nextval);
    			insert into t1 values(myseq.nextval,'name-'||myseq.nextval);
    			insert into t1 values(myseq.nextval,'name-'||myseq.nextval);
	
 	3.删除序列:
 		drop sequence 序列名
4.序列的注意:
1.	序列是公有对象,所以多张表同时使用序列,会造成主键不连续。	如:[1, 2, 3, 4, 5,, 20]
tableA:	1	2	4
tableB:	3	5				A、B表有可能主键不连续。

2.	回滚也可能造成主键不连续。	如:多次调用insert操作使用序列创建主键。但是当执行了rollback后再次使用insert借助序列创建主键的时候,nextval不会随着回滚操作回退。

3.	掉电等原因,也可能造成不连续。由于代表序列的数组保存在内存中,断电的时候内存的内容丢失。恢复供电时候,序列直接从21开始。

索引(了解)

索引是什么:相当于书的目录,提高数据检索速度。
索引有什么用:提高效率(视图不可以提高效率)
索引的使用:Oracle 管理系统决定何时使用索引,不是用户使用的,但要用户建立
索引的原理:
	原理,对数据某一列(或者多列)进行排序,将排序号的数据以及对应的行地址
    存起来,下次查询数据的时候先查询索引,然后再提取数据
创建索引:
	格式:
	create index 索引名 on 表名(列名)
    create index 索引名 on 表名(列名1,列名2 ....)
	语句:
    create index inx_emp_deptno on emp(deptno)
系统使用索引:
	1.	emp表中保存数据,其中包含部门号列。有10号部门,有20部门员工
	2.select * from emp where deptno=10 的时候。由于10号部门员工不连续,没规律。 
		为了提高访问速度,可以在数据库中,依照rowid给deptno列建立索引
		SQL> create index myindex on emp(deptno)   
		这样就建立了“索引表”可以通过rowid保存的行地址快速的找到表中数据。即使表中数据不连续。
	3.	建立了索引以后,如果再执行select语句的时候,会先检查表上是否有索引表。如果有,可以通过有规		律的rowid找到不连续的数据。
	4.	Oracle的数据库中,索引有 B树索引(默认)和 位图索引两种。
	5.	使用create index 索引表名 on 表名(列名1, 列名2…);来创建索引表。由数据库自动进行维护。	
	使用主键查询数据最快速,因为主键本身就是“索引”,所以检索比较快。

索引使用的场景:(讲义复制)
	以下情况可以创建索引:
	列中数据值分布范围很广
	列经常在 WHERE 子句或连接条件中出现
	表经常被访问而且数据量很大 
  
下列情况不要创建索引:
	表很小
	列不经常作为连接条件或出现在WHERE子句中
	查询的结果集占到表的95%及以上的数据
	表经常更新

删除索引:
	drop index 索引名;
    

同义词(了解)

同义词是为别的用户中的表取别名:
 1.切换方案:conn hr/11
 2.赋予某个方案访问本方案的某个表的权限:grant select on employees to scott
 注意:当前要在hr方案中,employees是hr方案的表
 
 
 为hr.employees表创建同义词
    格式:create synonym 别名 for 某数据库对象
        create synonym hh for hr.employees;
   
  
    删除同义词
        drop synonym 别名

2. Redis

2.1 基本知识点

  1. 安装包下载

  2. Redis安装

    • make
    • sudo make install
  3. redis中的两个角色

    • 服务器
    • 客户端
  4. 环境测试

    # 启动服务器
    redis-server  
    redis-server 配置文件
    # 启动客户端
    redis-cli 		- 使用默认端口连接
    redis-cli -p 	- 使用指定端口连接服务器
    redis-cli -h host -p port
    	- host -> redis 服务器的ip地址
    	- port -> redis 服务器监听的端口
    # 测试命令
    ping
    	- PONG
    ping msg
    	- msg
    # 在客户端通过命令关闭服务器
    shutdown
    
  5. redis中数据的组织格式

    • 通过 key - value 的方式存储数据
      • key -> 必须是字符串
      • value ->
        • String类型
        • List类型
        • Set类型
        • SortedSet类型
        • Hash类型
  6. redis中常用数据类型

    • String类型
      • 字符串 - “hello”
    • List类型
      • 存储多个字符串
    • Set类型
      • 集合
        • stl中的集合:
          • 自动排序
          • 存储的元素不能重复
        • redis中的集合
          • 存储的数据不排序
          • 存储的元素不能重复
    • SortedSet类型
      • 每个元素分为两部分: [分数 成员]
    • Hash类型
      • 哈希数据结构特点: 查找速度快, 键值对
      • <key, value>
      • map, hash

2.2 redis常用命令

  • String类型

    # 创建新键值对
    SETNX key value
     - key , 如果存在, 什么也不干
     - key, 如果不存在, 创建一个键值对
    # 设置数据
    SET key value [EX seconds] [PX milliseconds] [NX|XX]
     - key: 用户指定的key
     	- 如果key 存在, 覆盖原来的value
     	- 如果不存储, 创建一个key, 对应值为value
     - value: key对应的字符串
    # 设置N个键值对
    MSET key value [key value ...]
    # 获取数据
    GET key
    # 返回所有 (一个或多个) 给定 key 的值。
    MGET key [key ...]
    # 给value追加内容
    APPEND key value
    # 将 key 中储存的数字值减一
    DECR key
    	- key对应的value的要求: 必须是数字类型的字符串
    # value值加1
    INCR key
    # value 减去 指定的 值
    DECRBY key decrement
    # value 加上 指定的 值
    INCRBY key increment
    # value的长度
    STRLEN key
    
  • List类型 - 存储多个字符串

    # 如何存储
    LPUSH key value [value ...]  -> 新添加的字符串放到头部
    RPUSH key value [value ...]  -> 新添加的字符串放到尾部
    # 删除元素
    LPOP key   -> 删除最左侧字符串
    RPOP key   -> 删除最后一个字符串
    # 遍历
    LRANGE key start stop
    	- start: 0代表第一个元素
    	- stop: -1代表最后一个元素
    # 列表中字符串个数
    LLEN key
    # 根据位置index 取出 列表中的string
    LINDEX key index
    # 插入字符串
    LINSERT key BEFORE|AFTER pivot value
    # 删除指定字符串
    LREM key count value
    	- count > 0: 从前往后搜索, 删除value, 最大个数为count
    	- count < 0: 从后往前搜索, 删除value, 最大个数为count
    	- count = 0: 删除所有值为value的元素
    
  • Set类型

    # 添加数据
    SADD key member [member ...]
    # 遍历set
    SMEMBERS key
    # 集合求差集
    SDIFF key key1 [...]
    	- key - key1
    # 集合的交集
    SINTER key [key ...]
    # 集合的并集
    SUNION key [key ...]
    # 删除
    SREM key member [member ...] - 删除指定元素
    SPOP key 				    - 随机删除一个元素
    
  • SortedSet 类型

    # 每个元素有两部分 [分数, 成员]
    # 添加元素
    ZADD key score member [[score member] [score member] ...]
    # 遍历
    ZRANGE key start stop [WITHSCORES]			- 升序
    ZREVRANGE key start stop [WITHSCORES]		- 降序
    # 计算指定分数范围内成员的数量
    ZCOUNT key min max
    # 删除指定元素
    ZREM key member [member ...]
    # 通过成员名得到分数
    ZSCORE key member
    
  • Hash类型

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4RdMHbr8-1583041832410)(C:/Users/Administrator/Desktop/项目2/day02/01-教学资料/笔记/2.png)]

    # 数据添加
    HSET key field value
    # 根据key取field对应的value
    HGET key field
    # 批量设置
    HMSET key field value [field value ...]
    # 打印key对应的hash中都有的键值对
    HGETALL key
    
  • Key 相关的命令

    # 删除
    DEL key [key ...]
    # 根据指定条件查找key
    KEYS pattern
    # 根据key得到value的类型
    TYPE key
    # 给key-value设置生存时间
    EXPIRE key seconds
    

2.3 redis配置文件

配置文件是给redis服务器使用 的

  1. 配置文件位置

    • 去源码安装包中找 - redis.conf
  2. 配置文件配置项

    # 将允许访问redis服务器的主机的IP地址进行绑定
    bind 127.0.0.1 
    # 保护模式, 如果为yes远程客户端无法访问服务器
    protected-mode no
    # redis服务器默认绑定监听的端口
    port 6379 
    # 设置redis服务器进程是不是守护进程
    daemonize yes
    # 如果redis是守护进程, 会生成一个pid文件, 存储进程ID
    pidfile ./redis.pid
    # 日志级别
    loglevel notice
    # 日志文件 - redis服务器是守护进程才有日志文件
    logfile "./redis.log"
    # redis数据的个数
    databases 16
    
    ######################################3
    # 持久化的第一种方式 rdb
    # 更新的频率
    save 900 1
    save 300 10
    save 60 1000
    # 设置rdb文件的名字
    dbfilename dump.rdb
    # rdb文件生成的目录 ./ -> redis-server启动目录
    dir ./
    
    # aof模式相关的配置
    # aof模式是否开启
    appendonly no
    # aof 文件的名字
    appendfilename "appendonly.aof"
    # aof模式同步的频率
    appendfsync everysec
    

2.4 redis数据持久化

持久化: 数据从内存到磁盘的过程

  1. rdb方式 -> 默认使用的

    • 文件的后缀为 rdb, 将内存中的数据以二进制的方式存储
    • 数据同步的频率是在配置文件中进行设置的
    • rdb文件相对较小
    • 恢复数据时间短, 效率高
    • 数据完整性相对较低
  2. aof方式 -> 默认是关闭的

    • 文件的后缀是 aof, 文件中存储的是命令
    • aof文件相对较大
    • 恢复数据时间长, 效率低
    • 数据完整性高
  3. 两种模式是可以同时使用, 也可以都不使用

    # rdb更新频率
    save ""   - 关闭rdb
    

2.5 hiredis的使用

  1. hiredis的安装

  2. hiredis API接口的使用

    • 连接数据库

      // 连接数据库
      redisContext *redisConnect(const char *ip, int port);
      redisContext *redisConnectWithTimeout(const char *ip, 
                                            int port, const struct timeval tv);
      
    • 执行redis命令函数

      // 执行redis命令
      void *redisCommand(redisContext *c, const char *format, ...);
      // redisCommand 函数实际的返回值类型
      typedef struct redisReply {
          /* 命令执行结果的返回类型 */
          int type; 
          /* 存储执行结果返回为整数 */
          long long integer;
          /* str变量的字符串值长度 */
          size_t len;
          /* 存储命令执行结果返回是字符串, 或者错误信息 */
          char *str;
          /* 返回结果是数组, 代表数据的大小 */
          size_t elements;
          /* 存储执行结果返回是数组*/
          struct redisReply **element;
      } redisReply;
      
      状态表示含义
      REDIS_REPLY_STRING==1返回值是字符串,字符串储存在redis->str当中,字符串长度为redi
      REDIS_REPLY_ARRAY== 2返回值是数组,数组大小存在redis->elements里面,数组值存储在redis->element[i]里面。数组里面存储的是指向redisReply的指针,数组里面的返回值可以通过redis->element[i]->str来访问,数组的结果里全是type==REDIS_REPLY_STRING的redisReply对象指针。
      REDIS_REPLY_INTEGER == 3返回整数long long,从integer字段获取值
      REDIS_REPLY_NIL==4返回值为空表示执行结果为空
      REDIS_REPLY_STATUS ==5返回命令执行的状态,比如set foo bar 返回的状态为OK,存储在str当中 reply->str == “OK” 。
      REDIS_REPLY_ERROR ==6命令执行错误,错误信息存放在 reply->str当中。
    • 释放资源

      // 释放资源
      void freeReplyObject(void *reply);
      void redisFree(redisContext *c);
      

2.6 : hiredis 的使用

 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <unistd.h>
  5 #include <errno.h>
  6 #include <pthread.h>
  7 // hiredis 的头文件
  8 #include "hiredis/hiredis.h"
      
 16 int main(int argc, char *argv[])
 17 {
 18     // 创建连接的ip 和 port
 19     // 创建redisContext 进行保持状态
 20     redisContext * pc = redisConnect("127.0.0.1", 6379);
 21 
 22     // 进行判断创建为空, pc出现错误。err 是错误提示符
 23     if(pc == NULL || pc->err){
 24         if(pc){
 25             printf("error : %s\n ", pc->errstr);
 26         }
 27         else{
 28             printf("no useful space for redis\n");
 29         }
 30     }
 31     else{
 32         // 向redis 发出命令, 此函数采用的是printf() 的格式。
 33         freeReplyObject(redisCommand(pc, "set foo1 %s ", "hello worl    d" ));
 34         // freeReplyObject 表示的功能释放答复。破坏内存。
 35         freeReplyObject(redisCommand(pc, "set foo bar"));
 36     }
 37 
 38     redisReply *reply = (redisReply *)redisCommand(pc, "get foo");
 39     printf("get foo : %s\n", reply->str);
 40 
 41     // 断开和释放上下文
 42     redisFree(pc);
 43         return 0;
 	}

3: Oracle

3.1. oracle 数据库简介:
  • Oracle(甲骨文)公司成立于1977年,总部位于美国加州
  • Oracle也是一个软件

  • 1.一个数据库和多个实例组成

    • 什么是方案:也叫实例,是一系列的表,是存储在内存中的
  • 2.有一个客户端和一个服务端

  • 3.实例是存储在内存中,数据库是存储在硬盘中


3.2: Oracle 数据库的启动和关闭
  • 1: oracle有客户端和服务器,现在要开启服务端
  • 2: 需要用数据库的管理员权限进入数据库: 终端上:sqlplus / as sysdba
  • 3: 启动oracle服务 SQL> startup
  • 4: 关闭服务 SQL> shutdown
  • 5: 退出oracle客户端 exit (退出实例化对象)

  • 6:开启远程服务,在终端上开启 lsnrctl start
  • 7: 关闭远程服务连接 lsnrctl stop
  • 8: 查看连接情况 lsnrctl status

  • 数据库的操作方式:
    • 1.在虚拟机的终端操作
    • 2.用第三方软件连接操作系统,在操作数据库
    • 3.用专门的软件连接数据库(推荐)

3.3 : Oracle 数据库中用到的 sqlplus 语句 的基本操作:
  • 1: 查看当前用户 show user
  • 2 :查看当前用户下的表 select *from tab;
  • 3: 查看表的结构 desc 表名;
  • 4:修改用户的密码
    • 1.用数据库管理员的身份进入数据库: sqlplus / as sysdba
    • 2.修改密码: alter user scott identified by ”123”
  • 5: 登入scott用户 : sqlplus 用户名/密码 :在终端:sqlplus scott/11

3.4 : sql 和 sqlplus
  • SQLPlus:一种环境,是oracle公司所提供的工具,程序,是与oracle数据库进行交互的客户端工具,借助sqlplus工具可以查看、修改数据库记录。在sqlplus中,可以运行sql*plus命令与sql语句。
  • SQL:一种语言,是关系数据库的基本操作语言,它是应用程序与数据库进行交互操作的接口,从而使得应用开发人员、数据库管理员最终用户都可以通过SQL语言对数据库进行操作。

3.5: sql 语句
  • 1.对数据库里的数据进行操作叫做DML

    insert
    	删 delete
    	改 update
    	查 select
    
  • 2.对数据库里的表及其他进行操作的叫DDL

    	create table(创建表)alter table(修改表)truncate table(清空表)drop table(删除表)create view(视图)create index(索引)create sequence(序列)create synonym(同义词)
    
    
  • 数据库的操作叫DCL

    commit(提交)rollback(回滚) 
    
    

3.6: 常用查询

简单查询(重点)

1.查询emp表的所有数据:
select *from emp;
注意:*表示把表中所有的列名都显示出来
	
2.查询员工号,姓名,月薪,奖金,年薪,年收入 并修改列名为中文.
	注意:
		1.null和什么结合都为空
		2.nvl函数,nvl(参数1,参数2);如果参数1有数值,那么就返回参数1,如果是空,那么就返回参数2
		3.给字段取中文(字段 as "中文名") as可以不写,""可以不写
	答案:select empno as "工号",ename as 姓名,sal 月薪,sal*12 年薪,sal*12+nvl(comm,0) 年收入 from emp;
	
3.查看员工表所有部门编号并去除重复
	select distinct deptno from emp;
    distinct去除重复

4.计算表达式3+2
	select 3+2 from dual;
	dual--虚表
     

单条件查询(重点)

格式:	select ...
 from ...
 where cond

 查询10号部门的员工信息
     select *from emp where deptno=10;

 查询KING的信息
     select *from emp where ename='KING';
     注意:数据的字符串是用单引号引起来,大小写有区分

 查询薪水不等于1250的员工信息
  等于(=) 不等于(!=,<>) 大于(>) 小于(<)
 	select *from emp where sal!=1250;
    
 查询入职日期为19811117日的员工信息
 	select *from emp where hiredate='1981-11-17';
 	注意:查询日期时,需要和数据库的日期格式一样
 	查询数据库的日期格式:select * from v$nls_parameters;
 	中式日期格式:yyyy-mm-dd
 	修改日期格式:alter session set NLS_DATE_FORMAT = 'yyyy-mm-dd '
     

多条件查询(重点)

  与       或       非
c:  &&       ||       !
sql:and      or       not

 查询10号部门中月薪为1300的员工
 select *from emp where deptno=10 and sal=1300;

 查询部门号是10或者20的员工信息
 select *from emp where deptno=10 or deptno=20;
 select *from emp where deptno in(10,20);

 查询部门不是1020的员工信息
 select *from emp where deptno not in(10,20);

 查询工资介于10002000之间的员工
 select *from emp where sal>=1000 and sal<=2000;
 select *from emp where sal between 1000 and 2000;
 注意:between是闭区间
 
 查询19812月(含2月)到822月(不含2月)入职的员工信息
 select *from emp where hiredate between '1981-02-01' and '1982-01-31';

 查询没有奖金的员工信息
 select *from emp where comm=null;//错误查法
 select *from emp where comm is null;
 
 查询有奖金的员工信息
 select *from emp where comm is not null;
 select *from emp where comm>0;//打印奖金大于0元

模糊查询(重点)

格式:
select *from emp where 列名 like ...

% 表示任意字符任意次数
_ 表示单个任意字符

 查询员工首字母是S的员工信息
 select *from emp where ename like 'S%';
 
 查询名字是四个字母的员工信息
 select *from emp where ename like '____';
 
 查询姓名带下划线的员工信息
 //1.插入带下划线名字的员工信息
 insert into emp values(8888,'A_B','ddd',7777,sysdate,9999,null,10);
 //2.查询带下划线的员工信息
 select *from emp where ename like '%\_%' escape '\';
 

排序(重点)

格式:
	select *from emp
	where ..
	order by 列名1,列名2....

 员工信息按先后入职日期排序
 select *from emp order by hiredate;(默认是升序)
 select *from emp order by hiredate desc;
 注意:desc是降序,asc(升序)

 员工信息按薪水从大到小排序
 select *from emp order by sal desc;

 员工信息按部门号和薪水排列
 select *from emp order by deptno,sal;
 注意:先以第一个列排序,在这个基础上再以第二个列进行排序

 员工信息按部门和薪水排列,降序
	select *from emp order by deptno desc,sal desc;
	
 员工信息按奖金倒序
 select *from emp order by comm desc;//默认空在前面
 
 select *from emp order by comm  nulls last;//让空在后面
 select *from emp order by comm desc nulls first;//让空在前面
 注意:last,first不受降序还是升序的影响

 员工信息按第2列排序
 select *from emp order by 2;
 select ename,sal,deptno from emp order by 2;
 注意:by后面的2表示要显示的列数中的第2列

 员工信息按别名排序
 select ename,empno 工号 from emp order by 工号;

单行函数-字符函数(重点)

lower   将字符串转为小写
upper   将字符串转为大写
initcap 将首字母变成大写

select lower('HELLO'),upper('world'),initcap('hsadfs') from dual;
    

concat(a,b)    连接字符串a和b,只能连接两个
select concat('hello','world') from dual;
select concat('hello',concat('hahah','world')) from dual;
select 'hello' || 'world' || 'hahaha' from dual;
    
//获取子串
substr(a,b)    从a中,第b位开始取(计数从1开始),取到结尾
select substr('abcdef',2) from dual;
     
length:计算字符数,lengthb:计算字节数
select length('hello我'),lengthb('world我') from dual;

instr(B,A)  用来查找A字符串在B字符串中的位置
select instr('hello','llo') from dual;

lpad,rpad   左右填充
select lpad('hello',10,'#'),rpad('world',10,'$') from dual;
    
trim:去掉前后指定的字符
select trim('     hello      ') from dual;

select trim('h' from 'hhhhhhhhellohhhhhhhh') from dual;
    
replace:替换
select replace('hello','l','*') from dual;//he**o;
     

单行函数-数值函数(重点)

round   四舍五入

trunc   截取数值
ceil、floor  向上取整、向下取整
mod     取模 , %

select round(49.982,2),trunc(49.982,2),ceil(49.982),floor(49.982),mod(10,3) from dual;

单行函数-转换函数(重点)

数字转字符串:to_char
  将薪资转化为本地货币字符串
  select ename,sal,to_char(sal,'L9999.99') from emp;
  说明:L表示本地货币符号
  	  9表示是数字

字符串转数字: to_number
	select to_number('$8000','L9999.99') from dual;
 
日期转字符串:to_char
	select ename,to_char(hiredate,'dd,mm,yy') from emp;

字符串转日期:to_date
	select to_date('17,12,1981','dd,mm,yyyy') from dual;

结论:转换为字符串都用to_char,转换为数字to_number,转换为日期to_date

单行函数-日期函数(了解)

sysdate:表示今天日期
   显示昨天、今天、明天
   select sysdate-1 昨天,sysdate 今天,sysdate+1 明天 from dual;
         
   计算员工工龄,按照日、周、月、年显示
      select sysdate-hiredate 日,
      (sysdate-hiredate)/7,
      (sysdate-hiredate)/30,
      (sysdate-hiredate)/365from emp;
      打开编辑界面用ed,
      注意:在编辑界面写sql语句时,最后不要加上分号
      到SQL>时用/,不是用分号

months_between:计算两个时间日期的数值相差多少个月
	select months_between(sysdate,hiredate) 差月数
      from emp;

add_months:计算明年今日
	select add_months(sysdate,12) from dual;
         
last_day:计算月份的最后一天
	select last_day(sysdate) from dual;
         
next_day:计算下一个星期几
	select next_day(sysdate,'Monday') from dual;//默认是英文
	
        
设置成简体中文:
 alter SESSION set NLS_DATE_LANGUAGE='SIMPLIFIED CHINESE';
设置成英文:
 alter session set NLS_DATE_LANGUAGE='American';

单行函数-通用函数(了解)

nvl(exp,val)
     如果exp 为null ,就返回val
nvl2(exp,val1,val2)
     如果exp为null,就返回val2,否则返回val1

     查询员工信息,有奖金就显示'有奖金',没奖金就显示'没奖金'
     select ename,nvl2(comm,'有奖金','没奖金')from emp;
     
     select ename,nvl2(comm,'有奖金','没奖金') from emp where comm!=0 or comm is null;

单行函数-条件语句(重点)

类似于C语言的switch

标准sql写法:
格式:case when then else end
 总裁决定给大家涨工资,主管涨1000,销售涨500,其他涨200
 select ename,job,sal "涨薪资前",
 case job
 	when 'MANAGER' then sal+1000
 	when 'SALESMAN' then sal+500
 	else sal+200
 end "涨薪资后"
 from emp;
 
 switch(job)
 {
    case 'MANAGER'
    		sal+1000
    		break;
    case 'SALESMAN'
    		sal+500
    		break;
    default:
    		sal+200
 }

orcale的写法:
格式:decode(expr,val1,val2,val3,val4 ....,default)
select ename,job,sal "涨薪资前",
decode(job,'MANAGER',sal+1000,'SALESMAN',sal+500,sal+200) "涨薪资后" from emp;

多行函数-统计函数(重点)

多行函数需要全部或一大部分数据才能计算或者得出结果

	sum:
     求员工工资总和
     select sum(sal) from emp;
     
 count:
     只要某一行某一列有值,count就会+1

     求员工数量,有奖金的员工数
     select count(ename),count(comm) from emp;
     select count(mgr) from emp;
     
     结论:
      null不会参与count的计算

     求工作岗位数量
     select count(distinct job) from emp;
        

 max/min
     求员工最高工资和最低工资
     select max(sal),min(sal) from emp;
     
 avg
     求员工平均工资
     select avg(sal) from emp;
     select sum(sal)/count(ename) from emp;
         
     求员工平均奖金
     select avg(comm) from emp;
     select sum(comm)/count(comm) from emp;
     
     //平均所有的人
     select sum(comm)/count(ename) from emp;
         

多行函数-分组统计(重点)

格式:select ..
 from ...
 where cond1
 group by1,2...       #根据某一列或者多列来分组
 having cond2


 查询各部门平均工资
 select *from emp
 group by deptno;//报错,因为by后面的字段必须在select后面也要出现
 
 select deptno from emp group by deptno;
 答案:
 select deptno,avg(sal) //第二步
 from emp
 group by deptno;//第一步

 
 查询平均薪水大于2000的部门
select deptno,avg(sal) 
 from emp
 where avg(sal)>2000//报错,where后面不能使用多行函数
 group by deptno;
 //where是筛选数据的过程,但avg函数需要完整的一列数据才能得到计算结果
    
 答案:   
 select deptno,avg(sal) //第二步
 from emp
 group by deptno//第一步
 having avg(sal)>2000;//第三步10号部门员工的平均薪水
 select deptno,avg(sal)//avg计算是第三步
 from emp
 where deptno=10//第一步
 group by deptno;//第二步

 havingwhere的区别
 1.where优先于having运行,where进行筛选,能够减少计算数据,提高效率
 2.能用where就尽量用where
    

	sql查询先后顺序:

     select ...
     from ...
     where cond1
     group by ....
     having cond2
     order by ...

     1 遍历表,查询数据,每一行数据都要进行严格筛选,筛选条件就是where cond1,得到结果集1
     2 对结果集1求分组 ,计算统计函数的表达式的值,得到结果集2
     3 对结果集2 进行筛选,筛选条件就是 having cond2  ,得到结果集3
     4 排序,之后筛选出我们想要的列,返回最终结果集      

多表查询及笛卡尔积(重点)

1.要获取的数据不在同一个表中,要使用多表查询

2.笛卡尔积:

1.查询多张表时,会出现笛卡尔集问题,会多余垃圾信息
2.笛卡尔全集的行数是两张表的行数相乘,列数是两张表相加

查询员工信息:员工号,姓名,月薪和部门名称
     员工、姓名、月薪 在 EMP表
     部门名称 在 dept
     select empno,ename,sal,dname
     from emp e,dept d
     where e.deptno=d.deptno;
     //where emp.deptno=dept.deptno
     

使用sql标准连接:
	select empno,ename,sal,dname
     from emp e join dept d
     on e.deptno=d.deptno;
	

3.多表查询也叫表连接.where 条件就是连接条件,如果where条件是等号,那么就叫等值连接,如果是其他的就叫不等值连接


3.7 :表的连接-不等值连接(重点)
查询员工信息:员工号,姓名,月薪和月薪级别(salgrade表)
	select empno,ename,sal,GRADE
	from emp,salgrade
	where sal between LOSAL and HISAL;
	

表的连接-外连接(重点难点)

按部门统计员工人数,显示如下信息:部门号,部门名称,人数(注意统计40号部门)
部门号,部门名称在dept表
人数的统计在emp表中来统计
第一步:两张表进行连接,剔除垃圾数据
select *from dept,emp where dept.deptno=emp.deptno;
第二步:分组统计
select d.deptno,d.dname from dept d,emp e 
where d.deptno=e.deptno
group by d.deptno,d.dname
第三步:统计人数
select d.deptno,d.dname,count(empno)
from dept d,emp e 
where d.deptno=e.deptno
group by d.deptno,d.dname


外连接的目的是:保留没有通过筛选条件的数据
外连接分为:左外连接和右外连
select d.deptno,d.dname,count(empno)
from dept d,emp e 
where d.deptno=e.deptno(+)
group by d.deptno,d.dname
如果要保留等号的左边表中没有通过筛选的数据,就叫左外连接
如果要保留等号的右边表中没有通过筛选的数据,就叫右外连接
写法:
左外连接的写法是在等号的右边的表名后面加上(+)
右外连接的写法是在等号的左边的表名后面加上(+)

sql标准的外连接:

select d.deptno,d.dname,count(empno)
from dept d left join emp e 
on d.deptno=e.deptno
group by d.deptno,d.dname

自连接(了解)

1.要查询的数据在同一张表,但是不在同一行,表自己跟自己做表连接,尽量少用,因为会笛卡尔积平方增长

查询员工信息:将员工的主管名字也显示出来(KING的主管是他自己)
第一步:自己和自己连接
select a.ename,a.mgr,b.empno,b.ename
from emp a,emp b;
第二步:删除垃圾数据,并留下KING
select a.ename,a.mgr,b.empno,b.ename
from emp a,emp b
where a.mgr=b.empno(+);
第三步:
select a.ename || '''s manager is  ' || nvl(b.ename,'KING')
from emp a,emp b
where a.mgr=b.empno(+);

注意:要打印单引号,那么用两个单引号来打印

  • my _code 自连接

    select a.ename || ' ''s manager is   ' || b.ename
    from emp a, emp b
    where nvl(a.mgr, a.empno) = b.empno
    
  • my_code 子查询

    • 查询那组最小工资大于 30 组最小工资, 组 id ,部门名,工资
    select emp.deptno, dept.dname, min(sal) from emp, dept
    where emp.deptno = dept.deptno
    group by emp.deptno, dept.dname
    having min(sal) > 
    (
          select min(sal) from emp
          where deptno = 30
    )
    
    -- 如果 dept.dname 在这个组中不止一个,min()等函数就没有办法用了
    
  • 不是主管的员工信息

    -- 差集
    select * from emp
    where empno in
    (
           select empno from emp
           minus
           select mgr from emp 
    )
    -- 逻辑
    select * from emp
    where empno not in
    (
    	-- 主管集合, not in --> C: empno != mgr1 && empno != mgr2 ... empno != null
        					--	 最有一项恒为假, 所以没有数据 (in 是 || 短路逻辑 --> ok)
        select mgr from emp
        where mgr is not null
    )
    

3.8 : sql 语句中增、删、改、查

子查询(重点难点)

1.一个select语句里边可以嵌套其他select语句,就是子查询

2.为什么要有子查询: 1、方便理解。 2、实现更复杂的查询。 3、提高查询效率。

查询比scott工资高的员工信息 
1.查询scott的工资
select sal from emp where ename='SCOTT';//3000
2.查询比3000高的员工信息
select *from emp where sal>3000

答案:
	select *from emp where sal>
	(
		select sal from emp where ename='SCOTT'
	);
     

3.注意事项

1.注意书写风格
2.父查询和子查询可以是不同的表,子查询返回的结果父查询可以使用即可
     查询部门名称是 'SALES' 的员工信息
     需要dept表和emp表
     select *from emp
     where deptno=
     (
         --查询叫SALES的部门编号是什么
         select deptno from dept
         where dname='SALES'
     );
     
3.父查询的selectfromwherehaving都可以嵌套子查询
		select ...
     from ...
     where ...
     group by ...   --不能后置子查询
     having ...
     order by ...   --不能后置子查询
select 后置子查询:
	查询10号部门的员工号、员工姓名、部门编号、部门名称
	select empno,ename,deptno,
	(
		--将10号部门的名称查询出来
		select dname from dept
		where deptno=10
	) "部门名称"
	from emp
	where deptno=10;
	
         

from 后置子查询: 
	查询员工的姓名、月薪和年薪(使用select * from _________)
	select *from
	(
		select ename,sal,sal*12 年薪
		from emp
	);
	
	
        
where后置子查询: 
	查询与ward相同岗位并且月薪比他高的员工信息
    1.查询ward的岗位  
    select job from emp where ename='WARD';
    2.查询ward的薪资
    select sal from emp where ename='WARD';
    3.整合
    select *from emp
    where job=
    (
    	--ward的岗位
    	 select job from emp where ename='WARD'
    )
    and sal>
    (
     select sal from emp where ename='WARD'
    );

having后置子查询:
	查询哪个部门最低月薪高于30号部门的最低薪资,以及这个部门的最低月薪是多少
       1.查询30号部门的最低月薪
       select min(sal)
       from emp
       where deptno=30;//950
       2.确定哪个部门的最低月薪比这个高
       select deptno,min(sal) from emp
       group by deptno
       
       答案:
       select deptno,min(sal) from emp
       group by deptno
       having min(sal)>
       (
       	select min(sal)
       	from emp
       	where deptno=30
       );

4.单行子查询只能使用单行操作符,多行子查询只能使用多行操作符 (这里都是指单列)
  1.单行操作符,就是对某个单一数据的比较操作
     =|>|>=|<|<=2.多行操作符,就是对一个集合的比较操作(INANYALL)
  
  查询部门名称为SALES和ACCOUNTING的员工信息 (IN)
  1.员工信息在emp表
  2.部门名称中dept表
  3.这个两表的联系是deptno列
  第一步:查询出SALES和ACCOUNTING的部门编号
  select deptno from dept
  where dname='SALES' or dname='ACCOUNTING';//10,30
  第二步:查出这两个部门编号的员工信息
  select *from emp
  where deptno in(10,30);
  答案:
  select *from emp
  where deptno in
  (
  	select deptno 
  	from dept
  	where dname='SALES' or dname='ACCOUNTING'
  );
         
     
  查询月薪比30号部门任意一个(某一个any)员工高的员工信息
         1.查询30号部门最低的工资 --950
         2.查询比950高的员工信息
         答案:
         select *from emp
         where sal > any//sal只要大于下面的集合其中一个数就为真
         (
         	select sal
         	from emp
         	where deptno=30
         );
         
     
   查询比30号部门所有员工工资都高的员工信息(all)
   select *from emp
         where sal > all//sal需要大于下面的集合中所有的数才为真
         (
         	select sal
         	from emp
         	where deptno=30
         );
         
     
5.注意子查询中返回的null值影响最终计算结果
 
     查询不是主管的员工信息
     1.先查询是主管的员工编号
     select mgr from emp;
		2.取反
		select *from emp
		where empno not in
		(
			select mgr from emp
		)//查不到
		
		假设:select mgr from emp 的结果是(7902,7698,null)
		换成C语言的代码:empno !=7902 && empno!=7698 && empno!=null
		null和任何逻辑运行都为假
		
		假设查询是主管的信息
		where empno in (7902,7698,null)
		换成C语言的代码:empno==7902 || empno==7698 || empno==null
		
		答案
		select *from emp
		where empno not in
		(
			select mgr from emp where mgr is not null
		)


SQL解析:一般先执行子查询(内查询),再执行父查询(外查询);关联子查询除外
         一般子查询只执行一次,先于父查询来执行,关联子查询除外(作业会讲)

插入(重点)

1.根据表的设计,将val1,val2对应上每一列的定义,进行插入
insert into 表名 values(val1,val2,val3....)

2.根据前面列的顺序来调整values里边这些字段值的顺序       
insert into 表名(列名1,列名2,....) values(val1,val2 ....)
     
 
 往部门表里边插入以下几行信息
     DEPTNO DNAME                        LOC
 ---------- ---------------------------- --------------------------
         50 SUPPORT                      WASHINGTON
         60 TEST
         70 PURCHASING
insert into dept values(50,'SUPPORT','WASHINGTON');
insert into dept values(60,'TEST',null);
insert into dept(deptno,dname) values(70,'PURCHASING');      

更新(重点)

update 表名 set 列名1=1 , 列名2 =2...  [where cond]60号部门的LOC改成MIAMI
 update dept set LOC='MIAMI' where deptno=60;50号部门的部门名字改成 SUPPORT1 ,LOC改为NULL
 update dept set dname='SUPPORT1',LOC=null where deptno=50;
    

删除(重点)

delete from 表名 where cond
注意:删除数据都是以行为单位

 删除部门号为50的部门信息
 delete from dept where deptno=50;
    
 删除部门号大于40的部门信息
     delete from dept where deptno>40;

3.9 :集合运算(重点)
	交集:             intersect
     
 并集:             union
    
 全并集:            union all
    
 差集:分方向         minus
     求一个集合对于另一个集合没有的那部分
     
集合运算注意事项:
    * 参与运算的各个集合必须列数相同,且类型一致
    * 采用第一个集合的表头作为最终使用的表头,(别名也只能在第一个集合上起)
    * 可以使用括号修改各个sql执行的优先级
        
部门号是10的员工和部门号是20的员工信息做并集(以及全并集)
	select *from emp
	where deptno=10
	union
	select *from emp
	where deptno=20;10号部门的员工信息和 10,20号部门的员工信息做交集
	select *from emp
	where deptno=10
	intersect	
	select *from emp
	where deptno in(10,20);10,30的员工减去10,20的员工信息
	select *from emp
	where deptno in(10,30)
	minus
	select *from emp
	where deptno in(10,20);
        

    
查询三个部门的工资信息并分组统计,格式如下:
        DEPTNO JOB                  SUM(SAL)
    ---------- ------------------ ----------
            10 CLERK                    1300
               MANAGER                  2450
               PRESIDENT                5000
                                        8750

            20 ANALYST                  6000
               CLERK                    1900
               MANAGER                  2975
                                       10875

            30 CLERK                     950
               MANAGER                  2850
               SALESMAN                 5600
                                        9400

                                       29025
    1.每个部门,每个岗位的工资总和
    select deptno,job,sum(sal)
    from emp
    group by deptno,job;
    
    DEPTNO JOB         SUM(SAL)
------ --------- ----------
    20 CLERK           1900
    30 SALESMAN        5600
    20 MANAGER         2975
    30 CLERK            950
    10 PRESIDENT       5000
    30 MANAGER         2850
    10 CLERK           1300
    10 MANAGER         2450
    20 ANALYST         6000
    
    2.每个部门的工资总和
    select deptno,sum(sal)
    from emp
    group by deptno;
    
    DEPTNO   SUM(SAL)
------ ----------
    30       9400
    20      10875
    10       8750
    
    
    3.整个公司的工资总和
    select sum(sal)
    from emp;
    
      SUM(SAL)
----------
     29025
    
    整合:
    select deptno,job,sum(sal)
    from emp
    group by deptno,job
    union
    select deptno,null,sum(sal)
    from emp
    group by deptno
    union
    select null,null,sum(sal)
    from emp;

    DEPTNO JOB         SUM(SAL)
---------- --------- ----------
        10 CLERK           1300
        10 MANAGER         2450
        10 PRESIDENT       5000
        10                 8750
        20 ANALYST         6000
        20 CLERK           1900
        20 MANAGER         2975
        20                10875
        30 CLERK            950
        30 MANAGER         2850
        30 SALESMAN        5600
        30                 9400
                          29025
                          
                          
      DEPTNO JOB	       SUM(SAL)
---------- --------- ----------
	10 CLERK	   1300
	   MANAGER	   2450
	   PRESIDENT   5000
			       8750


	20 ANALYST	   6000
	   CLERK	   1900
	   MANAGER	   2975
			       10875


	30 CLERK	    950
	   MANAGER	   2850
	   SALESMAN	   5600
			        9400


			       29025
                    
    
        要在终端执行才有效果
        SQLplus中使用以下命令来去掉分组重复的deptno
            break on deptno skip 2;
        使用以下命令来恢复
            break on null;
        //先执行break on deptno skip 2;然后在执行答案,就可以得到最终的格式                               



3.10 : 事务

事务的概念(了解)

数据库事务,是由有限的数据库操作序列组成的逻辑执行单元,这一系列操作要么全部执行,要么全部放弃执行。
对数据库进行DML操作,没有提交事务前面,别的用户是看不到操作的,要提交事务才可以看到
提交事务:
显示:commit;
隐式:执行ddl或dcl及正常退出
回滚:rollback;是回到最近一次提交事务的状态
隐式回滚:掉电、宕机、非正常退出
隔离级别(面试):
问题:
1.	脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
2.	不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
3.	幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.

隔离级别:
SQL99定义4种隔离级别:	
1. 	Read Uncommitted	读未提交数据。
2.	Read Commited		读已提交数据。		(Oracle默认)
3.	Repeatable Read		可重复读。			(MySQL默认)			
4.	Serializable			序列化、串行化。 (查询也要等前一个事务结束)
这4种MySQL都支持
Oracle支持的隔离级别: Read Commited(默认)和 Serializable,以及Oracle自定义的Read Only三种。
Read Only:由于大多数情况下,在事务操作的过程中,不希望别人也来操作,但是如果将别人的隔离级别设置为Serializable(串行),但是单线程会导致数据库的性能太差。是应该允许别人来进行read操作的。


      

事务的控制(了解)

在事务的过程中可以使用保存点来记录过程
创建保存点:
    savepoint  保存点名字 
        
下次如果发现之前某一步做错了,不至于直接 rollback回到原始事务
 
回滚到保存点:       
    rollback to savepoint 保存点名字

    一但当前事务提交或者回滚,在当前事务建立的savepoint将失效


4: Oracle 、 Mysql 、Redis 优缺点对比

4.1 : 数据库

  • 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。

    • 每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。
    • 我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。
  • 所以,现在我们使用关系型数据库管理系统(RDBMS)来存储和管理大数据量。所谓的关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。

  • RDBMS 即关系数据库管理系统(Relational Database Management System)的特点:

    • 1.数据以表格的形式出现
    • 2.每行为各种记录名称
    • 3.每列为记录名称所对应的数据域
    • 4.许多的行和列组成一张表单
    • 5.若干的表单组成database


  • RDBMS 术语 : (Relational Database Management System)
    • 数据库: 数据库是一些关联表的集合。
    • 数据表: 表是数据的矩阵。在一个数据库中的表看起来像一个简单的电子表格。
    • 列: 一列(数据元素) 包含了相同类型的数据, 例如邮政编码的数据。
    • **行:**一行(=元组,或记录)是一组相关的数据,例如一条用户订阅的数据。
    • 冗余:存储两倍数据,冗余降低了性能,但提高了数据的安全性。
    • 主键:主键是唯一的。一个数据表中只能包含一个主键。你可以使用主键来查询数据。
    • **外键:**外键用于关联两个表。
    • 复合键:复合键(组合键)将多个列作为一个索引键,一般用于复合索引。
    • **索引:**使用索引可快速访问数据库表中的特定信息。索引是对数据库表中一列或多列的值进行排序的一种结构。类似于书籍的目录。
    • 参照完整性: 参照的完整性要求关系中不允许引用不存在的实体。与实体完整性是关系模型必须满足的完整性约束条件,目的是保证数据的一致性。
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RmRgnFKL-1583041832412)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20191119171402835.png)]

  • 表头(header): 每一列的名称;
  • 列(col): 具有相同数据类型的数据的集合;
  • 行(row): 每一行用来描述某条记录的具体信息;
  • 值(value): 行的具体信息, 每个值必须与该列的数据类型相同;
  • 键(key): 键的值在当前列中具有唯一性。

4.2 : 三种数据库

1: Mysql
1: 功能
  • MySQL 是开源的,所以你不需要支付额外的费用。
  • MySQL 支持大型的数据库。可以处理拥有上千万条记录的大型数据库。
  • MySQL 使用标准的 SQL 数据语言形式。
  • MySQL 可以运行于多个系统上,并且支持多种语言。这些编程语言包括 C、C++、Python、Java、Perl、PHP、Eiffel、Ruby 和 Tcl 等。
  • MySQL 对PHP有很好的支持,PHP 是目前最流行的 Web 开发语言。
  • MySQL 支持大型数据库,支持 5000 万条记录的数据仓库,32 位系统表文件最大可支持 4GB,64 位系统支持最大的表文件为8TB。
  • MySQL 是可以定制的,采用了 GPL 协议,你可以修改源码来开发自己的 MySQL 系统。
2: 优势
  • MySQL是一种关联数据库管理系统由于其体积小、速度快、总体拥有成本低,一般中小型网站的开发都选择MySQL 作为网站数据库。


2: redis

  • 简介
    • Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
    • 它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
  • 特点
    • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
    • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
    • Redis支持数据的备份,即master-slave模式的数据备份
  • 优势:
    • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
    • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
    • 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
    • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值