# oracle 常用知识
***
## checklist
- 建表,修改表结构
- 创建序列
- update的另一种写法
- 分区表操作
- 分区信息查询
- oracle parallel
- Job的基本操作,设置Job重复时间
- 存储过程搭配Job的使用
- 索引维护
- loop的三种形式
- 游标和循环
- 时间日期处理
- 锁表查询与kill
- 索引失效与重建 ,删分区可能使索引失效
- oracle length 和 lengthb函数
- sql%rowcount 影响的行数
- 集合Array
- oracle dblink
- oracle分组后按条件排序取第一条记录
***
## 建表,修改表结构
```sql
create table TT_TRMS_AIR_SHORT
(
ID NUMBER(18),
original_id NUMBER(18),
AIR_TASK_Id VARCHAR2(100), -- 短驳任务id
OP_TASK_ID VARCHAR2(50), -- 提发货任务id
JOB_ID VARCHAR2(100) not null, -- 作业id
ZONE_CODE VARCHAR2(20) , -- 场地代码
FLIGTH_NO VARCHAR2(50) , -- 航班号
LINE_CODE VARCHAR2(50), -- 线路编码
BATCH_DATE VARCHAR2(20), -- 班次日期 yyyymmdd
BATCH_CODE VARCHAR2(50) , -- 中转班次
GOODS_AGENT_NAME VARCHAR2(50), -- 货代简称
CABIN_TYPE VARCHAR2(10), -- 舱位类型
CABIN_WEIGHT VARCHAR2(20) default 0, -- 舱位重量
BATCH_BEGIN_DATE DATE , -- 班次开始时间
DEL_FLAG number(6), -- 删除标记
deal_tm DATE , -- 处理时间
deal_flg number(2) default 0, -- 处理标记
deal_ip varchar2(30) ,
deal_count number(2) ,
insert_tm timestamp(6) default SYSDATE, --入库时间
delive_code VARCHAR2(50) -- 分中心代码
)
partition by range (INSERT_TM)
(
partition TT_TRMS_AIR_SHORT_P20170619 values less than (TIMESTAMP‘ 2017-06-19 00:00:00‘),
partition TT_TRMS_AIR_SHORT_P20170626 values less than (TIMESTAMP‘ 2017-06-26 00:00:00‘)
);
```
###### 添加注释
```sql
comment on table TT_TRMS_AIR_SHORT
is ‘航空短驳信息表‘;
-- Add comments to the columns
comment on column TT_TRMS_AIR_SHORT.id
is ‘主键ID‘;
```
###### 添加字段
```sql
alter table 表名 add (字段名 字段类型 默认值 是否为空);
alter table sf_users add (HeadPIC blob);
alter table sf_users add (userName varchar2(30) default ‘空‘ not null);
```
###### 修改字段
```sql
alter table 表名 modify (字段名 字段类型 默认值 是否为空);
alter table sf_InvoiceApply modify (BILLCODE number(4));
```
###### 删除字段
```sql
alter table 表名 drop column 字段名;
alter table sf_users drop column HeadPIC;
```
***
## 序列
- currval:返回sequence的当前值
- nextval:返回增加sequence的值,然后返回sequence的值
```sql
SELECT SEQ_TT_TRMS_CAR_TASK.currval FROM dual;
SELECT SEQ_TT_TRMS_CAR_TASK.nextval FROM dual;
```
```sql
-- 创建序列
CREATE SEQUENCE SEQ_TT_TRMS_AIR_SHORT
minvalue 1
maxvalue 999999999999999999999
start with 1000
increment by 1
cache 20;
```
***
## DML语句
### update的另一种写法
```sql
UPDATE TT_IDENT_RS_FULL_BA T SET (tel_ident_flg) = (
SELECT DECODE(‘A‘,‘S‘,1,‘D‘,1,tel_ident_flg)
FROM DUAL )
WHERE T.ROWID = ‘AAEaJhAAWAABzkSAAA‘ ;
```
***
## 分区表操作
### 分区类型
```markdown
1.range分区 按时间 或 ID
2.hash分区 分区列的hash值
3.List分区 分区列确定的分区值,加一个DEFAULT存不在确定值范围的记录
4.组合分区 range-HASH , RANGE-LIST ; 根分区range,子分区hash或list
```
### 分区字段跨分区更新
- row movement策略如果是disabled的状态,不能跨分区更新分区字段
```sql
select table_name,owner,row_movement from dba_tables where table_name = ‘table_name‘;
```
- 强制更新分区字段
```sql
1.修改该策略
alter table schema.table_name enable row movement;
2.执行语句
---
3.修改回来
alter table schema.table_name disable row movement;
```
### 删除分区
```sql
ALTER TABLE TT_TRMS_ALL_AIR_TASK DROP PARTITION TT_TRMS_ALL_AIR_TASK_P20171030;
ALTER INDEX sales_area_ix REBUILD(如果含有全局索引);
```
### 增加分区
```sql
ALTER TABLE TT_TRMS_ALL_AIR_TASK ADD PARTITION TT_TRMS_ALL_AIR_TASK_P20171031 VALUES LESS THAN (TIMESTAMP‘ 2017-10-31 00:00:00‘);
```
### 合并分区
```sql
ALTER TABLE four_seasons MERGE PARTITIONS quarter_one, quarter_two INTO PARTITION quarter_two;
ALTER TABLE four_seasons MODIFY PARTITION quarter_two REBUILD UNUSABLE LOCAL INDEXES;
```
### 移动分区
```sql
ALTER TABLE parts MOVE PARTITION depot2 TABLESPACE ts094 NOLOGGING;
```
### 重命名分区
```sql
ALTER TABLE scubagear RENAME PARTITION sys_p636 TO tanks
```
### 分区拆分
```sql
ALTER TABLE RANGE_EXAMPLE SPLIT PARTITION
PART_1 at
(TO_DATE(‘ 1994-05-01 00:00:00‘, ‘SYYYY-MM-DD HH24:MI:SS‘))
INTO ( PARTITION PART_1 tablespace st1,
PARTITION PART_3 tablespace users);
```
### truncate 分区
```sql
ALTER TABLE sales TRUNCATE PARTITION dec98;
ALTER INDEX sales_area_ix REBUILD;
```
### 操作分区前先失效索引
```sql
-- 失效索引
ALTER TABLE sales DISABLE CONSTRAINT dname_sales1;
ALTER TABLE sales TRUNCATE PARTITTION dec94;
-- 恢复索引
ALTER TABLE sales ENABLE CONSTRAINT dname_sales1;
```
## 分区信息查询
### 分区分布查询
```sql
select utp.table_name,utp.partition_name,utp.tablespace_name from user_tab_partitions utp
where utp.table_name=‘TT_TRMS_CAR_TASK‘;
```
### 分区分布和分区索引联立查询
```sql
select index_name,null partition_name,tablespace_name,status
from user_indexes
where table_name=‘TT_TRMS_CAR_TASK‘
and partitioned=‘NO‘
union
select index_name,partition_name,tablespace_name,status from user_ind_partitions
where index_name in
(
select index_name from user_indexes
where table_name=‘TT_TRMS_CAR_TASK‘
)
order by 1,2,3
;
```
***
## 索引维护
### 创建local主键索引
```sql
alter table TT_OMS_ROUTE_LoCATION add (constraint IDX_TT_OMS_ROUTE_LoCATION primary key(ID,insert_tm) using index local);
```
### 创建local普通索引
```sql
create index IDX_TT_TRMS_CAR_TASK on TT_TRMS_CAR_TASK (DEAL_FLG) local;
```
### 创建函数local索引
```sql
CREATE INDEX IDX_billroute_status_id ON billroute(nvl(status, ‘0‘),id) LOCAL;
```
### 创建和删除全局主键索引
```sql
alter table TT_TRMS_CAR_TASK_DIST DROP constraint IDX_TT_TRMS_CAR_TASK_DIST ;
alter table TT_TRMS_CAR_TASK_DIST add constraint IDX_TT_TRMS_CAR_TASK_DIST primary key(ID)
```
### 索引重建
```sql
alter index IPK_TT_WAYBILL_DES REBUILD ;
```
### 删除索引
```sql
DROP INDEX TBILLTRACE_BACKUP_D_FLG_OPCODE;
```
### 创建复合索引
```sql
CREATE INDEX TBILLTRACE_BACKUP_D_FLG_OPCODE ON TBILLTRACE_BACKUP(DEAL_FLG,OPCODE);
```
### 重建local索引
```sql
ALTER INDEX I_FOUR_SEASONS_L REBUILD PARTITION I_QUARTER_FOUR
```
### 系统自动生成主键索引重命名
```sql
-- 删除自动生成索引
declare
v_cursor integer;
v_sql varchar2(500);
BEGIN
FOR RX IN (select index_name from user_indexes WHERE table_name = ‘TT_TRMS_CAR_TASK_DIST‘) LOOP
v_cursor:=dbms_sql.open_cursor;
v_sql:=‘alter table TT_TRMS_CAR_TASK_DIST drop constraint ‘ || RX.INDEX_NAME;
dbms_sql.parse(v_cursor, v_sql, dbms_sql.v7);
dbms_sql.close_cursor(v_cursor);
END LOOP;
end;
/
-- 添加索引
alter table TT_TRMS_CAR_TASK_DIST add (constraint IDX_TT_TRMS_CAR_TASK_DIST primary key(ID,insert_tm) using index local);
```
***
## oracle parallel
- parallel:并行处理
### 并行复制数据
```sql
create table tt_fvp_waybill_order0905 nologging parallel (DEGREE 16) as
select /*+parallel(d,8)*/* From tt_fvp_waybill_order partition(P_20170903) d where d.id >=536376116-5000000 and d.id <536376116
```
### 并行查询数据
```sql
select /*+ parallel(A 8) parallel(B 8) parallel(C 8) parallel(D 8) */
from A,B,C,D
where .....
```
- A、B、C、D为用到的表名
### 并行创建索引
```sql
CREATE INDEX index名称 ON 表名 (字段1,字段2) PARALLEL 16 INITRANS 16;
```
***
## Job的基本操作
> job 的创建,停止,删除,修改属性
- 创建Job
```sql
begin
sys.dbms_scheduler.create_job(job_name => ‘SSS.P_TRMS_CAR_TASK_JOB‘,
job_type => ‘PLSQL_BLOCK‘,
job_action => ‘BEGIN PROC_TT_TRMS_CAR_TASK; END;‘,
start_date => to_date(‘21-06-2017 00:00:00‘, ‘dd-mm-yyyy hh24:mi:ss‘),
repeat_interval => ‘Freq=MINUTELY;Interval=1‘,
end_date => to_date(null),
job_class => ‘DEFAULT_JOB_CLASS‘,
enabled => true,
auto_drop => true,
comments => ‘V9.2 巴枪操作关联车辆‘);
end;
/
```
- 查询job
```sql
select owner, job_name, state from dba_scheduler_jobs;
select * from user_scheduler_jobs
SELECT * FROM User_Scheduler_Job_Run_Details;
```
- 启用job
```sql
begin
dbms_scheduler.enable(‘P_TRMS_CAR_TASK_JOB‘);
end;
/
```
- 运行job
```sql
begin
dbms_scheduler.run_job(‘P_TRMS_CAR_TASK_JOB‘,TRUE); -- true代表同步执行
end;
/
```
- 停止job (不太好用)
```sql
begin
dbms_scheduler.stop_job(job_name => ‘P_TRMS_CAR_TASK_JOB‘,force => TRUE);
end;
/
```
- 删除job (对停job来说好用)
```sql
begin
dbms_scheduler.drop_job(job_name => ‘SSS.P_TRMS_CAR_TASK_JOB‘,force => TRUE);)
end;
/
```
- 删除job
```sql
begin
dbms_scheduler.drop_job(‘P_TRMS_CAR_TASK_JOB‘);
end;
```
- 修改job参数
```sql
begin
dbms_scheduler.set_attribute(‘PROCESS_SUB_BILL_0‘,‘job_action‘,‘BEGIN PROCESS_SUB_BILL_DATA(4,0,1000,100); END;‘);
END;
/
```
### job设置重复时间的用法
```sql
-- calendar expression
repeat_interval=>‘Freq=Secondly;Interval=30‘; -- 每4小时
repeat_interval=>‘FREQ=HOURLY ; INTERVAL=4‘; -- 每4小时
repeat_interval=>‘FREQ=DAILY‘; -- 每天重复一次
repeat_interval=>‘FREQ=MINUTELY ; INTERVAL=15‘; -- 每15分钟重复一次
repeat_interval=>‘FREQ=YEARLY ;
BYMONTH=MAR,JUN,SEP,DEC;
BYMONTHDAY=15‘; -- 每年5,7,9,12月的15号重复一次
-- pl/sql expression
repeat_interval=>‘SYSDATE + 26/24‘; -- 每36小时重复一次
repeat_interval=>‘SYSDATE + 1‘; --每天重复一次
repeat_interval=>‘SYSDATE + 15/(24*60)‘; -- 每15分钟重复一次
```
***
## 存储过程和Job的搭配使用
- 一个简单的过程创建
```sql
CREATE OR REPLACE PROCEDURE PROC_TT_TELHIS_SRC_DEALFLG
(
P_BATCH_NUM IN NUMBER DEFAULT 10000 --处理数据量
) AS
/*
CREATE DATE:2017-12-04
CREATE BY:01369076
DESC : 历史派件信息下发状态修改 deal_flg null-->0
*/
BEGIN
FOR X IN 1 .. 4 LOOP
UPDATE tt_telhis_src SET DEAL_FLG = 0 WHERE DEAL_FLG IS NULL AND insert_tm > TO_DATE(‘2017-12-04 00:00:00‘, ‘yyyy-mm-dd hh24:mi:ss‘) AND ROWNUM <= P_BATCH_NUM;
COMMIT;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
PKG_SYS_LOG.ERROR_LOG(NULL,
‘PROC_TT_TELHIS_SRC_DEALFLG‘,
SYSDATE,
SQLCODE,
SQLERRM,
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,NULL
);
END PROC_TT_TELHIS_SRC_DEALFLG;
/
```
- 一个简单的Job创建
```sql
begin
sys.dbms_scheduler.create_job(job_name => ‘SSS.PROC_TT_TELHIS_SRC_DEALFLG_JOB‘,
job_type => ‘PLSQL_BLOCK‘,
job_action => ‘BEGIN PROC_TT_TELHIS_SRC_DEALFLG(10000); END;‘,
start_date => to_date(‘04-12-2017 00:00:00‘, ‘dd-mm-yyyy hh24:mi:ss‘),
repeat_interval => ‘Freq=Secondly;Interval=20‘,
end_date => to_date(null),
job_class => ‘DEFAULT_JOB_CLASS‘,
enabled => true,
auto_drop => true,
comments => ‘历史派件信息状态更新‘);
end;
/
```
***
## loop的三种形式
- LOOP
- WHILE ... LOOOP
- FOR ... LOOP
### 基本的LOOP语句
```sql
SET serveroutput ON;
```
### exit ... when 结束循环
```sql
DECLARE
v_value NUMBER(8) := -3;
BEGIN
<<value_loop>> -- 循环标记
LOOP
dbms_output.put_line(‘v_value = ‘ || v_value);
v_value := v_value+1;
EXIT value_loop WHEN v_value > 3;
END LOOP;
dbms_output.put_line(‘loop循环结束!‘);
END;
```
### if ... exit 结束循环
```sql
DECLARE
v_value NUMBER(8) := -3;
BEGIN
<<value_loop>>
LOOP
dbms_output.put_line(‘value:‘ || v_value);
v_value := v_value +1;
IF v_value > 3 THEN
dbms_output.put_line(‘value is larger than 3 , current value is ‘ || v_value);
EXIT value_loop;
END IF;
END LOOP value_loop;
dbms_output.put_line(‘loop is end‘);
END;
```
### while ...loop 结构
- 本身可以结束循环
```sql
DECLARE
v_value NUMBER(8) := -3;
BEGIN
<<while_loop>>
WHILE(v_value < 4)
LOOP
dbms_output.put_line(‘value is ‘ || v_value);
v_value := v_value + 1;
END LOOP while_loop;
dbms_output.put_line(‘while loop is end‘);
END;
```
### FOR ... LOOP 结构
- 可以遍历某个范围整数
```sql
BEGIN
FOR v_value IN -3..3 LOOP
dbms_output.put_line(‘value is ‘ || v_value);
END LOOP ;
dbms_output.put_line(‘for loop is end‘);
END;
```
***
## 游标和循环
- RS 必须是单个字段
```sql
DECLARE
CURSOR RS IS SELECT zone_code FROM tt_trms_car_task;
zone_code VARCHAR2(50);
BEGIN
OPEN RS;
LOOP
FETCH RS INTO zone_code;
EXIT WHEN RS%NOTFOUND;
dbms_output.put_line(zone_code);
END LOOP;
CLOSE RS;
END;
/
```
- bulk collect显示游标
```sql
DECLARE
CURSOR RS IS SELECT zone_code FROM tt_trms_car_task;
zone_code_array dbms_sql.Varchar2_Table;
BEGIN
OPEN RS;
FETCH RS BULK COLLECT INTO zone_code_array;
FOR i IN 1 .. zone_code_array.count LOOP
dbms_output.put_line(zone_code_array(i));
END LOOP;
CLOSE RS;
END;
```
- bulk collect 显示游标 + limit
```sql
DECLARE
CURSOR RS IS SELECT zone_code FROM tt_trms_car_task;
zone_code_array dbms_sql.Varchar2_Table;
BEGIN
OPEN RS;
LOOP
FETCH RS BULK COLLECT INTO zone_code_array LIMIT 2;
EXIT WHEN RS%NOTFOUND;
FOR i IN 1 .. zone_code_array.count LOOP
dbms_output.put_line(zone_code_array(i));
END LOOP;
END LOOP;
CLOSE RS;
END;
```
- select into 隐式游标
```sql
DECLARE
zone_code VARCHAR2(100);
BEGIN
SELECT zone_code INTO zone_code FROM tt_trms_car_task WHERE ROWNUM = 1;
dbms_output.put_line(zone_code);
END;
```
- 动态sql,select into 隐式游标
```sql
DECLARE
zone_code VARCHAR2(50);
l_table VARCHAR2(200);
l_sql VARCHAR2(200);
BEGIN
l_table := ‘TT_TRMS_CAR_TASK‘;
l_sql := ‘select zone_code from ‘ || l_table || ‘ where rownum = 1‘;
EXECUTE IMMEDIATE l_sql INTO zone_code;
dbms_output.put_line(zone_code);
END;
```
- 动态sql select into 隐式游标 + bulk collect
```sql
DECLARE
zone_code_array dbms_sql.Varchar2_Table;
l_table VARCHAR2(20);
l_sql VARCHAR2(100);
BEGIN
l_table := ‘TT_TRMS_CAR_TASK‘;
l_sql := ‘select zone_code from ‘ || l_table;
EXECUTE IMMEDIATE l_sql BULK COLLECT INTO zone_code_array;
FOR i IN 1 .. zone_code_array .count LOOP
dbms_output.put_line(zone_code_array(i));
END LOOP;
END;
```
- for .. in 隐式游标
```sql
BEGIN
FOR RS IN (SELECT zone_code FROM tt_trms_car_task) LOOP
dbms_output.put_line(RS.ZONE_CODE);
END LOOP;
END;
BEGIN
FOR RS IN (SELECT * FROM tt_trms_car_task) LOOP
dbms_output.put_line(RS.ZONE_CODE);
END LOOP;
END;
```
***
## 时间日期处理
### oracle 系统时间
- SYSDATE 系统时间
- SYSTIMESTAMP 当前系统的时间戳
- CURRENT_TIMESTAMP 与时区设置有关,返回的秒是系统的,返回的日期和时间是根据时区转换过的.
- current_date 是对CURRENT_TIMESTAMP准确到秒的四舍五入。
```sql
select sysdate,systimestamp,current_date,current_timestamp from dual;
```
### 时间差计算函数
```sql
两个Date类型字段:START_DATE,END_DATE,计算这两个日期的时间差(分别以天,小时,分钟,秒,毫秒):
天:
ROUND(TO_NUMBER(END_DATE - START_DATE))
小时:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24)
分钟:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60)
秒:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60)
毫秒:
ROUND(TO_NUMBER(END_DATE - START_DATE) * 24 * 60 * 60 * 1000)
```
### 时间和日期格式化
```sql
-- 时间及日期
select to_char(sysdate,‘yyyy/mm/dd‘) from dual;
select to_char(sysdate,‘yyyy-mm-dd‘) from dual;
-- 公元标记
select to_char(sysdate,‘AD YYYY-MM-DD‘) from dual;
select to_char(sysdate,‘BC YYYY-MM-DD‘) from dual;
-- 子午线标识
select to_char(sysdate,‘YYYY-MM-DD AM hh24:mi:ss‘) from dual;
select to_char(sysdate,‘YYYY-MM-DD PM hh24:mi:ss‘) from dual;
-- 世纪标识
select to_char(to_date(‘2000-8-3‘,‘YYYY-MM-DD‘),‘cc‘) from dual;
select to_char(to_date(‘2001-8-3‘,‘YYYY-MM-DD‘),‘cc‘) from dual;
-- 自公元前4712年1月1日到指定日期的总天数
select to_char(sysdate,‘J‘) from dual;
-- 部分时间和日期
-- 指定日期在周中的数值范围(1-7) 星期日开始
select to_char(to_date(‘2017-07-05‘,‘yyyy-mm-dd‘),‘D‘) from dual;
-- 指定日期在当月中的天数 (1-31)
select to_char(to_date(‘2017-07-05‘,‘yyyy-mm-dd‘),‘DD‘) from dual;
-- 指定日期在当年中的天数(1-366)
select to_char(to_date(‘2017-07-05‘,‘yyyy-mm-dd‘),‘DDD‘) from dual;
-- 指定日期在周中的名称
select to_char(to_date(‘2017-07-04‘,‘yyyy-mm-dd‘),‘Day‘) from dual;
select to_char(sysdate,‘DY‘) from dual;
-- 返回指定日期在当月中的第X周(范围:1-5)
select to_char(to_date(‘2007-6-1‘,‘yyyy-mm-dd‘),‘w‘) from dual;
-- 返回指定日期在当年中的第X周(范围:1-53)
select to_char(to_date(‘2007-6-18‘,‘yyyy-mm-dd‘),‘ww‘) from dual;
select to_char(sysdate,‘IW‘) from dual; -- 指定日期在当年中第X周(范围:1-52或1-53(润年))
-- 指定日期的月份简写
select to_char(sysdate,‘MON‘) from dual; -- 7月
select to_char(sysdate,‘MONTH‘) from dual; -- 7月
select to_char(sysdate,‘MM‘) from dual; -- 07
select to_char(to_date(‘2007-11-3‘,‘yyyy-mm-dd‘),‘RM‘) from dual; -- 以罗马数字形式返回月份(范围I-XII)
select to_char(to_date(‘2007-2-3‘,‘yyyy-mm-dd‘),‘q‘) from dual; -- 返回指定日期的季度(范围:1-4)
-- 年份
select to_char(sysdate,‘year‘) from dual; -- twenty seventeen
select to_char(sysdate,‘yyyy‘) from dual; -- 2017
select to_char(sysdate,‘SYYYY‘) from dual; -- 2017
select to_char(sysdate,‘y,yyy‘) from dual; -- Y,YYY 返回有逗号分隔显示的年
select to_char(to_date(‘187-4-3‘,‘yyyy-mm-dd‘),‘IYYY‘) from dual; -- 返回ISO标准年
select to_char(sysdate,‘yy‘) from dual; --以指定长度返回日期的年份
-- 小时
select to_char(sysdate,‘am hh‘) from dual; -- 下午 03
select to_char(sysdate,‘am hh12‘) from dual; -- 下午 03
select to_char(sysdate,‘am hh24‘) from dual; -- 下午 15
-- 分钟
select to_char(sysdate,‘MI‘) from dual;
-- 秒数
select to_char(sysdate,‘ss‘) from dual;
select to_char(sysdate,‘sssss‘) from dual; -- 返回自午夜到指定时间共逝去的秒数(范围:0-86399)
-- 毫秒数 FF[1-9] 返回毫秒数,可指定长度1-9,默认6位
select to_char(systimestamp,‘ff‘) from dual;
select to_char(systimestamp,‘ff4‘) from dual;
-- 根据数据库nls_date_format参数中的设置及nls_language,nls_territory参数中的格式返回长日期形式
select to_char(sysdate,‘DL‘) from dual; -- 2017年7月4日 星期二
select to_char(sysdate,‘Ds‘) from dual; -- 短日期形式 2017-07-04
-- 时间
select to_char(sysdate,‘ts‘) from dual; -- 下午 3:55:51
--数据库的星期
alter session set nls_language=‘AMERICAN‘;
alter session set nls_language=‘SIMPLIFIED CHINESE‘;
select to_char(sysdate,‘dy‘) from dual;
```
### 时间日期加减
```sql
--加法
select sysdate,add_months(sysdate,12) from dual; --加1年
select sysdate,add_months(sysdate,1) from dual; --加1月
select sysdate,to_char(sysdate+7,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --加1星期
select sysdate,to_char(sysdate+1,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --加1天
select sysdate,to_char(sysdate+1/24,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --加1小时
select sysdate,to_char(sysdate+1/24/60,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --加1分钟
select sysdate,to_char(sysdate+1/24/60/60,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --加1秒
-- 减法
select sysdate,add_months(sysdate,-12) from dual; --减1年
select sysdate,add_months(sysdate,-1) from dual; --减1月
select sysdate,to_char(sysdate-7,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --减1星期
select sysdate,to_char(sysdate-1,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --减1天
select sysdate,to_char(sysdate-1/24,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --减1小时
select sysdate,to_char(sysdate-1/24/60,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --减1分钟
select sysdate,to_char(sysdate-1/24/60/60,‘yyyy-mm-dd HH24:MI:SS‘) from dual; --减1秒
```
***
## 锁表查询与kill
```sql
--锁表查询SQL
SELECT object_name, machine, s.sid, s.serial#
FROM gv$locked_object l, dba_objects o, gv$session s
WHERE l.object_id = o.object_id
AND l.session_id = s.sid;
--释放SESSION SQL:
--alter system kill session ‘sid, serial#‘;
ALTER system kill session ‘1065, 57065‘;
```
***
## 索引失效与重建 ,删分区可能使索引失效
```sql
-- 检查索引状态
select index_name, partition_name, status
from user_ind_partitions
where status = ‘UNUSABLE‘
union all
select index_name, ‘‘ as partition_name, status
from user_indexes
where status = ‘UNUSABLE‘;
-- 重建分区索引
alter index PK_SALE rebuild partition PY11Q3;
alter index IPK_TT_BSP_WAYBILL rebuild;
```
***
## oracle length 和 lengthb函数
- lengthb(string)计算string所占的字节长度 :返回字符串的长度,单位是字节
- length(string)计算string所占的字符长度 :返回字符串的长度,单位是字符
- 对于单字节字符,LENGTHB和LENGTH是一样的.
- 如可以用length(‘string’)=lengthb(‘string’)判断字符串是否含有中文。
```sql
select length(‘我‘) from dual --返回1
select lengthb(‘我‘) from dual --返回2
select length(‘AB‘) from dual --返回2
select lengthb(‘AB‘) from dual --返回2
```
***
## sql%rowcount
- oracle 的变量 影响的行数
***
## Array集合语法
```sql
Create Or Replace varray_type_name Is Varray(size_limit) Of Element_type [Not Null];
varray_obj varray_type_name;
```
> 注:下标从1开始,元素个数有限制 使用变长数组对象元素前,必须使用构造函数初始化
### 示例演示
```sql
Create Or Replace Type varray_type Is Varray(100) Of Varchar2(20) Not Null;
Declare
varray_obj varray_type;
n Number;
Begin
varray_obj:=varray_type(‘a‘,‘b‘,‘c‘);
If varray_obj.exists(1) Then
dbms_output.put_line(‘--从第1个元素开始输出‘);
n:=varray_obj.first;
Loop
dbms_output.put_line(‘下标:‘||n||‘ 值:‘||varray_obj(n));
Exit When n=varray_obj.last;
n:=varray_obj.next(n);
End Loop;
dbms_output.put_line(‘--从最后1个元素开始输出‘);
n:=varray_obj.last;
Loop
dbms_output.put_line(‘下标:‘||n||‘ 值:‘||varray_obj(n));
Exit When n=varray_obj.first;
n:=varray_obj.prior(n);
End Loop;
End If;
End;
```
## 输出:
```markdown
--从第1个元素开始输出
下标:1 值:a
下标:2 值:b
下标:3 值:c
--从最后1个元素开始输出
下标:3 值:c
下标:2 值:b
下标:1 值:a
```
***
## oracle dblink
### 删除dblink
```sql
DROP PUBLIC DATABASE LINK SUB_TO_HQ;
```
### 创建dblink
```sql
CREATE PUBLIC DATABASE LINK SUB_TO_HQ
CONNECT TO sss IDENTIFIED BY sfpwd12345#
USING ‘(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 10.202.46.36)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = ssssit)))‘;
```
***
## oracle分组后按条件排序取第一条记录
```sql
SELECT transit_code ,data_content
FROM (
SELECT *
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY transit_code ORDER BY insert_tm DESC) rn,
TT_TRANS_BASE_INFO.*
FROM TT_TRANS_BASE_INFO)
WHERE rn = 1
) t
WHERE data_content = ‘9.4‘ -- 已升级
-- where data_content != ‘9.4‘ -- 没有升级
```