• Oracle笔记(一)


    1.数据库的逻辑和物理结构

    wps_clip_image-28078

    • 表空间由多个数据文件组成

    • 数据文件只能属于一个表空间

    • 表空间为逻辑概念,数据文件为物理概念

    • 段存在于表空间中

    • 段是区的集合

    • 区是数据块的集合

    • 数据块会被映射到磁盘块

    2.用户登录

    登录普通用户:

    方式一:执行 sqlplus --> 输入用户名 --> 输入密码。

    方式二:执行 sqlplus {用户名} --> 输入密码。

    方式三:执行 sqlplus {用户名}/{密码}。

    例子:

    sqlplus --> 输入scott --> 输入tiger。

    sqlplus scott --> 输入密码。

    sqlplus scott/tiger。

    登录管理员:

    执行 sqlplus / as sysdba

    退出:

    exit

    3.修改权限

    ¨ 解锁用户:

    alter user 用户名 account unlock;

    ¨ 锁定用户:

    alter user 用户名 account lock;

    ¨ 修改密码:

    alter user 用户名 identified by 新密码;

    ¨ 修改管理员密码:

    alter user sys identified by 新密码;

    4.Oracle相关的服务

    OracleService+服务名,该服务是数据库启动的基础,只有该服务启动了,Oracle数据库才能正常启动。这是必须启动的服务。

    OracleOraDb10g_home1TNSListener,该服务是服务器端为客户端提供的监听服务,只有该服务在服务器上正常启动,客户端才能连接到服务器。该监听服务接收客户端发出的请求,然后将请求传递给数据库服务器。一旦建立了连接,客户端和数据库服务器就能直接通信了。

    OracleOraDb10g_home1iSQL*Plus,该服务提供了用浏览器对数据库中数据操作的方式。该服务启动后,就可以使用浏览器进行远程登录并进行数据库操作了。

    SQL可以分成以下几组:

    • DML(Data Manipulation Language) 数据操作语言,用于检索或者修改数据
    • DDL(Data Definition Language) 数据定义语言,用于定义数据的结构,创建、修改或者删除数据库对象
    • DCL(Data Control Language) 数据控制语言,用于定义数据库的权限

    简单查询指的是查询出一张表中的所有的数据,简单查询的语法如下:

    5.查询

    一、简单查询

    SELECT [DISTINCT] * | 字段 [别名] [,字段 [别名]]
    
    FROM 表名称 [别名];

    查询出来的内容中出现了重复的数据,而之所以数据会有重复,主要的原因是现在没有消除掉重复记录,可以使用DISTINCT消除掉所有的重复内容:

    SELECT DISTINCT job FROM emp;

    在简单查询中也可以使用“||”连接查询的字段。

    范例:观察“||”的使用

    SELECT empno || ',' || ename FROM emp;

    二、限定查询

    在之前的简单查询中,是将所有的记录进行显示,但是现在可以对显示的记录进行过滤的操作,而这就属于限定查询的工作了,限定查询就是在之前语法的基础上增加了一个WHERE子句,用于指定限定条件,此时语法如下:

    SELECT [DISTINCT] * | 字段 [别名] [,字段 [别名]] FROM 表名称 [别名] [WHERE 条件(S)];

    在WHERE子句之后可以增加多个条件,最常见的条件就是基本的关系运算:>、>=、<、<=、!=(<>)、BETWEEN、AND、LIKE、IN、IS NULL、AND、OR、NOT

    1、关系运算

    范例:查询出所有职位是办事员的雇员信息

    SELECT * FROM emp WHERE job='clerk';

    这个时候没有返回相应的查询结果,主要原因是在Oracle数据库中,所有的数据都是区分大小写的,所以代码修改如下:

    SELECT * FROM emp WHERE job='CLERK';

    2、范围判断:BETWEEN…AND…

    范例:要求查询出基本工资在1500~3000的雇员信息

    SELECT * FROM emp WHERE sal BETWEEN 1500 AND 3000;

    范例:现在也可以对BETWEEN…AND…操作求反

    SELECT * FROM emp WHERE NOT sal BETWEEN 1500 AND 3000;

    “BETWEEN…AND…”操作符不光只是针对于数字有用,对于日期也同样有用。

    3、判断是否为空:IS (NOT) NULL

    使用此语法可以判断某一个字段上的内容是否是“null”,但是null和数字0以及空字符串是两个概念。

    范例:查询出所有领取奖金的雇员信息

    SELECT * FROM emp WHERE comm IS NOT NULL;SELECT * FROM emp WHERE NOT comm IS NULL;

    范例:查询出所有不领取奖金的雇员

    SELECT * FROM emp WHERE comm IS NULL;
    4、指定范围的判断:IN操作符

    5、模糊查询:LIKE子句

    LIKE子句的功能是提供了模糊查找的操作,例如:某些程序上出现的搜索操作,都属于LIKE子句的实现,但是必须提醒的,搜索引擎上的查询可不是LIKE。

    但是要想使用LIKE子句则必须认识两个匹配符号:

    匹配单个字符:         _       ->  1个

    匹配任意多个字符: %      ->  0个、1个、多个

    优先级:

    wps_clip_image-3049

    空值(null)与对空值的处理

    ¨ 空值是无效的,未指定的,未知的或不可预知的值

    ¨ 空值不是空格或者0。

    ¨ 包含空值的数学表达式的值都为空值

    处理字符串与日期

    ¨ 字符和日期要包含在单引号中。

    ¨ 字符大小写敏感,日期格式敏感。

    ¨ 默认的日期格式是 DD-MON-RR。

    三、数据的排序

    SELECT [DISTINCT] * | 字段 [别名] [,字段 [别名]]

    FROM 表名称 [别名]

    [WHERE 条件(S)]

    [ORDER BY 字段 [ASC|DESC] [,字段 [ASC|DESC],…]];

    “ORDER BY”子句是写在所有的SQL语句最后的内容,而且对于排序有以下几点说明:

    排序的时候可以指定多个排序的字段;

    排序的方式有两种:

    • 升序(ASC):默认,不写也是升序;
    • 降序(DESC):用户需要指定,由大到小排序;

    单行函数

    wps_clip_image-4712

    一、字符函数

    字符函数的功能主要是进行字符串数据的操作,下面给出几个字符函数:

    • UPPER(字符串 | 列):将输入的字符串变为大写返回;
    • LOWER(字符串 | 列):将输入的字符串变为小写返回;
    • INITCAP(字符串 | 列):开头首字母大写;
    • LENGTH(字符串 | 列):求出字符串的长度;
    • REPLACE(字符串 | 列):进行替换;
    • SUBSTR(字符串 | 列,开始点 [,结束点]):字符串截取;

    wps_clip_image-5437

    wps_clip_image-5319[4]

    二、数字函数

    • ROUND(数字 | 列 [,保留小数的位数]):四舍五入的操作;
    • TRUNC(数字 | 列 [,保留小数的位数]):舍弃指定位置的内容;
    • MOD(数字 1,数字2):取模,取余数;

    三、日期函数

    取得当前的日期,这个当前日期可以使用“SYSDATE”取得,代码如下:

    SELECT SYSDATE FROM dual;

    除了以上的当前日期之外,在日期中也可以进行若干计算:

    • 日期 + 数字 = 日期,表示若干天之后的日期;
    SELECT SYSDATE + 3,SYSDATE + 300 FROM dual;
    • 日期 – 数字 = 日期,表示若干天前的日期;
    SELECT SYSDATE - 3,SYSDATE - 300 FROM dual;
    • 日期 – 日期 = 数字,表示的是两个日期间的天数,但是肯定是大日期 – 小日期;

    范例:求出每个雇员到今天为止的雇佣天数

    SELECT ename,hiredate,SYSDATE-hiredate FROM emp;

    而且很多的编程语言之中,也都会提出一种概念,日期可以通过数字表示出来。

    除了以上的三个公式之外,也提供了如下的四个操作函数:

    • LAST_DAY(日期):求出指定日期的最后一天;

    范例:求出本月的最后一天日期

    SELECT LAST_DAY(SYSDATE) FROM dual;
    • NEXT_DAY(日期,星期数):求出下一个指定星期X的日期;

    范例:求出下一个周一

    SELECT NEXT_DAY(SYSDATE,'星期一') FROM dual;
    • ADD_MONTHS(日期,数字):求出若干月之后的日期;

    范例:求出四个月后的日期

    SELECT ADD_MONTHS(SYSDATE,4) FROM dual;
    • MONTHS_BETWEEN(日期1,日期2):求出两个日期之间所经历的月份;

    范例:求出每个雇员到今天为止的雇佣月份

    SELECT ename,hiredate,TRUNC(MONTHS_BETWEEN(SYSDATE,hiredate)) FROM emp;

    在所有的开发之中,如果是日期的操作,建议使用以上的函数,因为这些函数可以避免闰年的问题。

    四、转换函数

    • TO_CHAR(字符串 | 列,格式字符串):将日期或者是数字变为字符串显示;
    • TO_DATE(字符串,格式字符串):将字符串变为DATE数据显示;
    • TO_NUMBER(字符串):将字符串变为数字显示;

    wps_clip_image-7687

    TO_CHAR()函数

    SELECT TO_CHAR(SYSDATE,'yyyy-mm-dd'),TO_CHAR(SYSDATE,'yyyy') year, TO_CHAR(SYSDATE,'mm') month, TO_CHAR(SYSDATE,'dd') day FROM dual;
    TO_CHAR(SY YEAR MO DA
    ---------- ---- -- --
    2012-08-12 2012 08 12

    但是这个时候的显示数据之中可以发现会存在前导0,如果要想消除掉这个0的话,可以加入一个“fm”。

    SELECT TO_CHAR(SYSDATE,'fmyyyy-mm-dd') day FROM dual;
    DAY
    ----------
    2012-8-12

    正常人都加0,所以这个标记知道就行了,可是在Oracle之中,DATE里面是包含了时间的,但是之前的代码没有显示出时间,要想显示时间则需要增加标记:

    SELECT TO_CHAR(SYSDATE,'fmyyyy-mm-dd hh24:mi:ss') day FROM dual;
    DAY
    -------------------
    2012-8-12 16:13:38

    一定要注意,使用TO_CHAR()函数之后,所有的内容都是字符串,不再是之前的DATE型数据,TO_CHAR()函数也可以用于数字的格式化上,这个时候每一个“9”表示一位数字的概念,而不是数字9的概念。

    SELECT TO_CHAR(89078907890,'L999,999,999,999,999') FROM dual;
    TO_CHAR(89078907890,'L999,999,
    ------------------------------
                  ¥89,078,907,890

    其中的字母“L”,表示的是“Local”的含义,即:当前的所在的语言环境下的货币符号。

    wps_clip_image-7977

    TO_DATE()函数

    此函数的主要功能是将一个字符串变为DATE型数据。

    SELECT TO_DATE('1989-09-12','yyyy-mm-dd') FROM dual;
    TO_DATE('1989-
    --------------
    12-9月 -89

    五、通用函数

    通用函数主要有两个:NVL()、DECODE()

    NVL()函数,处理null

    NVL函数将空值转换成一个已知的值:

    l 可以使用的数据类型有日期、字符、数字。

    l 函数的一般形式:

    • NVL(commission_pct,0)
    • NVL(hire_date,'01-JAN-97')
    • NVL(job_id,'No Job Yet')

    DECODE()函数:多数值判断

    DECODE()函数非常类似于程序中的if…else…语句,唯一不同的是DECODE()函数判断的是数值,而不是逻辑条件。

    例如,现在要求显示全部雇员的职位,但是这些职位要求替换为中文显示:

    • CLERK:办事员;
    • SALESMAN:销售;
    • MANAGER:经理;
    • ANALYST:分析员;
    • PRESIDENT:总裁;

    这种判断肯定是逐行进行判断,所以这个时候就必须采用DECODE(),而此函数的语法如下:

    DECODE(数值 | 列 ,判断值1,显示值1,判断值2,显示值2,判断值3,显示值3,…)

    范例:实现显示的操作功能

    SELECT empno,ename,job,DECODE(job,'CLERK','办事员','SALESMAN','销售人员','MANAGER','经理','ANALYST','分析员','PRESIDENT','总裁') FROM emp;
     
     

    多表查询

    一、多表查询的基本概念

    SELECT [DISTINCT] * | 字段 [别名] [,字段 [别名] ,…]

    FROM 表名称 [别名], [表名称 [别名] ,…]

    [WHERE 条件(S)]

    [ORDER BY 排序字段 [ASC|DESC] [,排序字段 [ASC|DESC] ,…]];

    笛卡尔集:学数学的都懂。。

    二、连接

    Oracle 连接:

    Ø Equijoin:等值连接

    Ø Non-equijoin:不等值连接

    Ø Outer join:外连接

    Ø Self join:自连接

    SQL: 1999

    Ø Cross joins

    Ø Natural joins

    Ø Using clause

    Ø Full or two sided outer joins

    1. 等值连接

    wps_clip_image-11951

    wps_clip_image-11991

    使用表的别名

    l 使用别名可以简化查询。

    l 使用表名前缀可以提高执行效率。

    2.连接多个表

    l 连接 n个表,至少需要 n-1个连接条件。 例如:连接三个表,至少需要两个连接条件。

    3. 非等值连接

    wps_clip_image-12608

    wps_clip_image-12637

    4.外连接(左、右连接)

    wps_clip_image-12918

    wps_clip_image-8470

    • (+)=:放在了等号的左边,表示的是右连接;
    • =(+):放在了等号的右边,表示的是左连接;

    但是不用去刻意的区分是左还是右,只是根据查询结果而定,如果发现有些需要的数据没有显示出来,就使用此符号更改连接方向。

    SQL:1999语法

    除了以上的表连接操作之外,在SQL语法之中,也提供了另外一套用于表连接的操作SQL,格式如下:

    SELECT table1.column,table2.column FROM table1 [CROSS JOIN table2]| [NATURAL JOIN table2]| [JOIN table2 USING(column_name)]| [JOIN table2 ON(table1.column_name=table2.column_name)]| [LEFT|RIGHT|FULL OUTER JOIN table2 ON(table1.column_name=table2.column_name)];

    以上实际上是属于多个语法的联合,下面分块说明语法的使用。

    1、交叉连接(CROSS JOIN):用于产生笛卡尔积

    SELECT * FROM emp CROSS JOIN dept;

    笛卡尔积本身并不是属于无用的内容,在某些情况下还是需要使用的。

    2、自然连接(NATURAL JOIN):自动找到匹配的关联字段,消除掉笛卡尔积

    SELECT * FROM emp NATURAL JOIN dept;

    但是并不是所有的字段都是关联字段,设置关联字段需要通过约束指定;

    3、JOIN…USING子句:用户自己指定一个消除笛卡尔积的关联字段

    SELECT * FROM emp JOIN dept USING(deptno);

    4、JOIN…ON子句:用户自己指定一个可以消除笛卡尔积的关联条件

    SELECT * FROM emp JOIN dept ON(emp.deptno=dept.deptno);

    5、连接方向的改变:

    • 左(外)连接:LEFT OUTER JOIN…ON;
    • 右(外)连接:RIGHT OUTER JOIN…ON;
    • 全(外)连接:FULL OUTER JOIN…ON; --> 把两张表中没有的数据都显示
    SELECT * FROM emp RIGHT OUTER JOIN dept ON(emp.deptno=dept.deptno);
    左外联接

    wps_clip_image-13783

    右外联接

    wps_clip_image-13937

    满外联接

    wps_clip_image-19637

    在Oracle之外的数据库都使用以上的SQL:1999语法操作,所以这个语法还必须会一些(如果你一直使用的都是Oracle就可以不会了)。

    再次强调:多表查询的性能肯定不高,而且性能一定要在大数据量的情况下才能够发现。

    四、统计函数及分组查询

    1、统计函数

    在之前学习过一个COUNT()函数,此函数的功能可以统计出表中的数据量,实际上这个就是一个统计函数,而常用的统计函数有如下几个:

    • COUNT():查询表中的数据记录;
    • AVG():求出平均值;
    • SUM():求和;
    • MAX():求出最大值;
    • MIN():求出最小值;

    范例:测试COUNT()、AVG()、SUM()

    统计出公司的所有雇员,每个月支付的平均工资及总工资。

    SELECT MAX(sal),MIN(sal) FROM emp;

    注意点:关于COUNT()函数

    COUNT()函数的主要功能是进行数据的统计,但是在进行数据统计的时候,如果一张表中没有统计记录,COUNT()也会返回数据,只是这个数据是“0”。

    SELECT COUNT(ename) FROM BONUS;

    如果使用的是其他函数,则有可能返回null,但是COUNT()永远都会返回一个具体的数字,这一点以后在开发之中都会使用到。

    2、分组查询

    SELECT [DISTINCT] *|分组字段1 [别名] [,分组字段2 [别名] ,…] | 统计函数

    FROM 表名称 [别名], [表名称 [别名] ,…]

    [WHERE 条件(s)]

    [GROUP BY 分组字段1 [,分组字段2 ,…]]

    [ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC]];

    但是现在一旦分组之后,实际上对于语法上就会出现了新的限制,对于分组有以下要求:

    • 分组函数可以在没有分组的时候单独用使用,可是却不能出现其他的查询字段;

    分组函数单独使用:

    SELECT COUNT(empno) FROM emp;

    错误的使用,出现了其他字段:

    SELECT empno,COUNT(empno) FROM emp;

    • 如果现在要进行分组的话,则SELECT子句之后,只能出现分组的字段和统计函数,其他的字段不能出现:

    正确做法:

    SELECT job,COUNT(empno),AVG(sal)

    FROM emp

    GROUP BY job;

    错误的做法:

    SELECT deptno,job,COUNT(empno),AVG(sal)

    FROM emp

    GROUP BY job;

    • 分组函数允许嵌套,但是嵌套之后的分组函数的查询之中不能再出现任何的其他字段。

    此时如果要对分组后的数据再次进行过滤,则使用HAVING子句完成,那么此时的SQL语法格式如下:

    SELECT [DISTINCT] *|分组字段1 [别名] [,分组字段2 [别名] ,…] | 统计函数

    FROM 表名称 [别名], [表名称 [别名] ,…]

    [WHERE 条件(s)]

    [GROUP BY 分组字段1 [,分组字段2 ,…]]

    [HAVING 分组后的过滤条件(可以使用统计函数)]

    [ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC]];

    SELECT d.deptno,d.dname,d.loc,COUNT(e.empno) mycount,NVL(AVG(e.sal),0) myavg
    FROM dept d,emp e
    WHERE d.deptno=e.deptno(+)
    GROUP BY d.deptno,d.dname,d.loc
    HAVING AVG(sal)>2000;

    注意点:WHERE和HAVING的区别

    • WHERE:是在执行GROUP BY操作之前进行的过滤,表示从全部数据之中筛选出部分的数据,在WHERE之中不能使用统计函数;
    • HAVING:是在GROUP BY分组之后的再次过滤,可以在HAVING子句中使用统计函数;

    五、子查询

    子查询 = 简单查询 + 限定查询 + 多表查询 + 统计查询的综合体;

    在之前强调过多表查询不建议大家使用,因为性能很差,但是多表查询最有利的替代者就是子查询,所以子查询在实际的开发之中使用的相当的多;

    所谓的子查询指的就是在一个查询之中嵌套了其他的若干查询,嵌套子查询之后的查询SQL语句如下:

    SELECT [DISTINCT] *|分组字段1 [别名] [,分组字段2 [别名] ,…] | 统计函数 ,(
    
          SELECT [DISTINCT] *|分组字段1 [别名] [,分组字段2 [别名] ,…] | 统计函数
    
          FROM 表名称 [别名], [表名称 [别名] ,…]
    
          [WHERE 条件(s)]
    
          [GROUP BY 分组字段1 [,分组字段2 ,…]]
    
          [HAVING 分组后的过滤条件(可以使用统计函数)]
    
          [ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC]])
    
    FROM 表名称 [别名], [表名称 [别名] ,…] ,(
    
          SELECT [DISTINCT] *|分组字段1 [别名] [,分组字段2 [别名] ,…] | 统计函数
    
          FROM 表名称 [别名], [表名称 [别名] ,…]
    
          [WHERE 条件(s)]
    
          [GROUP BY 分组字段1 [,分组字段2 ,…]]
    
          [HAVING 分组后的过滤条件(可以使用统计函数)]
    
          [ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC]])
    
    [WHERE 条件(s) (
    
          SELECT [DISTINCT] *|分组字段1 [别名] [,分组字段2 [别名] ,…] | 统计函数
    
          FROM 表名称 [别名], [表名称 [别名] ,…]
    
          [WHERE 条件(s)]
    
          [GROUP BY 分组字段1 [,分组字段2 ,…]]
    
          [HAVING 分组后的过滤条件(可以使用统计函数)]
    
          [ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC]])]
    
    [GROUP BY 分组字段1 [,分组字段2 ,…]]
    
    [HAVING 分组后的过滤条件(可以使用统计函数)]
    
    [ORDER BY 排序字段 ASC | DESC [,排序字段 ASC | DESC]];

    理论上子查询可以出现在查询语句的任意位置上,但是从个人而言,子查询出现在WHERE和FROM子句之中较多;

    以下的使用特点为个人总结,不是官方声明的:

    • WHERE:子查询一般只返回单行列、多行单列、单行多列的数据;
    • FROM:子查询返回的一般是多行的数据,当作一张临时表出现。

    如果现在的子查询返回的是多行单列数据的话,这个时候就需要使用三种判断符判断了:IN、ANY、ALL;

    1、 IN操作符:用于指定一个子查询的判断范围

    这个操作符的使用实际上与之前讲解的IN是一样的,唯一不同的是,里面的范围由子查询指定了。

    SELECT * FROM emp
    WHERE sal in (
    SELECT sal
    FROM emp
    WHERE job='MANAGER');

    但是在使用IN的时候还要注意NOT IN的问题,如果使用NOT IN操作,在子查询之中,如果有一个内容是null,则不会查询出任何的结果。

    2、 ANY操作符:与每一个内容想匹配,有三种匹配形式

    • =ANY:功能与IN操作符是完全一样的;
    SELECT * FROM emp
    WHERE sal=ANY (
    SELECT sal
    FROM emp
    WHERE job='MANAGER');
    • >ANY:比子查询中返回记录最小的还要大的数据;
    SELECT * FROM emp
    WHERE sal>ANY (
    SELECT sal
    FROM emp
    WHERE job='MANAGER');
    • <ANY:比子查询中返回记录的最大的还要小;

    3、 ALL操作符:与每一个内容相匹配,有两种匹配形式:

    • >ALL:比子查询中返回的最大的记录还要大
    SELECT * FROM emp
    WHERE sal>ALL (
    SELECT sal
    FROM emp
    WHERE job='MANAGER');
    • <ALL:比子查询中返回的最小的记录还要小
    SELECT * FROM emp
    WHERE sal<ALL (
    SELECT sal
    FROM emp
    WHERE job='MANAGER');

    以上的所有子查询都是在WHERE子句中出现的,那么下面再来观察在FROM子句中出现的查询,这个子查询一般返回的是多行多列的数据,当作一张临时表的方式来处理。

    使用子查询的确要比使用多表查询更加节省性能,所以在开发之中子查询出现是最多的,而且在给出一个不成文的规定:大部分情况下,如果最终的查询结果之中需要出现SELECT子句,但是又不能直接使用统计函数的时候,就在子查询中统计信息,即:有复杂统计的地方大部分都需要子查询。

  • 相关阅读:
    Linux rcp命令详解
    Linux patch命令详解
    Linux paste命令详解
    linux od命令详解
    linux mv命令详解
    Linux more命令详解
    Linux mktemp命令
    MySQL状态变量详解
    mysql性能分析show profile/show profiles
    MySQL执行计划
  • 原文地址:https://www.cnblogs.com/zzzt/p/3687440.html
Copyright © 2020-2023  润新知