Oracle备忘录

Oracle备忘录,在坑中前行

Oracle #

倒序查询某表的最后100条记录,并正序排列 #

select * from
(select * from FAC_HEAT_CONSUMPTION t order by id desc)
where rownum < 100 order by id


select * from
(select * from HS_CHEMICAL_IRON t order by id desc OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY)
order by id

从0开始,获取100个,OFFSET 0 ROWS可以省略掉。

删除sys.dbms_scheduler.create_job创建的日志 #

begin
  sys.dbms_scheduler.create_job(job_name            => 'ARIMSGTEST.UPDATE_PL_JOB',
                                job_type            => 'STORED_PROCEDURE',
                                job_action          => 'arimsgtest.update_pl_job',
                                start_date          => to_date(null),
                                repeat_interval     => 'Freq=Hourly;Interval=1',
                                end_date            => to_date(null),
                                job_class           => 'DEFAULT_JOB_CLASS',
                                enabled             => true,
                                auto_drop           => false,
                                comments            => '');
end;
/

SELECT * FROM User_Scheduler_Jobs; // 查看作业
SELECT * from All_scheduler_job_log where owner= 'ARIMSGTEST' and job_name= 'UPDATE_PL_JOB2' 
select * from All_scheduler_job_run_details where owner= 'ARIMSGTEST' and job_name= 'UPDATE_PL_JOB2'
Delete from all_scheduler_job_run_details where owner= 'ARIMSGTEST' and job_name= 'UPDATE_PL_JOB2'

logging_level——日志记录级别(DBMS_SCHEDULER.LOGGING_OFF,DBMS_SCHEDULER.LOGGING_RUNS,DBMS_SCHEDULER.LOGGING_FULL)https://blog.csdn.net/Seabiscuit_92/article/details/51038281 restartable max_runs max_failures

to_date(‘2004-05-07 13:23:44’,‘yyyy-mm-dd hh24:mi:ss’)

分组后只取第一条记录 #

SELECT *       
    FROM (SELECT ROW_NUMBER() OVER(PARTITION BY x ORDER BY y DESC) rn,       
          test1.*       
          FROM test1)       
   WHERE rn = 1  ;   

ora-00936:缺失表达式 #

当whereExpression为空时,会出现这个问题。基本可以判断是生成的sql语句不标准。在使用sugarsql时注意看下where语句使用。

修改oracle的密码永不过期 #

以dba方式登录:

12c开始可以自增id了 #

CREATE TABLE identity_test_tab ( id NUMBER GENERATED ALWAYS AS IDENTITY, description VARCHAR2(30) );

select * from v$resource_limit
select * from v$process
select * from v$bgprocess
select * from v$session
select * from v$session t where t.STATUS='ACTIVE'

select username,lockwait,status,machine,program from v$session where sid in
(select session_id from v$locked_object)

select sql_text from v$sql where hash_value in
(select sql_hash_value from v$session where sid in
(select session_id from v$locked_object))

SELECT s.username,l.OBJECT_ID,l.SESSION_ID,s.SERIAL#,
l.ORACLE_USERNAME,l.OS_USER_NAME,l.PROCESS
FROM V$LOCKED_OBJECT l,V$SESSION S WHERE l.SESSION_ID=S.SID;

alter system kill session '113,25455'; 

select * from v$process  p where not exists (select spid from v$session where paddr=p.addr)

exec DBMS_SCHEDULER.STOP_JOB(job_name =>'JOB_INSERT_L2_CCM',force => TRUE);
select name from v$database;
select * from dba_scheduler_running_jobs;

— Find the job

select * from dba_scheduler_running_jobs;

— Kill the job:

exec DBMS_SCHEDULER.STOP_JOB(job_name => 'JOB_INSERT_L2_CCM',force => TRUE);

Session Process与Connection的关系 #

select count(*) from v$session
select count(*) from v$process
select * from v$process where addr not in (select paddr from v$session)
select sid, serial#,username,program,machine,status from v$session where status = 'INACTIVE' order by machine;
select * from dba_profiles

Connection并不是直接建立在用户进程和数据库实例之间的。而是在用户进程和Server Process(服务器进程)之间的,因此有一个Connection就一定会有一个用户进程和一个服务器进程。但不一定会存在Session。比如,如果需要将东西从A运到B,Connection可以看成是一座“桥”,而卡车把东西从A运到B后并返回A,这就是Session。所以,只要不断开连接,随时都可以在这个连接上创建出会话。

Session占用问题 #

ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效: 首先检查是哪个sid,和serial。

select t2.username,t2.sid,t2.serial#,t2.logon_time
from v$locked_object t1,v$session t2
where t1.session_id=t2.sid order by t2.logon_time;

然后准备kill掉这个session,假设sid=111,serial=30547

alter system kill session '111,30547';

可能出现错误: ORA-00031:标记要终止的会话 解决方法 则首先执行,查看killed状态的spid,sid和serial:

select a.spid,b.sid,b.serial#,b.username from v$process a,v$session b where a.addr=b.paddr and b.status='KILLED';

准备使用oracle自带的命令删掉这个进程,需要在oracle服务器上执行cmd命令:

orakill  _db  _spid

其中,_db是通过以下命令获得:

select name from v$database;

_spid即为上述的spid值。

创建Sequence和插入时自增Trigger #

-- Create sequence 
create sequence HS_ADDITIVE_SEQ
minvalue 1
maxvalue 999999999999999999999999999
start with 1
increment by 1
cache 20;

创建触发器 HS_ADDITIVE_SEQ

create or replace trigger 
  HS_ADDITIVE_TRG BEFORE INSERT ON
 HS_ADDITIVE for each row
 begin if inserting then if :NEW."ID" is null
 then
   select HS_ADDITIVE_SEQ.nextval into :NEW."ID" from dual;
  end if;end if;end;

创建只读用户和某些表的同义词 #

!注意这是在一个管理员账号下给另一个 用户赋权 创建视图,并将视图赋予一个用户只读权限,操作步骤如下: OLDUSER用户具有创建视图的权限。 1)创建用户 zhangsan/zhangsan

CREATE USER ems IDENTIFIED BY ems;

2)给zhangsan赋予权限

GRANT CONNECT TO zhangsan;
GRANT SELECT ON OLDUSER.V_TEST TO zhangsan;

3)使用zhangsan用户登录系统,访问此视图

SELECT * FROM OLDUSER.V_TEST

4)如果不使用用户名访问,那么需要创建同义词,如下:

CREATE SYNONYM  zhangsan.V_TEST for OLDUSER.V_TEST;

创建同义词之后,在zhangsan登录之后就可以使用如下查询语句了

SELECT * FROM V_TEST

orcale 要减小精度 修改的列必须为空 #

/*修改原字段名name为name_tmp*/
alter table HS_LADLE_HISTORY rename column IRON_WEIGHT to name_tmp;
/*增加一个和原字段名同名的字段name*/
alter table HS_LADLE_HISTORY add IRON_WEIGHT number(13,3);
/*将原字段name_tmp数据更新到增加的字段name*/
update HS_LADLE_HISTORY set IRON_WEIGHT=name_tmp;
/*更新完,删除原字段name_tmp*/
alter table HS_LADLE_HISTORY drop column name_tmp;

恢复已经删除的记录 #

ALTER TABLE tableName ENABLE row movement ; flashback table tableName to timestamp to_timestamp(‘‘2011-02-28 10:40:00’’,‘‘yyyy-mm-dd hh24:mi:ss’’); 后面的参数为要还原的时间点 https://www.cnblogs.com/chaizp/p/5192522.html

TableSpace表空间 #

Oracle数据库是通过表空间来存储物理表的,一个数据库实例可以有N个表空间,一个表空间下可以有N张表。 有了数据库,就可以创建表空间。 表空间(tablespace)是数据库的逻辑划分,每个数据库至少有一个表空间(称作SYSTEM表空间)。为了便于管理和提高运行效率,可以使用一些附加表空间来划分用户和应用程序。例如:USER表空间供一般用户使用,RBS表空间供回滚段使用。一个表空间只能属于一个数据库。 https://zyjustin9.iteye.com/blog/2193804

select name from v$database;    //查询当前数据库名
select instance_name from v$instance;    //查询当前数据库实例名

Oracle数据库建好后,要想在数据库里建表,必须先为数据库建立用户,并为用户指定表空间。 有了数据库,表空间和用户,就可以用自定义的用户在自己的表空间创建表了。 数据库实例 -> 表空间 -> 创建用户 -> 创建表

 create tablespace DATA_CONFIG
  /*表空间物理文件名称*/
  datafile 'data_config.dbf' 
  size 500M autoextend on next 5M maxsize unlimited; 
  
create user arim3 
  IDENTIFIED BY arimyfzx --用户密码
  default tablespace DATA_CONFIG-- 表空间是上面创建的
  temporary tablespace TEMP -- 临时表空间默认 TEMP
  profile DEFAULT;
  --password expire;
   /*密码过期需要重设密码,意思是当你用这个新建立的密码过期用户首次登录后,系统会提示你重新输入新密码,不然会拒绝你登陆,重设新密码后就可以登录,该用户的密码就是你新设的密码,相当于首次登录修改密码这样的选项。*/
    
   /* 用户授权_1*/
  grant connect,resource,dba,create SEQUENCE,create trigger  to arim3;
create tablespace lgdd datafile 'lgdd.dbf'size 500M autoextend on next 5M maxsize unlimited;
create user arim IDENTIFIED BY arimyfzx default tablespace lgdd temporary tablespace TEMP profile DEFAULT;
grant connect,resource,dba,SEQUENCE,trigger to arim;
grant connect to arim with admin option;
grant dba to arim with admin option;
grant resource to arim with admin option;
 create user arim 
  IDENTIFIED BY arimyfzx --用户密码
  default tablespace lgdd-- 表空间是上面创建的
  temporary tablespace TEMP -- 临时表空间默认 TEMP
  profile DEFAULT;
  --password expire;
   /*密码过期需要重设密码,意思是当你用这个新建立的密码过期用户首次登录后,系统会提示你重新输入新密码,不然会拒绝你登陆,重设新密码后就可以登录,该用户的密码就是你新设的密码,相当于首次登录修改密码这样的选项。*/
    
   /* 用户授权_1*/
  grant connect,resource,dba,create SEQUENCE, create trigger  to arim;
  
   /* 用户授权_2*/
  grant connect to arim with admin option;
  grant dba to arim with admin option;
  grant resource to arim with admin option;

授予用户create sequence和trigger权限 #

GRANT CREATE SEQUENCE TO ARIM;
grant create trigger to arim;

Oracle执行外部文件 #

c:>sqlplus user/pwd@db sql>@new.sql

批量创建Sequence #

CREATE OR REPLACE PROCEDURE "ADD_SEQ_TRIGGER" AS
  ctr number := 0;
  ctr2 number := 0;
  addcount number := 0;
  totcount number := 0;
  var_name varchar(50) := 'ID';
  var_seq varchar(50);
  Var_Trg Varchar(50);
  var_nex varchar(50);
begin
 FOR t IN (select table_name from user_tables)
  LOOP
      select count(*) into ctr from user_tab_columns where table_name like t.table_name and column_name like var_name;
      IF (ctr > 0) THEN
        var_seq :=t.table_name||'_SEQ';
        var_trg :=t.table_name||'_TRG';
        var_nex :=t.table_name||'_SEQ'||'.nextval';
        select count(*) into ctr2 from USER_SEQUENCES where sequence_name = var_seq;
        if(ctr2> 0) THEN
           dbms_output.put_line('sequence exist for table: '||t.table_name||'!');
        ELSE
          EXECUTE IMMEDIATE 'CREATE SEQUENCE '||var_seq||' START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE';
          addcount := addcount + 1;
        END IF;
         dbms_output.put_line('create or replace trigger for table: '||t.table_name||'!');
        EXECUTE IMMEDIATE 'create or replace trigger '||var_trg||' BEFORE INSERT ON '||t.table_name||' for each row begin '||
                          'if inserting then if :NEW."ID" is null then '||
                          'select '||var_nex||' into :NEW."ID" from dual; end if;end if;end;';
      ELSE
        dbms_output.put_line('ID does NOT exist for table: '||t.table_name||'!');
      END IF;
         totcount :=  totcount + 1;
  END LOOP;
   DBMS_OUTPUT.PUT_LINE('total tables count: '||totcount);
   DBMS_OUTPUT.PUT_LINE('total add count: '||addcount);
END ADD_SEQ_TRIGGER;