-- 列操作 -- 增加和修改列不需要加关键字COLUMN -- 删除单列的话,一定要加COLUMN,删除多列的时候,不能加COLUMN关键字 -- 增加一列 alter table emp4 add test varchar2(10); -- 修改一列 alter table emp4 modify test varchar2(20); -- 删除一列 alter table emp4 drop column test; -- 增加多列 alter table emp4 add (test varchar2(10),test2 number); -- 修改多列 alter table emp4 modify (test varchar2(20),test2 varchar2(20)); -- 删除多列 alter table emp4 drop (test,test2);
--在sqlplus中执行sql脚本,下面两种方式都可以 START file_name @file_name --判断表是否存在,如果存在则删除 declare num number; begin select count(1) into num from all_tables where TABLE_NAME = 'EMP' and OWNER='SCOTT'; if num=1 then execute immediate 'drop table EMP'; end if; end; / --创建表 CREATE TABLE EMP (EMPNO NUMBER(4) NOT NULL, ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4), HIREDATE DATE, SAL NUMBER(7, 2), COMM NUMBER(7, 2), DEPTNO NUMBER(2)); 可以将上述存储过程加载到每一个create table前面。 --ORACLE 判断序列是否存在,如果存在就删除 declare V_NUM number; BEGIN ----多次删除时,每次都将v_num设置成为0 V_NUM := 0; ----判断序列 seq_name_1 是否存在(区分大小写) select count(0) into V_NUM from user_sequences where sequence_name = 'SEQ_BUSINESS_PROCESS_INDEX_ID'; ----如果存在立即删除 if V_NUM > 0 then execute immediate 'DROP SEQUENCE SEQ_BUSINESS_PROCESS_INDEX_ID'; end if; END;
-- 两个时间相隔的分钟数 select ceid((to_date('2016-07-21 12:12:12','yyyy-mm-dd hh24:mi:ss') - to_date('2016-07-20 11:11:11','yyyy-mm-dd hh24:mi:ss'))*24*60) from dual; -- 时间转换 select sysdate,to_char(sysdate,'yyyy/mm/dd HH24:MI:SS') from dual; -- 当前时间加十个月 select sysdate,add_months(sysdate,12) from dual; -- 当前时间的下一个周六,1 表示下个周日,2表示下个周一 select next_day(sysdate,7) from dual; -- 两个时间相隔的天数、月、分、秒 select extract(day from b-a) day, extract(hour from b-a) hour, extract(minute from b-a) minute, extract(second from b-a) second from ( select to_timestamp('2018-5-1 8:8:8','yyyy-mm-dd HH24:MI:SS') a, to_timestamp('2019-5-2 9:9:9','yyyy-mm-dd HH24:MI:SS') b from dual ); -- 当月的第一天以及最后一天对应的日期 select to_char((last_day(to_date(to_char(sysdate,'mm')-1,'mm'))+1), 'yyyy-mm-dd') as firstday, to_char(last_day(sysdate),'yyyy-mm-dd') as lastday from dual;
Oracle中row_number()、rank()、dense_rank() 的区别 row_number的用途非常广泛,排序最好用它,它会为查询出来的每一行记录生成一个序号,依次排序且不会重复,注意使用row_number函数时必须要用over子句选择对某一列进行排序才能生成序号。 rank函数用于返回结果集的分区内每行的排名,行的排名是相关行之前的排名数加一。简单来说rank函数就是对查询出来的记录进行排名,与row_number函数不同的是,rank函数考虑到了over子句中排序字段值相同的情况,如果使用rank函数来生成序号,over子句中排序字段值相同的序号是一样的,后面字段值不相同的序号将跳过相同的排名号排下一个,也就是相关行之前的排名数加一,可以理解为根据当前的记录数生成序号,后面的记录依此类推。 dense_rank函数的功能与rank函数类似,dense_rank函数在生成序号时是连续的,而rank函数生成的序号有可能不连续。dense_rank函数出现相同排名时,将不跳过相同排名号,rank值紧接上一次的rank值。在各个分组内,rank()是跳跃排序,有两个第一名时接下来就是第三名,dense_rank()是连续排序,有两个第一名时仍然跟着第二名 --row_number() 顺序排序 select name,course,row_number() over(partition by course order by score desc) rank from student; --rank() 跳跃排序,如果有两个第一级别时,接下来是第三级别 select name,course,rank() over(partition by course order by score desc) rank from student; --dense_rank() 连续排序,如果有两个第一级别时,接下来是第二级别 select name,course,dense_rank() over(partition by course order by score desc) rank from student; --每门课程第一名只取一个: select * from (select name,course,row_number() over(partition by course order by score desc) rank from student) where rank=1; --每门课程第一名取所有: select * from (select name,course,dense_rank() over(partition by course order by score desc) rank from student) where rank=1; --每门课程第一名取所有: select * from (select name,course,rank() over(partition by course order by score desc) rank from student) where rank=1;
-- 树形结构
-- 父节点向下查找 select level,a.* from t a start with a.id = '' connect by nocycle prior a.id = a.p_id ; -- 父节点向下查找 (不包括父节点) select level,a.* from t a start with a.p_id = '' connect by nocycle prior a.id = a.p_id ; -- 子节点向上查找所有父节点 select level,a.* from t a start with a.id = '' connect by nocycle prior a.p_id = a.id ;
lpad 与 rpad 函数:
-- 先看例子:
select lpad('1234',2) from dual; -- 12 select lpad('1234',5,'0') from dual; -- 01234 select rpad('1234',2,'0') from dual; -- 12 select rpad('1234',5,'0') from dual; -- 12340
中间的参数表示最终结果的长度,然后就是初始字符和是否 在左还是右 补充的问题了。
instr 函数
instr( string1, string2 [, start_position [, nth_appearance ] ] ) / instr(源字符串, 目标字符串, 起始位置, 匹配序号)
select substr('999999'+100000,-5,5) from dual;
REGEXP_SUBSTR函数(字符串转多行)
在oracle中,使用一条语句实现将'17,20,23'拆分成'17','20','23'的集合。
REGEXP_SUBSTR函数格式如下:
function REGEXP_SUBSTR(String, pattern, position, occurrence, modifier)
__srcstr :需要进行正则处理的字符串
__pattern :进行匹配的正则表达式
__position :起始位置,从第几个字符开始正则表达式匹配(默认为1)
__occurrence :标识第几个匹配组,默认为1
__modifier :模式('i'不区分大小写进行检索;'c'区分大小写进行检索。默认为'c'。)
-- 1、查询使用正则分割后的第一个值,也就是17 SELECT REGEXP_SUBSTR('17,20,23','[^,]+',1,1,'i') AS STR FROM DUAL; -- 2、查询使用正则分割后的最后一个值,也就是23 SELECT REGEXP_SUBSTR('17,20,23','[^,]+',1,3,'i') AS STR FROM DUAL; -- 3、获取一个多个数值的列,从而能够让结果以多行的形式展示出来 SELECT LEVEL FROM DUAL CONNECT BY LEVEL <=7; -- 4、将上面REGEXP_SUBSTR的occurrence关联 SELECT NVL(REGEXP_SUBSTR('17,20,23', '[^,]+', 1, LEVEL, 'i'), 'NULLL') AS STR FROM DUAL CONNECT BY LEVEL <= 7; -- 5、优化上面的SQL语句,让生成的行的数量符合实际情况 SELECT REGEXP_SUBSTR('17,20,23', '[^,]+', 1, LEVEL, 'i') AS STR FROM DUAL CONNECT BY LEVEL <= LENGTH('17,20,23') - LENGTH(REGEXP_REPLACE('17,20,23', ',', ''))+1;
wm_concat 函数 (多行字符串转一行)
select t.id,to_char(wm_concat(t.name)) from t group by t.id;
需要注意的是,WMSYS_CONCAT()只适用于oracle10.0及之前的版本。不然会报错: ora-00904: WM_CONCAT:invalid identifier
可以改成:
select listagg(t.name,',') within group(order by t.name) name,
t.id id from t group by t.id
获取特定字符串在字符串中出现的次数
语法: regexp_count(source_str, target_char [, position [, match_param]])
source_str:包含特定字符的字符串
target_char:特定字符
position: 从哪个下标开始搜索,可省略,但需>=1
match_param: 正则的匹配模式参数, 'i':忽略大小写; ‘c’或不配置该参数:不忽略大小写;此外还有‘n’、‘m’、‘x’等参数
select regexp_count(',abc,,,Ad,,ef,', ',') from dual;
行转列(oracle 11g) :
pivot(聚合函数 for 列名 in(类型))
列转行:
unpivot
在order by后面使用NLSSORT函数转化汉字列,如下
select * from student order by NLSSORT(name,'NLS_SORT=SCHINESE_PINYIN_M');
参数说明:
SCHINESE_RADICAL_M 按照部首(第一顺序)、笔划(第二顺序)排序
SCHINESE_STROKE_M 按照笔划(第一顺序)、部首(第二顺序)排序
SCHINESE_PINYIN_M 按照拼音排序
function REGEXP_SUBSTR(String, pattern, position, occurrence, modifier)
__srcstr :需要进行正则处理的字符串
__pattern :进行匹配的正则表达式
__position :起始位置,从第几个字符开始正则表达式匹配(默认为1)
__occurrence :标识第几个匹配组,默认为1
__modifier :模式('i'不区分大小写进行检索;'c'区分大小写进行检索。默认为'c'。)
select regexp_substr('aaa/bbbb/ccccc','[^/]+',1,2) from dual; -- bbbb