Oracle数据库学习一

1.简介

数据存储有哪些方式?电子表格,纸质文件,数据库。

那么究竟什么是关系型数据库?

目前对数据库的分类主要是关系型和非关系型两种,关系型的主要代表有oracle,db2,mysql,sqlserver等,非关系型数据库也称作nosql,

主要有mongodb,hbase等等。关系型数据库主要是以二维表的方式存数数据的,这是关系数据库最显著的特征,

什么是二维表呢?

Excel表格就是二维表,由行和列两个维度所组成,想想excel表格,你就会知道数据库里面的表是什么样子的,道理是一模一样的。

而非关系型数据库的数据组织方式就五花八门了,有星型的,网状的等等,他们都统称为非关系型数据库,也叫nosql。

关系型数据库需要一组操作符,实际上就是需要一套命令,或者说是语言,也就是我们现在要学习的sql,它是我们和数据库进行沟通的工具。

2.Structured Query Language 结构化查询语言

(1)包含4种类型语句:

数据操纵语言DML-Data Manipulation Language SELECT ,INSERT, UPDATE, DELETE

数据定义语言DDL-Data Definition Language CREATE, ALTER, DROP

数据控制语言DCL-Data Control Language  GRANT REVOKE

事物控制语句TCL-Transacation Contrl Language COMMIT , ROLLBACK

(2)如何书写sql

大小写不敏感,但单引和双引内的大小写是敏感的.

关键字不能缩写select不能写成sel

字符串用单引 比如 ename='SEKER'

列的别名含特殊字符用双引

可跨行,但不要将关键字和单引的内容跨行.

跨行是为了可读性,一般我们都把select子句和from子句分行写.

不要在自定义参数部分使用sql的关键字。

3.SQL语法学习

(1)整个学习SQL过程是使用SCOTT用户的表来学习的 默认scott是被锁定的 解锁的方法

原始状态下,这个用户是被锁定的,我们需要解锁这个用户

SQL> conn / as sysdba

SQL> alter user scott account unlock identified by tiger;

通过sys解锁scott用户 并将scott的密码设置成tiger

SQL> conn scott/tiger

在以后的学习过程中 scott的表经常被修改 如果想将scott环境恢复默认 使用系统自带脚本即可

SQL> show user

USER is "SYS"

SQL> @?/rdbms/admin/utlsampl.sql

如果是windows版本则是 @?\rdbms\admin\utlsampl.sql

@是加载OS中的SQL保存文件

?是$ORACLE_HOME的替代

执行完脚本 会自动退出 重新登录 再对scott解锁即可

(2)一个完整的SQL命令叫语句(statement),每个关键字和后面跟着的选项叫子句(clause)

select 指定查询的列

from  指定查询的表

where  过滤的条件

order by 排序的列

DESC|ASC 排序方法

连接到scott用户

1.scott用户拥有哪些表?

SQL>select * from tab;

查询表中所有行所有列

SQL>select * from dept;

SQL>select * from emp;

如果屏幕显示的内容串行 是因为默认的显示的行长度是80字节 而选出的内容超出了80字节 可以修正一下

SQL> set linesize 100

如果有多个列标题 是一页内行数默认14行 也可以修正

SQL> set pagesize 1000

这个修改只是内存中的 可以将命令保存住到文件 实现永久配置

SQL> !ls $ORACLE_HOME/sqlplus/admin/g*

/u01/oracle/product/10.2.0/sqlplus/admin/glogin.sql

2.描述表结构

desc TABLE_NAME

SCOTT@ora10g> desc emp

Name       Null? Type

----------------------------- -------- --------------------

EMPNO       NOT NULL NUMBER(4)

ENAME VARCHAR2(10)

JOB VARCHAR2(9)

MGR NUMBER(4)

HIREDATE DATE

SAL NUMBER(7,2)

COMM NUMBER(7,2)

DEPTNO NUMBER(2)

SCOTT@ora10g> desc dept

SQL@ora10g> desc SALGRADE

desc描述表的结构 所谓表的结构:就是表有多少列 列的名称和类型及约束(非空)

desc emp

emp表(员工表)的结构介绍:

          emp表(员工表)的结构介绍:

          empno  员工工号 列为整数,最大长度为4位.

           ename  员工名字 列为变长字符型,最大长度10个字符

           job    出任职位 列为变长字符型,最大长度9个字符

           mgr    所属领导工号 列为整数,最大长度为4位

            hiredate入职日期 列为日期类型

            sal    工资 列为浮点数,最大长度为7位,其中包含2位小数

            comm    奖金 列为浮点数,最大长度为7为,其中包含2位小数

             deptno  部门号 列为整数,最大长度为两位

desc dept

dept表(部门表)的结构介绍

              deptno  部门号 列为整数,最大长度为两位

              dname  部门名字 列为变长字符型,最大长度为14个字符

              loc    部门所在地理位置 列为变长字符型,最大长度为13个字符

DESC SALGRADE

SALGRADE表(薪水等级表)的结构介绍 三列都是数值型

                GRADE  薪水等级

                LOSAL  所在等级中薪水底线

                HISAL 所在等级中薪水上限

3.查询表中指定的列

SQL>select ename,sal From emp;

select ename,sal from emp;

错误语法: select *,sal from emp; 星号不可以与单列同时存在

4.在sql中使用算术表达式

select ename,sal*12 from emp;

select ename,(500+sal)*12 from emp;

算术运算符优先级:

先乘除后加减,同优先级自左至右

小括号提高优先级,多重括号则自内而外

5.在查询中为列命名别名

select ename,sal*12 as annual_salary from emp;

select ename,sal*12 annual_salary from emp;

6.在别名中使用特殊字符 要用双引号

select ename,sal*12 "annual salary" from emp;

7.表别名 对emp表取了个简单别名e  这样就可以在引用表名时简化输入

select ename,sal from emp e;

同时也解决了星号和列同时出现的语法错误 别名的本质就是将非法的内容合法化

select e.*,sal from emp e;

8.连接操作符

select ename,job from emp;

select ename||' is a '||job from emp;

SQL> select ename||q'['s sal is]'||sal from emp;

9.去重复值

select deptno from emp;

select distinct deptno from emp;

多列去重

select distinct deptno,job from emp;

10.日期的显示格式

select hiredate from emp;

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

修改系统参数

alter system set nls_date_format='yyyy-mm-dd hh24:mi:ss' scope=spfile;

需要sysdba权限,静态参数,需要重启数据库生效

修改会话参数

SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

11. 虚表

虚表 oracle自动创建的一张表 可以理解为是一张假想表 目的是为了使select语义完成

借助虚表 我们可以完成很多事

查看当前用户

select user from dual;

查看当前时间(OS时间)

select sysdate from dual;

计算

select 9+8 from dual;

获取随机数

select dbms_random.random from dual;

等等...以后还有很多查询需要借助虚表完成.

12.过滤条件

select empno,ename,sal from emp where sal >= 1500;

WHERE是关键字 后面跟限制条件

条件由列名,字符串,算术表达式,常量和比较运算符组成;

比较运算符:

> >= < <= = <> !=

逻辑运算符:

and  or  not

oracle提供的比较运算符

between and        in             like                  is null

数值比较 直接写数值

SQL> select ename,sal from emp where sal >= 800 and sal <= 1100;

SQL> select ename,sal from emp where sal between 800 and 1100;

字符串比较 字符串要加单引号 默认存储模式就是大写模式

SQL> select ename,sal from emp where ename='KING';

时间格式比较

日期区间表示法

先修改日期显示为我们习惯的格式 否则写系统默认的时间格式 DD-MON-RR

alter session set NLS_date_format='YYYY-MM-DD HH24:MI:SS';

select ename,hiredate from emp where hiredate between '1981-01-01' and '1981-05-31';

13.oracle的与and 或or  非not

and(与)

select ename,sal from emp where sal<=1300 and sal >=900;

or(或)

select ename,sal from emp where sal<=1000 or sal >=4000;

not(非)

select ename,sal from emp where not sal >=4000;

与 ==> 两端都为真 返回真 若有一端或两端为假则为假

或 ==> 若有一端或两端为真则为真 两端都为假 返回假

但oracle中又引入了NULL

AND运算表

T and F = F     T and T = T       T and NULL is NULL

F and F = F     F and T = F       F and NULL = F

NULL and F = F    NULL and T is NULL    NULL and NULL is NULL

idle> select ename,sal from emp where sal >2000 and sal <3000;

OR运算表

T or T = T   T or F = T200       T or NULL = T

F or T = T    F or F = F       F or NULL IS NULL

NULL or T = T    NULL OR F is NULL    NULL OR NULL IS NULL

idle> select ename,sal,comm from emp where sal = 1250 or comm is not null;

14.oracle提供的运算符

like     between and     in    not like

is not null     not between and

运算符的优先级不用记忆 想提高优先级加小括号即可

SQL> select *from scott.emp where sal>2000 and deptno=20 or deptno=30;

SQL> select *from scott.emp where sal>2000 and (deptno=20 or deptno=30);

用and or 来代替 between and 和 in

idle> select empno,ename,sal from emp where sal between 1000 and 1300;

idle> select empno,ename,sal from emp where sal >=1000 and sal <= 1300;

idle> select empno,ename,sal from emp where ename in ('SCOTT','KING','ADAMS');

idle> select empno,ename,sal from emp where ename = 'SCOTT' or ename = 'KING' or ename = 'ADAMS';

like 通配符: % 任意长度(包括零长度)通配符

_ 单个字符通配符

部门名像 SAL开头的

select ename,job from emp where job like 'SAL%';

任意一个字符后跟A之后任意字符串的名字

select ename,job from emp where ename like '_A%';

取反

select ename,job from emp where ename not like '_A%';

like中使用转义

如果查询的字符串包含_或%字面字符串则需要转义

转义符号需要在子句中用escape指明

select  * from dept_tmp where dname like 'IT_%';

select  * from dept_tmp where dname like 'IT\_%' escape '\';

15.order by 排序输出

排序一定要放在sql语句的最后

排序格式化了输出 确给SQL执行增加了负担

默认是从小到大(升序) ASC; 逆序(降序)DESC

select ename,sal from emp where sal < 1500 order by sal;

select ename,sal from emp where sal < 1500 order by sal asc;

select ename,sal from emp where sal < 1500 order by sal desc;

order by中使用表达式

select ename,sal*12 from emp where sal < 1500 order by sal*12;

order by中使用别名

select ename,sal*12 "abc" from emp where sal < 1500 order by "abc";

order by中使用列号 列号必须是select子句中已经选择的列的顺序号

select ename,sal*12 "abc" from emp where sal < 1500 order by 2;

order by中使用多列 先按职位A-Z的顺序 再按年薪小到大的顺序

select ename,job,sal*12 "abc" from emp where sal < 1500 order by 2,3;

order by中使用select子句中未选择的列

select ename,job,sal*12 "abc" from emp where sal < 1500 order by deptno;

4.单行函数

什么是函数?

通俗的讲 任何东西,只要它能接收输入,对输入进行加工并产生输出,它就可以被称之为函数

例如:牛是函数,它吃的是草(输入),挤出的是奶(输出)

函数是一种程序设计结构,它可以有一个或多个输入,但只能有一个输出.

函数只有一个出口,使用函数组成的程序很容易调试,也很容易被重用

1.字符类型的函数

字符型

ASCII      CHR        LOWER        UPPER            INITCAP  CONCAT    SUBSTR      

 LENGTH   INSTR   TRIM    dump   lpad   rpad      REPLACE

ASCII('字符')

返回字符的ASCII码值

SCOTT>>select ascii('a') from dual;

ASCII('a')

----------

        97

CHR('n')

返回n的字符值 n是ASCII码数

SCOTT>>select chr(97) from dual;

C

-

a

但是求单引号的ASCII码写法很特殊 两个单引带表一个单引

SCOTT>>select ascii(''') from dual;

ERROR:

ORA-01756: quoted string not properly terminated

SCOTT>>select ascii('''') from dual;

ASCII('''')

-----------

39

LOWER(列名|表达式)

小写转换

idle> select lower('ABC') from dual;

LOW

---

abc

UPPER(列名|表达式)

大写转换

SCOTT>>select upper('abc')from dual;

UPP

---

ABC

INITCAP(列名|表达式)

每个词的词头大写 其他小写

SCOTT>>select initcap('abc xyz qwe')from dual;

INITCAP('AB

-----------

Abc Xyz Qwe

CONCAT(列名|表达式,列名|表达式)

将第一个字符串和第二个字符串连接

SQL> select concat('abc','xyz') from dual;

CONCAT

------

abcxyz

该合数与||功能一样,但是我们常用的是后者

SQL> select 'abc'||'xyz' from dual;

'ABC'|

------

abcxyz

SUBSTR(列名|表达式,m,[n])

返回指定子串,该子串是从第m个字符开始,其长度为n,不指定n值则从m到最后

SQL> select substr('abcdefg',4,3)from dual;

SUB

---

def

SQL> select substr('abcdefg',4)from dual;

SUBS

----

defg

LENGTH(列名|表达式)

返回字符串的长度

SQL> select length('abcdef')from dual;

LENGTH('ABCDEF')

----------------

               6

LENGTHB(列名|表达式)

返回字符串所占用的字节数

INSTR (列名|表达式,'字符串',[m],[n])

从表达式或列中搜索给定的字符串的所处位置,m代表从第几个字符开始搜,n代表要搜索的字符第几次出现. m和n默认都是1

SQL> select instr('abcdddd','d') from dual;

INSTR('ABCDDDD','D')

--------------------

                    4

SQL> select instr('abcdddd','d',5) from dual;

INSTR('ABCDDDD','D',5)

----------------------

                      5

SQL> select instr('abcdddd','d',5,2) from dual;

INSTR('ABCDDDD','D',5,2)

------------------------

                      6

TRIM([leading|]trailing|both 要去掉的字符 FROM 源字符串)

从源字符串中去掉指定的字符 可以用leading tailing来修饰去掉的字符串是在开头或结尾,默认是两者都

默认截取的是空格,生产上有时候有的字段会产生空格,这个会给应用带来很大的麻烦,用这个函数就

可以很容易的,除去字段两头的空格,是非常实用的。

SQL> select trim(leading 'a' from 'aaabbbbbaaaa')from dual;

TRIM(LEAD

---------

bbbbbaaaa

SQL> select trim(trailing 'a' from 'aaabbbbbaaaa')from dual;

TRIM(TRA

--------

aaabbbbb

SQL> select trim(both 'a' from 'aaabbbbbaaaa')from dual;

TRIM(

-----

bbbbb

SQL> select trim('a' from 'aaabbbbbaaaa')from dual;

TRIM(

-----

bbbbb

SQL> select trim('  aaabbbbbaaaa  ')from dual;

TRIM('AAABBB

------------

aaabbbbbaaaa

左补齐lpad 右补齐rpad

将不足20个字符的位置用指定符号填充.

SQL> select lpad('abc',20,'-'),rpad('abc',20,'-') from dual;

LPAD('ABC',20,'-')  RPAD('ABC',20,'-')

-------------------- --------------------

-----------------abc abc-----------------

REPLACE(源字符串,OLD字符串,NEW字符串)

从源字符串中找到搜索的old字符串,替换成new字符串

SQL> select replace('abcdefxyz','def','DEF')from dual;

REPLACE('

---------

abcDEFxyz

dump('str'[,FMT[,S,E]])

用于转换进制格式

str 被转换的字符串

FMT 格式

默认是十进制的

8:用八进制方式显示

16:使用16进制方式显示

1016:把数据库当前字符集显示出来

S  str的开始字符位置

E  S开始的后续结束字符位置

SQL> select dump('abcd') from dual;

DUMP('ABCD')

--------------------------

Typ=96 Len=4: 97,98,99,100

SQL>

SQL>

SQL> select dump('abcd',2) from dual;

DUMP('ABCD',2)

--------------------------

Typ=96 Len=4: 97,98,99,100

SQL> select dump('abcd',10) from dual;

DUMP('ABCD',10)

--------------------------

Typ=96 Len=4: 97,98,99,100

SQL> select dump('abcd',8) from dual;

DUMP('ABCD',8)

-----------------------------

Typ=96 Len=4: 141,142,143,144

SQL> select dump('abcd',16) from dual;

DUMP('ABCD',16)

-------------------------

Typ=96 Len=4: 61,62,63,64

SQL> select dump('abcd',1010) from dual;

DUMP('ABCD',1010)

------------------------------------------------

Typ=96 Len=4 CharacterSet=ZHS16GBK: 97,98,99,100

SQL> select dump('戴')from dual;

DUMP('戴')

---------------------

Typ=96 Len=2: 180,247

SQL> select 180*power(256,1)+247 from dual;

180*256+247

-----------

46327

SQL> select chr(46327) from dual;

CH

--

SQL> select dump(987654321) from dual;

DUMP(987654321)

-------------------------------

Typ=2 Len=6: 197,10,88,66,44,22

197-193=4

10-1=9*power(100,(4-0))=900000000

88-1=87*power(100,(4-1))=87000000

66-1=65*power(100,(4-2))=650000

44-1=43*power(100,(4-3))=4300

22-1=21*power(100,(4-4))=21

2.数值型函数

           ROUND

           TRUNC

            MOD

            CEIL

            power

            greatest

            least

ROUND(列名|表达式,n)

四舍五入到小数点后的n位

SQL> select round(456.789,0),round(456.789,1),round(456.789,-1)from dual;

ROUND(456.789,0) ROUND(456.789,1) ROUND(456.789,-1)

----------------                    ----------------                   -----------------

          457                              456.8                            460

TRUNC(列名|表达式,n)

截取到小数点后的n位

SQL> select trunc(456.789,0),trunc(456.789,1),trunc(456.789,-1) from dual;

TRUNC(456.789,0) TRUNC(456.789,1) TRUNC(456.789,-1)

     ----------------                ----------------              -----------------

          456                            456.7                           450

MOD(m,n)

求m除以n的余数

SQL> select mod(10,3) from dual;

MOD(10,3)

  ----------

       1

SQL> select mod(3,10) from dual;

MOD(3,10)

   ----------

       3

CEIL 取整 向上补1  和trunc相反

SQL> select ceil(456.001)from dual;

CEIL(456.001)

    -------------

         457

power(底数,指数) 求次方

SQL> select power(10,3) from dual;

POWER(10,3)

   -----------

      1000

greatest(expr1,expr2.......) 求出所列出的表达式或者值中的最大值

SQL> select greatest(1,2,3,4)from dual;

GREATEST(1,2,3,4)

      -----------------

              4

least(expr1,expr2.......) 求出所列出的表达式或者值中的最小值

SQL> select least(1,2,3,4)from dual;

LEAST(1,2,3,4)

    --------------

           1

3.日期类型的函数

修改当前会话的日期显示格式

SQL> ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD HH24:MI:SS';

使用函数查看系统当前时间,这个时间来自于操作系统,数据库里面是不存储当前时间的

SQL> select sysdate from dual;

SYSDATE

-------------------

2016-05-20 13:35:57

日期的运算

默认情况下,参与运算的单位是‘天’

SQL> select sysdate-10 from dual;

SYSDATE-10

-------------------

2016-05-10 13:39:09

如果想让小时参与运算,可以处以24

SQL> select sysdate-10/24 from dual;

SYSDATE-10/24

-------------------

2016-05-20 03:48:42

以此类推,分钟,秒都可以这样计算

与日期有关的函数

MONTHS_BETWEEN

ADD_MONTHS

NEXT_DAY

LAST_DAY

ROUND 和 TRUNC 对日期的取舍

MONTHS_BEWTEEN(日期1,日期2)

计算两个日期间所相差的月份

日期1大于日期2返回正数,日期1小于日期2返回负数

SQL> select months_between('2016-07-21','2016-01-01') from dual;

MONTHS_BETWEEN('2016-07-21','2016-01-01')

       -----------------------------------------

                  6.64516129

ADD_MONTHS(日期,n)

把n个月加到日期上

SQL> select add_months(sysdate,5)from dual;

ADD_MONTHS(SYSDATE,

        -------------------

     2016-10-20 13:58:57

NEXT_DAY(日期,星期)

从给定日期算起,下一个指定的星期几是几号

SQL> select next_day(sysdate,'MONDAY')FROM DUAL;

NEXT_DAY(SYSDATE,'M

-------------------

2016-05-23 14:01:19

SQL> select next_day('2016-05-12','MONDAY')FROM DUAL;

NEXT_DAY('2016-05-1

-------------------

2016-05-16 00:00:00

LAST_DAY(日期)

返回该日期的所在月的最后一天

SQL> select last_day(sysdate) from dual;

LAST_DAY(SYSDATE)

-------------------

2016-05-31 14:03:17

我们修改一下日期显示的格式

ROUND(date,'[day|month|year]') 和 trunc(date,'[day|month|year]') 应用于日期型数据

数字的进位和截取是以小数点为中心,而日期的进位和截取是以年月日时分秒为中心

round 截取月份以16号为分割,16号及其以后的日期都入到下一个月

16号之前的日期都返回月初的日期

SQL> select round(to_date('2016-05-20'),'month')from dual;

ROUND(TO_DATE('2016

-------------------

2016-06-01 00:00:00

年的四舍五入要所输入的月份,六月及其以前的日期,都返回年初,六月之后的日期返回下一年年初

SQL> select round(to_date('2016-06-16'),'year')from dual;

ROUND(TO_DATE('2016

-------------------

2016-01-01 00:00:00

以周三中午12点为分界线,周三之前返回本周日的0:00,周三之后的日期,返回下周日的0:00

西方以周日为一周的开始

SQL> select round(to_date('2016-07-20 11:01:01'),'day') from dual;

ROUND(TO_DATE('2016

-------------------

2016-07-17 00:00:00

SQL> select round(to_date('2016-07-21 11:01:01'),'day') from dual;

ROUND(TO_DATE('2016

-------------------

2016-07-24 00:00:00

4.类型转换函数

不同数据类型之间的转换

在赋值语句中数据类型会隐式转换,隐式转换应当尽量避免,因为写出来的SQL难理解,随着时间流逝自己都很难理解

特别是嵌入到大型程序中时,另外,oracle升级会修改隐式转换的规则,这会使程序移植遇到问题.

尤其是索引列不能使用隐式转换 那样就不走索引了

赋值语句中oracle的自动转换规则:

1.将变长字符型(varchar2)或定长字符型(char)转换成数值型(number)

2.将变长字符型(varchar2)或定长字符型(char)转换成日期型(date)

3.将数值型(number)转换成变长字符型(varchar2)

4.将日期型(date)转换成变长字符型(varchar2)

表达式中oracle的自动转换规则:

1.将变长字符型(varchar2)或定长字符型(char)转换成数值型(number)

2.将变长字符型(varchar2)或定长字符型(char)转换成日期型(date)

转换成功的条件:

在将字符型数据转换成数字型时,要保证字符型数据为有效的数.

在将字符型数据转换成日期型时,要保证字符型数据为有效的日期.


SQL> select ename,sal from emp where sal>'4000';

ENAME   SAL

---------- ----------

KING 5000

以上例子中oracle自动将字符型的数据转换成了数值型

SQL> select ename,hiredate from emp where hiredate='1981-11-17';

ENAME   HIREDATE

---------- -------------------

KING   1981-11-17 00:00:00

以上例子中oracle自动将自负类型转换为了日期类型

注意:不能直接转换的情况

数值型和日期型之间不能直接转换,必须将其中之一先转换为字符型,之后再转换为另一种类型

显示转换函数:

to_char

to_number

to_date

to_char  两种情况:

1.to_char(数字) 目的是将数字格式化货币显示格式

2.to_char(日期) 目的是将日期格式化需要的格式

避免隐式转换

to_number 不常用,因为数值可以直接输入

to_date  很常用,因为日期是不可以输入 只能转


to_char(日期,'fmt')

将日期型数据转换成字变长字符串.fmt为日期格式

日期格式必须用单引号扩起来

常用的时间格式:

YYYY  数字年         YEAR  英文年

MM    数字月            MONTH 英文月

DY    缩写的星期       DAY  完整的星期

DD    数字日期            hh    12小时

HH24  24小时             MI    分钟

SS    秒

SQL> select ename,

to_char(hiredate,'yyyy-mm-dd year month day dy') hiredate

from emp where ename='SCOTT';

ENAME   HIREDATE

---------- --------------------------------------------------------------------------------

SCOTT   1987-04-19 nineteen eighty-seven april    sunday sun

以上例子中scott的入职日期被以各种维度显示出来了


to_char(数字,'fmt')

将数字转换成变长字符串.fmt为数字格式

9 一个数字  给定的9个数不足 会显示#

0 显示前导0

$ 美元符号

L 本地货币符号

. 小数点

, 千位符

SQL> select to_char(sal,'L99999')from emp where ename='SCOTT';

TO_CHAR(SAL,'L99999')

--------------------------------

¥3000

SQL> select to_char(sal,'L99999','nls_currency=rmb')from emp where ename='SCOTT';

TO_CHAR(SAL,'L99999','NLS_CURREN

--------------------------------

rmb3000

to_char 还可以将10进制数转换成16进制数

SQL> select to_char(97,'xxxx') from dual;

TO_CHAR(97

----------

61


to_number('字符串','数字格式')

这个数字格式体现的是前面字符串的格式

字符串一定要符合数字的格式

SQL> select to_number('$123.456','$99999.999')from dual;

TO_NUMBER('$123.456','$99999.999')

----------------------------------

123.456

to_number 也可以将16进制转换成10进制

SQL> select to_number('a','xxxxx')from dual;

TO_NUMBER('A','XXXXX')

----------------------

10

SQL> select to_number(61,'xxxxx')from dual;

TO_NUMBER(61,'XXXXX')

---------------------

97

TO_DATE('字符串','日期格式')

字符串一定要符合日期格式

SQL> select to_date('20-MAY-16','DD-MON-RR')from dual;

TO_DATE('20-MAY-16'

-------------------

2016-05-20 00:00:00

简化输入的操作,必须使用yyyy-mm-dd格式,并且只能精确到天

SQL> select date'2016-07-22' from dual;

DATE'2016-07-22'

-------------------

2016-07-22 00:00:00

5.NULL值处理函数

null值

是一个很特别的值,既不是0也不是空格.它的值是没有定义,不确定的未知值

比如一个案件的追踪表,警方在对犯罪分子一无所知,但在犯罪分子性别一栏不是男就是女,

只是此时还不确定

就可以把性别栏设置为未知,当案件侦破到一定程度,警方知道了犯罪分子的性别,

既从未知变成了已知.也就是由NULL变成男或女

SQL> select empno,ename,sal,comm from emp where ename in('SCOTT','WARD');

EMPNO ENAME     SAL      COMM

---------- ---------- ---------- ----------

7521 WARD     1250 500

7788 SCOTT     3000

以上输出内容的奖金一列存在空值,如果我们统计总收入的话,那么就会出现下面的情况

奖金为null的员工最终的工资还是null,这是不合理的

SQL> select empno,ename,sal,comm,sal+comm total_sal from emp where ename in('SCOTT','WARD');

EMPNO ENAME     SAL      COMM  TOTAL_SAL

---------- ---------- ---------- ---------- ----------

7521 WARD     1250 500   1750

7788 SCOTT     3000

SQL> select ename,sal from emp where comm=null;

no rows selected

想要找到奖金为null的员工信息,却没有任何结果

这是由null的特殊性决定的,null不参与运算,因此只能用is null来描述它

SQL> select ename,sal from emp where comm is null;

ENAME   SAL

---------- ----------

SMITH   800

JONES 2975

BLAKE 2850

CLARK 2450

SCOTT 3000

KING 5000

ADAMS 1100

JAMES   950

FORD 3000

MILLER 1300

SQL> select ename,sal,comm from emp where comm is not null;

ENAME   SAL     COMM

---------- ---------- ----------

ALLEN 1600     300

WARD 1250     500

MARTIN 1250     1400

TURNER 1500       0

要使null能够参与运算,需要用函数来将null值进行转化,相关函数有

NVL

NVL2

NULLIF

COALESCE

NVL(表达式1,表达式2)

如果表达式1是NULL,则返回表达式2

如果表达式1非NULL,则返回表达式1

表达式1和表达式2可以是数字,字符串,日期格式,1和2的数据类型必须一致

SQL> select ename,sal,comm,sal+nvl(comm,0)from emp where ename in('SCOTT','WARD');

ENAME   SAL     COMM SAL+NVL(COMM,0)

---------- ---------- ---------- ---------------

WARD 1250     500     1750

SCOTT 3000     3000

NVL2(expr1,expr2,expr3)

如果expr1为空,则返回expr3,否则返回expr2

SQL> select ename,sal,comm,sal+nvl2(comm,comm,0)from emp where ename in('SCOTT','WARD');

ENAME   SAL     COMM SAL+NVL2(COMM,COMM,0)

---------- ---------- ---------- ---------------------

WARD 1250     500   1750

SCOTT 3000   3000

NULLIF(expr1,expr2)

如果expr1和expr2相同,则返回空,否则返回expr1

SQL> select empno,ename,NULLIF(ename,'SCOTT')FROM EMP where ename in ('SCOTT','KING');

EMPNO ENAME      NULLIF(ENA

---------- ---------- ----------

7788 SCOTT

7839 KING      KING

空值的排序 升序会排在最后 降序排在最前

SQL> select empno,ename,sal,comm from emp where ename in('SCOTT','WARD') ORDER BY COMM;

EMPNO ENAME     SAL      COMM

---------- ---------- ---------- ----------

7521 WARD     1250 500

7788 SCOTT     3000

SQL> select empno,ename,sal,comm from emp where ename in('SCOTT','WARD') ORDER BY COMM DESC;

EMPNO ENAME     SAL      COMM

---------- ---------- ---------- ----------

7788 SCOTT     3000

7521 WARD     1250 500

COALESCE(expr1,expr2,expr3,...)

返回第一个非空的表达式

SQL> select coalesce('','','a','','','b','','')from dual;

C

-

a

SQL> select coalesce('','','','','','b','','')from dual;

C

-

b

emp表中有奖金的展示奖金,没有奖金的展示工资

6.分支函数

分支函数

decode函数

decode(expr,search1,result1,search2,result2......,default)

这个函数是返回一个表达式在各种可能取值的情况下的值

例如,expr满足search1,则返回result1,满足search2则返回result2,以此类推,

最终如果没有满足任何比对条件,则返回default值

SQL> select empno,ename,deptno,decode(deptno,10,'AAA',20,'BBB','CCC') FROM EMP;

EMPNO ENAME   DEPTNO DEC

---------- ---------- ---------- ---

7369 SMITH       20 BBB

7499 ALLEN       30 CCC

7521 WARD       30 CCC

7566 JONES       20 BBB

7654 MARTIN       30 CCC

7698 BLAKE       30 CCC

7782 CLARK       10 AAA

7788 SCOTT       20 BBB

7839 KING       10 AAA

7844 TURNER       30 CCC

7876 ADAMS       20 BBB

7900 JAMES       30 CCC

7902 FORD       20 BBB

7934 MILLER       10 AAA

练习:

按部分编号涨工资(只打印) 10号部门涨10% 20号部分涨20% 其他部分涨30%

SQL> select ename,sal deptno,case when deptno=10 then sal+sal*0.1

2  when deptno=20 then sal+sal*0.2

3  else sal+sal*0.3 end up_sal from emp;


case when 子句

case when 子句分为简单和搜索两种

简单case when子句的语法:

case expr when comparation_expr then return_expr...... else else_expr end

简单的case when子句可以实现等值比较,与decode一样

SQL> select ename,sal,case deptno when 10 then 'AAA' when 20 then 'BBB' else 'CCC' end from emp;

ENAME   SAL CAS

---------- ---------- ---

SMITH   800 BBB

ALLEN 1600 CCC

WARD 1250 CCC

JONES 2975 BBB

MARTIN 1250 CCC

BLAKE 2850 CCC

CLARK 2450 AAA

SCOTT 3000 BBB

KING 5000 AAA

TURNER 1500 CCC

ADAMS 1100 BBB

JAMES   950 CCC

FORD 3000 BBB

MILLER 1300 AAA

14 rows selected.

搜索case when可以实现不等值的比较

case  when condation then return_expr...... else else_expr end

SQL> select ename,sal,case

when sal<1000 then sal+1

when sal>=1000 and sal<2000 then sal+2

when sal>=2000 then sal+3

else sal+4 end up_sal

from emp

ENAME   SAL   UP_SAL

---------- ---------- ----------

SMITH   800     801

ALLEN 1600     1602

WARD 1250     1252

JONES 2975     2978

MARTIN 1250     1252

BLAKE 2850     2853

CLARK 2450     2453

SCOTT 3000     3003

KING 5000     5003

TURNER 1500     1502

ADAMS 1100     1102

JAMES   950     951

FORD 3000     3003

MILLER 1300     1302

14 rows selected.

7.聚集函数

多行函数 聚集函数

常用聚集函数

是对一组或一批数据进行综合操作后返回一个结果

count 行总数

avg         平均数

sum 列值的和

max 最大值

min         最小值

count([{distinct|all} '列名'|*) 为列值时空不在统计之内,为*时包含空行和重复行

SQL> select count(*) from emp;

COUNT(*)

----------

14

SQL>

SQL>

SQL> select count(comm)from emp;

COUNT(COMM)

-----------

4

SQL> select count(distinct deptno)from emp;

COUNT(DISTINCTDEPTNO)

---------------------

3

SQL> select count(deptno)from emp;

COUNT(DEPTNO)

-------------

14

SQL> select max(sal),avg(sal),min(sal),count(sal) from emp;

MAX(SAL)  AVG(SAL) MIN(SAL) COUNT(SAL)

---------- ---------- ---------- ----------

5000 2073.21429     800 14

上面执行的聚集函数都是对所有记录统计,一次只返回一行记录

如果想分组统计(比如统计部门的平均值)需要使用group by

为了限制分组统计的结果需要使用having过滤

GROUP BY 分组统计  9I要排序 10G不排序

求出每个部门的平均工资

SQL> select deptno,avg(sal) from emp group by deptno;

DEPTNO  AVG(SAL)

---------- ----------

30 1566.66667

20 2175

10 2916.66667

还可以按照给定字段进行排序

SQL> select deptno,avg(sal) from emp group by deptno order by deptno;

DEPTNO  AVG(SAL)

---------- ----------

10 2916.66667

20 2175

30 1566.66667

分组排序可以使用未被选择的列

SQL> select avg(sal) from emp group by deptno order by deptno;

AVG(SAL)

----------

2916.66667

2175

1566.66667

如果在查询中使用了分组函数,任何不在分组函数中的列或表达式必须在group by子句中

SQL> select deptno,avg(sal) from emp;

select deptno,avg(sal) from emp

*

ERROR at line 1:

ORA-00937: not a single-group group function

group by 的过滤

group by的过滤使用having子句,放在group by 子句的后面,

和where子句不同,having子句是在分组计算完成后进行的过滤,而where

子句是在分组计算前做的过滤,where 条件里面只能出现单行处理函数,而having

子句可以出现聚集函数

SQL> select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;

DEPTNO  AVG(SAL)

---------- ----------

20 2175

10 2916.66667

分组函数的注意事项:

1.分组函数只能出现在选择列,order by,having子句中

2.分组函数会忽略NULL 除了count(*)

3.分组函数中可以使用ALL或distinct;ALL是默认值,统计所有.加上distinct则只统计不同

4.如果选择的列里有普通列,表达式和分组列 那么普通列和表达式都必须出现在group by中

行转列

create table t4(id int,name varchar2(10),subject varchar2(20),grade number);

insert into t4 values(1,'ZORRO','语文',70);

insert into t4 values(2,'ZORRO','数学',80);

insert into t4 values(3,'ZORRO','英语',75);

insert into t4 values(4,'SEKER','语文',65);

insert into t4 values(5,'SEKER','数学',75);

insert into t4 values(6,'SEKER','英语',60);

insert into t4 values(7,'BLUES','语文',60);

insert into t4 values(8,'BLUES','数学',90);

insert into t4 values(9,'PG','数学',80);

insert into t4 values(10,'PG','英语',90);

commit;

SQL> select * from t4;

ID NAME      SUBOBJECT GRADE

---------- ---------- -------------------- ----------

1 ZORRO      语文                        70

2 ZORRO      数学                        80

3 ZORRO      英语                        75

4 SEKER      语文                        65

5 SEKER      数学                        75

6 SEKER      英语                        60

7 BLUES      语文                        60

8 BLUES      数学                        90

9 PG        数学                        80

10 PG        英语                        90

10 rows selected.

SQL> select name,sum(case when SUBJECT='语文' then GRADE else 0 end) "语文",sum(case when SUBJECT='数学' then GRADE else 0 end) "数学",sum(case when SUBJECT='英语' then GRADE else 0 end) "英语" from t5 group by name;

NAME                                                    语文      数学      英语

-------------------------------------------------- ---------- ---------- ----------

SEKER                                                      65        75        60

BLUES                                                       60        90          0

PG                                                               0        80        80

ZORRO                                                      70        80        75

推荐阅读更多精彩内容