目录

  • 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学习笔记整理相关推荐

  1. 【mysql学习笔记整理】

    /*mysql学习笔记整理*/ /*常用的数据库操作对象*/ #库的操作 #创建 #数据库的创建 USE mysql; CREATE DATABASE db_x; #删除 #删除数据库 DROP DA ...

  2. MySQL学习笔记整理(上部)

    文章目录 前言 登录命令 DDL数据定义语言 一.操作库 二.操作表 创建表 字符编码问题 查看表结构 数据类型 数值类型 日期和时间类型 字符串类型 表完整性约束 完整性约束的分类 案例演示 修改表 ...

  3. mysql学习笔记整理——my.ini配置文件

    前言 数据库的本质还是将数据以文件的形式存储在磁盘上,不过通过数据库服务进行管理,mysql就是这样的一个工具,言归正传,前面只是对我以前一直以来的疑惑进行了复述. my.ini配置文件可以对数据库一 ...

  4. MySQL学习笔记整理

    一.认识数据库 数据库的好处 1.可以持久化数据到本地 2.结构化查询 数据库存储数据的特点 1.数据存放到表中,然后表再存放到库中 2.一个库中可以有多张表,每张表具有唯一的表名来标识自己 3.表中 ...

  5. Kafka入门篇学习笔记整理

    Kafka入门篇学习笔记整理 Kafka是什么 Kafka的特性 应用场景 Kafka的安装 单机版部署 集群部署环境准备 Kafka 2.x集群部署 Kafka 3.x集群部署 监听器和内外网络 K ...

  6. MySQL学习笔记-基础篇1

    MySQL 学习笔记–基础篇1 目录 MySQL 学习笔记--基础篇1 1. 数据库概述与MySQL安装 1.1 数据库概述 1.1.1 为什么要使用数据库 1.2 数据库与数据库管理系统 1.2.1 ...

  7. MySQL学习笔记-基础篇2

    MySQL学习笔记-基础篇2 目录 MySQL学习笔记-基础篇2 8.子查询 8.1 需求分析与问题解决 8.1.1 实际问题 8.1.2 子查询的基本使用 8.1.3 子查询的分类 8.2 单行子查 ...

  8. MySQL学习笔记_上(select查询)

      上次整理了一些练习发到博客上了,也说要发基础的,整理了一下午才算是把查询那块的勉强整理完,下次再整理其他的,另外还在写设计模式和数据结构的草稿,写的差不多会慢慢发的,这两项算是副线发展,主线还是按 ...

  9. Deep Learning(深度学习)学习笔记整理系列之(五)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

最新文章

  1. 全球所有货币币种汇总
  2. CF912D Fishes 期望
  3. Unix编程艺术心得
  4. SQL旁注精华珍藏版代码
  5. hibernate框架学习之使用SQLQuery查询数据
  6. java开发技术有什么意义,零基础学Java开发技术有哪些优势和好处?
  7. Java项目权威排名:Nacos未上版,gradle排名第二,Maven排名28
  8. 程序的静态链接,动态链接和装载
  9. 架构 什么是CDN加速?为什么要用CDN
  10. 电源大师课笔记 1.3
  11. html mht word,mht格式怎么转换成word
  12. 在线报刊html代码,数字报纸HTML版本
  13. 手机上最好用的五笔输入法_什么手机输入法最实用?目前最受欢迎的3款盘点,你正在用哪款呢...
  14. magedu第一天学习(计算机基础部分)
  15. facebook 分享页面_如何建立Facebook页面
  16. 怎么画因果图?因果图绘图步骤详解
  17. 车展背后|车规级芯片知多少?
  18. OSChina 周二乱弹 ——宅女喵 租男友 包吃住 100一天
  19. redis 压缩存储 json
  20. 下载安装Xshell和Xftp的个人免费版

热门文章

  1. PGSQL中distinct和distinct on的用法与区别
  2. Redhat5_Raid信息监控与查询_IBM(MegaCli)+HP(hpacucli)+Adaptec(arcconf)
  3. java的parseInt用法
  4. uevent 使用示例
  5. cookie详解(含vue-cookie)
  6. React入门(3)-- React的错误边界(Error Boundaries)
  7. C++开发工具,C++的IDE推荐
  8. cf 923C Perfect Security
  9. mysql查询数据库心得_Mysql数据库学习心得
  10. 【Vue】Vue 的 Props 如何初始化