00_Oracle mysql学习笔记整理
目录
- 1.为什么要学习数据库
- 2.Oracle数据库
- 2.1 登录
- 2.2 简单查询:
- 2.3 单条件查询:
- ed 命令
- 2.4 多条件查询:
- 2.5 模糊查询
- 2.6 排序
- 2.7 字符函数:单行函数
- 2.8 数值函数
- 2.9 转换函数
- 2.10 日期函数
- 2.11 通用函数
- 2.12 条件语句 case、decode
- 2.13 统计函数:多行计算函数
- 2.14 分组统计
- 2.15 多表查询
- 1. 多表查询
- 2. 表的连接:等值连接和不等值连接
- 3. 表的连接:外连接
- 2.16 自连接
- 2.17 子查询
- 2.18 集合运算
- 2.19 新增数据:
- 2.20 修改数据
- 2.21 删除数据
- 2.22 事务
- 2.23 隔离级别
- 2.24 事务的控制
- 2.25 习题
- 1. 子查询和行号
- 2.自连接和关联子查询
- 关联子查询
- 3. 01标记法
- 2.26 oracle表操作
- 1.创建表
- 2.修改表
- 3.清空表
- 4.删除表
- 5. 表的约束
- 2.27 视图
- 2.28 序列
- 2.29 索引
- 2.30 同义词
- 3.mysql
- 3.0 创建scott表 并插入数据
- 3.1 登录mysql
- 3.2 库操作
- 3.3 表操作
- edit打开编辑器
- 3.4 操作表中的数据
- 3.5 综合查询
- 3.6 数据库的函数
- 3.7 多表查询
- 3.8 Top-N
- 3.9 表的约束
- 3.10 mysql如何打开事务
- 3.11 mysql中的乱码问题
- 3.12 mysql 编程的基础
- 3.13 mysql C-API-Code-Demo1
- 3.14mysql C-API-Code-Demo1改进版
- 3.14 额外的API补充
- 3.15 预处理语句
- 3.16mysql C-API-Code-Demo3
1.为什么要学习数据库
-- 市面上99%的软件都会用到数据库-- 查询、增、删、改、创表删表等操作
2.Oracle数据库
2.1 登录
-- 数据库启动关闭 -- 以oracle用户登录linux-- sqlplus / as sysdba-- 以数据库管理员的方式登录oracle数据库 ,默认用户名是sys-- sql> startup -- 启动数据库实例 (在sqlplus中执行)-- 实例:oracle的一组服务-- sql> shutdown -- 关闭数据库实例-- exit 退出sqlplus
-- 数据库监听服务启动和关闭-- lsnrctl start-- 启动数据库的监听服务-- 如果不启动监听服务,oracle远程没有办法连接上的-- lsnrctl stop-- 关闭数据库监听服务-- lsnrctl status-- 查看监听服务的状态
-- 修改scott用户密码-- 必须要oracle的管理员权限去修改-- sqlplus / as sysdba -- sql> alter user scott identified by "123456" ;-- 登录scott用户-- sqlplus 用户名/密码-- 本地登录-- sqlplus scott/11-- sqlplus 用户名/密码@//服务器ip/实例名(orcl)-- 远端登录-- sqlplus scott/11@//192.168.177.233/orcl-- 查看scott用户方案所拥有的表-- 使用scott用户登陆之后-- select * from tab;
2.2 简单查询:
select *
from tableName;select 列名1 as "别名1",列名2,表达式....
from 表名
-- 查询emp表的所有数据 select * from emp;-- 设置行宽 set linesize 140;-- 设置页高 set pagesize 50;-- 查询员工号,姓名,月薪,奖金,年薪,年收入 并修改列名为中文select empno as "工 号",ename as 姓名,sal 月薪,comm 奖金 ,sal*13 年薪, sal*13 + nvl(comm,0) 年收入from emp;-- 小结:-- 1 sql查询可以按照列名来查询-- 2 可以使用表-- 达式作为列名,数据库会自动计算出每一列每一行表达式的值-- 3 可以对列起别名-- nvl 函数:nvl(f1,f2)-- 如果参数1(表达式)为null,则返回参数2-- null 数据类型 -- 做任何的数值运算结果都为null-- 查看员工表所有部门编号并去除重复select distinct deptno from emp;
-- 说明:-- distinct 的作用:就是去除重复的行-- 计算表达式3+2select 3+2 from dual
-- 说明:-- dual是一张虚表,我们可以从这张表里边去计算表达式
2.3 单条件查询:
-- 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;-- 查询入职日期为1981年11月17日的员工信息-- 日期的比较可以直接使用字符串来比较,数据库会自动做一个隐式的转换select * from emp where hiredate = '1981-11-17';-- ORA-01861: 文字与格式字符串不匹配-- 当用字符串跟日期进行比较的时候,注意日期格式-- 查询当前会话的环境变量select * from v$nls_parameters; select * from emp where hiredate = '17-11月-81'-- 修改当前会话的时间日期格式字符串alter session set NLS_DATE_FORMAT='yyyy-mm-dd'
ed 命令
-- sqlplus 中 使用 ed 命令,打开一个编辑器,用来编辑上一条执行过的sql语句
-- 修改这条语句(最后不要使用分号),换行之后添加一个单独的 / 表示结束 ,保存退出,
-- 然后敲入/回车执行上一条指令
2.4 多条件查询:
-- -- 与 或 非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 = 20select * from empwhere deptno in (10,20)-- 查询部门不是10和20的员工信息select * from empwhere deptno not in (10,20)-- 查询工资介于1000到2000之间的员工select *from empwhere sal >=1000 and sal <=2000select *from empwhere sal between 1000 and 2000-- between and 是一个闭区间-- 查询1981年2月(含2月)到82年2月(不含2月)入职的员工信息1981-2-1 1982-1-31select * from empwhere hiredate between '1981-02-01' and '1982-01-31'-- 查询没有奖金的员工信息select * from empwhere comm = null-- 结论:-- null做任何逻辑运算,结果都为假-- 用下面这个select *from empwhere comm is null-- 查询有奖金的员工信息select *from empwhere comm is not null
2.5 模糊查询
-- 每次掉线之后重新连接之后都要设置行宽页高的问题
-- 配置 C:\app\itcast\product\11.2.0\client_1\sqlplus\admin\glogin.sql
-- 每次登录sqlplus之后都会马上执行的一些指令
select ..-- .
from ..
where 列名 like '模式字符串'-- % 表示:任意字符 任意次数
-- _ 表示:任意字符 单次-- sql 的模式匹配没有默认转义字符,可以指定转义字符
-- like '模式子串' escape '转义字符'-- 查询员工首字母是S的员工信息select *from empwhere ename like 'S%'-- 查询名字是四个字母的员工信息select *from empwhere ename like '____'-- 查询姓名带下划线的员工信息
insert into emp values(8000,'A_B','CLERK',7902,sysdate,900,null,20);select * from empwhere ename like '%\_%' escape '\'
2.6 排序
-- select ...from ....where ...order by 列名1,列名2... desc|asc-- asc 从小到大 升序 (默认)
-- desc 从大到小 降序
-- desc和asc 只对单列生效;对多列分别指定 会对指定的这些列分别生效-- 员工信息按先后入职日期排序select * from emp order by hiredate-- 员工信息按薪水从大到小排序 select *from emporder by sal desc-- 员工信息按部门号和薪水排列select *from emporder by deptno , sal-- 排序的规则,先排第一列,第一列相同的情况下再按照第二列来排序
-- 以此类推-- 员工信息按部门和薪水排列,降序
-- desc和asc 只对单列生效select *from emporder by deptno desc, sal desc-- 员工信息按奖金倒序select *from emporder by comm desc nulls last|first-- 结论:
-- null值会影响排序-- 员工信息按第2列排序
-- 按照第几列来排序是指结果集的第几列,不是表的第几列select ename , empnofrom emporder by 2-- 员工信息按别名排序select ename , empno "工号"from emporder by "工号"
2.7 字符函数:单行函数
-- lower 将字符串转为小写
-- upper 将字符串转为大写
-- initcap 将首字母变成大写
select lower('hELLO'),upper('heLlo'),initcap('hEllO')
from dualLOWER UPPER INITC----- ----- -----hello HELLO Helloconcatselect concat('hello ','world') from dual
-- concat 默认只接收两个参数select concat('hello ',concat('world','aaa')) from dual;
-- oracle还提供另一种方法,使用 ||select 'hello'||'world'||123||456 from dualsubstrselect substr('helloworld',3),substr('helloworld',3,5) from dual
substr(字符串,起始位置) 从起始位置开始一直取到字符串的结尾
substr(字符串,起始位置,n) 从起始位置开始取n个字符instr 用来查找A字符串在B字符串中的位置select instr('helloworld','llo') from duallpad,rpad 左右填充
-- 将字符串进行填充到10的长度,如果不够就填充#号select lpad('hello',10,'#') from dual-- trim 裁剪字符串两边空白的字符select trim(' Hello ') from dual;
-- 指定裁剪字符串两边特定的字符
-- 裁剪字符串两边大写的Hselect trim('H' from 'HHHHhelloHHHHH') from dual;replaceselect replace('hello','l','*') from dual;
2.8 数值函数
round 四舍五入trunc 截取数值ceil、floor 向上取整、向下取整mod 取模 , %select round(45.926,2),trunc(45.926,2),ceil(45.926),floor(45.926),mod(1000,600)from dual
2.9 转换函数
-- to_char :数字转字符串
-- to_char(数值表达式,'格式字符串')
-- 格式字符串:
-- L 本地货币符号
-- 9 表示一位数值
-- 将薪水转化为本地货币字符型select empno,ename,sal,to_char(sal,'L9999.99') from empto_number:字符串转数字 select to_number('¥800.00','L9999.99') from dual;to_char:日期转字符串 select empno,ename,to_char(hiredate,'dd,mm,yyyy') from emp;to_date:字符串转日期 select to_date('17,12,1980','dd,mm,yyyy') from dual说明:to_char用什么格式字符串,to_number或者to_date就可以使用该格式字符串转化回来
2.10 日期函数
sysdate-- 显示昨天、今天、明天select sysdate - 1 昨天,sysdate 今天 , sysdate +1 明天 from dual-- 时间日期数据类型计算单位是1天-- 计算员工工龄,按照日、周、月、年显示select sysdate-hiredate 日,(sysdate-hiredate)/7 周,(sysdate-hiredate)/30 月,(sysdate-hiredate)/365 年 from empmonths_between
-- 计算两个时间日期的数值相差多少个月select sysdate-hiredate 日,(sysdate-hiredate)/7 周,(sysdate-hiredate)/30 月,months_between(sysdate,hiredate) 月2,(sysdate-hiredate)/365 年 from empadd_months
-- 计算明年今日select add_months(sysdate,12) from duallast_day
-- 计算月份的最后一天select last_day(sysdate) from dualnext_day
-- 计算下一个星期几select next_day(sysdate,'星期五') from dual
2.11 通用函数
-- nvl(exp,val)
-- 如果exp 为null ,就返回val
--
-- nvl2(exp,val1,val2)
-- 如果exp为null,就返回val2,否则返回val1-- 查询员工信息,有奖金就显示'有奖金',没奖金就显示'没奖金'select ename,nvl2(comm,'有奖金','没奖金') from emp
2.12 条件语句 case、decode
-- case
-- when
-- then
-- else
-- end
-- 总裁决定给大家涨工资,主管涨1000,销售涨500,其他涨200switch(job){case 'MANAGER': sal+1000; break;case 'SALESMAN' : sal + 500 ;break;default : sal+200 ; break;}
-- case 是sql标准select ename,job,sal "涨前工资",case jobwhen 'MANAGER' then sal + 1000when 'SALESMAN' then sal + 500else sal+200end "涨后工资"from emp-- decode 不是sql标准,oracle自身拓展出来
-- decode(expr,val1,val2,val3,val4 ....,default)
-- 判断表达式expr 的值,如果为val1,就返回val2
-- 如果为val3,就返回val4 依次类推,如果都不是,就返回最后一个defaultselect ename,job,sal "涨前工资",decode(job,'MANAGER',sal+1000,'SALESMAN',sal+500,sal+200)"涨后工资"from emp
2.13 统计函数:多行计算函数
-- 多行函数相对于单行的函数来说,必须遍历整个表或者部分数据才可以计算出结果-- sum-- 求员工工资总和select sum(sal) from emp-- count 只要某一行某一列有值,count就会+1-- 求员工数量,有奖金的员工数select count(empno),count(*),count(comm) from empselect sum(1) from emp;-- 说明:
-- null不会参与统计函数的计算-- 求工作岗位数量select count(distinct job) from emp-- max/min
-- 求员工最高工资和最低工资-- avg-- 求员工平均工资select avg(sal) from emp-- 求员工平均奖金(三种方式)select sum(comm)/count(*),sum(comm)/count(comm),avg(comm)from emp
2.14 分组统计
-- -- select ..
-- -- from ...
-- -- where cond1
-- -- group by 列1,列2... --根据某一列或者多列来分组
-- -- having cond2-- 查询各部门平均工资select * -- 此处是错误示范from empgroup by deptno-- 注意:如果使用了group by来进行分组,select后面的列有限制
-- 能填的只能是group by 中出现过的列, 或者是 统计函数select deptno,avg(sal)from empgroup by deptno-- 小结:
-- 多行函数(统计函数)在没有分组的前提下,统计的是全表
-- (有where就是通过where筛选)的数据,
-- 在有分组的前提下,统计的就是分组-- 查询平均薪水大于2000的部门select deptno,avg(sal)from empwhere avg(sal)>2000 --第3行出现错误:ORA-00934: 此处不允许使用分组函数group by deptno
--注意:在where条件中不允许使用统计函数
-- 使用havingselect deptno,avg(sal)from empgroup by deptnohaving avg(sal) > 2000-- 求10号部门员工的平均薪水select deptno , avg(sal)from empwhere deptno = 10group by deptno
-- 换成havingselect deptno , avg(sal)from empgroup by deptnohaving deptno = 10having与where的区别
--结论:能够用where 就不要用having-- sql查询先后顺序:select ...from ...where cond1group by ....having cond2order by ...
-- 1 遍历表,查询数据,每一行数据都要进行严格筛选,筛选条件就是where cond1,得到结果集1
-- 2 对结果集1求分组 ,计算统计函数的表达式的值,得到结果集2
-- 3 对结果集2 进行筛选,筛选条件就是 having cond2 ,得到结果集3
-- 4 排序
-- 5 之后筛选出我们想要的列,返回最终结果集-- where筛选是先于having筛选的,
-- 先在where进行筛选,能够减少后边计算的数据量,从而提高查询语句性能
2.15 多表查询
1. 多表查询
--多表查询:要获取的数据不在同一个表中,要使用多表查询
-- select ...
-- from 表1,表2....
-- where ...--查询员工信息:员工号,姓名,月薪和部门名称--员工、姓名、月薪 在 EMP表--部门名称 在 deptselect empno,ename,sal,dname,e.deptnofrom emp e,dept dwhere e.deptno = d.deptno--join on:另外一个连接的语法(SQL标准),使用 join on
--将from 后面的逗号,换成join ,where 换成onselect empno,ename,sal,dname,e.deptnofrom emp e join dept don e.deptno = d.deptno
2. 表的连接:等值连接和不等值连接
--多表查询也称为表的连接,where筛选的条件就称为连接条件--根据连接条件里边使用的是等号还是不等号,可以称为等值连接和不等值连接--查询员工信息:员工号,姓名,月薪和月薪级别(salgrade表)select empno,ename,sal,grade from emp,salgradewhere sal between losal and hisal
3. 表的连接:外连接
--按部门统计员工人数,显示如下信息:部门号,部门名称,人数(注意统计40号部门)select d.deptno,d.dname,count(empno)from dept d , emp ewhere 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.deptnogroup by d.deptno,d.dname--外连接:如果想保留没有通过连接条件而被筛选掉的数据,那么就使用外连接--分方向,这是oracle的特有的玩法
-- 想保留哪一张表的额外的数据,就在连接条件等号的另一边使用(+)--左外连接
-- 想保留左边表的数据,使用左外连接
-- 就在等号右边使用(+)--右外连接
-- 想保留右边表的数据,使用右外连接
-- 就在等号左边使用(+)
2.16 自连接
-- 自连接:要查询的数据在同一张表,但是不在同一行,表自己跟自己做表连接--查询员工信息:将员工的主管名字也显示出来(KING的主管是他自己)select e.ename || '''s manager is '|| nvl(e2.ename,'his wife')from emp e ,emp e2where e.mgr = e2.empno (+)-- sql中的字符串,使用两个单引号来转义输出单个单引号
2.17 子查询
-- 子查询:一个select语句里边可以嵌套其他select语句,就是子查询
--
-- 查询比scott工资高的员工信息
-- 1 先查询出scott的工资select sal from emp where ename = 'SCOTT' -- 3000
-- 2 查询工资大于3000的员工信息select * from emp where sal > 3000select * from emp where sal >(--查询出scott的工资select sal from emp where ename = 'SCOTT')--注意事项
-- 注意书写风格
-- 父查询和子查询可以是不同的表,子查询返回的结果父查询可以使用即可-- 查询部门名称是 'SALES' 的员工信息
-- 1 先查询出salse部门编号(先根据部门名称查询出部门编号)
-- 2 查询出是该部门编号的所有员工信息(然后根据部门编号查询出所有的员工信息)select *from empwhere deptno =(--查询出sales的部门编号select deptnofrom deptwhere dname = 'SALES')
--父查询的select、from、where、having都可以嵌套子查询select ...from ...where ...group by ... --不能后置子查询having ...order by ... --不能后置子查询-- select 后置子查询:
-- 查询10号部门的员工号、员工姓名、部门编号、部门名称
-- select empno,ename,deptno ,(--将10号部门的名称查询出来select dname from deptwhere deptno = 10) "部门名称"from empwhere deptno = 10-- from 后置子查询:
-- 查询员工的姓名、月薪和年薪(使用select * from _________)select *from (select ename,sal,sal*13 年薪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 empwhere job= (--ward的岗位select job from emp where ename = 'WARD')and sal > (--ward的工资select sal from emp where ename= 'WARD')-- having后置子查询:
-- 查询部门最低月薪高于30号部门的部门以及其最低月薪
-- 1 查询30号部门的最低月薪select min(sal)from empwhere deptno = 30--950
-- 2 确定哪个部门的最低月薪比30号部门要高select deptno,min(sal)from empgroup by deptno
-- 3 组合使用select deptno,min(sal)from empgroup by deptnohaving min(sal) > ( select min(sal)from empwhere deptno = 30)
-- 单行子查询只能使用单行操作符,
-- 单行操作符,就是对某个单一数据的比较操作
-- = > >= < <= 等
-- 多行子查询只能使用多行操作符 (这里都是指单列)
-- 多行操作符,就是对一个集合的比较操作
-- IN ANY ALL--查询部门名称为SALES和ACCOUNTING的员工信息 (IN)--in 跟单行操作符 = 对应--1 先查询出 sales 和 accounting 的部门编号select deptno from dept where dname ='SALES' or dname = 'ACCOUNTING'--10,30--2 再查询出是这两个部门编号的员工信息select *from empwhere deptno in (10,30)--3 组合使用select *from empwhere deptno in (select deptno from dept where dname ='SALES' or dname = 'ACCOUNTING')-- 查询月薪比30号部门任意一个(某一个any)员工高的员工信息
-- any
-- ANY(表示和集合中的任意一个值比较):
-- 查询比30号部门最低月薪高的员工信息-- 1 先查询出 30部门的最低月薪 --950
-- 2 查询比950 高的员工信息select *from empwhere sal > any(--先将30号部门的所有员工的月薪都查询出来select salfrom empwhere deptno = 30)
-- 查询比30号部门所有员工工资都高的员工信息
-- all
-- 查询比30号部门最高月薪高的员工信息select *from empwhere sal > all(--先将30号部门的所有员工的月薪都查询出来select salfrom empwhere deptno = 30)
-- 注意子查询中返回的null值影响最终计算结果
-- 查询不是主管的员工信息
-- 1 先查询是主管的empnoselect mgr from emp
-- 2 取反select *from empwhere empno not in( select mgr from emp)
-- 假设
-- select mgr
-- from emp
-- 结果是 (7902,7698,null)where empno not in ( 7902,7698,null)
-- 换算成C的代码
-- empno!=7902 && empno!=7698 && empno!=null
-- 注意:null做任何逻辑运算,结果都为假-- 如果题设是查询是主管的信息where empno in ( 7902,7698,null)empno==7902 || empno==7698 || empno==null-- SQL解析:
-- 一般先执行子查询(内查询),
-- 再执行父查询(外查询);
-- 关联子查询除外
-- 一般子查询只执行一次,先于父查询来执行,关联子查询除外
2.18 集合运算
交集: intersect多个集合都有的那部分并集: union将多个集合合在一起 (去重)全并集: union all将多个集合合在一起(不去重)差集:分方向 minus求一个集合对于另一个集合没有的那部分
-- 部门号是10的员工和部门号是20的员工信息做并集(以及全并集)select *from empwhere deptno = 10unionselect *from empwhere deptno = 20-- 用10号部门的员工信息和 10,20号部门的员工信息做交集select *from empwhere deptno in (10,20)intersectselect *from empwhere deptno = 10-- 用10,30的员工减去10,20的员工信息select *from empwhere deptno in (10,30)minusselect *from empwhere deptno in (10,20)
-- 查询三个部门的工资信息并分组统计,格式如下:DEPTNO JOB SUM(SAL)---------- ------------------ ----------10 CLERK 1300MANAGER 2450PRESIDENT 5000875020 ANALYST 6000CLERK 1900MANAGER 29751087530 CLERK 950MANAGER 2850SALESMAN 5600940029025
-- 提示:
-- SQL plus中使用以下命令来去掉分组重复的deptnobreak on deptno skip 2;
-- 使用以下命令来恢复break on null;--以上的结果是使用3个集合拼凑在一起-- 1 每个部门,每个岗位的工资总和select deptno,job,sum(sal)from empgroup by deptno , jobDEPTNO JOB SUM(SAL)---------- --------- ----------20 CLERK 190030 SALESMAN 560020 MANAGER 297530 CLERK 95010 PRESIDENT 500030 MANAGER 285010 CLERK 130010 MANAGER 245020 ANALYST 6000
-- 2 每个部门的工资总和select deptno,sum(sal)from empgroup by deptnoDEPTNO SUM(SAL)---------- ----------30 940020 1087510 8750
-- 3 整个公司的工资总和select sum(sal)from empSUM(SAL)----------29025
-- 将以上3个集合拼在一起select deptno,job,sum(sal)from empgroup by deptno , jobunionselect deptno,null,sum(sal)from empgroup by deptnounionselect null,null,sum(sal)from emp
- 集合运算注意事项:
- 参与运算的各个集合必须列数相同,且类型一致
- 采用第一个集合的表头作为最终使用的表头,(别名也只能在第一个集合上起)
- 可以使用括号修改各个sql执行的优先级
2.19 新增数据:
-- insert into 表名 values(val1,val2,val3....)
-- 根据表的设计,将val1,val2对应上每一列的定义,进行插入
--
-- insert into 表名(列名1,列名2,....) values(val1,val2 ....)
-- 根据前面列的顺序来调整values里边这些字段值的顺序
--
-- 往部门表里边插入以下几行信息DEPTNO DNAME LOC
---------- ---------------------------- --------------------------50 SUPPORT WASHINGTON60 TEST70 PURCHASINGinsert into dept values(50,'SUPPORT','WASHINGTON')insert into dept(deptno,loc,dname) values(60,null,'TEST')insert into dept(deptno,dname) values(70,'PURCHASING')
2.20 修改数据
-- update 表名
-- set 列名1=值1 , 列名2 = 值2...
-- [where cond]
--
-- 将60号部门的LOC改成MIAMIupdate dept set loc='MIAMI' where deptno=60-- 将50号部门的部门名字改成 SUPPORT1 ,LOC改为NULLupdate dept set dname='SUPPORT1' , loc = null where deptno = 50
2.21 删除数据
-- delete
-- from 表名
-- where cond
-- 删除数据都是以行为单位-- 删除部门号为50的部门信息delete from dept where deptno = 50-- 删除部门号大于40的部门信息delete from dept where deptno > 40
2.22 事务
银行转账A 100 --如果A向B转账100B 0 --此时端断点了或者B销户了update 将 A - 100 机房断电 / B销户了update 将 B + 100A 100 --如果A向B转账100(事务1)B 0 --此时端断点了或者B销户了C 100 --同时C也向B转账(事务2)-- 多个事务并行执行时,要和串行执行时结果一致
-- 事务由以下部分组成
-- 一个或多个 DML 语句
-- 一个 DDL(Data Definition Language – 数据定义语言) 语句
-- 一个 DCL(Data Control Language – 数据控制语言) 语句
-- DML语句:增删查改 -- 数据操作语言
-- 增 insert
-- 删 delete
-- 改 update
-- 查 select
-- DDL语句 -- 数据定义语言 -- 一个DDL语句就是一个事务
-- create table(创建表)
-- alter table(修改表)
-- truncate table(清空表)
-- drop table(删除表)
-- create view(视图)
-- create index(索引)
-- create sequence(序列)
-- create synonym(同义词)
-- DCL语句:对事务进行操作 --数据控制语言(Data Control Language)
-- commit(提交)
-- rollback(回滚)
2.23 隔离级别
隔离级别某表某一行某一列有一个值 01 读未提交事务A 开启事务B 开启读取该值 0修改该值为100 读取该值 100提交事务2 读已提交 (Oracle默认)事务A 开启事务B 开启读取该值 0修改该值为100 读取该值 0提交事务commit读取该值 100结束事务3 可重复读 (MySQL默认)事务A 开启事务B 开启读取该值 0修改该值为100 读取该值 0提交事务commit读取该值 0结束事务事务C 开启读取该值 100结束事务
4 串行化 相当于单线程 ,服务器上同一时刻只有一个事务在跑事务A 开启修改该值为100 提交事务commit 事务B 开启读取到 100结束事务
2.24 事务的控制
在事务的过程中可以使用 : savepoint 保存点名字 创建一些保存点下次如果发现之前某一步做错了,不至于直接 rollback回到原始事务开始的地方
可以:rollback to savepoint 保存点名字一旦当前事务提交或者回滚,在当前事务建立的savepoint将失效
2.25 习题
1. 子查询和行号
-- 【第一题】:找到员工表中工资最高的前三名, 要求按如下格式输出
-- 补充知识:rownum 行号(伪列) select rownum , emp.* from emp
-- 在结果中看到行号,行号是筛选数据的过程中自动生成的,并不真正存在于表中select rownum , ename, sal from emporder by sal desc -- 问题是如何取出前三行
-- 行号是乱的,工资的降序是对的
-- 结论:行号在排序前已经生成好了-- 解决思路:
-- 1.先排序,
-- 2.再生成行号
-- 3.再筛选 行号 < 3
-- 1.子查询先排序,
-- 2.父查询生成行号
-- 3.父查询最后进行一次筛选select rownum, e.*from (select empno,ename,salfrom emporder by sal desc -- 一般不在子查询中使用order by,但在Top-N问题中,必须使用order by) ewhere rownum <=3-- 注意:行号只能用 < <= 不能用 > >=-- 延伸的问题: 分页问题,按照工资降序排序,取5-8 名
-- 也是依赖行号
-- rownum不能直接用 > 来比较 ,除了 >=1
-- 与行号的生成逻辑有关
-- 行号生成在where条件判断的时候
--
-- where rownum <=3
-- 1 king where 1<=3 为真 通过筛选
-- 2 ford where 2<=3 为真 通过筛选
-- ...
--
-- where rownum >=5
-- 1 king where 1>=5 为假 没通过筛选
-- 1 ford where 1>=5 为假 没通过筛选
-- ...
-- 因为king没有通过筛选,1号的行号保留
--
-- (分页问题的解决)先让行号固定下来,不要筛选的时候再生成select *from (select rownum r, e.*from (select empno,ename,salfrom emporder by sal desc) e)where r >=5 and r <=8
2.自连接和关联子查询
--【第二题提示】:找到emp表中薪水大于本部门平均薪水的员工
-- empno ename sal avgsal
-- 多表查询 ,自行构造另一张表
-- from 后置子查询--1 查询每个部门的平均工资select deptno,avg(sal)from empgroup by deptno --2 用以上的结果和emp表,进行多表连接select *from emp a,(select deptno,avg(sal) avg_salfrom empgroup by deptno ) bwhere a.deptno = b.deptno and a.sal > b.avg_sal--关联子查询 更适合用来解决这道题!!!
关联子查询
--关联子查询
-- 子查询不能独立的执行,必须依赖父查询select *from emp outerwhere sal > (--查询出该员工所在部门的平均工资select avg(sal)from emp innerwhere inner.deptno = outer.deptno)-- 一般先执行子查询(内查询),再执行父查询(外查询);关联子查询除外
-- 关联子查询原理,每次父查询迭代,都会执行一次子查询
-- 例子:
-- allen 部门号 30
-- 执行子查询 ,查询出30号部门的平均工资
-- select avg(sal) from emp where deptno = 30
-- 最后再通过父查询的where条件来判断
--
-- jones 部门号是20
-- 执行子查询,查询出20号部门的平均工资
-- select avg(sal) from emp where deptno = 20
-- ...
--
-- 结论:
-- 关联子查询中,where条件迭代多少次,子查询就执行多少次,导致效率不高
--
-- 慎用关联子查询!!!!
3. 01标记法
--【第三题提示】:统计每年入职的员工个数
-- 1980 1
-- 1981 2
-- .....select hire_year,count(*)from (select to_char(hiredate,'yyyy') hire_yearfrom emp)group by hire_year-- 1980 1
-- 1981 2
-- .....
-- 思路一可以使用01 标记法(依赖 条件语句)
-- 1980 1981 1982 ....
-- 1980 1 0 0
-- 1981 0 1
-- 1981 0 1
-- 1981
-- 1981
-- 1981
-- 1981
-- 1987
-- 1981
-- 1981
-- 1987
-- 1981
-- 1981
-- 1982
select count(*) total,sum("year_1980") "1980",sum("year_1981") "1981",sum("year_1982") "1982",sum("year_1987") "1987"
from (select hire_year,decode(hire_year,'1980',1,0) "year_1980",decode(hire_year,'1981',1,0) "year_1981",decode(hire_year,'1982',1,0) "year_1982",decode(hire_year,'1987',1,0) "year_1987"from (select to_char(hiredate,'yyyy') hire_yearfrom emp))
2.26 oracle表操作
1.创建表
-- create table 表名
-- (
-- 列名1 类型1,
-- 列名2 类型2,
-- .....
-- )--另一种创建表的方式
-- 创建一张表emp2,数据跟emp表一样create table emp2 as select * from emp
--创建一个员工表t1:员工号id(整数),和姓名name(字符串)create table t1(id number,name varchar2(30))sql 标准:varchar 可变长的字符串oracle 自身拓展了一下:varchar2--char 定长的字符串
--char(30):跟C中char[30]差不多,定长,不管存储什么数据,就固定占用30个字符空间
--varchar(30):最多也只能存储30个字符的空间,但是如果只存储hello,只会占用约5个字符空间
--char查询性能是要高于varchar,明确数据的长度就是固定的,可以直接用char
--例子:身份证号18位 -- 创建一张表emp3,数据跟emp表一样,只有表结构,没有数据create table emp3 as select * from emp;delete from emp3;create table emp4 as select * from emp where 1=2 -- 恒为假,所以数据不会拷贝过去
2.修改表
alter table tableName xxxxx-- 1 往t1表里边添加一列 email varchar(40)alter table t1 add email varchar(40)-- 2 修改t1表email列名为addressalter table t1 rename column email to address-- 3 修改t1表address列的类型为varchar(50)alter table t1 modify address varchar(50)-- 4 删除t1表address列alter table t1 drop column address-- 5 修改t1表名为t2rename t1 to t2
3.清空表
delete from 表名 truncate table t1
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。
4.删除表
drop table 表名oracle提供了回收站机制,删表的时候先移动到回收站purge table 表名从回收站中彻底删除某张表drop table 表名 purge彻底删除表,不移动到回收站oracle 提供一个闪回的技术,能够将表还原到以前的某个时间点flashback table 表名 to before dropshow recyclebinpurge recyclebin 清空回收站
5. 表的约束
1 非空not null2 唯一unique3 检查check4 主键primary key一个表中只能有一个主键(一列或者多列组合而成)主键约束隐含:not null + unique5 外键foreign key一张表的某一列(或多列)参照另一张表的某一列(或多列)在这张表填入的数据必须要在另一张表中能够找到,或者为null涉及的问题:父表的数据删除(更新)了子表数据怎么办1 不允许父表执行删除2 父表删除数据之后,子表对应的数据全部设置为null3 父表删除数据之后,子表对应的数据也跟着删除,级联删除
-- create table 表名
-- (
-- 列名1 类型1 [constraint 约束名 约束类型] constraint 约束名2 约束类型2 ..,
-- 列名2 类型2 [constraint 约束名 约束类型] ... ,
-- ....
-- ) 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 -- references dept (deptno) -- 外键约束(参照dept表中的deptno列)-- ON DELETE SET NULL -- 父表对应的列删除,子表对应的列值设置为空
) --可以查看指定表(如 student)的约束,注意表名必须大写。
select constraint_name, constraint_Type, search_condition
from user_constraints
where table_name='STUDENT'
2.27 视图
视图提供的目的就是为了简化查询视图的优点 1. 简化复杂查询: 原来分组、多表、子查询等可以用一条 select * from xxxview 代替。 视图可以看做是表的复杂的 SQL 一种封装。 2. 限制数据访问: 只看视图的结构和数据是无法清楚视图是怎样得来的。可以限制数据的访问。 例如: 银行项目,所谓的各个“表”都是“视图”,并有可能只是“只读视图”
注意: 1. 视图不能提高性能 2. 不建议通过视图对表进行修改。
create view 视图名称
as
子查询
要注意,创建视图需要权限,需要oracle管理员对scott赋予权限
在centos 上 使用 sqlplus / as sysdba
grant create view to scott
删除视图
drop view 视图名
创一个视图,用来观看10号部门的员工信息create view v_emp_10as select * from emp where deptno = 10create table t_emp_10as select * from emp where deptno = 10视图是不存在数据,只是一个查询语句的结果每次执行 select 去查看视图的时候,都会执行视图的sql语句视图其实也是一条查询sql语句的封装
2.28 序列
创建一张表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')
人工去记住这个idd递增,不靠谱,让计算机自身去记住这个id,每次自增
创建序列:create sequence sequenceName
删除序列:drop sequence sequenceName
currval
当前的序列的值
select myseq.currval from dual
第 1 行出现错误:
ORA-08002: 序列 MYSEQ.CURRVAL 尚未在此会话中定义
注意:获取currval 不能早于第一次获取nextval
nextval
从序列获取下一个值
select myseq.nextval from dual
注意:每次sql执行,nextval只会获取一次值
(一条SQL语句中多次使用nextval,但是取到的是相同的值,因为只获取一次值)
使用序列进行插入数据
insert into t1 values(sequenceName.nextval,‘name-’||sequenceName.nextval)
insert into t1 values(sequenceName.nextval,‘name-’||sequenceName.nextval)
…
2.29 索引
原理,对数据某一列(或者多列)进行排序,将排序好的数据以及对应的行地址存起来,下次查询数据的时候先查询索引,然后再提取数据创建索引 create index 索引名 on 表名(列名)create index 索引名 on 表名(列名1,列名2 ....)
删除索引 drop index 索引名字create index inx_emp_deptno on emp(deptno)索引创建完成之后,不用我们去管,正常做查询,数据库自动判断我们查询条件有没有用到索引,有用到就自动使用
什么情况下用到索引
create index inx_emp_deptno on emp(deptno)
where deptno = 10 – 用到了索引
create index idx2 on emp(deptno,job) 复合索引where job = 'CLERK' -- 没有用到索引where deptno>10 and job = 'xxxx' -- 使用到了索引
2.30 同义词
为hr.employees表创建同义词create synonym 别名 for 某数据库对象create synonym hremp for hr.employees;删除同义词drop synonym 别名
3.mysql
3.0 创建scott表 并插入数据
-- 00_scott_MySQL.sql
-- source /home/lwh/Desktop/study/test/00_scott_MySQL.sqldrop database if exists lwh_scott;
create database lwh_scott character set utf8;use lwh_scott;create table bonus
(ename VARCHAR(10),job VARCHAR(9),sal int,comm int
);create table dept
(deptno int not null,dname VARCHAR(14),loc VARCHAR(13)
);
alter table deptadd constraint PK_DEPT primary key (deptno);create table emp
(empno int not null,ename VARCHAR(10),job VARCHAR(9),mgr int,hiredate DATE,sal int,comm int,deptno int
)
;
alter table empadd constraint PK_EMP primary key (EMPNO);
alter table empadd constraint FK_DEPTNO foreign key (DEPTNO)references dept (DEPTNO);create table salgrade
(grade int,losal int,hisal int
)
;insert into dept (deptno, dname, loc)
values (10, 'ACCOUNTING', 'NEW YORK'),
(20, 'RESEARCH', 'DALLAS'),
(30, 'SALES', 'CHICAGO'),
(40, 'OPERATIONS', 'BOSTON');insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20),
(7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30),
(7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30),
(7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20),
(7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30),
(7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30),
(7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10),
(7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20),
(7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10),
(7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 1500, 0, 30),
(7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20),
(7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30),
(7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20),
(7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);insert into salgrade (grade, losal, hisal)
values (1, 700, 1200),
(2, 1201, 1400),
(3, 1401, 2000),
(4, 2001, 3000),
(5, 3001, 9999);-- mysql> show tables;
-- +---------------------+
-- | Tables_in_lwh_scott |
-- +---------------------+
-- | bonus |
-- | dept |
-- | emp |
-- | salgrade |
-- +---------------------+
-- 4 rows in set (0.00 sec)
--
-- mysql> select *
-- -> from bonus;
-- Empty set (0.00 sec)
--
-- mysql> select * from dept;
-- +--------+------------+----------+
-- | deptno | dname | loc |
-- +--------+------------+----------+
-- | 10 | ACCOUNTING | NEW YORK |
-- | 20 | RESEARCH | DALLAS |
-- | 30 | SALES | CHICAGO |
-- | 40 | OPERATIONS | BOSTON |
-- +--------+------------+----------+
-- 4 rows in set (0.00 sec)
--
-- mysql> select * from emp;
-- +-------+--------+-----------+------+------------+------+------+--------+
-- | empno | ename | job | mgr | hiredate | sal | comm | deptno |
-- +-------+--------+-----------+------+------------+------+------+--------+
-- | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800 | NULL | 20 |
-- | 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600 | 300 | 30 |
-- | 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250 | 500 | 30 |
-- | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975 | NULL | 20 |
-- | 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250 | 1400 | 30 |
-- | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850 | NULL | 30 |
-- | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450 | NULL | 10 |
-- | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000 | NULL | 20 |
-- | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000 | NULL | 10 |
-- | 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500 | 0 | 30 |
-- | 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100 | NULL | 20 |
-- | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950 | NULL | 30 |
-- | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000 | NULL | 20 |
-- | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300 | NULL | 10 |
-- +-------+--------+-----------+------+------------+------+------+--------+
-- 14 rows in set (0.00 sec)
--
-- mysql> select * from salgrade;
-- +-------+-------+-------+
-- | grade | losal | hisal |
-- +-------+-------+-------+
-- | 1 | 700 | 1200 |
-- | 2 | 1201 | 1400 |
-- | 3 | 1401 | 2000 |
-- | 4 | 2001 | 3000 |
-- | 5 | 3001 | 9999 |
-- +-------+-------+-------+
-- 5 rows in set (0.00 sec)
3.1 登录mysql
--直接在shell环境中 使用以下命令mysql -u用户名 -p密码mysql -uroot -proo123--其中root是用户名,该用户跟linux中的root不是同一个用户
--mysql有自己的账号体系,其中的数据库管理员也叫root
oracle 账号体系,一个用户对应一个方案,用户名就是方案名
在mysql中一个用户是可以拥有多个方案show databases|schemas 查看当前用户拥有哪些数据库(方案)use databaseName切换到某个数据库进行操作show tables 查看当前该数据库中有什么表结论:mysql账号体系比oracle要多一层,要操作方案(数据库)Oracle一个用户对应一个方案(数据库 database);该方案下有多张表(table)
MySQL一个用户用多个方案(数据库 database);每个方案下都有多张表(table)
3.2 库操作
--创建数据库d1 并指定默认字符集为UTF8
create database d1 default charset= 'UTF8';
--查看创建数据库的语句
show create database d1;
--删库 !!!危险,请勿操作
drop database 库名
3.3 表操作
- 创建表
-- 创建表
-- t1
-- ( id 整形
-- name 可变字符串30长度
-- )
create table t1
(id int,name varchar(30)
)
edit打开编辑器
-- "edit" 命令可以打开编辑器,默认是使用v,来编辑上一次输入的SQL语句
-- 把MySQL的SQL语句写进去,":wq "保存退出,不要以;结尾
-- 回到主界面,输入 ";" 开始执行SQL语句
- 查看表结构
--desc 表名
-- 查看表结构
- 修改表中的列
-- 添加一列
-- 添加一列email varchar(30)alter table t1 add email varchar(30)--修改列的属性
--修改name(姓名这列) 增加长度到40字符(修改属性)alter table t1 modify name varchar(40)--修改列名,修改列的属性
--修改email 列重命名 到 address ,并且修改类型为 varchar(40)alter table t1 change email address varchar(40)--显示创建该表的sql语句show create table t1;
--删除列
--删除列addressalter table t1 drop column address
- 修改表
--修改表名
--修改表t1表名为T2,注意大小写(MySQL中,表名是大小写敏感的)rename table t1 to T2--删除表T2drop table t2
--注意:mysql中表名等数据库对象名大小写敏感
3.4 操作表中的数据
--首先创建表employee
create table employee
(id int,name varchar(20),sex int,birthday date,salary double,entry_date date,resume text
);--添加数据
insert into employee values(1,'张三',1,'1983-04-27',15000,'2012-06-24','一个大牛');
insert into employee(id,name,sex,birthday,salary,entry_date,resume) values(2,'李四',1,'1984-02-22',10000,'2012-07-24','一个中牛');
insert into employee(id,name,sex,birthday,salary,entry_date,resume) values(3,'王五',0,'1985-08-28',7000,'2012-08-24','一个小虾');-- mysql> select * from employee;
-- +------+--------+------+------------+--------+------------+--------------+
-- | id | name | sex | birthday | salary | entry_date | resume |
-- +------+--------+------+------------+--------+------------+--------------+
-- | 1 | 张三 | 1 | 1983-04-27 | 15000 | 2012-06-24 | 一个大牛 |
-- | 2 | 李四 | 1 | 1984-02-22 | 10000 | 2012-07-24 | 一个中牛 |
-- | 3 | 王五 | 0 | 1985-08-28 | 7000 | 2012-08-24 | 一个小虾 |
-- +------+--------+------+------------+--------+------------+--------------+
-- 3 rows in set (0.00 sec)
--1 将所有员工薪水都增加500元。update employee set salary = salary+500 --2 将王五的员工薪水修改为10000元,resume改为也是一个中牛update employee set salary = 10000 ,resume = '也是一个中牛' where name = '王五'--3 查询员工的月薪以及年薪select name,salary 月薪, salary * 13 年薪from employee--删除一行记录
--4 删除表中姓名为王五的记录delete from employee where name = '王五'--5 删除表中所有记录delete from employee--mysql 中 默认 没有打开事务,所有没法回滚--6 使用truncate删除表中记录truncate table employee
3.5 综合查询
--综合查询:
-- 创建学生表,记录学生的id、姓名、语文、英语、数学课程的成绩create table student(id int,name varchar(20),chinese int,english int,math int);往表里边插入数据insert into student(id,name,chinese,english,math) values(1, '黄真',80,85,90);insert into student(id,name,chinese,english,math) values(2,'归辛树',90,95,95);insert into student(id,name,chinese,english,math) values(3,'李寻欢',80,96,96);insert into student(id,name,chinese,english,math) values(4,'叶开',81,97,85);insert into student(id,name,chinese,english,math) values(5,'袁承志',85,84,90);insert into student(id,name,chinese,english,math) values(6,'何红药',92,85,87);insert into student(id,name,chinese,english,math) values(7,'何铁手',75,81,80);insert into student(id,name,chinese,english,math) values(8,'夏雪宜',77,80,79);insert into student(id,name,chinese,english,math) values(9,'任我行',95,85,85);insert into student(id,name,chinese,english,math) values(10,'岳不群',94,85,84);
--1.查询表中所有学生的信息select * from student;
--2.查询表中所有学生的姓名和对应的英语成绩select name,english from student;
--3.查询所有出现的英语成绩(去掉重复)select distinct english from studentorder by english;
--4.在所有学生英语分数上加10分特长分update student set english = english+10;
--5.统计每个学生的总分(要用别名)select name , (chinese+english+math) as "总分"from student ;
--6.查询姓名为何铁手的学生成绩select * from student where name = "何铁手";
--7.查询英语成绩大于90分的同学select * from studentwhere english > 90;
--8.查询英语分数在 85-95之间的同学select * from student where english between 85 and 95;
--9.查询数学分数为84,90,91的同学select * from student where math in (84,90,91) order by math ;
--10.查询数学分>85,语文分>90的同学select * from studentwhere math>85 and chinese>90order by math,chinese;
--11.对总分排序后输出,然后再按从高到低的顺序输出select name,(chinese+english+math) zongfenfrom studentorder by zongfen desc;
--12.对姓何的学生总成绩倒序输出select name,(chinese+math+english)from studentwhere name like "何%"order by (chinese+math+english) desc;
--13.统计总分大于250的人数有多少?select count(*)from studentwhere (chinese+math+english) > 250
--14.求最高分和最低分select max(zongfen),min(zongfen)from(select (chinese+math+english) as zongfenfrom studentorder by (chinese+math+english) desc)s;
--------------------------以上自主完成--------------------------------------
--15.给学生表增加一列,class_id(班级) int类型alter table student add class_id int--16.将学生id为1-5的修改class_id为1班,将学生id为6-10的修改class_id为2班一个语句修改完成。update student set class_id = ceil(id/5) -- ceil 向上取整 0-1取整到1 1-2取整到2--17.求各个班英语的平均分 select class_id , avg(english)from studentgroup by class_id--18.求各个班的总成绩 select class_id , sum(chinese+english+math)from studentgroup by class_id--19.求总成绩大于1300的班级select class_id , sum(chinese+english+math)from studentgroup by class_idhaving sum(chinese+english+math) > 1300
3.6 数据库的函数
--用sql 求3+5*2表达式的值select 3+5*2;select 3+5*2 from dual;--from dual 语句在mysql中不是必须的
--今天、明天、明年今日
-- 在mysql中,没有sysdate,
-- 在mysql中使用now()函数获取当前的时间
-- 日期数据+1-1 单位是秒,会自动做一个隐式转换,转成数值型select date_add(now(),interval -1 day) 昨天 , now() 今天 , date_add(now(),interval 1 day) 明天--求下一分钟,下一小时(addtime函数实现)select now(),addtime(now(),'00:01:00') 下一分钟,addtime(now(),'01:00:00') 下一小时
--使用字符串拼接,输出'hello'和 'mysql'拼接值select concat('hello','mysql','中国')
-- 不能使用oracle 的 ||--输出'hello中国'字符串长度select length('hello中国')
--将当前日期以'dd-mm-yyyy' 形式转换成字符串输出select date_format(now(),'%d-%m-%Y');select date_format(now(),'%Y-%m-%d');--将字符串'31-01-2017' 以 'dd-mm-yyyy'形式转换回时间类型select str_to_date('31-01-2017','%d-%m-%Y')
3.7 多表查询
--在mysql中创建scott方案(数据库)以及对应表(参照3.0创建scott表)--查询员工号、姓名、部门编号、部门名称select empno,ename,e.deptno,d.dnamefrom emp e, dept dwhere e.deptno = d.deptnoselect empno,ename,e.deptno,d.dnamefrom emp e join dept don e.deptno = d.deptno--显示员工号,姓名,薪水,薪水级别select empno,ename,sal,gradefrom emp e join salgrade son e.sal between s.losal and s.hisal--显示部门编号、部门名称、人数 select d.deptno,d.dname , count(empno)from emp e right join dept don e.deptno = d.deptnogroup by d.deptno,d.dnameselect d.deptno,d.dname , count(empno)from emp e ,dept dwhere d.deptno= e.deptno(+)--mysql不支持这种操作 group by d.deptno,d.dname--显示员工姓名以及主管姓名
-- 自连接select a.ename,a.mgr,b.empno,b.enamefrom emp a left join emp bon a.mgr = b.empnoselect concat(a.ename,'''s manager is ',ifnull(b.ename,'himself'))from emp a left join emp bon a.mgr = b.empno--交叉连接 叉集 即笛卡尔积cross join--内连接 -- inner 可以省略inner joinon--左外连接 -- outer可以省略(保留右边表的数据)left outer joinon--右外连接 -- outer可以省略(保留右边表的数据)right outer joinon--全外连接(保留左边表的数据,也,保留右边表的数据)full outer join on
3.8 Top-N
-- 使用limit解决 Top-N 问题--查询emp表中工资前三名的员工信息select *from emporder by sal desc limit 3--翻页问题:使用limit解决,非常轻松--查询emp表中工资排5-8名的员工信息limit [m,]n -- []括起来,代表可省略
-- m 表示跳过前面多少条数据
-- n 表示返回多少条数据select * from emp order by sal desc limit 4,4;
3.9 表的约束
1、唯一 unique2、非空 not null3、主键(自增) primary key4、外键 foreign key5、没有检查约束 check ,语法上还保留,实际不生效但是新版本,已经生效,起码我现在这个版本是生效的!!!!
[root@lwh test]# mysql --version
mysql Ver 8.0.19 for Linux on x86_64 (MySQL Community Server - GPL)
-- 创建一个学生表:
-- (
-- id 学生的id 数值型 作为主键 自增,
-- name 学生的姓名 字符串型 非空,
-- email 电子邮箱 字符串类型 唯一,
-- sex 性别 字符串类型 只能填 '男' 或 '女',
-- deptno 学生所在部门号 以 dept表的deptno为外键参照
-- )create table student
(id int primary key auto_increment,name varchar(30) not null,email varchar(64) unique,sex varchar(10) check(sex in ('男','女')),deptno int , -- 上面每一行,后跟的是:列级约束‘-- 下面这个是:表级约束constraint fk_student_deptno foreign key(deptno ) references dept(deptno) on delete set null -- 父表中删除了,子表设置为nullon update cascade -- 父表中更改了,子表也跟着改 -- 级联更新
)--列级约束,就是定义每一列的时候直接定义约束的类型--表级约束,就是定义整个表的约束,在所有列都定义完之后,再单独写约束,
--常见于定义:多列的主键、多列外键insert into student(name,email,sex,deptno) values('aaa','aaa@itcast.cn','女',40)
3.10 mysql如何打开事务
autocommit:自动提交 、默认为true 1 执行一个语句,马上提交,相当于没有事务set autocommit=0将自动提交关闭,其实就是打开手动提交,其实就是打开事务
3.11 mysql中的乱码问题
--查看当前会话的环境变量,观察当前会话每个部分使用的字符集
show variables like 'character%';+--------------------------+--------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+--1、最终解决乱码问题的方案:将以上这些字符集调整统一即可--2、终端软件 xshell secure crt 等里面的字符集也要进行一个调整--3、linux shell 环境下的环境变量,也会影响到最终的一个显示
-- locale 去查看这些编码
3.12 mysql 编程的基础
--mysql提供了很多api ,支持不同语言--以下包需要通过一些方式来安装
-- apt-get install libmysqlclient-dev
-- yum install limysqlclient--头文件 mysql.h
--库文件 libmysqlclient.a-- /usr/include/mysql/mysql.h
-- /usr/local/include/fakemysql.h-- /usr/lib64/mysql/libmysqlclient.so
--C语言的API,三种类型--1 初始化:环境初始化,建立连接MYSQL *mysql_init(MYSQL *mysql)
-- 返回值
-- 返回的句柄,句柄不直接使用,而是给其他API来调用
-- 失败:返回NULL mysql_real_connect() --连接到MySQL服务器。MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, //服务器ipconst char *user, //rootconst char *passwd, //root23const char *db, //lwh_scott unsigned int port, //3306const char *unix_socket, //本地套接字unsigned long client_flag //0)
-- 返回值
-- 连接成功,返回MYSQL*连接句柄。返回值与第1个参数的值相同。
-- 连接失败,返回NULL。
--2 业务处理:执行sql , curd的操作------------------------1、执行 增 删 改 查---------------------------
-- -- 执行 增 删 改 查int mysql_query(MYSQL *mysql, const char *query)
-- 返回值:
-- 查询成功:返回0
-- 出现错误:返回非0值
------------------------------------------------------------------ ------------------------2、取得结果集-----------------------------------------
-- -- 结果集MYSQL_RES *mysql_store_result(MYSQL *mysql)
-- 返回值:
-- 成功:返回结果集的指针
-- 失败:返回NULL
------------------------------------------------------------------ --------------1、获得列数 2、获得表头 3、根据列数 for循环输出表头--------- -- 列数:unsigned int mysql_num_fields(MYSQL_RES *result)
-- 返回值:
-- 返回结果集的列数-- 表头MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)
-- 返回值:
-- 返回每一列的字段信息,包括名字
--------------------------------------------------------------------------------从结果集中取出一行数据------------------------------------ 该函数返回结果集中的一行数据-- 连续调用就会连续遍历每一行数据,直到返回NULL MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)-- MYSQL_ROW中存储了 完整的一行数据;结合列数,才完整输出一行数据--结合行数,输出 所有行;解开结果集里边的数据获取每一行每一列的内容
-- 返回值:
-- 成功:结果集中的一行
-- 失败:NULLtypedef char **MYSQL_ROW
-- 返回的一行数据:就是字符串数组
------------------------------------------------------------------
--3 垃圾回收:环境销毁,断开连接-- 使用结果集之后要释放资源void mysql_free_result(MYSQL_RES *result)-- 关闭服务器连接。mysql_close() void mysql_close(MYSQL *mysql)
#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define DB_HOST "127.0.0.1"
#define DB_USER "root"
#define DB_PASSWD "root123"
#define DB_NAME "lwh_scott"
#define DB_PORT 3306int main()
{//1、初始化MYSQL *mysql = mysql_init(NULL);if (mysql == NULL){ //报错fprintf(stderr, "Error in mysql_init()\n");exit(-1);}//2、建立连接if (mysql_real_connect(mysql,DB_HOST,DB_USER,DB_PASSWD,DB_NAME,DB_PORT,NULL,0) == NULL){ //报错fprintf(stderr, "Error in mysql_real_connect():%s\n", mysql_error(mysql));exit(-1);}else{ //执行成功printf("mysql_real_connect() -- 执行成功\n");}//3.1.1、执行sql: 插入一条记录const char sql_insert[] = "insert into dept(deptno,dname,loc) values(40,'OPERATIONS','BOSTON')";if (0 == mysql_query(mysql, sql_insert)){ //执行成功printf("Execute succees: insert 执行成功\n");}else{ //执行失败fprintf(stderr, "Error in mysql_query() insert :%s\n", mysql_error(mysql));exit(-1);} //3.1.2、执行sql: 删除一条记录const char sql_delete[] = "delete from dept where deptno = 40";if (0 == mysql_query(mysql, sql_delete)){ //执行成功printf("Execute succees: delete 执行成功\n");}else{ //执行失败fprintf(stderr, "Error in mysql_query() delete :%s\n", mysql_error(mysql));exit(-1);}//4、垃圾回收mysql_close(mysql);return 0;
}
3.13 mysql C-API-Code-Demo1
开发需求:实现一个类似于 mysql的客户端 ,能够读取用户的输入的数据,拿去给服务器执行,获取结果集后打印输出开发计划:1 实现连接2 实现插入/删除/更新3 实现查询处理返回结果集,打印4 实现跟用户的交互 使用死循环一直读取标注你输入的数据,每当有数据进来就执行SQL语句终端提示符:MySQL> 退出条件:1 ctrl + d -> EOF read 会返回 ,而且 返回值 是 02 quit / exit
#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>#define DB_HOST "127.0.0.1"
#define DB_USER "root"
#define DB_PASSWD "root123"
#define DB_NAME "lwh_scott"
#define DB_PORT 3306// 1、初始化 连接mysql 设置当前连接的字符集
void mysql_init_connect_setCharacter(MYSQL *mysql)
{// 1.1、初始化if ((mysql_init(mysql)) == NULL){fprintf(stderr, "Error in mysql_init()\n");exit(-1);}// 1.2、建立连接if (mysql_real_connect(mysql,DB_HOST,DB_USER,DB_PASSWD,DB_NAME,DB_PORT,NULL,0) == NULL){fprintf(stderr, "Error in mysql_real_connect():%s\n", mysql_error(mysql));exit(-1);}else{printf("mysql_real_connect() -- 执行成功\n");}// 1.3、设置UTF8编码:因为有些时候显示乱码,所以需要设置if (mysql_set_character_set(mysql, "utf8") != 0){fprintf(stderr, "Error in mysql_set_character_set():%s\n", mysql_error(mysql));//exit(-1);}else{printf("mysql_set_character_set() utf8 -- 执行成功\n");}
}// 3、打印结果集
void printResultSet(MYSQL_RES *res)
{// 获得列数unsigned int num_fields = mysql_num_fields(res);//获得表头:各列的名字MYSQL_FIELD *fields = mysql_fetch_field(res);//输出表头:各列的名字unsigned int i = 0;for (i = 0; i < num_fields; ++i){printf("%s\t", fields[i].name);}printf("\n-----------------------------------------------------------------\n");//输出表头下面的:各行数据MYSQL_ROW row;while ((row = mysql_fetch_row(res))) // != NULL{for (i = 0; i < num_fields; ++i){printf("%s\t", row[i]);}printf("\n");}
}// 2、获取用户输入并执行sql
// 调用 3、打印结果集
void getUserInputAndExecute(MYSQL *mysql, char sql[], unsigned int NUM)
{while (1){memset(sql, 0, NUM);// 2.1打印提示符write(STDOUT_FILENO, "MySQL> ", 7);// 2.2 获得用户输入int ret = read(STDIN_FILENO, sql, NUM);// read读取失败if (ret < 0){perror("read");break;}// 按了ctrl+d ,接受了EOF,read就会返回0else if (ret == 0){printf("Byebye!\n");break;}// 如果输入的是quit 或者 exit 直接退出if ((strcmp(sql, "quit\n") == 0) || (strcmp(sql, "exit\n") == 0)){printf("Byebye!\n");break;}// 2.3 执行sql语句,获得结果集if (mysql_query(mysql, sql) == 0){//printf("Execute mysql_query() succeed\n");MYSQL_RES *res = mysql_store_result(mysql);if (res != NULL){// 3、打印结果集printResultSet(res);//结果集中有多少行数据printf("%lld rows in set \n", mysql_affected_rows(mysql));// 释放结果集mysql_free_result(res);}else{//有多少行数据被affectedprintf("%lld row affected \n", mysql_affected_rows(mysql));}}else{//执行失败fprintf(stderr, "Error in mysql_query:%s\n", mysql_error(mysql));}}
}int main()
{MYSQL mysql;char sql[1024] = {0};// 1、初始化 连接mysql 设置当前连接的字符集memset(&mysql, 0, sizeof(mysql));mysql_init_connect_setCharacter(&mysql);// 2、获取用户输入并执行sql// 调用 3、打印结果集getUserInputAndExecute(&mysql, sql, sizeof(sql));//4、垃圾回收mysql_close(&mysql);return 0;
}
[root@lwh test]# ./execute
mysql_real_connect() -- 执行成功
mysql_set_character_set() utf8 -- 执行成功
MySQL> select * from employee;
id name sex birthday salary entry_date resume
-----------------------------------------------------------------
1 张三 1 1983-04-27 17000 2012-06-24 一个大牛
2 李四 1 1984-02-22 12000 2012-07-24 一个中牛
3 王五 0 1985-08-28 10000 2012-08-24 也是一个中牛
MySQL>
改进版代码如下:使得输出格式与MySQL标准格式一致(等宽、+、- )
3.14mysql C-API-Code-Demo1改进版
#include <mysql.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>#define _HOST_ "127.0.0.1"
#define _PORT_ 3306
#define _USER_ "root"
#define _PASSWD_ "root123"
#define _DB_ ""#define MAX(a, b) ((a) > (b) ? (a) : (b))
MYSQL mysql;//1 每次等待用户输入
//2 将用户输入进行查询,并将结果显示出来
//3 如果用户输入的是exit或者quit,就退出void displayResultSet(MYSQL_RES *result)
{//1 计算每一列的最大宽度// 该列每行数据(包括表头)长度作比较,取最大值// 这时候就要使用一个数组记录最大长度,同时因为要遍历每一行,所以// 也选用哦一个额外的数组来保存每一行每一列的数据免得重复遍历//2 输出表格,列与列之间用|分隔,每一格数据补空格使其和最长值相等//3 竖线与横线交叉的位置用+表示//格式样例/*+------+----------+--------+|deptno|dname |loc |+------+----------+--------+|10 |ACCOUNTING|NEW YORK||20 |RESEARCH |DALLAS ||30 |SALES |CHICAGO ||40 |OPERATIONS|BOSTON |+------+----------+--------+*/assert(result);//列坐标int colIndex = 0;//行坐标int rowIndex = 0;//获取列数const unsigned int colCount = mysql_field_count(&mysql);//获取行数const unsigned int rowCount = mysql_num_rows(result);int i;//计算每列的最大长度,并用动态数组记录好int *colMaxLength = (int *)malloc(sizeof(int) * colCount);//用一个动态数组记录结果集的每一个字符串char **resultStrArray = (char **)malloc(sizeof(char *) * colCount * rowCount);assert(colMaxLength);assert(resultStrArray);memset(colMaxLength, 0, sizeof(int) * colCount);memset(resultStrArray, 0, sizeof(char *) * colCount * rowCount);//遍历结果集每一行每一列,记录每个字符串,同时记住每列最长长度MYSQL_ROW row = NULL;for (rowIndex = 0; (row = mysql_fetch_row(result)); ++rowIndex){unsigned long *lengths = mysql_fetch_lengths(result);for (colIndex = 0; colIndex < colCount; ++colIndex){colMaxLength[colIndex] = MAX(colMaxLength[colIndex], lengths[colIndex]);resultStrArray[rowIndex * colCount + colIndex] = row[colIndex];}}//获取列信息,用来计算表头每列的长度MYSQL_FIELD *fields = mysql_fetch_fields(result);for (colIndex = 0; colIndex < colCount; ++colIndex){colMaxLength[colIndex] = MAX(strlen(fields[colIndex].name), colMaxLength[colIndex]);}//画横线,横线和竖线交叉部分用+号for (colIndex = 0; colIndex < colCount; ++colIndex){printf("+");for (i = 0; i < colMaxLength[colIndex]; ++i){printf("-");}}printf("+\n");//显示表头for (colIndex = 0; colIndex < colCount; ++colIndex){printf("|");int colLength = colMaxLength[colIndex];printf("%s", fields[colIndex].name);for (i = 0; i < colLength - strlen(fields[colIndex].name); ++i){printf(" ");}//printf("%s\t" ,row[i]);}printf("|\n");//划横线for (colIndex = 0; colIndex < colCount; ++colIndex){printf("+");for (i = 0; i < colMaxLength[colIndex]; ++i){printf("-");}}printf("+\n");//显示结果集数据for (rowIndex = 0; rowIndex < rowCount; ++rowIndex){for (colIndex = 0; colIndex < colCount; ++colIndex){printf("|");int colLength = colMaxLength[colIndex];int index = rowIndex * colCount + colIndex;const char *str = resultStrArray[index] ? resultStrArray[index] : "";int padding = colLength - strlen(str);printf("%s", str);//每一个格子的数据都要用空格补全,使其长度刚好登录该列最长长度,达到对齐效果for (i = 0; i < padding; ++i){printf(" ");}}printf("|\n");}//画最后一行横线for (colIndex = 0; colIndex < colCount; ++colIndex){printf("+");for (i = 0; i < colMaxLength[colIndex]; ++i){printf("-");}}printf("+\n");//释放动态数组free(colMaxLength);free(resultStrArray);
}void displayAffactRows()
{my_ulonglong rowCount = mysql_affected_rows(&mysql);printf("%lld rows affected! \n", rowCount);
}int main()
{//初始化Mysqlif (!mysql_init(&mysql)){//如果返回值是NULL,那么初始化失败printf("mysql init error\n");exit(1);}//建立连接if (!mysql_real_connect(&mysql,_HOST_,_USER_,_PASSWD_,_DB_,_PORT_,NULL,0)){//如果连接失败,就打印printf("Mysql connect error\n");exit(1);}//修改字符集为UTF8if (mysql_set_character_set(&mysql, "UTF8")){printf("Mysql set character set error\n");exit(1);}printf("Welcome to MySQL\n");char sql[1024]={0};while (1){memset(sql, 0, sizeof(sql));//输出提示write(STDOUT_FILENO, "MySQL> ", 7);//等待用户输入int ret = read(STDIN_FILENO, sql, sizeof(sql));//判断用户是否要退出if (ret == 0 || strcmp(sql, "exit\n") == 0 || strcmp(sql, "quit\n") == 0){//quit the clientprintf("\n");break;}if (mysql_query(&mysql, sql)){printf("Query error: %s \n", mysql_error(&mysql));continue;}//Get result setMYSQL_RES *res = mysql_store_result(&mysql);if (!res){printf("Result is empty\n");//no result set , display affact rowsdisplayAffactRows();}else{displayResultSet(res);mysql_free_result(res);displayAffactRows();}}//关闭连接mysql_close(&mysql);return 0;
}
3.14 额外的API补充
额外的API补充my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)打开或者关闭 自动提交 ,关闭自动提交就是为了开启事务mode 1 启用mode 0 禁用返回值:成功:0失败:非0值mysql_commit()mysql_rollback()
3.15 预处理语句
--防止sql注入网页:用户名:______ itcast' or '1'='1 密码:________ select xxxfrom userwhere name = 'xxxxx' and password = 'xxxxx'防御措施:1、严格判断用户输入的数据,遇到特殊的符号,就要转义处理2、对数据库的操作,使用预处理API预处理语句使用方式:1 先创建预处理语句2 先扔给服务器去解析这个语句3 将该填的数据传递给服务器,让服务器去执行
3.16mysql C-API-Code-Demo3
// prepare
// 使用 MySQL的预处理语句 编写代码
// 对MySQL数据库的操作,使用预处理API// 预处理:先解析好你的SQL语句,然后下次客户端直接扔每个字段的值过来,就带入进来
// 优点:
// 对于多次使用的SQL语句(比如插入大量数据时),不用频繁的解析SQL语句(节省了时间);
// 防止SQL注入// 预处理语句使用方式:
// 1 先创建预处理语句
// 2 先扔给服务器去解析这个语句
// 3 将该填的数据传递给服务器,让服务器去执行#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STRING_SIZE 50
//删除数据表
#define DROP_SAMPLE_TABLE "DROP TABLE IF EXISTS test_table"
//创建数据表
#define CREATE_SAMPLE_TABLE "CREATE TABLE test_table(\col1 INT,\col2 VARCHAR(40),\col3 SMALLINT,\col4 TIMESTAMP)"
//插入数据的SQL语句,以?表示待填入的数据
#define INSERT_SAMPLE "INSERT INTO test_table(col1,col2,col3) VALUES(?,?,?)"#define _HOST_ "127.0.0.1"
#define _PORT_ 3306
#define _USER_ "root"
#define _PASSWD_ "root123"
#define _DB_ "lwh_scott"MYSQL mysql_instance;
int main(int argc, char **argv)
{MYSQL_STMT *stmt;MYSQL_BIND bind[3];my_ulonglong affected_rows;int param_count;short small_data;int int_data;char str_data[STRING_SIZE];unsigned long str_length;bool is_null;//初始化MysqlMYSQL *mysql = &mysql_instance;if (!mysql_init(mysql)){//如果返回值是NULL,那么初始化失败printf("mysql init error\n");exit(1);}//建立连接if (!mysql_real_connect(mysql,_HOST_,_USER_,_PASSWD_,_DB_,_PORT_,NULL,0)){//如果连接失败,就打印printf("Mysql connect error\n");exit(1);}//修改字符集if (mysql_set_character_set(mysql, "UTF8")){printf("Mysql set character set error\n");exit(1);}//如果表存在删除表if (mysql_query(mysql, DROP_SAMPLE_TABLE)){fprintf(stderr, " DROP TABLE failed\n");fprintf(stderr, " %s\n", mysql_error(mysql));exit(0);}//重新创建表if (mysql_query(mysql, CREATE_SAMPLE_TABLE)){fprintf(stderr, " CREATE TABLE failed\n");fprintf(stderr, " %s\n", mysql_error(mysql));exit(0);}/* Prepare an INSERT query with 3 parameters *//* (the TIMESTAMP column is not named; the server *//* sets it to the current date and time) *///初始化一个准备语句stmt = mysql_stmt_init(mysql);if (!stmt){fprintf(stderr, " mysql_stmt_init(), out of memory\n");exit(0);}if (mysql_stmt_prepare(stmt, INSERT_SAMPLE, strlen(INSERT_SAMPLE))){fprintf(stderr, " mysql_stmt_prepare(), INSERT failed\n");fprintf(stderr, " %s\n", mysql_stmt_error(stmt));exit(0);}fprintf(stdout, " prepare, INSERT successful\n");/* Get the parameter count from the statement */param_count = mysql_stmt_param_count(stmt);fprintf(stdout, " total parameters in INSERT: %d\n", param_count);if (param_count != 3) /* validate parameter count */{fprintf(stderr, " invalid parameter count returned by MySQL\n");exit(0);}/* Bind the data for all 3 parameters */memset(bind, 0, sizeof(bind));/* INTEGER PARAM *//* This is a number type, so there is no need to specify buffer_length */bind[0].buffer_type = MYSQL_TYPE_LONG;bind[0].buffer = (char *)&int_data;bind[0].is_null = 0;bind[0].length = 0;/* STRING PARAM */bind[1].buffer_type = MYSQL_TYPE_STRING;bind[1].buffer = (char *)str_data;bind[1].buffer_length = STRING_SIZE;bind[1].is_null = 0;bind[1].length = &str_length;/* SMALLINT PARAM */bind[2].buffer_type = MYSQL_TYPE_SHORT;bind[2].buffer = (char *)&small_data;bind[2].is_null = &is_null;bind[2].length = 0;/* Bind the buffers */if (mysql_stmt_bind_param(stmt, bind)){fprintf(stderr, " mysql_stmt_bind_param() failed\n");fprintf(stderr, " %s\n", mysql_stmt_error(stmt));exit(0);}//第一次插入数据/* Specify the data values for the first row */int_data = 10; /* integer */strncpy(str_data, "MySQL", STRING_SIZE); /* string */str_length = strlen(str_data);/* INSERT SMALLINT data as NULL */is_null = 1;/* Execute the INSERT statement - 1*/if (mysql_stmt_execute(stmt)){fprintf(stderr, " mysql_stmt_execute(), 1 failed\n");fprintf(stderr, " %s\n", mysql_stmt_error(stmt));exit(0);}/* Get the total number of affected rows */affected_rows = mysql_stmt_affected_rows(stmt);fprintf(stdout, " total affected rows(insert 1): %lu\n",(unsigned long)affected_rows);//判断数据是否添加成功,只需要判断影响行数是不是1if (affected_rows != 1) /* validate affected rows */{fprintf(stderr, " invalid affected rows by MySQL\n");exit(0);}//第二次插入数据/* Specify data values for second row, then re-execute the statement */int_data = 1000;strncpy(str_data, "The most popular Open Source database", STRING_SIZE);str_length = strlen(str_data);small_data = 1000; /* smallint */is_null = 0; /* reset *//* Execute the INSERT statement - 2*/if (mysql_stmt_execute(stmt)){fprintf(stderr, " mysql_stmt_execute, 2 failed\n");fprintf(stderr, " %s\n", mysql_stmt_error(stmt));exit(0);}/* Get the total rows affected */affected_rows = mysql_stmt_affected_rows(stmt);fprintf(stdout, " total affected rows(insert 2): %lu\n",(unsigned long)affected_rows);if (affected_rows != 1) /* validate affected rows */{fprintf(stderr, " invalid affected rows by MySQL\n");exit(0);}/* Close the statement */if (mysql_stmt_close(stmt)){fprintf(stderr, " failed while closing the statement\n");fprintf(stderr, " %s\n", mysql_stmt_error(stmt));exit(0);}//关闭连接mysql_close(mysql);return 0;
}
00_Oracle mysql学习笔记整理相关推荐
- 【mysql学习笔记整理】
/*mysql学习笔记整理*/ /*常用的数据库操作对象*/ #库的操作 #创建 #数据库的创建 USE mysql; CREATE DATABASE db_x; #删除 #删除数据库 DROP DA ...
- MySQL学习笔记整理(上部)
文章目录 前言 登录命令 DDL数据定义语言 一.操作库 二.操作表 创建表 字符编码问题 查看表结构 数据类型 数值类型 日期和时间类型 字符串类型 表完整性约束 完整性约束的分类 案例演示 修改表 ...
- mysql学习笔记整理——my.ini配置文件
前言 数据库的本质还是将数据以文件的形式存储在磁盘上,不过通过数据库服务进行管理,mysql就是这样的一个工具,言归正传,前面只是对我以前一直以来的疑惑进行了复述. my.ini配置文件可以对数据库一 ...
- MySQL学习笔记整理
一.认识数据库 数据库的好处 1.可以持久化数据到本地 2.结构化查询 数据库存储数据的特点 1.数据存放到表中,然后表再存放到库中 2.一个库中可以有多张表,每张表具有唯一的表名来标识自己 3.表中 ...
- Kafka入门篇学习笔记整理
Kafka入门篇学习笔记整理 Kafka是什么 Kafka的特性 应用场景 Kafka的安装 单机版部署 集群部署环境准备 Kafka 2.x集群部署 Kafka 3.x集群部署 监听器和内外网络 K ...
- MySQL学习笔记-基础篇1
MySQL 学习笔记–基础篇1 目录 MySQL 学习笔记--基础篇1 1. 数据库概述与MySQL安装 1.1 数据库概述 1.1.1 为什么要使用数据库 1.2 数据库与数据库管理系统 1.2.1 ...
- MySQL学习笔记-基础篇2
MySQL学习笔记-基础篇2 目录 MySQL学习笔记-基础篇2 8.子查询 8.1 需求分析与问题解决 8.1.1 实际问题 8.1.2 子查询的基本使用 8.1.3 子查询的分类 8.2 单行子查 ...
- MySQL学习笔记_上(select查询)
上次整理了一些练习发到博客上了,也说要发基础的,整理了一下午才算是把查询那块的勉强整理完,下次再整理其他的,另外还在写设计模式和数据结构的草稿,写的差不多会慢慢发的,这两项算是副线发展,主线还是按 ...
- Deep Learning(深度学习)学习笔记整理系列之(五)
Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...
最新文章
- 全球所有货币币种汇总
- CF912D Fishes 期望
- Unix编程艺术心得
- SQL旁注精华珍藏版代码
- hibernate框架学习之使用SQLQuery查询数据
- java开发技术有什么意义,零基础学Java开发技术有哪些优势和好处?
- Java项目权威排名:Nacos未上版,gradle排名第二,Maven排名28
- 程序的静态链接,动态链接和装载
- 架构 什么是CDN加速?为什么要用CDN
- 电源大师课笔记 1.3
- html mht word,mht格式怎么转换成word
- 在线报刊html代码,数字报纸HTML版本
- 手机上最好用的五笔输入法_什么手机输入法最实用?目前最受欢迎的3款盘点,你正在用哪款呢...
- magedu第一天学习(计算机基础部分)
- facebook 分享页面_如何建立Facebook页面
- 怎么画因果图?因果图绘图步骤详解
- 车展背后|车规级芯片知多少?
- OSChina 周二乱弹 ——宅女喵 租男友 包吃住 100一天
- redis 压缩存储 json
- 下载安装Xshell和Xftp的个人免费版
热门文章
- PGSQL中distinct和distinct on的用法与区别
- Redhat5_Raid信息监控与查询_IBM(MegaCli)+HP(hpacucli)+Adaptec(arcconf)
- java的parseInt用法
- uevent 使用示例
- cookie详解(含vue-cookie)
- React入门(3)-- React的错误边界(Error Boundaries)
- C++开发工具,C++的IDE推荐
- cf 923C Perfect Security
- mysql查询数据库心得_Mysql数据库学习心得
- 【Vue】Vue 的 Props 如何初始化