Oracle日常维护笔记-数据操作

1 数据操作

1.1 用A表的数据 某一列 更新B表 数据的某一列

Update tableA a set a.col1 = (select b.col1 from tableB b where b.ind = a.ind)

l 如果再A表中有的列,而在B表中没有,那么A表中的列会被更新成空

解决方法:

update test3 b set b.username = (select c.username from test2 c where c.ind = b.ind)

where b.ind in (select e.ind from test3 e inner join test2 f on e.ind = f.ind);

1.2 用表复制,用A表来创建B表

create table test4 as select * from test2;

此方法会把A表的数据也复制给B表,但是不会创建索引

l 只创建表,不复制数据:

create table test4 as select * from test2 where 1 = 2;

1.3 PL/SQL插入批量数据

DECLARE

CUSTOMER_ID NUMBER(18);

BEGIN

CUSTOMER_ID := 302000000035000001;

WHILE CUSTOMER_ID <= 302000000035000001 LOOP

BEGIN

insert into cps_customer_last_activity values(CUSTOMER_ID, sysdate-200,'');

commit;

CUSTOMER_ID := CUSTOMER_ID +1;

END;

END LOOP;

END;

1.4 分批更新数据

方法一:

drop table t ;

create table t as select * from dba_objects;

create index i_t_id on t(object_id);

/

create or replace procedure p_update as

type type_1 is table of t%rowtype index by binary_integer;

va type_1;

cur sys_refcursor;

begin

open cur for 'select * from dba_objects t where owner=''SYS''';

loop

fetch cur bulk collect

into va limit 10000;

exit when va.count = 0;

forall i in 1 .. va.count

update t

set t.object_name = va(i).object_name

where t.object_id = va(i).object_id;

commit;

end loop;

end;

/

方法二:

loop
update table
where rownum<=10000;
if sql%found then
commit;
else
exit;
end if;
end loop;

1.5 导出导入某个分区数据

导出:

expdp cpstxn22/Aa123456 dumpfile=CPS_TRANS_RECORD.dmp logfile=20150310.log tables=CPS_TRANS_RECORD:SYS_P4703;

-----------导出多个分区用逗号隔开

导入:

impdp cpstxn22/Aa123456 DIRECTORY=DATA_PUMP_DIR DUMPFILE=CPS_TRANS_RECORD.dmp TABLES=CPS_TRANS_RECORD logfile=imp.log table_exists_action=append

---记得赋权限

综合语句:

example: imp scott/tiger ignore=y tables=(emp,dept) full=n

or tables=(t1:p1,t1:p2), if t1 is partitioned table

example: exp scott/tiger grants=y tables=(emp,dept,mgr)

or tables=(t1:p1,t1:p2), if t1 is partitioned table

example: expdp scott/tiger dumpfile=scott.dmp directory=dmpdir schemas=scott or tables=(t1:p1,t1:p2), if t1 is partitioned table

example: impdp scott/tiger directory=dmpdir dumpfile=scott.dmp

1.6 数据清理

1. 首先执行生成批量删除存储过程:

create or replace procedure delBigTab

(

p_TableName in varchar2,

p_Condition in varchar2,

p_Count in varchar2

)

as

pragma autonomous_transaction;

n_delete number:=0;

begin

while 1=1 loop

EXECUTE IMMEDIATE

'delete from '||p_TableName||' where '||p_Condition||' and rownum <= :rn'

USING p_Count;

if SQL%NOTFOUND then

exit;

else

n_delete:=n_delete + SQL%ROWCOUNT;

end if;

commit;

end loop;

commit;

DBMS_OUTPUT.PUT_LINE('Finished!');

DBMS_OUTPUT.PUT_LINE('Totally '||to_char(n_delete)||' records deleted!');

end;

/

2 . 执行命令

exec delBigTab('TABLE_NAME’,’ CUSTOMER_ID < 205000000008000000','10000');

第一个参数是表明,第二个参数是 删除的范围,第三个参数是每次提交的数量

1.7 导入外部数据

1.1 使用sqlldr导入文件

1 编写控制文件

使用sqlldr命令导入数据,要另外再写一个控制文件(.ctl格式),这里假设控制文件名是test.ctl。

2 向一个空表student中插入数据的test.ctl内容如下:

Load DATA

infile 'input.unl'

Insert

into table student

FIELDS TERMINATED by '|'

(ID,Name,SCORE)

"replace(:name, '\\n',chr(10))"

3 向一个有数据的表student中插入数据的test.ctl内容如下:

Load DATA

infile 'input.unl'

Append

into table student

FIELDS TERMINATED by '|'

(ID,Name,SCORE)

4 Shell命令行执行命令

sqlldr 数据库用户名/数据库用户密码 control=test.ctl

5 SQLLDR导入换行特殊字符

Name "replace(:name, '\\n',chr(10))"

1.2 使用PL/SQL导入外部数据

1.构建UNL文件,按列值|列值的形式构建数据文件。

2.用对应数据库用户登录PL/SQL:选择tools菜单下的 text importer菜单,

选择红色菜单,然后导入unl文件

3然后配置导入数据选项

选择菜单页data from textfile

①中的2表示你有多少列数据要导入到表中, end at line-end 表示在换行时表示所有列输入结束,"表示用什么符号去引用你的分割符

②列格式预览和选择

③列格式起始位置和结束位置标记

④列值的预览

4导入数据选项

选择菜单页 data to oracle

1 表示导入到的数据库用户和数据库表名, 复选项表示是否删除之前已经有的数据

2 表示多少条数据提交一次, 是否/忽略覆盖重复数据,

3 每列对应哪个字段,需要用户自己定义,有点繁琐,

5 选择好以后点击 import导入

1.8 快速把某个字段值更新成同一个值

方法就是通过删除列和添加带默认值的列来操作:

alter table cps_customer drop column dates;

alter table cps_customer add load_data_ts TIMESTAMP default to_date(sysdate,'yyyy-MM-dd HH24:mi:ss') not null;

1.9 MERGE用法

MERGE语句会检查原数据表记录和目标表记录。如果记录在原数据表和目标表中均存在,则目标表中的记录将被原数据表中的记录所更新(执行Update操作);如果目标表中不存在的某(些)记录,在原数据表中存在,则原数据表的这(些)记录将被插入到目标表中(执行Insert操作)。

在Oracle 10g之前,merge语句支持匹配更新和不匹配插入两种简单的用法,在10g中Oracle对merge语句做了增强,增加了条件选项和DELETE操作。

语法:

MERGE [hint] INTO [schema ] table [t_alias]

USING [schema ]{ table | view | subquery } [t_alias]

ON ( condition )

WHEN MATCHED THEN merge_update_clause

WHEN NOT MATCHED THEN merge_insert_clause;

1.MERGE INTO test T1

2.USING (SELECT OWNER , OBJECT_NAME , MAX(ID) ID FROM T GROUP BY OWNER, OBJECT_NAME) T

3.ON (T.OWNER = T1.OWNER AND T.OBJECT_NAME = T1.TABLE_NAME)

4.WHEN MATCHED THEN UPDATE SET T1.ID = T.ID

5.WHEN NOT MATCHED THEN INSERT VALUES (T.ID, T.OWNER, T.OBJECT_NAME);

第一行 命名目标表并给别名T1

第二行 using子句提供merge操作的数据源,命名T

第三行 on子句指定合并的条件

第四行 when matched then 子句判定条件符合则对表T1做什么改变(或删除)

第五行 when not matched then 子句判断条件不符合则插入的操作

1.10 根据临时表删除重复记录

delete from cps_product_service p
where exists (select 1
from cps_temp t
where t.product_unique_id = p.product_unique_id
and t.service_index = p.service_index);
commit;

1.11 十进制转36进制存储过程

create or replace function f_36_tr_10(v_36_data in varchar)

return number

is

v_data number(18);

begin

select sum(data) into v_data from

(

select (

case substr(upper(v_36_data),rownum,1)

when 'A' then '10'

when 'B' then '11'

when 'C' then '12'

when 'D' then '13'

when 'E' then '14'

when 'F' then '15'

when 'G' then '16'

when 'H' then '17'

when 'I' then '18'

when 'J' then '19'

when 'K' then '20'

when 'L' then '21'

when 'M' then '22'

when 'N' then '23'

when 'O' then '24'

when 'P' then '25'

when 'Q' then '26'

when 'R' then '27'

when 'S' then '28'

when 'T' then '29'

when 'U' then '30'

when 'V' then '31'

when 'W' then '32'

when 'X' then '33'

when 'Y' then '34'

when 'Z' then '35'

else substr(v_36_data,rownum,1) end

)*power(36,length(v_36_data)-rownum) data

from dual

connect by rownum<=length(v_36_data)

);

return v_data;

exception

when others then

return null;

end;

CREATE OR REPLACE FUNCTION N10_TO_36(V_NUM NUMBER)
RETURN VARCHAR IS RESULT VARCHAR(10);
NUM NUMBER;
TMP NUMBER;
TEMP NUMBER;
BEGIN
NUM := V_NUM;
TMP := TRUNC(NUM / 36);
WHILE NUM > 0 LOOP
TEMP := MOD(NUM, 36);
IF TEMP < 10 THEN
RESULT := TEMP || RESULT;
ELSE
RESULT := CHR(TEMP + 55) || RESULT;
END IF;
NUM := TMP;
TMP := TRUNC(NUM / 36);
END LOOP;
return RESULT;
end;

1.12 使用存储过程

create or replace procedure pro_1(id varchar2)

is

name varchar2(20); -- 声明一个变量

begin

-- 以下就是存储过程的主体部分

dbms_output.put_line('id:' || id || ' name:' || name);

end;

alter procedure procedure_name compile; ---编译

set serveroutput on;

execute pro_1(00813025); --执行

使用游标和循环匹配

DECLARE

cursor temp

is select * from lbi_dw.t_s_sys_log t where t.task_status not in (1,2,-1,-2) and t.task_name='prc_m_r_iden_funds_detail_c';

begin

for t in temp

loop

if t.task_id = 540137 then

dbms_output.put_line(t.table_name||' '||t.task_id);

end if;

end loop;

end;

/

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

declare

orgid number(18):=0;

shorts varchar(24):='';

flag number(2):=0;

cursor temp is select account_no, entryCount from (

select t.account_no account_no, count(1) as entryCount from cpstxn.cps_account_entry t

where t.transaction_time>=to_date('20160623 00:00:00','yyyymmdd hh24:mi:ss')

and t.transaction_time<=to_date('20160623 23:59:59','yyyymmdd hh24:mi:ss')

and t.identity_type!='1000'

and t.realtime_update='0'

group by t.account_no having count(1)> 10

order by entryCount desc

) n where rownum<50 ;

begin

for te in temp

loop

if te.entryCount >= 3000 then

select count(s.identity_id) into flag from cpstxn.cps_org_account s where s.ACCOUNT_NO = te.account_no ;

if flag >= 1 then

select s.identity_id into orgid from cpstxn.cps_org_account s where s.ACCOUNT_NO = te.account_no ;

select short_code into shorts from cpsmgt.cps_biz_org where BIZ_ORG_ID=orgid;

dbms_output.put_line(orgid||' , '||shorts);

end if;

end if;

end loop;

end;

/

1.13 更改数据库快照时间更新周期

begin

DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(11520,60);

end;

/

1.14 关于_ktb_debug_flags

alter system set "_ktb_debug_flags"=8 scope=both sid='*';

1.15 修改数据库密码错误重试延迟

alter system set event ="28401 TRACE NAME CONTEXT FOREVER, LEVEL 1" scope=spfile;

1.16 如何对数据进行按每10分钟统计一次

发布于 2018-09-12 17:31