【sql】编写基本的SQL SELECT语句二


过滤和排序数据

-     在查询中过滤行。

-     在查询中对行进行排序。

-     在运行时使用“&”字符替换来限制和排序输出

1.1.  过滤

-     使用WHERE子句,将不满足条件的行过滤掉

-     WHERE子句紧随FROM子句

语法:

SELECT *|{[DISTINCT] column|expression [alias],...}

FROM   table

[WHERE condition(s)];

 

1)   使用WHERE子句

SELECT employee_id, last_name, job_id, department_id

  FROM employees

 WHERE department_id = 90;

2)   WHERE 子句中的字符和日期

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

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

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

 

SELECT last_name, job_id, department_id

  FROM employees

 WHERE last_name = 'Whalen'

/

SELECT last_name, hire_date

  FROM employees

 WHERE hire_date = '2007-6-21'

/

hire_date字段为日期型,'2007-6-21'的格式要与当前会话的nls_date_format的格式相同

    格式相同,字符串会做一个隐式的转换

1.2.  比较运算符

=,>,>=,<,<=,<>(!=,^=),BETWEEN...AND...,IN(),LIKE,IS NULL

1)   使用比较运算符

SELECT last_name, salary

  FROM employees

 WHERE salary <= 3000;

2)   使用BETWEEN 操作符

SELECT last_name, salary

  FROM employees

 WHERE salary BETWEEN 2500 AND 3500;

注使用 BETWEEN 操作符来显示在一个区间内的值,结果包含边界值

3)   使用IN 操作符

SELECT employee_id, last_name, salary, manager_id

  FROM employees

 WHERE manager_id IN (100, 101, 201);

4)   使用LIKE 操作符

-     % 代表一个或多个字符。

-     _ 代表一个字符。

SELECT first_name FROM employees WHERE first_name LIKE 'S%'

/

SELECT last_name FROM employees WHERE last_name LIKE '_o%'

/

-     使用 ESCAPE 标识符

SELECT employee_id, last_name, job_id FROM employees

 WHERE job_id LIKE '%SA\_%' ESCAPE '\';

问:如果字符串中有两个连续的“_”,那么是否需要两次转义不需要

测试脚本如下:

insert into t_like values(6,'a__d');

commit;

SQL1select * from t_like where y like 'a\__d%' escape '\';

SQL2select * from t_like where y like 'a\_\_d%' escape '\';

5)   使用NULL条件

使用IS NULL 操作符判断空值

SELECT last_name, manager_id FROM employees WHERE manager_id IS NULL;

注在检索null时,无法用=<>来进行判断,只允许用is nullis not null来进行判断

1.3.  逻辑运算符

AND,OR,NOT

1)   使用AND 运算符(要求两边条件都为真)

SELECT employee_id, last_name, job_id, salary

  FROM employees

 WHERE salary >= 10000 AND job_id LIKE '%MAN%';

2)   使用OR 运算符(只要任一条件为真即可)

SELECT employee_id, last_name, job_id, salary

  FROM employees

 WHERE salary >= 10000 OR job_id LIKE '%MAN%'

3)   使用NOT 操作符

SELECT last_name, job_id

  FROM employees

 WHERE job_id NOT IN ('IT_PROG', 'ST_CLERK', 'SA_REP')

/

SELECT last_name, manager_id FROM employees WHERE manager_id IS NOT NULL

/

1.4.  表达式中运算符优先级

1.   算数运算符

2.   连接符

3.   比较符

4.   IS [NOT] NULL, LIKE, [NOT] IN

5.   [NOT] BETWEEN

6.   不等于

7.   NOT

8.   AND

9.   OR

SELECT last_name, job_id, salary

  FROM employees

 WHERE job_id = 'SA_REP'

    OR job_id = 'AD_PRES'

   AND salary > 15000

/

SELECT last_name, job_id, salary

  FROM employees

 WHERE (job_id = 'SA_REP' OR job_id = 'AD_PRES')

   AND salary > 15000

/

1.5.  排序

-     使用ORDER BY 子句排序:ASC(升序,默认),DESC(降序)

-     ORDER BY 子句在SELECT 语句结尾

1)   默认(升序)排序

SELECT last_name, job_id, department_id, hire_date

  FROM employees

 ORDER BY hire_date;

2)   降序排序

SELECT last_name, job_id, department_id, hire_date

  FROM employees

 ORDER BY hire_date DESC;

3)   使用别名默认排序

SELECT employee_id, last_name, salary * 12 annsal

  FROM employees

 ORDER BY annsal;

4)   使用的列的数字位置

SELECT last_name, job_id, department_id, hire_date

  FROM employees

 ORDER BY 3;

5)   按多个列排序

SELECT last_name, department_id, salary

  FROM employees

 ORDER BY department_id DESC, salary ASC;

6)   排序字段包含NULL

SELECT DISTINCT department_id FROM employees ORDER BY 1;

    我们会发现,结果中有NULL值,升序排序后,NULL值在最下面(反之在最上面),因为NULL值是未知的,也就是无穷大

    如果,我们的需求是,非空值升序,空值在显示结果的最上面

SELECT DISTINCT department_id FROM employees ORDER BY 1 ASC NULLS FIRST;

    如果,我们的需求是,非空值降序,控制在显示结果的最下面

SELECT DISTINCT department_id FROM employees ORDER BY 1 DESC NULLS LAST;

1.6.  替代变量

-     使用&&&临时存储值,替代变量

-     使用替代变量,可以替代以下内容

ü   WHERE 条件

ü   ORDER BY 子句

ü   列表达式

ü   表名

ü   整个 SELECT 语句

1)   数值型变量

HR@ORA11GR2>SELECT employee_id, last_name, salary, department_id

  2    FROM employees

  3   WHERE employee_id = &v_num;

Enter value for v_num: 101

old   3:  WHERE employee_id = &v_num

new   3:  WHERE employee_id = 101

 

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID

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

 101 Kochhar                       17000            90

 

HR@ORA11GR2>

2)   字符型变量

HR@ORA11GR2>SELECT last_name, department_id, salary*12

  2  FROM   employees

  3  WHERE  job_id = '&job_title' ;

Enter value for job_title: HR_REP

old   3: WHERE  job_id = '&job_title'

new   3: WHERE  job_id = 'HR_REP'

 

LAST_NAME                 DEPARTMENT_ID  SALARY*12

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

Mavris                               40      78000

 

HR@ORA11GR2>

3)   日期型变量

HR@ORA11GR2>SELECT last_name, department_id, salary FROM employees WHERE hire_date = '&hd';

Enter value for hd: 2008/1/13

old   1: SELECT last_name, department_id, salary FROM employees WHERE hire_date = '&hd'

new   1: SELECT last_name, department_id, salary FROM employees WHERE hire_date = '2008/1/13'

 

LAST_NAME                DEPARTMENT_ID     SALARY

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

Grant                               50       2600

 

HR@ORA11GR2>

HR@ORA11GR2>SELECT last_name, department_id, salary FROM employees WHERE hire_date = to_date('&hd', 'yyyy-mm-dd');

Enter value for hd: 2008/1/13

old   1: SELECT last_name, department_id, salary FROM employees WHERE hire_date = to_date('&hd', 'yyyy-mm-dd')

new   1: SELECT last_name, department_id, salary FROM employees WHERE hire_date = to_date('2008/1/13', 'yyyy-mm-dd')

 

LAST_NAME                DEPARTMENT_ID     SALARY

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

Grant                               50       2600

 

HR@ORA11GR2>

4)   WHERE子句、ORDER BY子句、字段

HR@ORA11GR2>SELECT employee_id, last_name, job_id, &column_name

  2    FROM employees

  3   WHERE &condition

  4   ORDER BY &order_column;

Enter value for column_name: email

old   1: SELECT employee_id, last_name, job_id, &column_name

new   1: SELECT employee_id, last_name, job_id, email

Enter value for condition: manager_id=101

old   3:  WHERE &condition

new   3:  WHERE manager_id=101

Enter value for order_column: 1

old   4:  ORDER BY &order_column

new   4:  ORDER BY 1

 

EMPLOYEE_ID LAST_NAME                 JOB_ID     EMAIL

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

 108 Greenberg                 FI_MGR     NGREENBE

 200 Whalen                    AD_ASST    JWHALEN

  203 Mavris                    HR_REP     SMAVRIS

  204 Baer                      PR_REP     HBAER

  205 Higgins                   AC_MGR     SHIGGINS

 

HR@ORA11GR2>

5)   使用&&替代变量(重复变量,无需再次录入)

HR@ORA11GR2>SELECT employee_id, last_name, job_id, &&column_name

  2    FROM employees

  3   WHERE &condition

  4   ORDER BY &column_name;

Enter value for column_name: hire_date

old   1: SELECT employee_id, last_name, job_id, &&column_name

new   1: SELECT employee_id, last_name, job_id, hire_date

Enter value for condition: department_id=20

old   3:  WHERE &condition

new   3:  WHERE department_id=20

old   4:  ORDER BY &column_name

new   4:  ORDER BY hire_date

 

EMPLOYEE_ID LAST_NAME                 JOB_ID     HIRE_DATE

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

 201 Hartstein                 MK_MAN     2004-02-17 00:00:00

202 Fay                       MK_REP     2005-08-17 00:00:00

 

HR@ORA11GR2>

1.7.  DEFINE命令

-     使用DEFINE命令创建和分配一个变量的值。

-     使用UNDEFINE命令来删除一个变量。

HR@ORA11GR2>DEFINE employee_num = 200

HR@ORA11GR2>SELECT employee_id, last_name, salary, department_id

  2    FROM employees

  3   WHERE employee_id = &employee_num;

old   3:  WHERE employee_id = &employee_num

new   3:  WHERE employee_id = 200

 

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID

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

 200 Whalen                          4400            10

 

HR@ORA11GR2>DEFINE

DEFINE _DATE           = "2013-03-05 16:47:25" (CHAR)

DEFINE _CONNECT_IDENTIFIER = "ORA11GR2" (CHAR)

DEFINE _USER           = "HR" (CHAR)

DEFINE _PRIVILEGE      = "" (CHAR)

DEFINE _SQLPLUS_RELEASE = "1102000100" (CHAR)

DEFINE _EDITOR         = "ed" (CHAR)

DEFINE _O_VERSION      = "Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options" (CHAR)

DEFINE _O_RELEASE      = "1102000100" (CHAR)

DEFINE EMPLOYEE_NUM    = "200" (CHAR)

HR@ORA11GR2>

HR@ORA11GR2>UNDEFINE employee_num

HR@ORA11GR2>DEFINE

DEFINE _DATE           = "2013-03-05 16:47:46" (CHAR)

DEFINE _CONNECT_IDENTIFIER = "ORA11GR2" (CHAR)

DEFINE _USER           = "HR" (CHAR)

DEFINE _PRIVILEGE      = "" (CHAR)

DEFINE _SQLPLUS_RELEASE = "1102000100" (CHAR)

DEFINE _EDITOR         = "ed" (CHAR)

DEFINE _O_VERSION      = "Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

With the Partitioning, OLAP, Data Mining and Real Application Testing options" (CHAR)

DEFINE _O_RELEASE      = "1102000100" (CHAR)

HR@ORA11GR2>

1.8.  VERIFY命令

使用VERIFY命令来显示替换变量之前和之后的值,默认值为ON,即显示替换变量之前之后的值

HR@ORA11GR2>show VERIFY

verify ON

HR@ORA11GR2>SELECT employee_id, last_name, salary, department_id

  2    FROM employees

  3   WHERE employee_id = &employee_num;

Enter value for employee_num: 200

old   3:  WHERE employee_id = &employee_num

new   3:  WHERE employee_id = 200

 

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID

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

 200 Whalen                          4400            10

 

HR@ORA11GR2>SET VERIFY OFF   

HR@ORA11GR2>show VERIFY

verify OFF

HR@ORA11GR2>

HR@ORA11GR2>SELECT employee_id, last_name, salary, department_id

  2    FROM employees

  3   WHERE employee_id = &employee_num;

Enter value for employee_num: 200

 

EMPLOYEE_ID LAST_NAME                     SALARY DEPARTMENT_ID

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

 200 Whalen                          4400            10

 

HR@ORA11GR2>


 

单行函数

1.9.  字符型函数

1.9.1.  ASCII

1)   返回与指定的字符对应的ASCII;

SCOTT@ORA11GR2>select ascii('A') A,ascii('a') "a",ascii('0') zero,ascii(' ') space from dual;

 

A          a       ZERO      SPACE

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

65         97         48 32

 

SCOTT@ORA11GR2>

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

SCOTT@ORA11GR2> select ASCII(''') from dual;

ERROR:

ORA-01756: quoted string not properly terminated

 

 

SCOTT@ORA11GR2> select ASCII('''') from dual;

 

ASCII('''')

-----------

         39

 

SCOTT@ORA11GR2>

3)   通过下面的例子我们发现,ASCII只针对第一个字符进行转换

SCOTT@ORA11GR2>select ascii('A') ,ascii('AB') ,ascii('ABC') from dual;

 

ASCII('A') ASCII('AB') ASCII('ABC')

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

 65          65           65

 

SCOTT@ORA11GR2>

ASCII美国信息交换标准码的英文缩写(American Standard Code for Information Interchange)

1.9.2.  CHR

语法CHR(n [ USING NCHAR_CS ])

返回n的字符值 nASCII码数

SCOTT@ORA11GR2> select chr(39) from dual;

 

C

-

'

 

SCOTT@ORA11GR2>

SCOTT@ORA11GR2>select 'I''m sorry' as sorry1,'I'||chr(39)||'m sorry' as sorry2 from dual;

 

SORRY1    SORRY2

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

I'm sorry I'm sorry

 

SCOTT@ORA11GR2>

注:

回车:chr(13)

换行:chr(10)

1.9.3.  ASCIISTR&UNISTR

语法:

ASCIISTR(char)

UNISTR(char)

在任何字符集和数据库字符集中返回一个ASCII字符串。非ASCII字符转换为\ xxxx,其中xxxx表示一个UTF-16代码单元的形式。

SQL> select ASCIISTR('你好hello') from dual;

 

ASCIISTR('你好HELLO')

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

\4F60\597Dhello

 

SQL> select UNISTR('\4F60\597Dhello') from dual;

 

UNISTR('\4F60\597DHELLO')

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

你好hello

 

SQL>

例:显示表t字段name中,没有中文字符的记录

SQL> with t as (

select 'abc' as name from dual

union all

select 'abc' from dual

union all

select '哈哈' from dual

union all

select 'hao' from dual)

select * from t where asciistr(name) not like '%\%';

 

NAME

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

abc

 

SQL>

1.9.4.  CONCAT

语法:CONCAT(char, dest_char_set[, source_char_set ])

连接两个字符串;

SCOTT@ORA11GR2> select concat('Hello'||chr(32),'OCM')||'!' as "HELLO OCM!" from dual;等同于select concat('Hello',' OCM!') AS "HELLO OCM!" from dual;

 

HELLO OCM!

----------

Hello OCM!

 

SCOTT@ORA11GR2>

1.9.5.  INITCAP

语法:INITCAP(char)

返回字符串并将字符串的第一个字母变为大写;

SCOTT@ORA11GR2> select initcap('james') as james from dual;

 

JAMES

-----

James

 

SCOTT@ORA11GR2>

1.9.6.  INSTR

在一个字符串中搜索指定的字符,返回发现指定的字符的位置;

语法:INSTR(C1,C2,I,J)

ü   C1:被搜索的字符串

ü   C2:希望搜索的字符串

ü   I:搜索的开始位置,默认为1

ü   J:出现的位置,默认为1

SCOTT@ORA11GR2> select instr('a2a4a6a8','a') as "instr" from dual;

 

instr

----------

 1

 

SCOTT@ORA11GR2> select instr('a2a4a6a8','a',2,1) as "instr" from dual;

 

instr

----------

  3

 

SCOTT@ORA11GR2> select instr('a2a4a6a8','a',1,2) as "instr" from dual;

 

     instr

----------

3

 

SCOTT@ORA11GR2> select instr('a2a4a6a8','a',-1,1) as "instr" from dual;

 

 instr

----------

7

 

SCOTT@ORA11GR2>

1.9.7.  SUBSTR

语法:substr(string,start,count)l

示例:SUBSTR('HelloWorld',1,5) 输出hello

示例:select substr(first_name,2) from employees;表示从输入字符第二位之前的字符截断

取子字符串,start开始,count

1)   字符串'a2a4a6a8',从后面数第一个'a'开始,截取之后的所有字符串

SCOTT@ORA11GR2>select substr('a2a4a6a8',instr('a2a4a6a8','a',-1))  from dual;

 

SU

--

a8

 

SCOTT@ORA11GR2>

2)   从第二个a开始到第三个a之前这段儿字符串

SCOTT@ORA11GR2>SELECT substr('a2a4a6a8', instr('a2a4a6a8', 'a', 2, 1), instr('a2a4a6a8', 'a', -1, 1) -  instr('a2a4a6a8', 'a', 2, 1)) FROM dual;

 

SUBS

----

a4a6

 

SCOTT@ORA11GR2>

1.9.8.  VSIZE

语法:VSIZE(expr)

VSIZE返回expr的内部表示的字节数。如果expr是空的,那么这个函数返回null,此功能不支持直接CLOB数据

SCOTT@ORA11GR2> select vsize('') from dual;

 

VSIZE('')

-----------

  2

 

SCOTT@ORA11GR2>

1.9.9.  LOWER

语法:LOWER(char)

返回字符串,并将所有的字符小写

SCOTT@ORA11GR2> select 'OcP'as "OcP",lower('OcP') as "ocp" from dual;

 

OcP ocp

--- ---

OcP ocp

 

SCOTT@ORA11GR2>

1.9.10.     UPPER

语法:UPPER(char)

返回字符串,并将所有的字符大写

SCOTT@ORA11GR2> select 'OcP'as "OcP",upper('OcP') as "OCP" from dual;

 

OcP OCP

--- ---

OcP OCP

 

SCOTT@ORA11GR2>

1.9.11.     RPAD&LPAD

语法:LPAD(expr1, n [, expr2 ])在列的左边粘贴字符

语法:RPAD(expr1, n [, expr2 ])在列的右边粘贴字符

LPAD(salary,10,'*');输出:*****24000

RPAD(salary, 10, '*') ;输出:24000*****

1)   字符'0'使字符串在列的左侧补足5

SCOTT@ORA11GR2> select lpad(rownum,5,'0') as left from dual connect by rownum<=5;

 

LEFT

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

00001

00002

00003

00004

00005

 

SCOTT@ORA11GR2>

2)   字符'0'使字符串在列的右侧补足5

SCOTT@ORA11GR2> select rpad(rownum,5,'0') as right from dual connect by rownum<=5;

 

RIGHT

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

10000

20000

30000

40000

50000

 

SCOTT@ORA11GR2>

3)   用字符'0'使字符串在列的左侧补足5位,然后再在右侧补字符'0',使其到10

SCOTT@ORA11GR2> select lpad(rpad(rownum,5,'0'),10,'0') as lr from dual connect by rownum<=5;

 

LR

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

0000010000

0000020000

0000030000

0000040000

0000050000

 

SCOTT@ORA11GR2>

1.9.12.     LTRIM  &  RTRIM

语法:LTRIM(char [, set ])删除左边出现的字符串

语法:RTRIM(char [, set ])删除右边出现的字符串

1)   构造str字符串

SCOTT@ORA11GR2>with t as (select lpad(rpad(rownum,5,'0'),10,'0') as str from dual connect by rownum<=5)

  select str from t;

 

STR

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

0000010000

0000020000

0000030000

0000040000

0000050000

 

SCOTT@ORA11GR2>

2)   删除字符串str左侧的'0'

SCOTT@ORA11GR2>with t as (select lpad(rpad(rownum,5,'0'),10,'0') as str from dual connect by rownum<=5)

  select ltrim(str,'0') as "ltrim"  from t;

 

ltrim

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

10000

20000

30000

40000

50000

 

SCOTT@ORA11GR2>

3)   删除字符串str右侧的'0'

SCOTT@ORA11GR2>with t as (select lpad(rpad(rownum,5,'0'),10,'0') as str from dual connect by rownum<=5)

  select rtrim(str,'0') as "rtrim"  from t;

 

rtrim

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

000001

000002

000003

000004

000005

 

SCOTT@ORA11GR2>

1.9.13.     REPLACE

语法:

REPLACE('string','s1','s2')

ü   string   希望被替换的字符或变量

ü   s1       被替换的字符串

ü   s2       要替换的字符串

REPLACE示例:('JACK and JUE','J','BL') 输出:BLACK AND BLUE.

 

1)   将字符串的'0'都替换为null

SCOTT@ORA11GR2>select replace('0000010000','0') from dual;

 

R

-

1

 

SCOTT@ORA11GR2>

注:如果replace的第二个参数没有指定,那么默认为null,当然,我们也可以采用如下方式达到这个效果

SCOTT@ORA11GR2>select replace('0000010000','0',null) from dual;

 

R

-

1

 

SCOTT@ORA11GR2>select replace('0000010000','0','') from dual;

 

R

-

1

 

SCOTT@ORA11GR2>

2)   将字符串的'0'都替换为'1'

SCOTT@ORA11GR2>select replace('0000010000','0','1') from dual;

 

REPLACE('0

----------

1111111111

 

SCOTT@ORA11GR2>

3)   将字符串的'0'都替换为'dt'

SCOTT@ORA11GR2>select replace('0000010000','0','dt') from dual;

 

REPLACE('0000010000

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

dtdtdtdtdt1dtdtdtdt

 

SCOTT@ORA11GR2>

1.9.14.     TRANSLATE

语法:TRANSLATE(expr, from_string, to_string)

    返回将出现在from_string中的每个字符替换为to_string中的相应字符以后的字符串。若from_stringto_string字符串长,那么在from_string中比to_string中多出的字符将会被删除。三个参数中有一个是空,返回值也将是空值。

SCOTT@ORA11GR2> select translate('abclloc','abc','he') from dual;

 

TRANS

-----

hello

 

SCOTT@ORA11GR2>

分析:

1)   abc替换为he

2)   a对应hb对应ec没有对应值

3)   替换,a都替换为hb都替换为ec由于没有对应值,故全部删掉

1:删除字符串中所有数字

SCOTT@ORA11GR2> select translate('123abc','a0123456789','a') from dual;

 

TRA

---

abc

 

SCOTT@ORA11GR2>

SCOTT@ORA11GR2> with t as(

select '123abc456' as str from dual union all

select 'eess5533' from dual union all

select '8hello world8' from dual union all

select '#$%123abc' from dual)

select translate(str,'#0123456789','#') from t;

 

TRANSLATE(STR,'#0123456789','#')

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

abc

eess

hello world

#$%abc

 

SCOTT@ORA11GR2>

2:统计逗号的个数

SCOTT@ORA11GR2>select length(translate('a,b,c,d',',abcd',',')) from dual;

 

LENGTH(TRANSLATE('A,B,C,D',',ABCD',','))

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

3

 

SCOTT@ORA11GR2>

1.9.15.     SOUNDEX

语法:SOUNDEX(char)

返回一个与给定的字符串读音几乎相同的字符串

SCOTT@ORA11GR2> with t as (

select 'sun' as val from dual union all

select 'son' from dual union all

select 'hello' from dual)

select * from t where soundex(val)=soundex('san');

 

VAL

-----

sun

son

 

SCOTT@ORA11GR2>

1.9.16.     TRIM

语法:

TRIM([ { { LEADING | TRAILING | BOTH }

         [ trim_character ]

       | trim_character}FROM]trim_source)

LEADING   剪掉前面的字符

TRAILING  剪掉后面的字符

BOTH      前后都剪

1)   默认(等同于BOTH

SCOTT@ORA11GR2> with t as

(SELECT chr(32)||'OCP'||chr(32) as name FROM dual)

select '|'||name||'|', '|'||trim(name)||'|' from t;

 

'|'||NA '|'||

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

| OCP | |OCP|

 

SCOTT@ORA11GR2>

SCOTT@ORA11GR2> with t as

(SELECT chr(32)||'OCP'||chr(32) as name FROM dual)

select '|'||name||'|', '|'||trim(BOTH from name)||'|' from t;

 

'|'||NA '|'||

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

| OCP | |OCP|

 

SCOTT@ORA11GR2>

2)   剪掉前面的空格

SCOTT@ORA11GR2> with t as

(SELECT chr(32)||'OCP'||chr(32) as name FROM dual)

select '|'||name||'|', '|'||trim(LEADING from name)||'|' from t;

 

'|'||NA '|'||T

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

| OCP | |OCP |

 

SCOTT@ORA11GR2>

3)   剪掉后面的空格

SCOTT@ORA11GR2> with t as

(SELECT chr(32)||'OCP'||chr(32) as name FROM dual)

select '|'||name||'|', '|'||trim(TRAILING from name)||'|' from t;

 

'|'||NA '|'||T

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

| OCP | | OCP|

 

SCOTT@ORA11GR2>

4)   剪掉两边的指定字符“P”

SCOTT@ORA11GR2> with t as

(SELECT chr(32)||'OCP'||chr(32) as name FROM dual)

select trim(upper('p') from trim(name))||'M' from t;

 

TRI

---

OCM

 

SCOTT@ORA11GR2>

5)   剪掉后面的指定字符“P”

SCOTT@ORA11GR2> with t as

(SELECT chr(32)||'OCP'||chr(32) as name FROM dual)

select '|'||trim(TRAILING upper('p') from trim(name))||'M|' from t;

 

'|'||

-----

|OCM|

 

SCOTT@ORA11GR2>

1.9.17.     ABS

语法:ABS(n)

返回指定值的绝对值

SCOTT@ORA11GR2> select abs(-95) from dual;

 

  ABS(-95)

----------

95

 

SCOTT@ORA11GR2>

1.9.18.     半角/全角转换

语法:TO_MULTI_BYTE(char)半角转全角

语法:TO_SINGLE_BYTE(char)全角转半角

SCOTT@ORA11GR2> select TO_MULTI_BYTE('a'),TO_SINGLE_BYTE('') from dual;

 

TO_MULTI_BYTE('A') TO_SINGLE_BYTE('')

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

a

 

SCOTT@ORA11GR2>

1.9.19.     LEAST&GREATEST

语法:LEAST(expr [, expr ]...)

expr为字符型,返回一组字符串的最小值

语法:GREATEST(expr [, expr ]...)

expr为字符型,返回一组字符串的最大值

SCOTT@ORA11GR2> select least('aa','ab','ac') as s,greatest('aa','ab','ac') as b from dual;

 

S  B

-- --

aa ac

 

SCOTT@ORA11GR2>

巧用LEASTGREATEST去除重复

SCOTT@ORA11GR2> with t as(

select 'zhangfei' as name1,'zhangyide' as name2 from dual

union all select 'liubei','liuxuande' from dual

union all select 'guanyu','guanyuchang' from dual

union all select 'liubei','liuxuande' from dual

union all select 'guanyu','guanyuchang' from dual

union all select 'zhangyide','zhangfei' from dual

union all select 'guanyuchang','guanyu' from dual)

select * from t;

 

NAME1       NAME2

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

zhangfei    zhangyide

liubei      liuxuande

guanyu     guanyuchang

liubei     liuxuande

guanyu     guanyuchang

zhangyide   zhangfei

guanyuchang guanyu

 

7 rows selected.

 

SCOTT@ORA11GR2>

SCOTT@ORA11GR2> with t as(

select 'zhangfei' as name1,'zhangyide' as name2 from dual

union all select 'liubei','liuxuande' from dual

union all select 'guanyu','guanyuchang' from dual

union all select 'liubei','liuxuande' from dual

union all select 'guanyu','guanyuchang' from dual

union all select 'zhangyide','zhangfei' from dual

union all select 'guanyuchang','guanyu' from dual)

select distinct least(name1,name2) as name1,greatest(name1,name2) as name2 from t;

 

NAME1       NAME2

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

liubei      liuxuande

guanyu      guanyuchang

zhangfei    zhangyide

 

SCOTT@ORA11GR2>

1.10.    数值型函数

1.10.1.     CEIL

语法:ceil(n)

大于等于数值n最小整数

SCOTT@ORA11GR2> select ceil(9.9),ceil(9),ceil(9.1) from dual;

 

 CEIL(9.9)    CEIL(9)  CEIL(9.1)

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

 10          9         10

 

SCOTT@ORA11GR2>

1.10.2.     FLOOR

语法:floor(n)

小于等于数值n最大整数

SCOTT@ORA11GR2> select floor(9.9),floor(9),floor(9.1) from dual;

 

FLOOR(9.9)   FLOOR(9) FLOOR(9.1)

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

9          9          9

 

SCOTT@ORA11GR2>

1.10.3.     TRUNC

语法:trunc(x [,y])

1)   其中y表示小数点后面保留的位数,如果没有指定y,则对x0位小数进行截断,如:

SCOTT@ORA11GR2> select trunc(3.1415) from dual;

 

TRUNC(3.1415)

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

 3

 

SCOTT@ORA11GR2>

2)   如果指定y为正数, 则对xy位小数进行截断,如下:

SCOTT@ORA11GR2> select trunc(9.99,1) from dual;

 

TRUNC(9.99,1)

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

 9.9

 

SCOTT@ORA11GR2>

3)   如果y是负数,则对x在小数点左边的第|y|位处进行截断,如:

SCOTT@ORA11GR2> select trunc(9.99,-1) from dual;

 

TRUNC(9.99,-1)

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

  0

 

SCOTT@ORA11GR2> select trunc(129.99,-1) from dual;

 

TRUNC(129.99,-1)

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

  120

 

SCOTT@ORA11GR2> select trunc(129.99,-2) from dual;

 

TRUNC(129.99,-2)

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

100

 

SCOTT@ORA11GR2>

1.10.4.     ROUND

语法:round(x [,y])

用法同trunc区别在于round四舍五入如果没有指定y,则对x0位小数的后以为进行四舍五入;

测试效果如下:

SCOTT@ORA11GR2> select round(3.1415) from dual;

 

ROUND(3.1415)

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

  3

 

SCOTT@ORA11GR2> select round(3.1415,2) from dual;

 

ROUND(3.1415,2)

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

 3.14

 

SCOTT@ORA11GR2> select round(9.99,1) from dual;

 

ROUND(9.99,1)

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

10

 

SCOTT@ORA11GR2> select round(9.99,-1) from dual;

 

ROUND(9.99,-1)

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

 10

 

SCOTT@ORA11GR2> select round(129.99,-1) from dual;

 

ROUND(129.99,-1)

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

  130

 

SCOTT@ORA11GR2> select round(129.99,-2) from dual;

 

ROUND(129.99,-2)

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

 100

 

SCOTT@ORA11GR2>

1.10.5.     MOD

语法:  MOD(n1,n2)

返回n1除以n2的余数.如果n20,则返回n1

SCOTT@ORA11GR2> select mod(10,3),mod(3,3),mod(2,3),mod(9,0) from dual;

 

MOD(10,3)   MOD(3,3)   MOD(2,3)   MOD(9,0)

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

1          0          2          9

 

SCOTT@ORA11GR2>

1.10.6.     POWER

语法:POWER(x,y)

返回XY次幂。底X和指数Y都不必是正整数,但如果X是负数的话,Y必须是整数。

SCOTT@ORA11GR2> SELECT trunc(power(10, 1 / 2), 2), trunc(power(10, -1 / 2), 2), power(-2, 2) FROM dual;

 

TRUNC(POWER(10,1/2),2) TRUNC(POWER(10,-1/2),2) POWER(-2,2)

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

3.16                     .31           4

 

SCOTT@ORA11GR2>

小缺陷:Y为小数会报错(注:-81/3次方是有意义的)

SCOTT@ORA11GR2> select power(-8,1/3) from dual;

select power(-8,1/3) from dual

             *

ERROR at line 1:

ORA-01428: argument '-8' is out of range

 

 

SCOTT@ORA11GR2>

1.10.7.     SIGN

语法:SIGN(n)

sign函数就是实现如下功能:

CREATE OR REPLACE FUNCTION my_sign(p_val IN NUMBER) RETURN NUMBER IS

  v_return NUMBER;

BEGIN

  IF p_val > 0 THEN

    v_return := 1;

  ELSIF p_val < 0 THEN

    v_return := -1;

  ELSE with

    v_return := 0;

  END IF;

  RETURN v_return;

END;

/

1)   测试自定义的my_sign函数:

SCOTT@ORA11GR2> select my_sign(100),my_sign(0),my_sign(-1),my_sign(5-6) from dual;

 

MY_SIGN(100) MY_SIGN(0) MY_SIGN(-1) MY_SIGN(5-6)

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

1          0          -1           -1

SCOTT@ORA11GR2>

2)   测试sign函数:

SCOTT@ORA11GR2> select sign(100),sign(0),sign(-1),sign(5-6) from dual;

 

SIGN(100)    SIGN(0)   SIGN(-1)  SIGN(5-6)

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

1          0         -1         -1

 

SCOTT@ORA11GR2>

1.11.    日期型函数

1.11.1.     SYSDATE

1)   用来得到系统的当前日期,不过,这种格式不使我们常用的“年--日”

SCOTT@ORA11GR2> select sysdate from dual;

 

SYSDATE

---------

09-JUN-12

 

SCOTT@ORA11GR2>

-     我们可以在当前会话修改日期格式(默认的日期格式是 DD-MON-RR

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

 

Session altered.

 

SCOTT@ORA11GR2>

2)   再次查看即为我们习惯的格式

SCOTT@ORA11GR2> select sysdate from dual;

 

SYSDATE

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

2012-06-06 15:48:50

 

SCOTT@ORA11GR2>

3)   当然也可以通过修改参数达到效果(注:参数nls_date_format为静态参数,修改时必须加上scope=spfile子句,重启数据库参数生效)

SCOTT@ORA11GR2> show parameter nls_date_format

 

NAME                      TYPE        VALUE

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

nls_date_format  string

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

 

System altered.

 

SCOTT@ORA11GR2> startup force;

ORACLE instance started.

 

Total System Global Area  285212672 bytes

Fixed Size                  1218992 bytes

Variable Size              92276304 bytes

Database Buffers          188743680 bytes

Redo Buffers                2973696 bytes

Database mounted.

Database opened.

SCOTT@ORA11GR2>

SCOTT@ORA11GR2> select sysdate from dual;

 

SYSDATE

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

2012-06-09 17:15:51

 

SCOTT@ORA11GR2> show parameter nls_date_format

 

NAME                           TYPE    VALUE

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

nls_date_format              string yyyy-mm-dd hh24:mi:ss

SCOTT@ORA11GR2>

1.11.2.     SYSTIMESTAMP

带有时区及毫秒的日期格式

SCOTT@ORA11GR2> select systimestamp from dual;

 

SYSTIMESTAMP

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

09-JUN-12 10.20.23.211333 PM +08:00

 

SCOTT@ORA11GR2>

1.11.3.     ADD_MONTHS

语法:ADD_MONTHS(date, integer)

用于从一个日期值增加或减少一些月份

1)   返回系统时间一个月后的日期

SYS@ORA11GR2>select sysdate,add_months(sysdate,1) as "months+1" from dual;

 

SYSDATE             months+1

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

2012-06-06 14:31:47 2012-07-06 14:31:47

 

SYS@ORA11GR2>

2)   返回系统时间一年后的日期

SYS@ORA11GR2>select sysdate,add_months(sysdate,12) as "months+12" from dual;

 

SYSDATE             months+12

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

2012-06-06 14:33:16 2013-06-06 14:33:16

 

SYS@ORA11GR2>

3)   返回系统时间一年前的日期

SYS@ORA11GR2>select sysdate,add_months(sysdate,-12) as "months-12" from dual;

 

SYSDATE             months-12

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

2012-06-06 14:33:45 2011-06-06 14:33:45

 

SYS@ORA11GR2>

1.11.4.     LAST_DAY

语法:LAST_DAY(date)

返回包含了日期参数的月份的最后一天的日期

SYS@ORA11GR2> select sysdate, last_day(sysdate) "last" from dual;

 

SYSDATE             last

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

2012-06-06 18:08:21 2012-06-30 18:08:21

 

SYS@ORA11GR2>

1.11.5.     DBTIMEZONE

返回数据库的时区

SYS@ORA11GR2> select dbtimezone from dual;

 

DBTIME

------

+08:00

 

SYS@ORA11GR2>

CREATE DATABASE db01
...
SET TIME_ZONE='+08:00';

alter database set time_zone='+08:00';

时区分东西,东时区都带+号标识,西时区用-号。在一个特定的时间点,时区号越大(考虑正负号)的地方,时间越晚,比如北京在+08:00, St. Louis-06:00区,北京已经是傍晚了,St. Louis还在凌晨,它们之前相差即+08:00-(-06:00)=14(受夏时制的影响,可能会有一个小时的误差)。

1.11.6.     SESSIONTIMEZONE

返回当前会话的时区

SYS@ORA11GR2> select sessiontimezone from dual;

 

SESSIONTIMEZONE

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

+08:00

 

SYS@ORA11GR2>

1.11.7.     CURRENT_DATE

1)   返回当前会话时区中的当前日期

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

 

Session altered.

 

SYS@ORA11GR2> col sessiontimezone for a10

SYS@ORA11GR2> select dbtimezone,sessiontimezone,current_date from dual;

 

DBTIME SESSIONTIM CURRENT_DATE

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

+08:00 +08:00     2012-06-06 18:00:46

 

SYS@ORA11GR2>

2)   当前会话改为西六区

SYS@ORA11GR2> alter session set time_zone = '-6:0';

 

Session altered.

 

SYS@ORA11GR2>

3)   我们发现,CURRENT_DATE时间为会话所在时区的时间

SYS@ORA11GR2> select dbtimezone,sessiontimezone,current_date from dual;

 

DBTIME SESSIONTIM CURRENT_DATE

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

+08:00 -06:00     2012-06-06 04:00:58

 

SYS@ORA11GR2>

1.11.8.     CURRENT_TIMESTAMP

语法:CURRENT_TIMESTAMP [ (precision) ]

Precision:毫秒的精确度,默认为6位毫秒

1)   timestamp with time zone数据类型返回当前会话时区中的当前日期

SYS@ORA11GR2> col SESSIONTIMEZONE for a15

SYS@ORA11GR2> col CURRENT_TIMESTAMP for a40

SYS@ORA11GR2> select dbtimezone,sessiontimezone,current_timestamp from dual;

 

DBTIME SESSIONTIMEZONE CURRENT_TIMESTAMP

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

+08:00 +08:00          06-JUN-12 06.14.15.872734 PM +08:00

 

SYS@ORA11GR2>

2)   当前会话改为西六区

SYS@ORA11GR2> alter session set time_zone = '-6:0';

 

Session altered.

 

SYS@ORA11GR2>

3)   返回为当前会话所在时区的timestamp with time zone时间

SYS@ORA11GR2> select dbtimezone,sessiontimezone,current_timestamp from dual;

 

DBTIME SESSIONTIMEZONE CURRENT_TIMESTAMP

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

+08:00 -06:00          06-JUN-12 04.14.37.777012 AM -06:00

 

SYS@ORA11GR2>

4)   我们也可以控制毫秒的位数

SYS@ORA11GR2> select CURRENT_TIMESTAMP(3) from dual;

 

CURRENT_TIMESTAMP(3)

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

06-JUN-12 04.22.15.438 AM -06:00

 

SYS@ORA11GR2> select CURRENT_TIMESTAMP(2) from dual;

 

CURRENT_TIMESTAMP(2)

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

06-JUN-12 04.22.22.32 AM -06:00

 

SYS@ORA11GR2>

5)   巧妙显示为标准日期型

SYS@ORA11GR2> col CURRENT_TIMESTAMP for a35

SYS@ORA11GR2> select current_timestamp,current_timestamp+0 from dual;

 

CURRENT_TIMESTAMP                       CURRENT_TIMESTAMP+0

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

09-JUN-12 07.10.02.835011 PM +08:00 2012-06-09 19:10:02

 

SYS@ORA11GR2>

1.11.9.     LOCALTIMESTAMP

语法:LOCALTIMESTAMP [ (timestamp_precision) ]

1)   返回会话中的日期和时间

SYS@ORA11GR2> col CURRENT_TIMESTAMP for a38 

SYS@ORA11GR2> col LOCALTIMESTAMP for a30

SYS@ORA11GR2> select current_timestamp, localtimestamp from dual;

 

CURRENT_TIMESTAMP                      LOCALTIMESTAMP

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

06-JUN-12 07.02.07.314525 PM +08:00 06-JUN-12 07.02.07.314525 PM

 

SYS@ORA11GR2>

2)   将会话改为西六区

SYS@ORA11GR2> alter session set time_zone = '-6:0';

 

Session altered.

 

SYS@ORA11GR2>

3)   此时返回的是西六区的会话时间

SYS@ORA11GR2>select current_timestamp, localtimestamp from dual;

 

CURRENT_TIMESTAMP                      LOCALTIMESTAMP

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

06-JUN-12 05.02.23.734885 AM -06:00 06-JUN-12 05.02.23.734885 AM

 

SYS@ORA11GR2>

4)   此函数也可以控制毫秒的位数

SYS@ORA11GR2> select current_timestamp, localtimestamp(3) as "localtimestamp" from dual;

 

CURRENT_TIMESTAMP                      localtimestamp

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

06-JUN-12 05.03.03.079213 AM -06:00 06-JUN-12 05.03.03.079 AM

 

SYS@ORA11GR2>

1.11.10.   EXTRACT

语法:

EXTRACT( { { YEAR| MONTH| DAY| HOUR| MINUTE| SECOND}

         | { TIMEZONE_HOUR| TIMEZONE_MINUTE}

         | { TIMEZONE_REGION| TIMEZONE_ABBR}}

FROM { datetime_value_expression | interval_value_expression}

)

提取日期或时间指定的信息值

1)   返回指定时间的年份

SYS@ORA11GR2> select extract(year from date '2009-5-11') as year from dual;

 

YEAR

----------

2009

 

SYS@ORA11GR2>

2)   返回指定时间的月份

SYS@ORA11GR2> select extract(month from date '2009-5-11') as mon from dual;

 

MON

----------

5

 

SYS@ORA11GR2>

3)   返回指定时间的日

SYS@ORA11GR2> select extract(day from to_date('2009-5-11','yyyy-mm-dd')) as day from dual;

 

DAY

----------

11

 

SYS@ORA11GR2>

4)   返回指定时间的小时

SYS@ORA11GR2>select extract(hour from TIMESTAMP '2009-5-11 08:09:10') as hour from dual;

 

HOUR

----------

8

 

SYS@ORA11GR2>

5)   返回指定时间的分钟

SYS@ORA11GR2> select extract(minute from TIMESTAMP '2009-5-11 08:09:10') as minute from dual;

 

MINUTE

----------

9

 

SYS@ORA11GR2>

6)   返回指定时间的秒

SYS@ORA11GR2> select extract(second from TIMESTAMP '2009-5-11 08:09:10') as second from dual;

 

SECOND

----------

10

 

SYS@ORA11GR2>

1.11.11.   MONTHS_BETWEEN

语法:MONTHS_BETWEEN(date1, date2)

判断两个日期之间的月份数量

SYS@ORA11GR2>select months_between(to_date('2012-06-06', 'yyyy-mm-dd'), to_date('2009-05-11', 'yyyy-mm-dd')) "months" from dual;

 

    months

----------

36.8387097

 

SYS@ORA11GR2>

问:下面SQL是否可以执行,如果不能执行,为什么?如果可以执行,请问什么情况下可以执行?为什么?

select months_between('20110701','20110501') as mb from dual;

可以,因为当前的系统时间格式为:YYYY-MM-DD格式。

1.11.12.   NEXT_DAY

语法:NEXT_DAY(date, char)

给定一个日期值,返回由第二个参数指出的日子第一次出现的日期值

英文字符集:

select NEXT_DAY(trunc(sysdate),'Monday') from dual

中文字符集:

select NEXT_DAY(trunc(sysdate),'星期一') from dual

1)   格式化日期格式

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

 

Session altered.

 

SYS@ORA11GR2>

2)   2009-05-11之后的第一个星期二

SYS@ORA11GR2>select next_day(to_date('2009-05-11','yyyy-mm-dd'),'tuesday') as "next day" from dual;

 

next day

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

2009-05-12 00:00:00

 

SYS@ORA11GR2>

3)   2009-05-11之后的第一个星期

SYS@ORA11GR2>select next_day('2009-05-11',6) "next day" from dual;

 

next day

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

2009-05-15 00:00:00

 

SYS@ORA11GR2>

注:

next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。

1:周日;           2:周一;          3:周二;           4:周三;

5:周四;           6:周五;          7:周六;

1.11.13.   TRUNC

语法:trunc(date,fmt)

按照给出的要求将日期截断,如果fmt='mi'表示保留分,截断秒

1)   格式化时间

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

 

Session altered.

 

SYS@ORA11GR2>

2)   trunc函数处理日期,没有fmt参数,默认截取到日

SYS@ORA11GR2>select trunc(sysdate) from dual;

 

TRUNC(SYSDATE)

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

2012-11-21 00:00:00

 

SYS@ORA11GR2>

3)   时间截取到小时,截取到分钟

SYS@ORA11GR2>select trunc(sysdate,'hh') "hh",trunc(sysdate,'mi') "hh-mi" from dual;

 

hh                    hh-mi

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

2012-11-21 15:00:00 2012-11-21 15:11:00

 

SYS@ORA11GR2>

 

4)   返回本周周一

SYS@ORA11GR2>select trunc(sysdate,'iw') from dual;

 

TRUNC(SYSDATE,'IW')

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

2012-11-19 00:00:00

 

SYS@ORA11GR2>

5)   例:返回近10年的周一和周日

select trunc(sysdate - 3650, 'iw') + 7 * rownum monday, trunc(sysdate - 3650, 'iw') +7 * rownum + 6 sunday from dual connect by rownum <= 500;

……请自行测试……

6)   返回指定日期当周的周日

SYS@ORA11GR2>select trunc(to_date('2008.08.08','yyyy.mm.dd'),'d') from dual;

 

TRUNC(TO_DATE('2008

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

2008-08-03 00:00:00

 

SYS@ORA11GR2>

7)   返回指定日期当周的周一

SYS@ORA11GR2>select trunc(to_date('2008.08.08','yyyy.mm.dd'),'d')+1 from dual;

 

TRUNC(TO_DATE('2008

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

2008-08-04 00:00:00

 

SYS@ORA1

8)   返回指定日期所在月份的第一天

SYS@ORA11GR2>select trunc(to_date('2008.08.08','yyyy.mm.dd'),'mm') from dual;

 

TRUNC(TO_DATE('2008

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

2008-08-01 00:00:00

 

SYS@ORA11GR2>

9)   返回指定日期所在月份的上个月的最后一天

SYS@ORA11GR2>select trunc(to_date('2008.08.08','yyyy.mm.dd'),'mm')-1 from dual;

 

TRUNC(TO_DATE('2008

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

2008-07-31 00:00:00

 

SYS@ORA11GR2>

10)  返回指定日期所在年份的第一天

SYS@ORA11GR2>select trunc(to_date('2008.08.08','yyyy.mm.dd'),'y') from dual;

 

TRUNC(TO_DATE('2008

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

2008-01-01 00:00:00

 

SYS@ORA11GR2>

注:返回指定日期所在年份的前一年的最后一天,只需在这个结果集上-1即可。

1.11.14.   ROUND()日期四舍五入

月份四舍五入:15号舍去,16号进一;

SYS@ORA11GR2>select round(dd,'MONTH'),

  2         round(dd,'YEAR'),

  3         trunc(dd,'MONTH'),

  4         trunc(dd,'YEAR') from

  5  (select to_date('2008-08-15','yyyy-mm-dd') as dd from dual);

 

ROUND(DD,'MONTH')   ROUND(DD,'YEAR')    TRUNC(DD,'MONTH')   TRUNC(DD,'YEAR')

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

2008-08-01 00:00:00 2009-01-01 00:00:00 2008-08-01 00:00:00 2008-01-01 00:00:00

 

SYS@ORA11GR2>select round(dd,'MONTH'),

  2         round(dd,'YEAR'),

  3         trunc(dd,'MONTH'),

  4         trunc(dd,'YEAR') from

  5  (select to_date('2008-08-16','yyyy-mm-dd') as dd from dual);

 

ROUND(DD,'MONTH')   ROUND(DD,'YEAR')    TRUNC(DD,'MONTH')   TRUNC(DD,'YEAR')

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

2008-09-01 00:00:00 2009-01-01 00:00:00 2008-08-01 00:00:00 2008-01-01 00:00:00

 

SYS@ORA11GR2>

1.11.15.   日期计算

1)   计算两个时间相差的月数(trunc不加参数默认是截取到0位);

SYS@ORA11GR2> SELECT trunc(months_between(DATE '2003-7-11', DATE '1999-9-1')) MONTHS from dual;

 

    MONTHS

----------

        46

 

SYS@ORA11GR2>

2)   计算两个时间相差的 天数、小时数、分钟数、秒数

SYS@ORA11GR2>select (to_date('20120511', 'yyyymmdd') - to_date('20120401', 'yyyymmdd')) * decode(upper('mi'), 'ss', 24 * 60 * 60, 'mi', 24 * 60, 'hh', 24, 1) as val from dual;

 

       VAL

----------

        40

 

SYS@ORA11GR2>

注:这是一个通用的方法,只需要替换upper中的值就可以计算相差的天数、小时、分钟、秒。

hh:计算返回相差的小时数

mi:计算返回相差的分钟数

ss:计算返回相差的描述

不等于上述三个字符的任意字符都返回相差的天数

3)   给出两个时间,显示这两个时间之间的连续时间

要求:返回20101225日到201115日之间的连续日期(不包含这两个日期)

SYS@ORA11GR2>select to_date('20101225','yyyymmdd')+rownum from dual connect by rownum <to_date('20110105','yyyymmdd')-to_date('20101225','yyyymmdd');

 

TO_DATE('20101225',

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

2010-12-26 00:00:00

2010-12-27 00:00:00

2010-12-28 00:00:00

2010-12-29 00:00:00

2010-12-30 00:00:00

2010-12-31 00:00:00

2011-01-01 00:00:00

2011-01-02 00:00:00

2011-01-03 00:00:00

2011-01-04 00:00:00

 

10 rows selected.

 

SYS@ORA11GR2>

请问:如果要求包含20101225日和201115日这两个日期,那么这个SQL语句该如何修改?

4)   指定时间加1

SYS@ORA11GR2> alter session set nls_date_format='yyyy-mm-dd';

 

Session altered.

 

SYS@ORA11GR2>

SYS@ORA11GR2> with t as (select to_date('20120601','yyyymmdd') as dd from dual)

select dd,dd+1 from t;

 

DD         DD+1

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

2012-06-01 2012-06-02

 

SYS@ORA11GR2>

5)   指定时间加1小时(注:一天有24小时,加1/24即为加1小时)

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

 

Session altered.

 

SYS@ORA11GR2> with t as (select to_date('20120601','yyyymmdd') as dd from dual)

select dd,dd+1/24 from t;

 

DD                      DD+1/24

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

2012-06-01 00:00:00 2012-06-01 01:00:00

 

SYS@ORA11GR2>

6)   指定时间加5分钟,注:一天有24小时,一小时有60分钟,那么一天即为24*60=1440分钟,加5/1440即为加5分钟)

SYS@ORA11GR2> with t as (select to_date('20120601','yyyymmdd') as dd from dual)

select dd,dd+5/(24*60) from t;

 

DD                      DD+5/(24*60)

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

2012-06-01 00:00:00 2012-06-01 00:05:00

 

SYS@ORA11GR2>

问:下面sql的结果与上面的结果相同吗?

with t as (select to_date('20120601','yyyymmdd') as dd from dual)

select dd,dd+5/24*60 from t;

不一样,因为*/的优先顺序不同了;

1.12.    隐式转换

1.12.1.     隐式数据类型转换

源数据类型

目标数据类型

VARCHAR2 or CHAR

NUMBER

VARCHAR2 or CHAR

DATE

NUMBER

VARCHAR2

DATE

VARCHAR2

1)   字符型隐式转换为数值型

SCOTT@ORA11GR2>create table t1(x number(10));

 

Table created.

 

SCOTT@ORA11GR2>insert into t1 values('1');

 

1 row created.

 

SCOTT@ORA11GR2>commit;

 

Commit complete.

 

SCOTT@ORA11GR2>select * from t1;

 

X

----------

  1

 

SCOTT@ORA11GR2>

2)   字符型隐式转换为日期型

SCOTT@ORA11GR2>create table t2(x date);

 

Table created.

 

SCOTT@ORA11GR2>insert into t2 values('2012-12-12');

 

1 row created.

 

SCOTT@ORA11GR2>commit;

 

Commit complete.

 

SCOTT@ORA11GR2>select * from t2;

 

X

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

2012-12-12 00:00:00

 

SCOTT@ORA11GR2>

3)   数值型隐式转换为字符型

SCOTT@ORA11GR2>create table t3(x varchar2(10));          

 

Table created.

 

SCOTT@ORA11GR2>insert into t3 values(1);

 

1 row created.

 

SCOTT@ORA11GR2>commit;

 

Commit complete.

 

SCOTT@ORA11GR2>select * from t3;

 

X

----------

1

 

SCOTT@ORA11GR2>

4)   日期型隐式转换为字符型

SCOTT@ORA11GR2>create table t4(x varchar2(20));

 

Table created.

 

SCOTT@ORA11GR2>insert into t4 values(to_date('20121212','yyyymmdd'));

 

1 row created.

 

SCOTT@ORA11GR2>commit;

 

Commit complete.

 

SCOTT@ORA11GR2>select * from t4; 

 

X

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

2012-12-12 00:00:00

 

SCOTT@ORA11GR2>

1.12.2.     表达式中数据类型自动转换

源数据类型

目标数据类型

VARCHAR2 or CHAR

NUMBER

VARCHAR2 or CHAR

DATE

1)   数值型隐式转换为字符型

SCOTT@ORA11GR2>desc t3

 Name                               Null?    Type

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

 X                                              VARCHAR2(10)

 

SCOTT@ORA11GR2>select * from t3;

 

X

----------

1

 

SCOTT@ORA11GR2>select * from t3 where x=1;

 

X

----------

1

 

SCOTT@ORA11GR2>

 

2)   日期型隐式转换为字符型

SCOTT@ORA11GR2>desc t4

Name                               Null?    Type

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

 X                                              VARCHAR2(20)

 

SCOTT@ORA11GR2>

SCOTT@ORA11GR2>select * from t4;

 

X

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

2012-12-12 00:00:00

 

SCOTT@ORA11GR2>select * from t4 where x<=to_date('2012-12-31','yyyy-mm-dd');

 

X

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

2012-12-12 00:00:00

 

SCOTT@ORA11GR2>

备注:虽然我们在测试的时候已经成功的进行了隐式转换,并且成功的将数据写入到表中或者在表达式中进行了隐式转换,不过,都不直观,我们通过查看执行计划,可以清晰的看到隐式转换,如下:

SYSTEM@ORA11GR2>set autot trace exp

SYSTEM@ORA11GR2>select * from scott.t3 where x=1;

 

Execution Plan

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

Plan hash value: 4161002650

 

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

| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT  |      |     1 |     7 |     3   (0)| 00:00:01 |

|*  1 |  TABLE ACCESS FULL| T3   |     1 |     7 |     3   (0)| 00:00:01 |

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

 

Predicate Information (identified by operation id):

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

 

   1 - filter(TO_NUMBER("X")=1)

 

Note

-----

   - dynamic sampling used for this statement (level=2)

 

SYSTEM@ORA11GR2>

1.13.    显示转换(补)

1.13.1.     TO_CHAR

TO_CHAR日期语法

TO_CHAR(date, 'format_model')

格式要求:

-    必须包含在单引号中而且大小写敏感。

-    可以包含任意的有效的日期格式。

-    可以使用fm去掉多余的空格或者前导零。

-    与日期值用逗号隔开。

TO_CHAR数值语法

TO_CHAR(number, 'format_model')

9

代表一位数字

0

强制显示为零

$

放置一个浮动的美元符号

L

采用本地货币符号

.

小数点

,

千位符

1)   fm的使用

--去掉空格

SYS@ORA11GR2>select replace(to_char(123.456,'99999.999'),' ','*') as num from dual;

NUM

----------

***123.456

SYS@ORA11GR2>select replace(to_char(123.456,'fm99999.999'),' ','*') as num from dual;

NUM

----------

123.456

SYS@ORA11GR2>

--去掉前导0

SYS@ORA11GR2>select to_char(sysdate,'yyyy-mm-dd') as dd from dual;

DD

----------

2012-09-07

SYS@ORA11GR2>select to_char(sysdate,'fmyyyy-mm-dd') as dd from dual;

DD

----------

2012-9-7

SYS@ORA11GR2>

2)   日期格式转换

--scccc显示世纪

SYS@ORA11GR2>select to_char(sysdate,'scc yyyy-mm-dd hh24:mi:ss') sys_date from dual;

 

SYS_DATE

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

 21 2012-09-08 00:44:53

 

SYS@ORA11GR2>

 

--yyyy显示年

SYS@ORA11GR2>col yyyy for a10

SYS@ORA11GR2>select to_char(sysdate,'yyyy') as yyyy from dual;

 

YYYY

----------

2012

 

SYS@ORA11GR2>select to_char(sysdate,'y,yyy') as yyyy from dual;

 

YYYY

-----

2,012

 

SYS@ORA11GR2>select to_char(sysdate,'yyy') as yyy from dual;

 

YYY

---

012

 

SYS@ORA11GR2>select to_char(sysdate,'yy') as yy from dual;

 

YY

--

12

 

SYS@ORA11GR2>select to_char(sysdate,'y') as y from dual;

 

Y

-

2

 

SYS@ORA11GR2>

--ISO标准的年IYYY,IYY,IY,I,年的4321位值

SYS@ORA11GR2>select to_char(sysdate,'iyyy') as iyyy from dual;

 

IYYY

----

2012

 

SYS@ORA11GR2>select to_char(sysdate,'iyy') as iyy from dual;

 

IYY

---

012

 

SYS@ORA11GR2>select to_char(sysdate,'iy') as iy from dual;

 

IY

--

12

 

SYS@ORA11GR2>select to_char(sysdate,'i') as i from dual;

 

I

-

2

 

SYS@ORA11GR2>

--yearsyear,显示英文拼写的年

SYS@ORA11GR2>select to_char(sysdate,'year') as year from dual;

 

YEAR

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

twenty twelve

 

SYS@ORA11GR2>select to_char(sysdate,'syear') as syear from dual;

 

SYEAR

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

 twenty twelve

 

SYS@ORA11GR2>

 

--Q当前时间为一年的第几季度

SYS@ORA11GR2>select to_char(sysdate,'q') as q,to_char(sysdate,'yyyy-mm-dd') as sdate from dual;

 

Q SDATE

- ----------

3 2012-09-08

 

SYS@ORA11GR2>

 

--mm显示两位的月份

SYS@ORA11GR2>select to_char(sysdate,'mm') as mm from dual;

 

MM

--

09

 

SYS@ORA11GR2>

 

--month完整的月份名称

9位字符长度(不足9位填充空格)月的名字

SYS@ORA11GR2>select to_char(sysdate,'month') as month from dual;

 

MONTH

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

september

 

SYS@ORA11GR2>

SYS@ORA11GR2>select to_char(sysdate-30,'month') from dual;

 

TO_CHAR(SYSDATE-30,'MONTH')

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

august

 

SYS@ORA11GR2>select length(to_char(sysdate-30,'month')) as len from dual;

 

       LEN

----------

         9

 

SYS@ORA11GR2>

 

--mon3位缩写字母的月的名字

SYS@ORA11GR2>select to_char(sysdate,'mon') as mon from dual;

 

MON

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

sep

 

SYS@ORA11GR2>

 

--ww一年中的第几周w一个月中的第几周

SYS@ORA11GR2>select to_char(sysdate,'ww') as y,to_char(sysdate,'w') as m from dual;

 

y  m

-- -

36 2

 

SYS@ORA11GR2>

 

--ddd:一年中的第几天;dd:一个月中的第几天;d:一周中的第几天

SYS@ORA11GR2>select to_char(sysdate,'ddd') as y,to_char(sysdate,'dd') as m,to_char(sysdate,'d') as w from dual;

 

Y   M  W

--- -- -

252 08 7

 

SYS@ORA11GR2>

注:一周中的第几天,按照如下方式排列

1:周日;

2:周一;

3:周二;

4:周三;

5:周四;

6:周五;

7:周六;

 

--day,输出星期几;9位字符长度(不足9位填充空格)天的名字

SYS@ORA11GR2>select to_char(sysdate,'day') as day from dual;

 

DAY

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

saturday

 

SYS@ORA11GR2>

 

--dy3位字母缩写天的名字

SYS@ORA11GR2>select to_char(sysdate,'dy') as dy from dual;

 

DY

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

sat

 

SYS@ORA11GR2>

 

--AMPM,显示上下午标识

SYS@ORA11GR2>

with t as (select to_date('20120908 100000','yyyymmdd hh24miss') as t1,to_date('20120908 180000','yyyymmdd hh24miss') as t2 from dual)

select to_char(t1,'yyyy-mm-dd hh24:mi:ss am') as t1am,to_char(t1,'yyyy-mm-dd hh24:mi:ss pm') as t1pm,       to_char(t2,'yyyy-mm-dd hh24:mi:ss am') as t2am,to_char(t2,'yyyy-mm-dd hh24:mi:ss pm') as t2pm from t;

SYS@ORA11GR2>

T1AM                   T1PM                   T2AM                   T2PM

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

2012-09-08 10:00:00 am 2012-09-08 10:00:00 am 2012-09-08 18:00:00 pm 2012-09-08 18:00:00 pm

--hh(天的小时),hh121-12,hh240-23

SYS@ORA11GR2>with t as (select to_date('20120908 22:22:22','yyyymmdd hh24:mi:ss') as dt from dual) select to_char(dt,'yyyy-mm-dd hh:mi:ss') as hh,to_char(dt,'yyyy-mm-dd hh12:mi:ss') as hh12,to_char(dt,'yyyy-mm-dd hh24:mi:ss') as hh24 from t;

 

HH                  HH12                HH24

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

2012-09-08 10:22:22 2012-09-08 10:22:22 2012-09-08 22:22:22

 

SYS@ORA11GR2>

 

--ddth,显示序数,如:

SYS@ORA11GR2>select to_char(sysdate,'ddth') as ddth from dual;

 

DDTH

----

08th

 

SYS@ORA11GR2>

 

--ddsp,显示英文日期

SYS@ORA11GR2>select to_char(sysdate,'ddsp') as ddth from dual;

 

DDTH

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

eight

 

--ddspthddthsp

SYS@ORA11GR2>select to_char(sysdate,'ddspth') as ddspth,to_char(sysdate,'ddthsp') as ddthsp from dual;

 

DDSPTH         DDTHSP

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

eighth         eighth

 

SYS@ORA11GR2>

3)   数字格式转换

--9:表示一个数字,9的个数决定显示的宽度,如小数点后显示的小于实际数字,那么实际数字按照显示的位数四舍五入

SYS@ORA11GR2>select to_char('123','999999') as val from dual;

 

VAL

-------

    123

 

SYS@ORA11GR2>

 

--0:显示前导0,数字的实际位数与要求不符,没有要求的,那么以0补齐

SYS@ORA11GR2>select to_char('123','0999999') as val from dual;

 

VAL

--------

 0000123

 

SYS@ORA11GR2>

3$:显示美元符号

SYS@ORA11GR2>select to_char('123','$999999') as val from dual;

 

VAL

--------

    $123

 

SYS@ORA11GR2>

4L:浮动本地货币符号(这个与字符集有关系,如果是中文字符集,那么会显示¥

SYS@ORA11GR2>select to_char('123','L999999') as val from dual;

 

VAL

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

             $123

 

SYS@ORA11GR2>

5.:小数点位置指定,即指定了小数的位置,没有补0.(有的话,四舍五入)

SYS@ORA11GR2>select to_char('123','9999.99') as val from dual;

 

VAL

--------

  123.00

 

SYS@ORA11GR2>

6,:显示逗号位置

SYS@ORA11GR2>select to_char('12345','999,999') as val from dual;

 

VAL

--------

  12,345

 

SYS@ORA11GR2>

7mi:负号显示在右侧

SYS@ORA11GR2>select to_char('-12345','999999mi') as val from dual;

 

VAL

-------

 12345-

 

SYS@ORA11GR2>

8pr:负数变成<>

SYS@ORA11GR2>select to_char('-12345','999999pr') as val from dual;

 

VAL

--------

<12345>

 

SYS@ORA11GR2>

9eeee:科学技术法

SYS@ORA11GR2>select to_char('12345','999999eeee') as val from dual;

 

VAL

-------

  1E+04

 

SYS@ORA11GR2>

10v:输入值乘以10n次方,n次方的n即为v后面9的个数

SYS@ORA11GR2>select to_char('123','99999v99') as val1,123*100 as val2 from dual;

 

VAL1           VAL2

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

   12300      12300

 

SYS@ORA11GR2>

1.13.2.     TO_DATE

语法:TO_DATE(char[, 'format_model'])

 

select

       to_date('2011-08-01', 'yyyy-mm-dd') as d1,

       to_date('2011.08.01', 'yyyy.mm.dd') as d2,

       to_date('2011/08/01', 'yyyy/mm/dd') as d3,

       to_date('20110801', 'yyyymmdd') as d4,

       to_date('20110801', 'yyyy-mm-dd') as d5,

       to_date('8/1', 'MM/DD') as d6,

       date '2011-08-01' as d7

  from dual;

 

SELECT to_date('2011-08-01', 'yyyy.mm.dd')  FROM dual;

SELECT to_date('2011-08-01', 'yyyymmdd')  FROM dual;

SELECT to_date('2011-08-01', 'yyyy/mm.dd')  FROM dual;

SELECT to_date('2011.08.01', 'yyyy/mm\dd')  FROM dual;

SELECT to_date('20110801', 'yyyy/mm\dd')  FROM dual;

1.13.3.     TO_NUMBER

语法:TO_NUMBER(char[, 'format_model'])

1.14.    单值通用函数

1.14.1.     NVL

语法:NVL(expr1, expr2)

expr1NULL,返回expr2;不为NULL,返回expr1注意两者的类型要一致

SYS@ORA11GR2> select nvl(null,0),nvl(2,0) from dual;

 

NVL(NULL,0)   NVL(2,0)

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

0          2

 

SYS@ORA11GR2>

1.14.2.     NVL2

语法:NVL2(expr1, expr2, expr3)

expr1NULL,返回expr3;不为NULL,返回expr2

expr2expr3类型不同的话,expr3会转换为expr2的类型

SYS@ORA11GR2> select nvl2(null,1,2),nvl2(3,1,2) from dual;

 

NVL2(NULL,1,2) NVL2(3,1,2)

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

  2           1

 

SYS@ORA11GR2>

下面的例子我们可以看出,expr3参数有个隐式转换为expr2参数类型的动作

SYS@ORA11GR2> select nvl2(null,1,2),nvl2(3,1,'A') from dual;

select nvl2(null,1,2),nvl2(3,1,'A') from dual

                               *

ERROR at line 1:

ORA-01722: invalid number

 

 

SCOTT@ORA11GR2>col n1 for 99999

SCOTT@ORA11GR2>col n2 for a5

SCOTT@ORA11GR2>select nvl2(null,1,2) as n1,nvl2(3,'b',1) as n2 from dual;

 

 N1 N2

------ -----

2 b

 

SCOTT@ORA11GR2>

1.14.3.     NULLIF

语法:NULLIF(expr1, expr2)

expr1, expr2相等则返回NULL,不等则返回expr1

SYS@ORA11GR2> select nullif(1,1),nullif(2,1) from dual;

 

NULLIF(1,1) NULLIF(2,1)

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

2

 

SYS@ORA11GR2>

1.14.4.     LNNVL

语法:LNNVL(condition)

LNNVL <==> IS NULL OR IS NOT TRUE即与所筛选条件相反的选项,包括null值。

create table t_null(id number(5) primary key,name varchar2(10),age number(3));

insert into t_null values(1,'zhangsan',20);

insert into t_null values(2,'lisi',21);

insert into t_null values(3,'wangwu',null);

insert into t_null values(4,'zhaoliu',19);

commit;

查询age小于等于20或者age为空的所有人

SCOTT@ORCL>select * from t_null;

 

ID NAME              AGE

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

1 zhangsan           20

 2 lisi               21

3 wangwu

 4 zhaoliu            19

 

SCOTT@ORCL>

SCOTT@ORCL>SELECT * FROM t_null WHERE age <= 20 or age is null;

 

ID NAME              AGE

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

1 zhangsan           20

3 wangwu

 4 zhaoliu            19

 

SCOTT@ORCL>

SCOTT@ORCL>SELECT * FROM t_null WHERE lnnvl(age > 20);

 

ID NAME              AGE

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

1 zhangsan           20

3 wangwu

 4 zhaoliu            19

 

SCOTT@ORCL>

1.14.5.     COALESCE

语法:COALESCE(expr1 , expr2 ... exprN)

返回expr1,expr2….,exprN,第一个非null

SCOTT@ORCL> select COALESCE(null,1,null,2) from dual;

 

COALESCE(NULL,1,NULL,2)

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

1

 

SCOTT@ORCL>

1.15.    条件表达式

1.15.1.     CASE WHEN END

语法:

CASE expr WHEN comparison_expr1 THEN return_expr1

[WHEN comparison_expr2 THEN return_expr2

          WHEN comparison_exprn THEN return_exprn

          ELSE else_expr]

END

SCOTT@ORCL>with t as (

select 1 as sno,60 as score from dual union all

select 2,70 from dual union all

select 3,59 from dual)

select sno,score,case when score>=60 then 'Congratulations' else 'Thank you' end as ocm from t;

 

SNO      SCORE OCM

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

 1        60 Congratulations

 2         70 Congratulations

 3        59 Thank you

 

SCOTT@ORCL>

例:薪水小于等于1000的增加40%,薪水大于1000小于等于2000的增加30%,大于2000小于等于3000的增加20%3000以上的增加10%

SCOTT@ORCL> SELECT ename, sal, CASE

          WHEN sal <= 1000 THEN

           sal + sal * 0.4

          WHEN sal > 1000 AND sal <= 2000 THEN

           sal + sal * 0.3

          WHEN sal > 2000 AND sal <= 3000 THEN

           sal + sal * 0.2

          ELSE

           sal + sal * 0.1

        END new_sal

  FROM emp

 ORDER BY sal;

 

ENAME             SAL    NEW_SAL

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

SMITH             800       1120

JAMES             950       1330

ADAMS            1100       1430

WARD             1250       1625

MARTIN           1250       1625

MILLER           1300       1690

TURNER           1500       1950

ALLEN            1600       2080

CLARK            2450       2940

BLAKE            2850       3420

JONES            2975       3570

SCOTT            3000       3600

FORD             3000       3600

KING             5000       5500

 

14 rows selected.

 

示例hr用于下:

SQL> select first_name,salary,

  2  case when salary<=1000 then salary*1.4

  3  when salary >1000 and salary <=2000 then salary*1.3

  4  when salary >2000 and salary <=3000 then salary*1.2

  5  else salary*1.1

  6  end as jiaxin from employees;

FIRST_NAME               SALARY     JIAXIN

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

Donald                     2600       3120

Douglas                    2600       3120

Jennifer                   4400       4840

Michael                   13000      14300

Pat                        6000       6600

Susan                      6500       7150

Hermann                   10000      11000

Shelley                   12008    13208.8

William                    8300       9130

Steven                    24000      26400

Neena                     17000      18700

 

FIRST_NAME               SALARY     JIAXIN

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

Lex                       17000      18700

Alexander                  9000       9900

Bruce                      6000       6600

David                      4800       5280

Valli                      4800       5280

Diana                      4200       4620

Nancy                     12008    13208.8

Daniel                     9000       9900

John                       8200       9020

Ismael                     7700       8470

Jose Manuel                7800       8580

 

FIRST_NAME               SALARY     JIAXIN

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

Luis                       6900       7590

Den                       11000      12100

Alexander                  3100       3410

Shelli                     2900       3480

Sigal                      2800       3360

Guy                        2600       3120

Karen                      2500       3000

Matthew                    8000       8800

Adam                       8200       9020

Payam                      7900       8690

Shanta                     6500       7150

 

FIRST_NAME               SALARY     JIAXIN

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

Kevin                      5800       6380

Julia                      3200       3520

Irene                      2700       3240

James                      2400       2880

Steven                     2200       2640

Laura                      3300       3630

Mozhe                      2800       3360

James                      2500       3000

TJ                         2100       2520

Jason                      3300       3630

Michael                    2900       3480

 

FIRST_NAME               SALARY     JIAXIN

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

Ki                         2400       2880

Hazel                      2200       2640

Renske                     3600       3960

Stephen                    3200       3520

John                       2700       3240

Joshua                     2500       3000

Trenna                     3500       3850

Curtis                     3100       3410

Randall                    2600       3120

Peter                      2500       3000

John                      14000      15400

 

FIRST_NAME               SALARY     JIAXIN

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

Karen                     13500      14850

Alberto                   12000      13200

Gerald                    11000      12100

Eleni                     10500      11550

Peter                     10000      11000

David                      9500      10450

Peter                      9000       9900

Christopher                8000       8800

Nanette                    7500       8250

Oliver                     7000       7700

Janette                   10000      11000

 

FIRST_NAME               SALARY     JIAXIN

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

Patrick                    9500      10450

Allan                      9000       9900

Lindsey                    8000       8800

Louise                     7500       8250

Sarath                     7000       7700

Clara                     10500      11550

Danielle                   9500      10450

Mattea                     7200       7920

David                      6800       7480

Sundar                     6400       7040

Amit                       6200       6820

 

FIRST_NAME               SALARY     JIAXIN

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

Lisa                      11500      12650

Harrison                  10000      11000

Tayler                     9600      10560

William                    7400       8140

Elizabeth                  7300       8030

Sundita                    6100       6710

Ellen                     11000      12100

Alyssa                     8800       9680

Jonathon                   8600       9460

Jack                       8400       9240

Kimberely                  7000       7700

 

FIRST_NAME               SALARY     JIAXIN

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

Charles                    6200       6820

Winston                    3200       3520

Jean                       3100       3410

Martha                     2500       3000

Girard                     2800       3360

Nandita                    4200       4620

Alexis                     4100       4510

Julia                      3400       3740

Anthony                    3000       3600

Kelly                      3800       4180

Jennifer                   3600       3960

 

FIRST_NAME               SALARY     JIAXIN

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

Timothy                    2900       3480

Randall                    2500       3000

Sarah                      4000       4400

Britney                    3900       4290

Samuel                     3200       3520

Vance                      2800       3360

Alana                      3100       3410

Kevin                      3000       3600

 

107 rows selected.

1.15.2.     DECODE(如果,那么)

语法:

DECODE(expr, search, result[, search, result ]...[, default ])

 

 

 

 

 

示例:

SELECT last_name, job_id, salary,

       DECODE(job_id, 'IT_PROG',  1.10*salary,

                         'ST_CLERK', 1.15*salary,

                         'SA_REP',   1.20*salary,

              salary)

       REVISED_SALARY

FROM   employees;

输出为:

 

SYS@ORA11GR2> with t as(

select decode(rownum,1,2,mod(rownum,2)) as gender from dual connect by rownum<10)

select gender as sex,decode(gender,0,'M',1,'F','U') as gender from t;

 

SEX GENDER

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

2 U

0 M

1 F

0 M

1 F

0 M

1 F

0 M

1 F

 

9 rows selected.

 

SYS@ORA11GR2>

1巧用decode解决条件判断问题(注:因为decode只能用于判断相等的值,无法判断不等条件,此例是利用sign这个函数来迂回解决判断问题)

SYS@ORA11GR2>with t as (

select 1 as sno,60 as score from dual union all

select 2,70 from dual union all

select 3,59 from dual)

select sno,score,decode(sign(score-60),-1,'Thank you','Congratulations') as ocm from t;

 

SNO      SCORE OCM

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

 1        60 Congratulations

 2         70 Congratulations

 3         59 Thank you

 

SYS@ORA11GR2>

2利用decode统计数量

SYS@ORA11GR2> with t as(

select mod(rownum,2) as type,mod(rownum,3) as state from dual connect by rownum <=33)

select type,count(*) as num,

       sum(decode(state,0,1,0)) as s1,

       sum(decode(state,1,1,0)) as s2,

       sum(decode(state,2,1,0)) as s3

from t group by type;

 

 TYPE        NUM        S1        S2         S3

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

1         17          6          6          5

0         16          5          5          6

 

SYS@ORA11GR2>

 

1.16.    其它

1.16.1.     USERENV

语法:USERENV('parameter')

1)   ISDBA 查看当前用户是否是DBA如果是则返回true

SYS@ORA11GR2> select userenv('isdba') from dual;

 

USEREN

------

TRUE

 

SYS@ORA11GR2>

2)   SESSION 返回会话标志

SYS@ORA11GR2> select userenv('sessionid') from dual;

 

USERENV('SESSIONID')

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

4294967295

 

SYS@ORA11GR2>

3)   ENTRYID 返回会话人口标志

SYS@ORA11GR2> select userenv('entryid') from dual;

 

USERENV('ENTRYID')

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

0

 

SYS@ORA11GR2>

4)   INSTANCE 返回当前INSTANCE的标志

SYS@ORA11GR2> select userenv('instance') from dual;

 

USERENV('INSTANCE')

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

1

 

SYS@ORA11GR2>

5)   LANGUAGE 返回当前环境变量

SYS@ORA11GR2> select userenv('language') from dual;

 

USERENV('LANGUAGE')

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

AMERICAN_AMERICA.US7ASCII

 

SYS@ORA11GR2>

6)   LANG 返回当前环境的语言的缩写

SYS@ORA11GR2> select userenv('lang') from dual;

 

USERENV('LANG')

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

US

 

SYS@ORA11GR2>

7)   TERMINAL 返回用户的终端或机器的标志

SYS@ORA11GR2> select userenv('terminal') from dual;

 

USERENV('TERMINAL')

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

XXF-PC

 

SYS@ORA11GR2>

 

请使用浏览器的分享功能分享到微信等