Oracle--SQL基础

Oralce基础数据类型

四大类,下面列出一些常用类型

  • 字符型
    char(最大2000),nchar(最大1000,支持Unicode) 。固定长度
    varchar2(最大4000), nvarchar2(最大2000, 支持Unicode)--->可变长度
  • 数字类型
    包括整数和小数
     number(有效数字, 总位数);
     float()--->存储二进制类型的数据, 1-126位0.30103
    double()
  • 日期类型
    date:取值范围:公元前4712年1月1号---公元9999年12月31号, 可以直接精确到秒
    timestamp(时间戳: 更精确的数据, 可以精确到毫秒)
  • 其它类型:大文本, 文件
    blob: 最大4G, 以二进制的形式来存放数据
    clob: 最大4G, 以字符串的形式存放

优先级:在数据转换时,优先转换为高级别的数据类型
date type > binary_double > binary_float > number > char

Oracle运算符

算术运算符(+ - * /)
比较运算符(> >= < <= = <>/!=)
逻辑运算符(and or not)
字符串连接符(||)

Oracle单行函数

单行函数格式:
    函数名[(参数1,参数2,参数3,...)]
    其中参数可以为用户定义的常量、变量、列名和表达式。
    单行函数只对表中的一行数据进行操作,并且对每一行数据只产生一个输出结果。
    单行函数可用在SELECT、WHERE和ORDER BY的子句中,而且单行函数可以嵌套。
    单行函数包含字符型。数字型、日期型、转换型和一般型函数。

  1. 单行字符型函数
    (1) LOWER(列名|表达式):该函数用于把字符转换成小写。
    SELECT LOWER('SQL: Structural Query Language')
    FROM dual;
    dual是系统的一个虚表(伪表),原因:
    在查询语句中必须包含SELECT和FROM两个子句,可是LOWER('SQL: Structural Query Language')不属于任何表,于是用Oracle提供的虚表dual来解决这一难题。

    (2)UPPER(列名|表达式):该函数用于把字符转换成大写。
    SELECT UPPER('sql is used exclusively in rdbmses')
    FROM dual;

    (3)INITCAP(列名|表达式):该函数用于把每个字的头一个字符转换成大写,其余转换成小写。
    SELECT INITCAP('SQL is an ENGLISH LIKE language')
    FROM dual;

    (4)CONCAT(列名|表达式,列名|表达式):该函数用于把第1个字符串和第2个字符串连接成一个字符串。
    SELECT CONCAT('SQL alows you to manipulate the data in DB',' without any programming knowledge')
    FROM dual;

    (5)SUBSTR(列名|表达式,m,[n]):该函数用于返回指定的子串,该子串从第m个字符开始,其长度为n。
    SELECT SUBSTR('SQL lets you concentrate on what has to be done',14)
    FROM dual;

    (6)LENGTH(列名|表达式):该函数用于返回列或表达式中字符串的长度。
    SELECT LENGTH('SQL does no let you concentrate on how it will be achieved')
    FROM dual;

    (7)INSTR(列名|表达式,‘字符串’,[m],[n]):该函数用于返回所给字符串的数字位置,m表示从第m个字符开始搜索,n表示所给字符串出现的次数,它们的默认值都为1。
    SELECT INSTR('SQL allows for dynamic DB changes','F')
    FROM dual;
    SELECT INSTR('SQL allows for dynamic DB changes','f')
    FROM dual;

    (8)TRIM([leading|trailing|both]要去掉的字符FROM源字符串):该函数能够从“源字符串”中的头(leading)部、尾(trailing)部或头部和尾部中(both)去掉“要去掉的字符串”。如果没有指定头或尾,TRIM函数按默认(both)处理(该函数是8i引入的,在8i之前的版本中是LTRIM和RTRIM两个函数)。
    trim 去掉前后指定的字符
    select trim('H' from 'Hello WorldH') from dual;-->ello World

    (9)REPLACE(正文表达式,要搜寻的字符串,替换字符串):该函数用于在“正文表达式”中查找“要搜寻的字符串”,如果找到了就用“替换字符串”替代。
    select replace('Hello World','l','') from dual;-->Heo Word

    (10)NVL(列名|表达式 1,列名|表达式 2)将一个NULL转换为另外一个值,如果1为NULL,则返回2,否则返回1值本身
    select nvl(address,'北京市') from student;

  2. 数字型函数
    (1)ROUND(列名|表达式,n):该函数将列名或表达式所表示的数值四舍五入到小数点的n位。注意下标从0开始。
                select round(555.666) from dual;--返回结果为556,不加n时默认去掉小数部分
                select round(555.666,2) from dual;--返回结果为555.67
                select round(555.666,-2) from dual;--返回结果为600
    (2)TRUNC(列名|表达式,n):该函数将列名或表达式所表示的数值取到小数点的后n位。
                select trunc(555.666) from dual; --返回结果为555,不加n时默认去掉小数部分
                select trunc(555.666,2) from dual;--返回结果为555.66
                select trunc(555.666,-2) from dual;--返回结果为500
    (3)MOD(m,n):该函数将m除以n并取余数。
                select mod(1600,300) from dual;--返回结果是100
    (4)ABS(value)返回value的绝对值
                select abs(-10) from dual;--返回结果为10
    (5)CEIL(value)返回大于等于value的最小整数
                select ceil(2.3) from dual; --返回结果为3
    (6)FLOOR(value)返回小于等于value的最大整数
                select floor(2.3) from dual; --返回结果为2
    注意:1. trunc和round用法类似,只不过trunc是硬生生截取,并不进行四舍五入,而round进行截取时四舍五入
       2. 都还可以对日期的截取

  3. 日期函数
    -- 系统时间
    select sysdate from dual;
    把一个日期型数据和一个数字相加减,结果仍为日期型。
    select sysdate-10 from dual;--当前时间减10天,返回的是天数
    select sysdate+10 from dual;--日期不能相加
    --计算员工的工龄:天 星期 月 年 (月数不是个准确的值)
    select ename,hiredate,(sysdate-hiredate) 天,(sysdate-hiredate)/7 星期, (sysdate-hiredate)/30 月,(sysdate-hiredate)/365 年 from emp;

(1)MONTHS_BETWEEN(x,y),两个日期相差的月数
--计算员工的工龄:months_between()计算后月数是个准确的值
select ename,hiredate,(sysdate-hiredate)/30 一, months_between(sysdate,hiredate) 二
from emp;
(2)ADD_MONTHS(d,n),在某一个日期 d 上,加上指定的月数 n,返回计算后的新日期。d 表示日期,n 表示要加的月数。
SELECT SYSDATE,add_months(SYSDATE,5) FROM dual;
------->
2017/12/10 23:17:34 -- > 2018/5/10 23:17:34
(3)NEXT_DAY(x,y),指定日期的下一个日期
            select next_day(sysdate,'星期二') from dual;-->从当前时间开始算,下一个星期二的日期。
(4)LAST_DAY(d),返回指定日期当月的最后一天。
            SELECT SYSDATE,last_day(SYSDATE) FROM dual;
(5)ROUND(d[,fmt]),返回一个以 fmt 为格式的四舍五入日期值, d 是日期, fmt 是格式模型。默认 fmt 为 DDD,即月中的某一天。
          ① 如果 fmt 为“YEAR”则舍入到某年的 1 月 1 日,即前半年舍去,后半年作为下一年。
          ② 如果 fmt 为“MONTH”则舍入到某月的 1 日,即前半月舍去,后半月作为下一月。
          ③ 默认为“DDD”,即月中的某一天,最靠近的天,前半天舍去,后半天作为第二天。
          ④ 如果 fmt 为“DAY”则舍入到最近的周的周日,即上半周舍去,下半周作为下一周周日。
SELECT SYSDATE,ROUND(SYSDATE),ROUND(SYSDATE,'day'),
ROUND(SYSDATE,'month'),ROUND(SYSDATE,'year') FROM dual;


rerere.png

(6)ROUND(d[,fmt]),返回指定一个截取后的日期,不会四舍五入,而是直接截取。


YYTYTY.png

(7)EXTRACT(fmt FROM d),提取日期中的特定部分。
fmt 为:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND。其中 YEAR、MONTH、DAY可以为 DATE 类型匹配,也可以与 TIMESTAMP 类型匹配;但是 HOUR、MINUTE、SECOND 必须与 TIMESTAMP 类型匹配。

HOUR 匹配的结果中没有加上时区,因此在中国运行的结果小 8 小时。


yuyuyu.png
  1. 转换函数
    转换函数将值从一种数据类型转换为另外一种数据类型。
    (1)TO_CHAR(d|n[,fmt])把日期和数字转换为制定格式的字符串。Fmt是格式化字符串。
              SELECT TO_CHAR(SYSDATE,'YYYY"年"MM"月"DD"日" HH24:MI:SS')"date" FROM dual;
    (2)TO_DATE(X,[,fmt])把一个字符串以fmt格式转换成一个日期类型
              SELECT TO_DATE('2017/12/10 23:40:34','YYYY-MM-DD HH24:MI:SS') FROM dual;
    (3)TO_NUMBER(X,[,fmt])把一个字符串以fmt格式转换为一个数字
              格式值            含义
              9           代表一个数字
               0           强迫0显示
              $           显示美元符号
              L           强制显示一个当地的货币符号
              .           显示一个小数点
              ,           显示一个千位分隔符号
    ①select to_number('88877') from dual;
    ②如果数字在格式范围内的话,就是正确的,否则就是错误的;如:
    select to_number('$12345.678', '$999999.99') from dual; -- 错误
    select to_number('$12345.678', '$999999.999') from dual;--正确
    ③可以用来实现进制转换;16进制转换为10进制:
    select to_number('19f','xxx') from dual;
    select to_number('f','xx') from dual;

Oracle聚合函数

(1)avg(x):返回x的平均值
          select avg(grade) from sc;

(2)count(x):返回统计的行数
          select count(name) from sc;
          count(*)和count(列名)的区别:count(*)不会忽略列值为空的情况,count(列名)会忽略。如:

--平均奖金(某些员工可能没有奖金)
select sum(comm)/count(*) 一,
       sum(comm)/count(comm)  二,
       avg(comm) 三
from emp;

        一         二         三                                                                                                                      
---------- ---------- ----------                                                                                                                      
157.142857        550        550 

原因是:
select count(*),count(comm) from emp;

  COUNT(*)    COUNT(COMM)                                                                                                                                
----------    -----------                                                                                                                                
        14           4    

上述例子中avg(comm)跟sum(comm)/count(comm)结果一样的,
原因是聚合函数自动过滤掉为空的列,
如果不想过滤可以这样:
      count(comm)  -->  count(nvl(comm,0))
      avg(comm)  --> avg(nvl(comm,0))

(3)max(x):返回x的最大值
          select max(grade) from sc;

(4)min(x):返回x的最小值
          select min(grade) from sc;

(5)sum(x):返回x的总计值
          select sum(grade) from sc;

聚合函数需要注意的是:
          1.当分组时select子句后边要检索的列中出现聚合函数,其他的列必须与group by子句后的列名一致。
              select deptno,avg(sal) from EMP;--错误,因为deptno不是聚集函数,也不是group by后面跟的列名
          2.不能使用聚集函数作为WHERE子句的筛选条件
              select deptno from emp where avg(sal)>1000;--错误
          3.分组后,需要使用条件进行筛选,则使用having过滤分组后的行,不能使用where,where只能放在group by前面。
              select deptno, avg(sal) from emp               where deptno<>10
              group by deptno
              having avg(sal) > 900;

Oracle表达式

oracle中sql的表达式可以用if-else if-else来理解

  • CASE表达式:
-- 按员工职位加薪
select ename,job,sal 涨前,
        case job when 'PRESIDENT' then sal+1000
                 when 'MANAGER' then sal+800
                 else sal+400
        end 涨后
from emp;

ENAME      JOB             涨前       涨后                                                                                                            
---------- --------- ---------- ----------                                                                                                                                                                                                                                   
MARTIN     SALESMAN        1250       1650                                                                                                            
BLAKE      MANAGER         2850       3650                                                                                                                                                                                                                    
KING       PRESIDENT       5000       6000                                                                                                            
TURNER     SALESMAN        1500       1900                                                                                                            
ADAMS      CLERK           1100       1500  
  • DECODE表达式:
select ename,job,sal 涨前,
    decode(job,'PRESIDENT',sal+1000,
               'MANAGER',sal+800,
                sal+400) 涨后
from emp;

ENAME      JOB             涨前       涨后                                                                                                            
---------- --------- ---------- ----------                                                                                                                                                                                                                                   
MARTIN     SALESMAN        1250       1650                                                                                                            
BLAKE      MANAGER         2850       3650                                                                                                                                                                                                                    
KING       PRESIDENT       5000       6000                                                                                                            
TURNER     SALESMAN        1500       1900                                                                                                            
ADAMS      CLERK           1100       1500  

多表查询

*笛卡尔积
           当多表关联查询时必然产生笛卡尔积。产生笛卡尔积后的结果是:
               总列数 = 表1的列数 + 表2的列数 + ....
               总行数 = 表1的行数 * 表2的行数 * ....


1513085800(1).png

           多表查询造成结果变大而且有些数据错乱,那么就要通过下面的各种连接来消除这种弊端。

  • 等值连接
select e.empno,e.ename,e.sal,d.dname
 from emp e,dept d
 where e.deptno=d.deptno;
条件中有 “=” 号的连接就是等值连接
  • 不等值连接
               条件中不是 “=” 号的连接都是不等值连接
  • 外连接
左外连接: 当where e.deptno=d.deptno 不成立的时候,等号左边的表任然被包含(这样的话至少可以保证左边表数据的完整)
      写法: where e.deptno=d.deptno(+)
右外连接: 当where e.deptno=d.deptno 不成立的时候,等号右边的表任然被包含(这样的话至少可以保证右边表数据的完整)
      写法: where e.deptno(+)=d.deptno
  • 自连接
自连接: 通过表的别名,将同一张表视为 多张表
select e.ename 员工姓名,b.ename 老板姓名
 from emp e,emp b
where e.mgr=b.empno;
自连接不适合操作大表
  • 自连接--层次查询


    层次查询.png
层次查询是通过start with和connect by子句标识的:
select level,empno,ename,mgr --levle是伪列
 from emp
connect by prior empno=mgr
start with mgr is null -- 从根节点开始
order by 1;
-- Start with是表示开始节点
-- connect by prior是指定父子关系
    LEVEL      EMPNO(员工id)     ENAME(员工姓名)       MGR(员工对应领导的id)                                                                                                           
----------     ----------        ----------         ----------                                                                                                           
         1          7839            KING                                                                                                                            
         2          7566           JONES                 7839                                                                                                           
         2          7698           BLAKE                  7839                                                                                                           
         2          7782           CLARK                 7839                                                                                                           
         3          7902           FORD                  7566                                                                                                           
         3          7521           WARD                  7698                                                                                                           
         3          7900           JAMES                7698                                                                                                           
         3          7934           MILLER               7782                                                                                                           
         3          7499           ALLEN                 7698                                                                                                           
         3           7788          SCOTT                7566                                                                                                           
         3          7654            MARTIN             7698  

子查询

子查询其实就是select 嵌套 select

  1. 可以在主查询的where select having from 后面放置子查询
  2. 不可以在group by后面放置子查询
  3. 主查询和子查询可以不是同一张表;只要子查询返回的结果,主查询可以使用即可
  4. 一般不在子查询中使用order by;但在Top-N分析问题中,必须对子查询排序
  5. 一般先执行子查询,再执行主查询;但相关子查询例外
  6. 单行子查询只能使用单行操作符;多行子查询只能使用多行操作符
  • in
    只要在集合中有值就匹配成功,注意如果集合中有null值不能使用in,因为得不到任何结果。但可以使用not in 。oracle中判断是否是null不能使用 = 号来判断如果这样判断永远是不等的,只能通过 is null 或 is not null来判断。
  • any
    和集合中的任意一个值比较
查询工资比30号部门任意一个员工高的员工
select *
from emp
where sal > any (select sal from emp where deptno=30);
等同于:
select *
from emp
where sal > (select min(sal) from emp where deptno=30)
  • all
    和集合的所有值比较
查询工资比30号部门所有员工高的员工
select *
from emp
where sal > all (select sal from emp where deptno=30);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 1.简介 数据存储有哪些方式?电子表格,纸质文件,数据库。 那么究竟什么是关系型数据库? 目前对数据库的分类主要是...
    乔震阅读 1,699评论 0 2
  • ORACLE日期时间函数大全 TO_DATE格式(以时间:2007-11-02 13:45:25为例) Year:...
    雨一流阅读 653评论 0 2
  • 目录 简介 在Android中存储数据有时会用到数据库,Android给我们提供了 一系列的API来操作数据库,非...
    慕涵盛华阅读 998评论 1 2
  • 回望一路的过往, 哀叹时光的匆忙, ...
    百里寻陌阅读 256评论 0 1
  • 我在之前的《做Uber司机太没新意,当行家才是正经事》(http://shibeichen.com/post/12...
    师北宸阅读 562评论 1 4