ORACLE编程详解

0 . 查看系统表空间

select * from dba_tablespaces

1 . 查看表结构

desc table_name

2 . 查询数据库SID

select name from v$database;

3 . 用 B 表的数据更新 A 表数据 ( 有关联的字段 )

UPDATE A SET name=(SELECT name FROM B WHERE
A.id=B.id) WHERE B.id IS NOT NULL ;

4 . 随机数函数 DBMS_RANDOM.RANDOM

SQL> select dbms_random.random from dual

5 . 如何在字符串里加回车?

SQL> select 'line1'||chr(10)||'line2' from dual;

6 . 如何使 select 语句使查询结果自动生成序号 ?

SQL> select rownum, fieldname from table;

7 . 怎么可以快速做一个和原表一样的备份表 ?

create table new_table as (select * from old_table) ;

8 . 如何单独备份一个或多个表?

exp 用户 / 密码 tables=( 表 1 , … ,表 2)

9. 如何单独备份一个或多个用户?

exp system/manager owner=( 用户 1 ,用户 2 , … ,用户 n) file= 导出文件

10 . 如何执行脚本 SQL 文件 ?

SQL>@$PATH/filename.sql ;

11. 如何快速清空一个大表 ?

SQL>truncate table table_name ;

12 . 字符串的连接

select concat(col1 , col2) from table ;
select col1||col2 from table ;

13 . 怎么把 select 出来的结果导到一个文本文件中?

SQL> spool c:\test.txt;
SQL> select * from emp;
SQL> spool off ;

14. 如何测试 SQL 语句执行所用的时间 ?

SQL>set timing on ;
SQL>select * from tablename ;

15 . 改变字段大小 ?

-- 改大行,改小不行(除非都是空的)
SQL>alter table table_name modify (field_name varchar2(100)) ;

16 . 如何查询某天的数据 ?

-- datefield为要查询的日期字段
SQL>select * from table_name where trunc( datefield ) = to_date('2003-05-02' ,'yyyy-mm-dd') ;

17. 如何修改表名 ?

SQL> alter table old_table_name rename to new_table_name;

18 . 如何搜索出前 N 条记录?

SQL> SELECT * FROM empLOYEE WHERE ROWNUM < n ORDER BY empno;

-- 搜索一个范围的数据 
SQL> SELECT * FROM (SELECT ROWNUM RN,EMPNO,ENAME FROM EMP) WHERE RN > 5 AND RN < 10 ORDER BY empno;

19 . 怎样用 Sql 语句实现查找一列中第 N 大值?

SQL> select * from (select t.* , dense_rank() over (order by sal) rank from employee) where rank = N ;

20 . 如何在给现有的日期加上 2 年?

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

21 . 返回大于等于 N 的最小整数值 ?

SQL> SELECT CEIL(N) FROM DUAL ;

22 . 返回小于等于 N 的最小整数值 ?

SQL> SELECT FLOOR(N) FROM DUAL ;

23 . 返回当前月的最后一天 ?

SQL> SELECT LAST_DAY(SYSDATE) FROM DUAL ;

24 . 如何不同用户间数据导入 ?

IMP SYSTEM/MANAGER FILE=AA.DMP FROMUSER=USER_OLD TOUSER=USER_NEW ROWS=Y INDEXES=Y ;

25 . 如何找数据库表的主键字段的名称 ?

SQL>SELECT * FROM user_constraints WHERE CONSTRAINT_TYPE='P' and table_name='TABLE_NAME' ;

26 . 两个结果集互加的函数 ?

SQL>SELECT * FROM BSEMPMS_OLD INTERSECT SELECT * FROM BSEMPMS_NEW ;
SQL>SELECT * FROM BSEMPMS_OLD UNION SELECT * FROM BSEMPMS_NEW;
SQL>SELECT * FROM BSEMPMS_OLD UNION ALL SELECT * FROM BSEMPMS_NEW ;

27 . 两个结果集互减的函数 ?

SQL>SELECT * FROM BSEMPMS_OLD MINUS SELECT * FROM BSEMPMS_NEW ;

28. 如何配置 Sequence?

  • 创建sequence
create sequence seq_cust start 1 incrememt by
  • 建表
create table cust { 
    cust_id smallint not null,
    ...
}
  • insert 数据
insert into table cust values( seq_cust.nextval, ... )
insert into table cust values( seq_cust.currval, ... )

29 . 日期各部分的写法

-- 取时间点的年份的写法:
SELECT TO_CHAR(SYSDATE , 'YYYY') FROM DUAL ;
-- 取时间点的月份的写法:
SELECT TO_CHAR(SYSDATE , 'MM') FROM DUAL ;
-- 取时间点的日的写法:
SELECT TO_CHAR(SYSDATE , 'DD') FROM DUAL ;
-- 取时间点的时的写法:
SELECT TO_CHAR(SYSDATE , 'HH24') FROM DUAL ;
-- 取时间点的分的写法:
SELECT TO_CHAR(SYSDATE , 'MI') FROM DUAL ;
-- 取时间点的秒的写法:
SELECT TO_CHAR(SYSDATE , 'SS') FROM DUAL ;
-- 取时间点的日期的写法:
SELECT TRUNC(SYSDATE) FROM DUAL ;
-- 取时间点的时间的写法:
SELECT TO_CHAR(SYSDATE , 'HH24 : MI : SS') FROM DUAL ;
-- 日期,时间形态变为字符形态:
SELECT TO_CHAR(SYSDATE) FROM DUAL ;
-- 将字符串转换成日期或时间形态:
SELECT TO_DATE('2003/08/01') FROM DUAL ;
-- 返回参数的星期几的写法:
SELECT TO_CHAR(SYSDATE , 'D') FROM DUAL ;
-- 返回参数一年中的第几天的写法:
SELECT TO_CHAR(SYSDATE , 'DDD') FROM DUAL ;
-- 返回午夜和参数中指定的时间值之间的秒数的写法:
SELECT TO_CHAR(SYSDATE , 'SSSSS') FROM DUAL ;
-- 返回参数中一年的第几周的写法:
SELECT TO_CHAR(SYSDATE , 'WW') FROM DUAL ;

30 . ROWNUM

-- 按设定排序的行的序号
SELECT * FROM emp WHERE ROWNUM < 10 ;

31. 如何查找重复记录?

SELECT * FROM TABLE_NAME WHERE ROWID!=( 
    SELECT MAX(ROWID) 
        FROM TABLE_NAME D 
        WHERE TABLE_NAME.COL1=D.COL1 AND TABLE_NAME.COL2=D.COL2
    );

32 . 如何删除重复记录?

DELETE FROM TABLE_NAME WHERE ROWID!=( 
    SELECT MAX(ROWID) 
        FROM TABLE_NAME D 
        WHERE TABLE_NAME.COL1=D.COL1 AND TABLE_NAME.COL2=D.COL2
    );

33 . 赋予权限

GRANT
  CONNECT,                
  RESOURCE,               
  --DBA,                  
  --unlimited tablespace,
  CREATE  SESSION,         
  CREATE ANY SEQUENCE,     
  CREATE ANY TABLE,        
  CREATE ANY VIEW ,        
  CREATE ANY INDEX,        
  CREATE ANY PROCEDURE,    
  CREATE ANY DIRECTORY,    
  ALTER  SESSION, 
  ALTER ANY SEQUENCE,     
  ALTER ANY TABLE,        
  --ALTER ANY VIEW ,        --不能修改视图
  ALTER ANY INDEX,        
  ALTER ANY PROCEDURE,    
  --ALTER ANY DIRECTORY,    --不能修改目录
  --DROP  SESSION,       --不能删除Session
  DROP ANY SEQUENCE,     
  DROP ANY TABLE,        
  DROP ANY VIEW ,        
  DROP ANY INDEX,        
  DROP ANY PROCEDURE,    
  DROP ANY DIRECTORY,    
  SELECT ANY TABLE, 
  SELECT ANY DICTIONARY,
  INSERT ANY TABLE, 
  UPDATE ANY TABLE, 
  DELETE ANY TABLE,
  DEBUG ANY PROCEDURE,
  DEBUG CONNECT SESSION,
  exp_full_database,  
  imp_full_database     
TO user;

34 . 导出视图数据

  create table v_table as( select * from view_table);

35 . 解决Temp01.dbf不断变大的问题

第一步:
alter database tempfile 'F:\oracle\product\10.1.0\oradata\orcl\TEMP01.DBF' drop;

第二步:
alter tablespace temp add tempfile
'F:\oracle\product\10.1.0\oradata\orcl\TEMP01.DBF'
size 2048M reuse autoextend on next 100M;

第三步:
select d.file_name, d.file_id, d.tablespace_name, d.bytes 
from dba_temp_files d;

第四步:
alter database tempfile 'F:\oracle\product\10.1.0\oradata\orcl\TEMP01.DBF' autoextend off; 

36 . 行转列的多记录合并

id name
1 a
1 b
1 c
2 aa
2 bb

1 . 使用 WM_CONCAT 函数

SQL> select wmsys.wm_concat(distinct name) from t; 
SQL> select id,wmsys.wm_concat(distinct name) con_name from t group by id;  

ID   CON_NAME  
--------------  
1     a,b,c  
2     aa,bb  

2 . 使用 STRAGG

SQL> SELECT TRIM(',' FROM SYS.STRAGG(NAME||NVL2(NAME,',',''))) CON_NAME FROM T;  
  
CON_NAME  
----------  
a,b,c,aa,bb  

3 . 使用 partition by

select id,sys_connect_by_path(name,'>')  con_name  
    from ( select id,name,row_number() over( partition by id order by name) rn  from (select id,name from t )) t  
start 
    with t.rn=1  
connect by 
    t.id=prior t.id and t.rn-1=prior t.rn  

    ID CON_NAME  
------- --------------------  
     1 >a  
     1 >a>b  
     1 >a>b>c  
     2 >aa  
     2 >aa>bb  
     2 >aa>bb>china  
     2 >aa>bb>china>china  

select id,substr(max(sys_connect_by_path(name,'>')),2)  con_name  
  from (select id,name,row_number() over(partition by id order by name) rn  from (select id,name from t ))t  
  start with t.rn=1  
  connect by t.id=prior t.id and t.rn-1=prior t.rn  
  group by id  

   ID CON_NAME  
------- --------------------  
    1 a>b>c  
    2 aa>bb>china>china  

4 . 使用 XMLAGG 函数

RTRIM(XMLAGG(XMLPARSE(CONTENT field || ',' WELLFORMED)) .GETCLOBVAL(), ',')

5 . 自定义类型 VARCHAR2

-- create function of strcat 
CREATE OR REPLACE FUNCTION strcat (input VARCHAR2) RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE USING strcat_type; 

-- create type define of strcat_type
create or replace type strcat_type as object 
( 
    currentstr varchar2(4000), 
    currentseprator varchar2(8), 
    static function ODCIAggregateInitialize(sctx IN OUT strcat_type) return number, 
    member function ODCIAggregateIterate(self IN OUT strcat_type,value IN VARCHAR2) return number, 
    member function ODCIAggregateTerminate(self IN strcat_type,returnValue OUT VARCHAR2, flags IN number) return number, 
    member function ODCIAggregateMerge(self IN OUT strcat_type,ctx2 IN strcat_type) return number 
) 

-- create type body of strcat_type
create or replace type body strcat_type is 
      static function ODCIAggregateInitialize(sctx IN OUT strcat_type) return number is 
      begin 
        sctx := strcat_type('',','); 
        return ODCIConst.Success; 
      end; 
      member function ODCIAggregateIterate(self IN OUT strcat_type, value IN VARCHAR2) return number is 
      begin 
        if self.currentstr is null then 
           self.currentstr := value; 
        else 
          self.currentstr := self.currentstr ||currentseprator || value; 
        end if; 
        return ODCIConst.Success; 
      end; 
      member function ODCIAggregateTerminate(self IN strcat_type, returnValue OUT VARCHAR2, flags IN number) return number is 
      begin 
        returnValue := self.currentstr; 
        return ODCIConst.Success; 
      end; 
      member function ODCIAggregateMerge(self IN OUT strcat_type, ctx2 IN strcat_type) return number is 
      begin 
        if ctx2.currentstr is null then 
          self.currentstr := self.currentstr; 
        elsif self.currentstr is null then 
          self.currentstr := ctx2.currentstr; 
        else 
          self.currentstr := self.currentstr || currentseprator || ctx2.currentstr; 
        end if; 
        return ODCIConst.Success; 
      end; 
      end; 

6 . 自定义类型 clob

-- create function of strcat 
CREATE OR REPLACE FUNCTION strcat (input VARCHAR2) RETURN clob PARALLEL_ENABLE AGGREGATE USING strcat_type;

-- create type define of strcat_type
create or replace type strcat_type as object
(
  CURR_STR clob,
  STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT strcat_type) RETURN NUMBER,
  MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT strcat_type, P1 IN VARCHAR2) RETURN NUMBER,
  MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN strcat_type, RETURNVALUE OUT clob, FLAGS IN NUMBER) RETURN NUMBER,
  MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF  IN OUT strcat_type, SCTX2 IN strcat_type) RETURN NUMBER
)

-- create type body of strcat_type
create or replace type body strcat_type is
  static function ODCIAggregateInitialize(sctx IN OUT strcat_type)
    return number is
  BEGIN
    SCTX := strcat_type(NULL);
    RETURN ODCICONST.SUCCESS;
  END;
  MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT strcat_type,P1 IN VARCHAR2) RETURN NUMBER IS
  BEGIN
    IF (CURR_STR IS NOT NULL) THEN
      CURR_STR := CURR_STR || ',' || P1;
    ELSE
      CURR_STR := P1;
    END IF;
    RETURN ODCICONST.SUCCESS;
  END;
  MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN strcat_type,  RETURNVALUE OUT clob,  FLAGS IN NUMBER) RETURN NUMBER IS
  BEGIN
    RETURNVALUE := CURR_STR;
    RETURN ODCICONST.SUCCESS;
  END;
  MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF  IN OUT strcat_type, SCTX2 IN strcat_type) RETURN NUMBER IS
  BEGIN
    IF (SCTX2.CURR_STR IS NOT NULL) THEN
      SELF.CURR_STR := SELF.CURR_STR || ',' || SCTX2.CURR_STR;
    END IF;
    RETURN ODCICONST.SUCCESS;
  END;
END;

37 . 去掉重复字符串

  /****************************************************
  ** Oracle去掉重复字符串
  ** 函数名称:RemoveSameStr
  ** 参    数:【名称】         【类型 】      【说明】
  **                 oldStr           varchar2       要处理的字符串
  **                 sign               varchar2       字符串分隔符
  ** 返 回 值: result          varchar2        不包含重复子串的记录
  ****************************************************/

create or replace function rm_same_str(oldStr clob, sign varchar2)
  return varchar2 is
    str          clob;
    currentIndex number;
    startIndex   number;
    endIndex     number;
    type str_type is table of varchar2(1000) index by binary_integer;
    arr str_type;
    Result varchar2(4000);
begin
    -- null string
    if oldStr is null then
    return('');
    end if;

    --string is too long
    if length(oldStr) > 32000 then
    return(oldStr);
    end if;
    str := oldStr;

    currentIndex := 0;
    startIndex   := 0;

    loop
    currentIndex := currentIndex + 1;
    endIndex     := instr(str, sign, 1, currentIndex);
    if (endIndex <= 0) then
      exit;
    end if;

    arr(currentIndex) :=substr(str,startIndex + 1,  endIndex - startIndex - 1);

    -- arr(currentIndex) := trim(substr(str,startIndex + 1,endIndex - startIndex - 1));
    startIndex := endIndex;
    end loop;

    --get the last string
    arr(currentIndex) := substr(str, startIndex + 1, length(str));

    --remove the same string
    for i in 1 .. currentIndex - 1 loop
    for j in i + 1 .. currentIndex loop
      if arr(i) = arr(j) then
        arr(j) := '';
      end if;
    end loop;
    end loop;

    str := '';
    for i in 1 .. currentIndex loop
    if arr(i) is not null then
      str := str || sign || arr(i);
      --set arrar to null:
      arr(i) := '';
    end if;
    end loop;

    --remove the prev mark
    Result := substr(str, 2, length(str));

    return(Result);
end rm_same_str;

38 . 主要函数

  • INITCAP(CHAR):将字符串 CHAR 的第一个字符为大写,其余为小写。
SELECT INITCAP('ABCDE') FROM DUAL ;
  • LENGTH(CHAR) : 取一字符串 CHAR 的长度。
SELECT LENGTH('ABCDE') FROM DUAL ;
  • LOWER(CHAR) :将字符串 CHAR 全部变为小写。
SELECT LOWER('ABCDE') FROM DUAL ;
  • LPAD(CHAR1 , N , CHAR2) :用字符串 CHAR2 包括的字符左填 CHAR1 ,使其长度为 N 。
SELECT LPAD('ABCDEFG' , 10'123') FROM DUAL ;
-- 结果: '123ABCDEFG'
  • LTRIM(CHAR , SET) :从字符串 CHAR 的左边移去字符串 SET 中的字符,直到第一个不是 SET 中的字符为
SELECT ('CDEFG' , 'CD') FROM DUAL ;
-- 结果: 'EFG'
  • NLS_INITCAP(CHAR):取字符 CHAR 的第一个字符大写,其余字符为小写。
SELECT NLS_INITCAP('ABCDE') FROM DUAL ;
  • NLS_LOWER(CHAR):将字符串 CHAR 包括的字符全部小写。
SELECT NLS_LOWER('AAAA') FROM DUAL ;
  • NLS_UPPER(CHAR):将字符串 CHAR 包括的字符全部大写。
SELECT NLS_UPPER('AAAA') FROM DUAL ;
  • REPLACE(CHAR1 , CHAR2 , CHAR3):用字符串 CHAR3 代替每一个列值为 CHAR2 的列,其结果放在 CHAR1 中。
SELECT REPLACE(EMP_NO , '123' , '456') FROM DUAL ;
  • RPAD(CHAR1 , N , CHAR2):用字符串 CHAR2 右填字符串 CHAR1 ,使其长度为 N 。
SELECT RPAD('234' , 8 , '0') FROM DUAL ;
  • RTRIM(CHAR , SET):移去字符串 CHAR 右边的字符串 SET 中的字符,直到最后一个不是 SET 中的字符为止。
SELECT RTRIM('ABCDE' , 'DE') FROM DUAL ;
  • SUBSTR(CHAR , M , N):得到字符串 CHAR 从 M 处开始的 N 个字符 . 双字节字符,一个汉字为一个字符的。
SELECT SUBSTR('ABCDE' , 2 , 3) FROM DUAL ;
  • SUBSTRB(CHAR , M , N):得到字符串 CHAR 从 M 处开始的 N 个字符 . 双字节字符,一个汉字为二个字符的。
SELECT SUBSTRB('ABCDE' , 2 , 3) FROM DUAL ;
  • TRANSLATE(CHAR1 , CHAR2 , CHAR3):将 CHAR1 中的 CHAR2 的部分用 CHAR3 代替。
SELECT TRANSLATE('ABCDEFGH' , 'DE' , 'MN') FROM DUAL ;
  • UPPER(CHAR):将字符串 CHAR 全部为大写。
  • ADD_MONTHS(D , N):将 N 个月增加到 D 日期。
SELECT ADD_MONTHS(SYSDATE , 5) FROM DUAL ;
  • LAST_DAY(D):得到包含 D 日期的月份的最后的一天的日期。
SELECT LAST_DAY(SYSDATE) FROM DUAL ;
  • MONTH_BETWEEN(D1 , D2):得到两个日期之间的月数。
SELECT MONTH_BETWEEN(D1 , D2) FROM DUAL ;
  • NEXT_DAY(D , CHAR):得到比日期 D 晚的由 CHAR 命名的第一个周日的日期。
SELECT NEXT_DAY(TO_DATE('2003/09/20') , 'SATDAY') FROM DUAL ;
  • ROUNT(D , FMT):得到按指定的模式 FMT 舍入到的最进的日期。
SELECT ROUNT('2003/09/20' , MONTH) FROM DUAL ;
  • SYSDATE:得到当前系统的日期和时间。
SELECT SYSDATE FROM DUAL ;
  • TO_CHAR(D , FMT):将日期 D 转换为 FMT 的字符串。
SELECT TO_CHAR(SYSDATE , 'YYYY/MM/DD') FROM DUAL ;
  • TO_DATE(CHAR , FMT):将字符串 CHAR 按 FMT 的格式转换为日期。
SELECT TO_DATE('2003/09/20' , 'YYYY/MM/DD') FROM DUAL ;
  • ABS(N):得到 N 的绝对值。
SELECT ABS(-6) FROM DUAL ;
  • EXP(N):得到 N 的 E 的 N 次幂。
SELECT EXP(1) FROM DUAL ;
  • MOD(M , N):得到 M 除以 N 的余数。
SELECT MOD(100 , 7) FROM DUAL ;
  • POWER(M , N):得到 M 的 N 幂。
SELECT POWER(4 , 3) FROM DUAL ;
  • ROUND(N , M):将 N 舍入到小数点后 M 位。
SELECT (78.87653 , 2) FROM DUAL ;
  • SIGN(N):当 N<0 时,得到 -1 ;当 N>0 时,得到 1 ;当 N=0 时,得到 0 ;
SELECT SIGN(99) FROM DUAL ;
  • TRUNC(N , M):得到在 M 位截断的 N 的值。
SELECT TRUNC(7.7788 , 2) FROM DUAL ;
  • COUNT():计算满足条件的记录数。
SELECT COUNT(*) FROM TABLE1 WHERE COL1='AAA' ;
  • MAX():对指定的列求最大值。
SELECT MAX(COL1) FROM TABLE1 ;
  • MIN():对指定的列求最小值。
SELECT MIN(COL1) FROM TABLE1 ;
  • AVG():对指定的列求平均值。
SELECT AVG(COL1) FROM TABLE1 ;
  • SUM():计算列的和。
SELECT SUM(COL1) FROM DUAL ;
  • TO_NUMBER(CHAR):将字符转换为数值。
SELECT TO_NUMBER('999') FROM DUAL ;
  • empty_b|clob():返回一个空的 LOB 定位符 , 用在初始化 LOB 变量 , 或用在 INSERT 及 UPDATE 声明去初始 化
    LOB 列或将其属性置为空。
INSERT INTO TABLE1 VALUES(EMPTY_BLOB()) ;
UPDATE TABLE1 SET CLOB_COL=EMPTY_BLOB() ;
  • NVL(EXPR1 , EXPR2):若 EXPR1 是 NULL ,则返回 EXPR2 ,否则返回 EXPR1 。
SELECT NAME , NVL(TO_CHAR(COMM) , 'NOT APPLICATION') FROM TABLE1 ;

39. CASE WHEN 和 DECODE

1 . case表达式

--简单Case函数  
CASE sex  
    WHEN '1' THEN '男'  
    WHEN '2' THEN '女'  
    ELSE '其他' 
END  

--Case搜索函数  
CASE
    WHEN sex = '1' THEN '男'  
    WHEN sex = '2' THEN '女'  
    ELSE '其他' 
END  

2 . CASE WHEN 在语句中不同位置的用法

  • 2.1 SELECT 用法
SELECT 
    grade,
    COUNT ( CASE WHEN sex = 1 THEN 1 ELSE NULL END) 男生数, 
    COUNT ( CASE WHEN sex = 2 THEN 1 ELSE NULL END) 女生数
FROM 
    students
GROUP BY  
    grade
  • 2.2 WHERE 用法
SELECT 
    T2.*, T1.*
FROM 
    T1, T2
WHERE ( 
    CASE 
        WHEN T2.COMPARE_TYPE  = 'A' AND T1.SOME_TYPE LIKE 'NOTHING%' THEN 1
        WHEN T2.COMPARE_TYPE != 'A' AND T1.SOME_TYPE NOT LIKE 'NOTHING%' THEN 1
        ELSE 0
    END ) = 1
  • 2.3 GROUP BY 用法
SELECT  
    CASE 
        WHEN salary <= 500 THEN '1'  WHEN salary > 500 AND salary <= 600  THEN '2'  
        WHEN salary > 600 AND salary <= 800  THEN '3'  
        WHEN salary > 800 AND salary <= 1000 THEN '4'  
        ELSE NULL 
    END salary_class, -- 别名命名
    COUNT(*)  
FROM    
    A  
GROUP BY  
    CASE 
        WHEN salary <= 500 THEN '1'  
        WHEN salary > 500 AND salary <= 600  THEN '2'  
        WHEN salary > 600 AND salary <= 800  THEN '3'  
        WHEN salary > 800 AND salary <= 1000 THEN '4'  
        ELSE NULL 
    END;  

3 . DECODE() 函数

基本语法: decode(条件, 值1, 返回值1, 值2, 返回值2, ..., 值n, 返回值n, 缺省值)

select decode(sex, 'M', 'Male', 'F', 'Female', 'Unknown') from employees;

40. 修改clob字段为varchar2

alter table tablename add (new_column varchar2(4000));
update tablename set new_column=dbms_lob.substr(old_column,1000,1);
alter table tablename drop column old_column;
alter table tablename rename column new_column to old_column;

41. 使用正则表达式查询

--非正整数 
select 字段 from 表 where regexp_replace(字段,'\d','') is not null;

--非数值类型
select 字段 from 表 where regexp_replace(字段,'^[-\+]?\d+(\.\d+)?$','') is not null;

--自定义函数,判断非值类型
create or replace function isnumber(col varchar2) return   i number;
begin
  i := to_number(col);
  return 1;
exception
  when others then
    return 0;
end;

select 字段 from 表 where isnumber(字段)=0;

42. 判断某個字段的值是不是数字

共有三种方法,分别是使用to_number()regexp_like()translate()三种函数来进行匹配。如果字段的值是数字,返回1,否则返回0,具体的实现如下,三种方法任选壹种即可。运行结果:如果字符串是数字格式则返回1,不是则返回0。

--1、利用 to_number
CREATE OR REPLACE FUNCTION isnumeric(str IN VARCHAR2)
    RETURN NUMBER
IS
    v_str FLOAT;
BEGIN
    IF str IS NULL
    THEN
       RETURN 0;
    ELSE
       BEGIN
          SELECT TO_NUMBER (str)
            INTO v_str
            FROM DUAL;
       EXCEPTION
          WHEN INVALID_NUMBER
          THEN
             RETURN 0;
       END;
       RETURN 1;
    END IF;
END isnumeric;
/

--2、利用 regexp_like
CREATE OR REPLACE FUNCTION isnumeric (str IN VARCHAR2)
    RETURN NUMBER
IS
BEGIN
    IF str IS NULL
    THEN
       RETURN 0;
    ELSE
       IF regexp_like (str, '^(-{0,1}+{0,1})[0-9]+(.{0,1}[0-9]+)$')
       THEN
          RETURN 1;
       ELSE
          RETURN 0;
       END IF;
    END IF;
END isnumeric;
/

--3、利用 translate
CREATE OR REPLACE FUNCTION isnumeric (str IN VARCHAR2)
    RETURN NUMBER
IS
    v_str VARCHAR2 (1000);
BEGIN
    IF str IS NULL
    THEN
       RETURN 0;
    ELSE
       v_str := translate(str, '.0123456789', '.');

       IF v_str = '.' OR v_str = '+.' OR v_str = '-.' OR v_str IS NULL
       THEN
          RETURN 1;
       ELSE
          RETURN 0;
       END IF;
    END IF;
END isnumeric;

由于 Oracle 数据库本身没有提供检测字段是否为数字的方法,因此我们需要自己创建壹個 isnumeric() 的函数,然后再调用它来进行判断。具体的调用方式如下:

SQL> select isnumeric('123a') from dual;
ISNUMERIC('123A')
-----------------
                0

SQL> select isnumeric('123.509') from dual;
ISNUMERIC('123.509')
--------------------
                1

SQL> select isnumeric('123.205.10.8') from dual;
ISNUMERIC('123.205.10.8')
-------------------------
                0

43. 重复记录查询

1、查找表中多余的重复记录,重复记录是根据单个字段 xxxId 来判断

select * from 
  xxx_table
where 
  xxxId in (select xxxId from  xxx_table group by xxxId having count(xxxId) > 1)

2、删除表中多余的重复记录,重复记录是根据单个字段 xxxId 来判断,只留有rowid最小的记录

delete from 
  xxx_table 
where 
  xxxId in (select xxxId from xxx_table group by xxxId having count(xxxId) > 1) and 
  rowid not in (select min(rowid) from xxx_table group by xxxId having count(xxxId)>1)

3、查找表中多余的重复记录(多个字段)

select * from 
  xxx_table a
where 
  (a.xxxIdA,a.xxxIdB) in   (select xxxIdA,xxxIdB from xxx_table group by xxxIdA,xxxIdB having count(*) > 1)

4、删除表中多余的重复记录(多个字段),只留有rowid最小的记录

delete from xxx_table a
where (a.xxxIdA,a.xxxIdB) in   (select xxxIdA,xxxIdB from xxx_table group by xxxIdA,xxxIdB having count(*) > 1)
and rowid not in (select min(rowid) from xxx_table group by xxxIdA,xxxIdB having count(*)>1)

5、查找表中多余的重复记录(多个字段),不包含rowid最小的记录

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

推荐阅读更多精彩内容