zoukankan      html  css  js  c++  java
  • 【Oracle】基础知识查漏补缺

    前言

    该文章内容不是学习oracle的基础知识,而是在大致了解oracle的基础知识上看我自己还有什么不知道或者不明白的地方,有兴趣的小伙伴可以在网上找找李兴华的oracle培训资料。

    SQL简介

    SQL 功能强大,概括起来,它可以分成以下几组:

    · DML(Data Manipulation Language,数据操作语言) —— 指的是实现数据库的查询与更新操作,其中针对于 数据库的查询有部分人员会将其称为 DQL,因为最麻烦的部分就是查询。

    · DDL(Data Definition Language,数据定义语言) —— 定义数据库对象,例如:在一些系统设计人员的工作里 面需要进行数据表的定义。

    · DCL(Data Control Language,数据控制语言) —— 控制用户的操作权限,一般由 DBA 负责。

     

    简单查询

    对于重复的数据是有一个基本的原则:只有在所有列的数据都重复的情况下才叫 做重复数据。

    SELECT DISTINCT ename,job FROM emp 
    

    “||”的连接符,可以进行数据的连接。

    SELECT '编号:' || empno || '、姓名:' || ename || '、工资:' || sal info FROM emp 

     

    IN查询

    对于 IN 操作而言是针对于基数的判断,如果说此时在使用 NOT IN 的时候基数里面包含了 NULL,那么所有满足

    的数据都不会被显示。
    范例:观察程序,在 IN 之中使用 NULL —— 现在没有任何的影响

    SELECT * FROM emp WHERE empno IN (7369,7566,7839,NULL) ;
    

    范例:观察程序,在 NOT IN 之中使用 NULL

    SELECT * FROM emp WHERE empno NOT IN (7369,7566,7839,NULL) ;
    

    不满足的原因是数据库自身的保护机制,避免大数据所带来的问题

    模糊查询

    字段 LIKE 匹配关键字,而在进行关键字匹配的时候有两个符号标记:

    |- “_”:匹配任意一个字符;

    |- “%”:匹配 0 个、1 个或多个任意字符。

    范例:查询所有姓名第二个字母以 A 开头的所有雇员

    SELECT * FROM emp WHERE ename LIKE '_A%' ;
    

     

    SQL执行顺序

    自定义输入数据

    要查询的数据表名称由用户输入
    SELECT * FROM &tablename 
    
    利用替代变量输入雇员姓名
    SELECT * FROM emp WHERE ename=UPPER('&name') ;
    

      

    字符串函数

    • UPPER()、LOWER()
    • 首字母大写,其余字母小写:字符串 initcap(字符串 | 列)

      将每一位雇员姓名的首字母大写,其余字母小写
      SELECT INITCAP(ename) FROM emp ;
    • 取得字符串长度:数字 LENGTH(字符串 | 列)
    • 替换指定字符串的内容:字符串 REPLACE(字符串 | 列,要替换的内容,新的内容)
    替换数据列 
    SELECT ename,REPLACE(ename,'A','_') FROM emp ;
    • 字符串截取操作:
      • 由指定位置截取到结尾:字符串 SUBSTR(字符串 | 数据列,截取开始索引);
      • 指定截取的开始和结束位置:字符串 SUBSTR(字符串 | 数据列,截取开始索引,截取结束索引);
    SELECT SUBSTR('hello world',0,5) FROM dual ;
    SELECT SUBSTR('hello world',1,5) FROM dual ;
    以上俩个结果一致,实际上在 Oracle 之中,字符串的索引下标是从 1 开始的(程序是从 0 开始的),但是为了考虑到程序人员的使用习惯, 所以即使设置了 0,那么也表示从 1 开始,这一点会由 Oracle 自己进行处理。
    • 去掉左右空格函数:字符串 TRIM(字符串 | 列)

      截取每一位雇员姓名的后三位字母
      SELECT ename,SUBSTR(ename,LENGTH(ename)-2) FROM emp ;
      SELECT ename,SUBSTR(ename,-3) FROM emp ;

    数字函数

    • 四舍五入函数:数字 ROUND(数字 | 列 [,保留小数位])
    SELECT ROUND(9615.7652) ,               ➡️9616
    ROUND(9615.7652,2),                         ➡️9615.77
    ROUND(9615.7652,-2),                        ➡️9600
    ROUND(-15.5)                                     ➡️-16
    FROM dual ;
    • 截取小数函数:数字 TRUNC(数字 | 列 [,保留小数位])
    SELECT ROUND(9615.7652) ,               ➡️9615
    ROUND(9615.7652,2),                         ➡️9615.76
    ROUND(9615.7652,-2),                        ➡️9600
    ROUND(-15.5)                                     ➡️-15
    FROM dual ;
    • 求模:数字 MOD(数字1| 列1,数字2| 列2)
    求余数
    SELECT MOD(10,3) FROM dual ;
    

      

    日期函数

    取得当前的系统日期时间,为此在 Oracle 里面提供有两个伪列(是不存在表中的列,但是却可以直接使用的列):SYSDATE、SYSTIMESTAMP

    • 计算两个日期之间所经历的月数:数字 MONTHS_BETWEEN(日期 1 | 列 1,日期 2 | 列 2)
    计算每一位雇员到今天为止雇佣的年数
    SELECT ename,MONTHS_BETWEEN(SYSDATE,hiredate) , TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12)
    FROM emp ;
    • 加上指定月之后的日期:日期 ADD_MONTHS(日期 | 列 ,月数)
    要求计算出每一位雇员到今天为止雇佣的年限(理解)
    A、 例如:今天是 2014 年 08 月 12 日,CLARK 的雇佣日期是:1981 年 06 月 09 日 
    B、 到今天 CLARK 已经在公司服务了:33 年、02 月、03 天
    SELECT ename,hiredate,
    TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)/12) year , TRUNC(MOD(MONTHS_BETWEEN(SYSDATE,hiredate),12)) months ,
    TRUNC(SYSDATE - ADD_MONTHS(hiredate,MONTHS_BETWEEN(SYSDATE,hiredate))) day
    FROM emp ;
    • 求出指定的下一个一周时间数的日期:日期 NEXT_DAY(日期 | 列,一周时间数)
    计算下一个星期二
    SELECT NEXT_DAY(SYSDATE,'星期二') FROM dual ;
    • 求出指定日期所在月的最后一天日期:日期 LAST_DAY(日期 | 列)
    查询出在每个雇员雇佣所在月倒数第二天雇佣的全部雇员信息
    SELECT ename,hiredate,LAST_DAY(hiredate)-2 
    FROM emp
    WHERE LAST_DAY(hiredate)-2=hiredate ;
    

      

    转换函数

    • 转字符串数据:字符串 TO_CHAR(数字 | 日期 | 列,转换格式)
    拆分日期数据
    SELECT TO_CHAR(SYSDATE,'yyyy') year , 
    TO_CHAR(SYSDATE,'mm') months , 
    TO_CHAR(SYSDATE,'dd') day
    FROM dual ;
    • 转日期数据:日期 TO_DATE(字符串,转换格式)
    • 转数字类型:数字 TO_NUMBER(字符串,转换格式)

    通用函数

    • 处理 null 数据:数字 NVL(列 | 数据,默认值)
    在数据库之中,null 与任何的数据进行数 学计算其结果都是 null,那么如果遇到了 null 应该按照数字 0 来处理,所以就可以使用 NVL()函数。
    SELECT ename,sal,comm,(sal+NVL(comm,0))*12 FROM emp ;
    • 多数据判断:数据 DECODE(字段 | 数据,判断数据 1,显示数据 1,判断数据 2,显示数据 2,... [默认显示])
    将所有雇员的职位数据变为中文
    SELECT ename,job , DECODE(job,'CLERK','办事员','SALESMAN','销售','MANAGER','经理','ANALYST','分析员','PRESIDENT','总裁','未
    处理')
    

      

    多表查询 

    将 emp 表(14行数据)和 dept(4行数据) 表实现多表查询
    SELECT * FROM emp ,dept ;
    

    执行结果会发现,返回结果有56条数据,为什么呢?出现这样的结果主要是由于数据库的数学公式所导致的,这是两个集合的“积”,而这种积在数据库之中被称为“笛卡尔积”。

    如何去消除掉 这样的“笛卡尔积”呢?唯一的方案就是使用关联字段。

    不推荐使用的关联方式:

    SELECT e.empno,e.ename,e.job,e.sal,d.dname,d.loc
    FROM emp e , dept d
    WHERE e.deptno=d.deptno ;
    

    虽然消除掉了显示的笛卡尔积,但是整个运算执行过程非常的缓慢。

    对于多表查询来讲其有两种表的连接方式:

    • 内连接:也被称为等值连接,上面不推荐的查询属于内连接;
    • 外连接:左外连接、右外连接、全外连接
      • 左外连接:字段 = 字段(+),“(+)”在等号右边表示左外连接
    SELECT *
    FROM emp e,dept d
    WHERE e.deptno=d.deptno(+) ;
      • 右外连接:字段(+) = 字段,“(+)”在等号左边表示右外连接
    SELECT *
    FROM emp e,dept d
    WHERE e.deptno(+)=d.deptno ;
    

      

    SQL:1999 语法支持

    SELECT * | 字段 [别名]
    FROM 表 [CROSS JOIN 表] [NATURAL JOIN 表] [JOIN] [USING(字段)] [ON(条件)]
    [LEFT | RIGTH | FULL | OUTER JOIN 表] ;
    
    • 交叉连接,其主要的目的是为了产生笛卡尔积(不常用)
    SELECT * | 字段 [别名] FROM 表 CROSS JOIN 表 ;
    • 自然连接,主要是消除掉笛卡尔积(内连接)(不常用)
    SELECT * | 字段 [别名] FROM 表 NATURAL JOIN 表 ;
    
    • 使用 USING 子句,用户指定关联字段(不常用)
    SELECT * | 字段 [别名] FROM 表 JOIN 表 USING(字段);
    
    • 使用 ON 子句指定关联条件(不常用)
    SELECT * | 字段 [别名] FROM 表 JOIN 表 ON(条件);
    
    • 外连接(必须熟悉)
    SELECT * | 字段 [别名] FROM 表 LEFT | RIGTH | FULL OUTER JOIN 表];
    
    SELECT * FROM emp e LEFT OUTER JOIN dept d ON (e.deptno=d.deptno);
    SELECT * FROM emp e RIGHT OUTER JOIN dept d ON (e.deptno=d.deptno);
    SELECT * FROM emp e FULL OUTER JOIN dept d ON (e.deptno=d.deptno);
    

      

    查询结果连接

    SELECT [DISTINCT] * | 列名称 [别名] , 列名称 [别名] ,... FROM 数据表 [别名] , 数据表 [别名] ,...
    [WHERE 条件(s)]
    [ORDER BY 字段 [ASC | DESC] , 字段 [ASC | DESC] ,...]
    [UNION | UNION ALL | INTERSECT | MINUS]
    SELECT [DISTINCT] * | 列名称 [别名] , 列名称 [别名] ,... FROM 数据表 [别名] , 数据表 [别名] ,...
    [WHERE 条件(s)]
    [ORDER BY 字段 [ASC | DESC] , 字段 [ASC | DESC] ,...]
    [UNION | UNION ALL | INTERSECT | MINUS]
    SELECT [DISTINCT] * | 列名称 [别名] , 列名称 [别名] ,... FROM 数据表 [别名] , 数据表 [别名] ,...
    [WHERE 条件(s)]
    [ORDER BY 字段 [ASC | DESC] , 字段 [ASC | DESC] ,...]
    • UNION 操作,不显示重复记录
    • UNION ALL 操作,显示所有数据,包含重复数据
    • INTERSECT 操作,返回相同的部分,交集
    • MINUS 操作,返回不同的部分,是一个差集
     

    组函数  

    统计函数常见的有五个:COUNT()(个数)、SUM()(求和)、AVG()(平均)、MAX()(最大值)、MIN()(最 小值)。

     关于统计查询的限制:

    • 限制一:统计函数单独使用时(没有 GROUP BY 子句)只能够出现统计函数,不能够出现其它字段。

    • 限制二:使用统计查询时(存在 GROUP BY 子句),SELECT 子句之中只允许出现统计函数与分组字段, 其它的任何字段都不允许出现。

    • 限制三:统计函数在分组之中可以嵌套使用,但是嵌套之后的统计查询之中,SELECT 子句不允许再出现 任何的字段,包括分组字段。

    关于 WHERE 和 HAVING 的区别? 

    • WHERE 子句:是在分组前使用,而且不能够使用统计函数进行验证,经过 WHERE 筛选后的数据才可以分组;
    • HAVING 子句:必须结合 GROUP BY 子句一起出现,是在分组后的过滤,可以使用统计函数。 

    子查询

    • 在 WHERE 子句之中使用子查询
      • IN:在指定范围内
      • NOT IN:不在指定范围内
      • ANY
        • =ANY:此功能与 IN 操作完全一样
        • >ANY:比子查询的最小值要大
        • <ANY:比子查询的最大值要小
    SELECT * FROM emp WHERE sal <ANY (
    SELECT sal FROM emp WHERE job='MANAGER') 
      • ALL
        • >ALL:比子查询返回的最大值还要大
        • <ALL:比子查询最小值还要小
    SELECT * FROM emp WHERE sal <ALL (
    SELECT sal FROM emp WHERE job='MANAGER') 
    • 在 HAVING 子句之中使用子查询
    SELECT deptno,AVG(sal) FROM emp
    GROUP BY deptno HAVING AVG(sal)>(
    SELECT AVG(sal) FROM emp)
    • 在 FROM 子句之中使用子查询
    SELECT d.deptno,d.dname,d.loc,temp.count,temp.avg FROM dept d , (
    SELECT deptno ,COUNT(empno) count,AVG(sal) avg FROM emp
    GROUP BY deptno) temp
    WHERE d.deptno=temp.deptno(+) ;
    

    问题: FROM 子句查询和多表查询有什么差异?emp 表之中存在有 14000 条数据,dept 表中存在有 4000 条数据,查找这两张表会有什么差异呢?

    • 采用方式一的数据量,方式一使用的是多字段分组,那么就一定需要多表查询,多表查询一定会产生笛卡尔积;

                |- 积的数量:emp 的 14000 条 * dept 的 4000 条 = 56,000,000 条数据

    • 采用方式二的数据量,方式二使用的是子查询完成,需要分两步操作:

                |- 第一步(内嵌子查询):针对于 emp 表查询,最多操作 14000 条记录,最多返回 4000 条记录; |- 第二步,子查询和 dept 表关联;

                |- 积的数量:dept 表的 4000 条 * 子查询返回的最多 4000 条 = 16000000 条记录; |- 总的数据量:16000000 + 14000 = 16,014,000 条记录

          主要目的:子查询的出现主要是为了解决多表查询之中的性能问题

          次要目的:很多时候在 FROM 子句里面使用子查询,是因为在外部查询里无法再继续使用统计函数操作的时候

    数据更新

    复制表

    CREATE TABLE myemp AS SELECT * FROM emp ;

    数据删除

    # 删除掉那些没有领导的雇员
    DELETE FROM myemp WHERE mgr IS NULL ;
    # 所有员工删除
    DELETE FROM myemp;
    

      

    表的创建和管理

    在 Oracle 之中数据表就被称为 数据库对象,而对 象 的 操作语法一共 有三种:

    • 创建对象:CREATE 对象类型 对象名称 [选项];
    • 删除对象:DROP 对象类型 对象名称 [选项];
    • 修改对象:ALTER 对象类型 对象名称 [选项]。

    常见的数据类型

    • VARCHAR2:表示字符串,Oracle 的 VARCHAR2 类型可以保存 2000 个字符 
    • NUMBER:

      NUMBER(n):表示不大于 n 位的整数,可以使用 INT 代替 

      NUMBER(n,m):表示有 m 个小数位和 n-m 个整数位,使用 FLOAT 代替 

      直接写 NUMBER 表示小数和整数都可以 

    • DATE:表示日期时间的数据,在 Oracle 中的 DATE 是存在有时间 
    • CLOB:大文本数据,可以保存 4G的文字数据 
    • BLOB:二进制数据,可以保存图片、音乐、电影、文字,最多能够保存 4G 的数据。 (少用)

    重命名表名

    RENAME旧的表名称 TO 新的表名称 ;
    

    截断表 

    “DELETE FROM 表名称”这样的语 句完成,但是使用删除语句删除数据有一个问题:所有的数据被事务所管理,可以恢复,而且所有的数据删除之后其所占 用的一些资源(约束、索引等资源)并不能够立刻释放,那么如果希望表的所有资源被彻底释放,则只能够使用截断表的 操作,其操作语法如下: 

    TRUNCATE TABLE 表名称;

     删除表

    删除完成之后会遗留下一些内容

    DROP TABLE 表名称;

    修改表

    # 为表中增加数据列
    ALTER TABLE 表名称 ADD(
    列名 数据类型 [DEFAULT 默认值],
    列名 数据类型 [DEFAULT 默认值]
    )
    
    # 修改列结构
    ALTER TABLE 表名称 MODIFY(
    列名 数据类型 [DEFAULT 默认值],
    列名 数据类型 [DEFAULT 默认值]
    )
    

      

  • 相关阅读:
    【Java123】HTTP Post Form Data 传输的Java实现
    【数据库123】Oracle数据库数据实时监控
    【Java123】Java基础知识点
    【测试123】ISTQB AL
    【Git123】Git 常用命令
    [Java123] Spring
    【Java123】JavaWeb Servlet开发
    [Java123] JBoss
    [SQL123] Oracle SQL 统计一定时间间隔内的数据
    【测试123】性能测试之压力测试
  • 原文地址:https://www.cnblogs.com/CSgarcia/p/11434295.html
Copyright © 2011-2022 走看看