Oracle 学习笔记,,,经验总结整理的。。。

cmd进入:
1. D:\oracle\ora92\bin>
2. sqlplus /nolog
3. conn sys/sys as sysdba

sqlplus进入:
username:sys
password:sys
HostString: test as sysdba
重复



用户管理
创建用户,设定权限

  1. create user fusp identified by fusp default tablespace users temporary tablespace temp;
  2. grant dba to fusp; –dba,recource,connect –赋权限
  3. alter system set resource_limit=true scope=both; –期限,密码等
  4. disconnect;
  5. conn fusp/fusp;
  6. show user;

创建profile
create profile px_test limit
sessions_per_user 3
idle_time 10; –单位:分钟

创建用户
create user dd identified by dd
default tablespace users
temporary tablespace temp
profile px_test;



创建的dba用户,都会存放到dba_users表中
修改用户的默认表空间:
alter user fusp default tablespace users;

查询:
select username,DEFAULT_TABLESPACE from dba_users;




启动:
SQL> startup
ORACLE instance started.

    Total System Global Area  143727516 bytes
    Fixed Size                   453532 bytes
    Variable Size             109051904 bytes
    Database Buffers           33554432 bytes
    Redo Buffers                 667648 bytes
    Database mounted.
    Database opened.

看数据库归档模式
SQL> archive log list;
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination D:\oracle\ora92\RDBMS
Oldest online log sequence 15
Current log sequence 17

查看归档相关初始化参数
show parameter archive


创建spfile
1. startup pfile=D:\oracle\admin\test\pfile\init.ora
2. create pfile from spfile;(根据提示将相应的文件拷贝)


更改存档路径
1. startup; –启动oracle
2. alter system set log_archive_start = true scope = spfile; –修改数据库
3. show parameter archive –查看归档参数参数
4. alter system set log_archive_dest_1=’location=D:\oracle\admin\test\temp’ scope =spfile; –更改log_archive_dest_1的存档路径
5. shutdown –关闭
6. startup; –启动
7. show parameter archive –再次查看一下归档参数

把归档日志文件切换:
1. alter system switch logfile;

创建表空间:
create tablespace exam datafile ‘D:\app\tablespace\example1.dbf’ size 10M;

修改表空间:
alter tablespace exam add datafile ‘D:\oracle\admin\test\temp\example2.dbf’ size 5M;

查看表空间大小:
select tablespace_name,sum(bytes/1024/1024)
from dba_data_files group by tablespace_name;

查询动态表空间
select * from v$tablespace;

区管理方式
Select tablespace_name,extent_management from dba_tablespaces;

表空间类型
Select tablespace_name,status,contents from dba_tablespaces;

数据文件自动扩展
Select file_name, AUTOEXTENSIBLE,status,bytes/1024/1024 from dba_data_files where tablespace_name= ‘USERS’;

查看日志
select * from v logfile;selectfromv l o g f i l e ; s e l e c t ∗ f r o m v log;

添加group
alter database add logfile ‘d:\temp\aa.log’ size 5M;
alter database add logfile group 5 ‘d:\temp\aa1.log’ size 5M;

添加成员member
alter database add logfile member ‘d:\temp\aa2.log’ to group 4;

控制文件位置:
1.查看初始化参数 :init.ora
2 打开文件找到control_files:*

生成本地Tablespace
create tablespace example02 datafile ‘c:\’ ????????????????????????????


修改表空间状态 (读和写 在线与下线)
变:
alter tablespace exam read only;
alter tablespace exam read write;
查:
select tablespace_name,status,contents
from dba_tablespaces;


变:
alter tablespace exam offline;
alter tablespace exam online;
查:
select name,status from v$datafile;


创建临时表空间:
create temporary tablespace temptablespace tempfile ‘d:\temp\temptablespace.dbf’ size 5M
extent management local uniform size 100k;

付少苹
查询表数据文件实际大小
select file_name,bytes/1024/1024 from dba_data_files ;

查询表空间空闲
select tablespace_name,sum(bytes/1024/1024)
from dba_free_space group by tablespace_name;

查询 临时表空间 实际大小
select tablespace_name,file_name,bytes/1024/1024 from dba_temp_files;

设置行长
set linesize 100;

设置 格式
col tablespace_name format a50;


查看表空间大小:
select tablespace_name,sum(bytes/1024/1024)
from dba_data_files
where tablespace_name=’EXAM’
group by tablespace_name;

修改表空间大小
alter database datafile ‘D:\oracle\admin\test\temp\example2.DBF’ resize 20M;

自动变更表空间大小
alter database datafile ‘D:\oracle\admin\test\temp\example2.DBF’ autoextend on next 1M maxsize 20M;


删除表空间:
drop tablespace example02;
including contents and datafiles;(连带数据文件一起删除)


查询表空间tablesapce:
select tablespace_name,status from dba_tablespaces;
select * from v$tablespace;

查询块segment:
select segment_name,tablespace_name from dba_segments where segment name=’DEPT’;

查询extent:
select segment_name,extent_id from dba_extents where segment_name=’DEPT’;









DBA基础操作:

创建表:
create table employee
(
empno char(5),
ename varchar2(10),
job varchar2(20),
deptno char(2)
)
–storage(initial 200k next 200k minextents 2,maxextents 100)
tablespace exam;

变更表:
alter table employee storage(next 300k maxextents 150);

alter table employee allocate extent(size 600k);

alter table employee deallocate unused;

添加column:
alter table employee add column(sal number(5));

删除里column:
1.alter table employee drop column job;

2.alter table employee set unused column job; –需要先将其置为不用,然后再进行删除,提高性能
alter table employee drop unused columns;

创建临时表:
1. create global temporary table temp1 –事务提交时,数据被删除
(a number, b number)
on commit delete rows;

  1. create global temporary table temp2 –session结束时将其删除,与事务无关
    (a number, b number)
    on commit preserve rows;


删除表数据:
Truncate table employee; –不可恢复;

删除表
drop table employee;

删除表连带相关约束
drop table dept cascade constraints;


查看该用户下,所有的表:
select table_name from user_tables;

***********************************************************************8

导出数据库:
在cmd化境下:
exp scott/tiger file=d:/test1.dmp log=d:/test1.log tables=dept –tables
exp scott/tiger file=d:/test1.dmp log=d:/test1.log owner=scott –user
exp scott/tiger file=d:/test1.dmp log=d:/test1.log tablespaces=users –tablespaces
exp scott/tiger file=d:/test1.dmp log=d:/test1.log full=y –all

导入数据库:
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log tables=dept row=y
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log fromuser=scott touser=scott
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log tablespaces=users
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log full=y

查询Server端 字符集
select userenv(‘language’) from dual;

oracle解决temp01.dbf文件过大的方法2009-09-09 09:25第一步删除原来的文件
SQL>alter database tempfile ‘d:\oracle\oradata\ynrmdb\temp01.dbf’ drop ;
Database altered.
第二步添加新的临时文件
SQL>alter tablespace temp add tempfile
2’d:\oracle\oradata\ynrmdb\temp01.dbf’
3 size 2048M reuse autoextend on next 100M;
Tablespace altered.
SQL> select d.file_name, d.file_id, d.tablespace_name, d.bytes from dba_temp_files d;
第三步查看当前临时文件
FILE_NAME FILE_ID TABLESPACE_NAME BYTES


D:\ORACLE\ORADATA\YNRMDB\TEMP01.DBF 1 TEMP 2147483648

=============================================================================================================
Oracle数据导入导出imp/exp就相当于oracle数据还原与备份。exp命令可以把数据从远程数据库服务器导出到本地的dmp文件,imp命 令可以把dmp文件从本地导入到远处的数据库服务器中。 利用这个功能可以构建两个相同的数据库,一个用来测试,一个用来正式使用。

执行环境:可以在SQLPLUS.EXE或者DOS(命令行)中执行,
DOS中可以执行时由于 在oracle 8i 中 安装目录\ora81\BIN被设置为全局路径,
该目录下有EXP.EXE与IMP.EXE文件被用来执行导入导出。
oracle用java编写,SQLPLUS.EXE、EXP.EXE、IMP.EXE这两个文件有可能是被包装后的类文件。
SQLPLUS.EXE调用EXP.EXE、IMP.EXE所包裹的类,完成导入导出功能。

下面介绍的是导入导出的实例。
数据导出:
1 将数据库TEST完全导出,用户名system 密码manager 导出到D:\daochu.dmp中
exp system/manager@TEST file=d:\daochu.dmp full=y

2 将数据库中system用户与sys用户的表导出
exp system/manager@TEST file=d:\daochu.dmp owner=(system,sys)

3 将数据库中的表inner_notify、notify_staff_relat导出
exp aichannel/aichannel@TESTDB2 file= d:\data\newsmgnt.dmp tables=(inner_notify,notify_staff_relat)

4 将数据库中的表table1中的字段filed1以”00”打头的数据导出
exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\” where filed1 like ‘00%’\”

上面是常用的导出,对于压缩,既用winzip把dmp文件可以很好的压缩。
也可以在上面命令后面 加上 compress=y 来实现。

数据的导入
1 将D:\daochu.dmp 中的数据导入 TEST数据库中。
imp system/manager@TEST file=d:\daochu.dmp
imp aichannel/aichannel@HUST full=y file=file= d:\data\newsmgnt.dmp ignore=y
上面可能有点问题,因为有的表已经存在,然后它就报错,对该表就不进行导入。
在后面加上 ignore=y 就可以了。

2 将d:\daochu.dmp中的表table1 导入
imp system/manager@TEST file=d:\daochu.dmp tables=(table1)

基本上上面的导入导出够用了。不少情况要先是将表彻底删除,然后导入。

注意:
操作者要有足够的权限,权限不够它会提示。
数据库时可以连上的。可以用tnsping TEST 来获得数据库TEST能否连上。

附录一:
给用户增加导入数据权限的操作
第一,启动sql*puls
第二,以system/manager登陆
第三,create user 用户名 IDENTIFIED BY 密码 (如果已经创建过用户,这步可以省略)
第四,GRANT CREATE USER,DROP USER,ALTER USER ,CREATE ANY VIEW ,
DROP ANY VIEW,EXP_FULL_DATABASE,IMP_FULL_DATABASE,
DBA,CONNECT,RESOURCE,CREATE SESSION TO 用户名字
第五, 运行-cmd-进入dmp文件所在的目录,
imp userid=system/manager full=y file=*.dmp
或者 imp userid=system/manager full=y file=filename.dmp

执行示例:
F:\Work\Oracle_Data\backup>imp userid=test/test full=y file=inner_notify.dmp

屏幕显示
Import: Release 8.1.7.0.0 - Production on 星期四 2月 16 16:50:05 2006
(c) Copyright 2000 Oracle Corporation. All rights reserved.

连接到: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production

经由常规路径导出由EXPORT:V08.01.07创建的文件
已经完成ZHS16GBK字符集和ZHS16GBK NCHAR 字符集中的导入
导出服务器使用UTF8 NCHAR 字符集 (可能的ncharset转换)
. 正在将AICHANNEL的对象导入到 AICHANNEL
. . 正在导入表 “INNER_NOTIFY” 4行被导入
准备启用约束条件…
成功终止导入,但出现警告。

附录二:
Oracle 不允许直接改变表的拥有者, 利用Export/Import可以达到这一目的.
先建立import9.par,
然后,使用时命令如下:imp parfile=/filepath/import9.par
例 import9.par 内容如下:
FROMUSER=TGPMS
TOUSER=TGPMS2 (注:把表的拥有者由FROMUSER改为TOUSER,FROMUSER和TOUSER的用户可以不同)
ROWS=Y
INDEXES=Y
GRANTS=Y
CONSTRAINTS=Y
BUFFER=409600
file==/backup/ctgpc_20030623.dmp
log==/backup/import_20030623.log

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

*****************************************************************************8

–example6.1.1>cursor ‘s row set is allowed null;
DECLARE
CURSOR query_member
IS
SELECT name FROM MEMBER WHERE member_id=300;
BEGIN
OPEN query_member;
END;

*****************************************************************************8

–example6.1.2>it’s will be fetch,even if null;
DECLARE
CURSOR query_employee
IS
SELECT NAME FROM MEMBER WHERE member_id=300;
v_name MEMBER.NAME%TYPE;
BEGIN
OPEN query_employee;
FETCH query_employee INTO v_name ;
dbms_output.put_line(v_name);
END;

*****************************************************************************8

–example6.1.3>you should be familiar with the loop syntax .
DECLARE
CURSOR query_member IS SELECT * FROM MEMBER;
member_row MEMBER%ROWTYPE;
BEGIN
OPEN query_member;
LOOP
FETCH query_member INTO member_row ;
EXIT WHEN query_member%NOTFOUND OR query_member%ROWCOUNT > 2;
dbms_output.put_line(‘name is ‘||member_row.NAME);
END LOOP;
CLOSE query_member;
END;

*****************************************************************************8

–example6.2.1>a general syntax ,with conditions.
DECLARE
CURSOR query_employee IS SELECT first_name||last_name
FROM employees GROUP BY first_name||last_name ;
v_name VARCHAR2(20) ;
BEGIN
IF NOT query_employee%ISOPEN THEN
OPEN query_employee;
END IF ;

LOOP
FETCH query_employee INTO v_name ;
EXIT WHEN query_employee%NOTFOUND ;
dbms_output.put_line(‘name is ‘||v_name);
END LOOP;
CLOSE query_employee;
END;

*****************************************************************************8

–example6.2.2>explicit cursor attribute - %rowcount
DECLARE
CURSOR query_employee IS SELECT first_name||last_name FROM employees WHERE
employee_ID=5;
v_name VARCHAR2(20) ;
BEGIN
IF NOT query_employee%ISOPEN THEN
OPEN query_employee;
END IF ;
DBMS_OUTPUT.put_line(query_employee%Rowcount);
CLOSE query_employee;
END;

*****************************************************************************8

–example 6.3> for ..loop syntax
DECLARE
CURSOR member_cur IS SELECT NAME ,sal FROM MEMBER;
BEGIN
FOR member_rec IN member_cur LOOP
dbms_output.put(‘name =’|| member_rec.name|| ’ ‘);
dbms_output.put_line(‘sal = ‘||member_rec.sal);
END LOOP;
END;

*****************************************************************************8

–example 7.1>Cursors with parameters
DECLARE
CURSOR query_dept(dno NUMBER) IS
SELECT NAME,sal FROM MEMBER
WHERE dept_id=dno;
BEGIN
FOR r1 IN query_dept(10) LOOP
dbms_output.put_line(r1.NAME);
END LOOP;
END;

*****************************************************************************8

–example 8.1>using a no_data_found exception
DECLARE
v_name MEMBER.NAME%TYPE;
BEGIN
SELECT NAME INTO v_name FROM MEMBER
WHERE member_id = 100000;
Dbms_Output.put_line(v_name);
EXCEPTION
WHEN no_data_found THEN
Dbms_Output.put_line(‘the user doesn”t exist’);
END;

*****************************************************************************8

–example 8.2>using a too_many_rows exception
DECLARE
v_name MEMBER.Name%TYPE;
BEGIN
SELECT NAME INTO v_name FROM MEMBER WHERE dept_id=20;
EXCEPTION

WHEN too_many_rows THEN
dbms_output.put_line(‘too many rows’);
WHEN OTHERS THEN
dbms_output.put_line(‘others’);
END;

*****************************************************************************8

–example 8.3>confusion
BEGIN
DELETE FROM employees WHERE employee_id=&ID;
IF SQL%ROWCOUNT > 0 THEN
Dbms_Output.put_line(‘yes’);
ELSE
Dbms_Output.put_line(‘no’);
END IF;
END;

*****************************************************************************8

–example 8.4>using a invalid_cursor exception
DECLARE
v_name employees.first_name%TYPE;
CURSOR emp_cursor IS
SELECT first_name FROM employees WHERE employee_id=&ID;
BEGIN
FETCH emp_cursor INTO v_name;
CLOSE emp_cursor;
EXCEPTION
WHEN invalid_cursor THEN
dbms_output.put_line(‘请检查游标’);
END;

*****************************************************************************8

–example8.5>using a DUP_VAL_ON_INDEX exception
BEGIN
INSERT INTO employees (employee_id) VALUES(&ID);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
dbms_output.put_line(‘违反PK 约束’);
END;

*****************************************************************************8

–example8.6>no-pre exception
DECLARE
myexception EXCEPTION;
PRAGMA EXCEPTION_INIT (myexception,-2292);
BEGIN
DELETE FROM dept WHERE dept_id=20;
EXCEPTION
WHEN myexception THEN
dbms_output.put_line(‘该行已被其他表参照’);
WHEN OTHERS THEN
dbms_output.put_line(‘…..’);
END;

*****************************************************************************8

–example 8.7>user-defined exception
–[09:00-18:00] access
DECLARE
myexception EXCEPTION;
BEGIN
IF to_char(SYSDATE,’HH24:MI’) NOT BETWEEN ‘09:00’
AND ‘17:00’ THEN
RAISE myexception;
END IF;
dbms_output.put_line(‘001’);

EXCEPTION
WHEN myexception THEN
dbms_output.put_line(‘bbbb’);
END;

*****************************************************************************8

–example8.8>raise_application_error

BEGIN
IF to_char(SYSDATE,’HH24:MI’) NOT BETWEEN ‘09:00’
AND ‘17:00’ THEN
raise_application_error(‘-20000’,’不允许登陆’);
END IF;
dbms_output.put_line(‘001’);
/*EXCEPTION
WHEN OTHERS THEN
raise_application_error(‘-20030’,’不允许登陆’); */
END;

2.5*7/8=2.5

*****************************************************************************8
–example9.1>no parameter
CREATE OR REPLACE PROCEDURE procedure_no
IS
BEGIN
DBMS_OUTPUT.put_line(‘这是一个没有参数的例子’);
END ;

执行procedure的两种方法:
1:
BEGIN
procedure_no;
END;

2:在comm 上面
SQL> set serveroutput on
SQL> exec procedure_no;


create or replace procedure pp
is
begin
dbms_output.put_line(‘ddddd’);
end;

*****************************************************************************8

–example9.2>in parameter ,where is error .
CREATE OR REPLACE PROCEDURE PROCEDURE_PARAMETER_IN(P_DEPTNO IN
NUMBER) IS
V_MAX MEMBER.SAL%TYPE;
BEGIN
SELECT MAX(SAL) INTO V_MAX FROM MEMBER WHERE DEPT_ID = P_DEPTNO;
IF v_max IS NULL THEN
DBMS_OUTPUT.PUT_LINE(‘该部门目前没有员工’);
ELSE
DBMS_OUTPUT.PUT_LINE(P_DEPTNO || ’ 部门的最大薪资是’ || V_MAX);
END IF;
END;

执行
begin
PROCEDURE_PARAMETER_IN(11);
end;
*****************************************************************************8

–example9.3>out parameter
CREATE OR REPLACE PROCEDURE PROCEDURE_PARAMETER_OUT(P_ENO IN NUMBER,
P_ENAME OUT VARCHAR2)
IS
BEGIN
SELECT NAME INTO P_ENAME FROM MEMBER WHERE MEMBER_ID = P_ENO;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘没有这个员工’);
END;
/*
define call env variable
exec procedure_name(in parameter, :define call env variable);
print define call env variable
*/
方法:
1: 在plsql:command环境下:
var name varchar2(20)
exec procedure_parameter_out(100,:name)
(补充:可以打印参数:print name)
2:
在sql*plus环境下:
SQL> set serveroutput on
SQL> declare v_name member.name%type;
2 begin
3 procedure_parameter_out(100,v_name);
4 dbms_output.put_line(v_name);
5 end;
6 /
3: 在plsql的sqlwindow下
declare v_name member.name%type;
begin
procedure_parameter_out(100,v_name);
dbms_output.put_line(v_name);
end;

*****************************************************************************8

–example9.5>in&out parameter
CREATE OR REPLACE PROCEDURE inout(p_input in OUT NUMBER)
IS
BEGIN
p_input :=p_input*p_input;
END;
/*
define call env variable & value
exec procedure_name(define call env variable);
print define call env variable
*/

调用方法:
方法1:plsql的command窗口下:
SQL> set serveroutput on
SQL> var num number
SQL> exec :num:=3

  PL/SQL procedure successfully completed
  num
  ---------
  3
  SQL> exec inout(:num)
  PL/SQL procedure successfully completed
  num
  ---------
  9

方法2:sql plus环境下:
SQL> declare
2 v_num number;
3 begin
4 v_num :=3;
5 inout(v_num);
6 dbms_output.put_line(v_num);
7 end;
8 /
9
PL/SQL 过程已成功完成。

*****************************************************************************8

–example9.6>parameter assign value
CREATE OR REPLACE PROCEDURE emp_info(p_dpid employees.department_id%TYPE,
p_j obid employees.j ob_id%TYPE DEFAULT 1)
IS
v_lastname employees.last_name%TYPE;
BEGIN
SELECT last_name INTO v_lastname FROM employees
WHERE department_id=p_dpid AND j ob_id=p_j obid;
dbms_output.put_line(‘last_name is ‘||v_lastname);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line(‘没有你要找的信息’);
END;
/*
exec procedure_name(Actual Parameters,Actual Parameters)
exec procedure_name(Formal parameters=>values,Formal parameters=>values)
exec procedure_name(Actual Parameters,Formal parameters=>values)
*/
CREATE OR REPLACE PROCEDURE test01 (
num1 NUMBER DEFAULT 1,
num2 NUMBER DEFAULT 2,
num3 NUMBER DEFAULT 3)
IS
BEGIN
dbms_output.put_line(‘num1 = ‘||num1);
dbms_output.put_line(‘num2 = ‘||num2);
dbms_output.put_line(‘num3 = ‘||num3);
END;
–run
EXEC test01(3,4,5);
EXEC test01(num2=>66,num3=>100,num1=>23);
EXEC test01(num2 => 33);
EXEC test01(11,num2=>44);
EXEC test01(num1=>30);
EXEC test01(1,num2=>44,2); 改正:EXEC test01(1,num2=>44,2);
exec test01(num3=>44,11,2);
BEGIN
FOR i IN 1..9 LOOP
FOR j IN 1..i LOOP
dbms_output.put(i||’*’||j ||’ = ‘||i*j || ’ ‘) ;
END LOOP;
dbms_output.put_line(”);
END LOOP;
END;

*****************************************************************************8

–example9.7>declaring subprograms
CREATE OR REPLACE PROCEDURE subproc (p_eid MEMBER.MEMBER_ID%TYPE)
IS
v_lastname MEMBER.Name%TYPE;
PROCEDURE log_select
IS
BEGIN
INSERT INTO Log_Table VALUES(USER,SYSDATE);
COMMIT;
END log_select;
BEGIN
SELECT NAME INTO v_lastname FROM MEMBER WHERE member_id=p_eid;
dbms_output.put_line(‘last_name’||v_lastname);
log_select;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line(‘没有你要找的信息’);
END;

*****************************************************************************8

CREATE OR REPLACE PROCEDURE add_member (p_eid MEMBER.MEMBER_ID%TYPE)
IS
v_lastname MEMBER.Name%TYPE;
PROCEDURE log_select
IS
BEGIN
INSERT INTO Log_Table VALUES(USER,SYSDATE);
COMMIT;
END log_select;
BEGIN
SELECT NAME INTO v_lastname FROM MEMBER WHERE member_id=p_eid;
dbms_output.put_line(‘last_name’||v_lastname);
log_select;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line(‘没有你要找的信息’);
END;

–9.8>handled exceptions
–9.8.1 raised a unhandle exception
CREATE OR REPLACE PROCEDURE TEST03 IS
BEGIN
INSERT INTO TEST VALUES (10, ‘test03’);
INSERT INTO TEST VALU

ES (11, ‘test03’);
TEST04;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘Create a exception ‘);
END;

CREATE OR REPLACE PROCEDURE TEST04 IS
BEGIN
INSERT INTO TEST VALUES (21, ‘test04’);
INSERT INTO TEST VALUES (22, ‘test04’);
RAISE_APPLICATION_ERROR(-20020, ‘raise a exception’);
END;

*****************************************************************************8

–9.8.2
/*the whole can be commit or rollback
called procedure’s exception is handled by itself */
CREATE OR REPLACE PROCEDURE test03
IS
BEGIN
INSERT INTO test VALUES(10,’test03’);
INSERT INTO test VALUES(11,’test03’);
test04;
COMMIT;
INSERT INTO test VALUES(13,’001’);
END;

CREATE OR REPLACE PROCEDURE test04
IS
BEGIN
INSERT INTO test VALUES(21,’test04’);
INSERT INTO test VALUES(22,’test04’);
raise_application_error(-20020,’001’);
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(‘test04’);
END;

*****************************************************************************8

–9.8.3
/* commit part */
CREATE OR REPLACE PROCEDURE test05(p_id NUMBER,p_name VARCHAR2)
IS
BEGIN
IF (p_id >20) THEN
INSERT INTO test VALUES(p_id,p_name);
COMMIT;
END IF;
test06(p_id);
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
dbms_output.put_line(‘have handled’);
END;

CREATE OR REPLACE PROCEDURE test06(p_id NUMBER)
IS
BEGIN
IF (p_id >30) THEN
INSERT INTO test VALUES(p_id,USER);
COMMIT;
ELSE
raise_application_error(‘-20011’,’001’);
END IF;
END;

*****************************************************************************8

*****************************************************************************8

CREATE OR REPLACE FUNCTION f1 RETURN NUMBER
IS
BEGIN
RETURN 1;
END;

如何调用:
方法1:
select f1 from dual;

方法2:
plsql command环境下:
SQL> set serveroutput on
SQL> var num number
SQL> exec :num:=f1

*****************************************************************************8

–10.1>
CREATE OR REPLACE FUNCTION GET_SAL(P_ID IN NUMBER) RETURN NUMBER IS
V_SALARY MEMBER.SAL%TYPE;
BEGIN
SELECT SAL INTO V_SALARY FROM MEMBER WHERE MEMBER_ID = P_ID;
RETURN V_SALARY;
END;
–select name,get_sal(member_id) from member;
–select get_sal(100) from dual;
/*
define call env variable
exec procedure_name(in parameter, :define call env variable);
print define call env variable
*/

调用: select name,get_sal(member_id) from member;

*****************************************************************************8

DECLARE
v_name MEMBER.Name%TYPE;
BEGIN
SELECT NAME INTO v_name FROM MEMBER WHERE member_id=120;
EXCEPTION
WHEN no_data_found THEN
IF SQL%NOTFOUND THEN
dbms_output.put_line(‘a’);
ELSE
dbms_output.put_line(‘b’);
END IF;
END;

*****************************************************************************8

–10.2>
CREATE OR REPLACE FUNCTION fun01
(p_id IN NUMBER)
RETURN NUMBER IS

V_num NUMBER(5);

BEGIN
v_num :=p_id;
RETURN v_num;

END;

*****************************************************************************8
–10.3>parameter rowtype note:rowtype equals cursor sometime.
CREATE OR REPLACE FUNCTION get_fun–function can have no parameters
(p_row MEMBER%ROWTYPE) RETURN MEMBER%ROWTYPE
IS
BEGIN
RETURN p_row;
END;

VARCHAR2 (p_row.member_id||’ ‘||p_row.NAME||’ ‘||p_row.sal)
CREATE OR REPLACE PROCEDURE display_pro
IS
CURSOR m_cur IS SELECT * FROM MEMBER;
BEGIN
FOR m_rec IN m_cur LOOP
dbms_output.put_line(get_fun(m_rec));
END LOOP;
END;

*****************************************************************************8

–revoke
BEGIN
display_pro;
END;

*****************************************************************************8

–10.4>at least a return statement,but return the first value
–a
CREATE OR REPLACE FUNCTION return_more_fun RETURN VARCHAR2
IS
BEGIN
RETURN ‘a’;
RETURN ‘b’;
RETURN ‘c’;
RETURN ‘d’;

END;
–b
CREATE OR REPLACE FUNCTION tran_FUN(P_NUM NUMBER) RETURN VARCHAR2 IS
BEGIN
IF P_NUM BETWEEN 90 AND 100 THEN
RETURN P_num ||’ 的成绩是A’;
ELSE
IF P_NUM BETWEEN 80 AND 89 THEN
RETURN P_num ||’ 的成绩是B’;
ELSE
IF P_NUM BETWEEN 70 AND 79 THEN
RETURN P_num ||’ 的成绩是C’;
ELSE
IF P_NUM BETWEEN 60 AND 69 THEN
RETURN P_num ||’ 的成绩是D’;
ELSE
RETURN P_num ||’ 的成绩是E’;
END IF;
END IF;
END IF;
END IF;
END;

*****************************************************************************8

–revoke
BEGIN
dbms_output.put_line(tran_fun(91));
dbms_output.put_line(tran_fun(85));
dbms_output.put_line(tran_fun(70));
dbms_output.put_line(tran_fun(61));
dbms_output.put_line(tran_fun(45));
END;

*****************************************************************************8

–c
CREATE OR REPLACE FUNCTION f RETURN BOOLEAN
IS
BEGIN
dbms_output.put_line(‘true’);
RETURN TRUE;
dbms_output.put_line(‘001001’);
END;

BEGIN
IF f THEN
dbms_output.put_line(‘true’);
ELSE
dbms_output.put_line(‘false’);
END IF;
END;

*****************************************************************************8

–dsame table
CREATE OR REPLACE FUNCTION change_sal(p_id NUMBER) RETURN NUMBER
IS
v_sal MEMBER.Sal%TYPE;
BEGIN
UPDATE MEMBER SET sal=sal*1.1WHERE member_id=p_id;
SELECT sal INTO v_sal FROM MEMBER WHERE member_id=p_id;
RETURN v_sal;
END;
UPDATE MEMBER SET sal=change_sal(102) WHERE member_id=102
–dif
CREATE OR REPLACE FUNCTION change_sal(p_id NUMBER) RETURN NUMBER
IS
BEGIN
UPDATE dept SET dept_name=’lg’ WHERE dept_id=p_id;
RETURN 102;
END;

SELECT NAME ,change_sal(dept_id) FROM MEMBER;

*****************************************************************************8

–…
CREATE OR REPLACE FUNCTION get_count(p_dept NUMBER) RETURN NUMBER
IS
v_count NUMBER;
BEGIN

SELECT COUNT(*) INTO v_count FROM MEMBER WHERE dept_id=p_dept
;
RETURN v_count;
END;
–SELECT dept_id ,get_count(dept_id) FROM MEMBER

DECLARE
CURSOR M_CUR IS
SELECT DEPT_ID AS “aa” , COUNT(DEPT_ID) AS “bb” FROM MEMBER GROUP BY
DEPT_ID;
TYPE T_TYPE IS TABLE OF M_CUR%ROWTYPE INDEX BY BINARY_INTEGER;
V_COUNT NUMBER := 1;
T_TYPE_TEM T_TYPE;
CREATE OR REPLACE FUNCTION TT(D_DEPTID NUMBER) RETURN T_TYPE
IS
BEGIN
RETURN T_TYPE_TEM;
END;
BEGIN
FOR 001 IN t_type_tem LOOP
dbms_output.put_line(001.aa);
END;
END;


/* restrictions 1 and 2 sample */
create or replace function f01(v_deptid in number)
return number is
v number;
begin
update dept set loc_id=102 where dept_id=v_deptid;
v:=v_deptid;
return v;
end;
select * from member;

select * from member where member.dept_id=f01(10);

update member set member.name=’fushaoping’ where member.dept_id=f01(10);

*****************************************************************************8

–restrictions 3 sample
CREATE OR REPLACE FUNCTION get_deptid(p_id NUMBER) RETURN NUMBER
IS
v NUMBER;
BEGIN
SELECT dept_id INTO v FROM MEMBER WHERE member_id=p_id;
RETURN v;
END;

–revoke
UPDATE MEMBER SET bonus=100 WHERE dept_id=get_deptId(100);

*****************************************************************************8

–restrictions 4 sample
CREATE OR REPLACE FUNCTION commit_fun RETURN NUMBER
IS
BEGIN
COMMIT;
RETURN 100;
END;

begin
dbms_output.put_line(commit_fun);
end;

UPDATE MEMBER SET bonus=100 WHERE member_id=commit_fun;

*****************************************************************************8

–restrictions 5.1 sample
CREATE OR REPLACE FUNCTION res5 RETURN NUMBER
IS
v_num NUMBER;
PROCEDURE p1
IS
BEGIN
dbms_output.put_line(‘ok’);
END;

FUNCTION temp1 RETURN NUMBER
IS
BEGIN
RETURN 100;
END;
BEGIN
v_num := temp1;
p1;
RETURN v_num;
END;

*****************************************************************************8

–restrictions 5.2 sample
CREATE OR REPLACE FUNCTION res52(p_id NUMBER) RETURN NUMBER
IS
v_sal MEMBER.Sal%TYPE;
FUNCTION CHANGE_SAL(P_ID NUMBER) RETURN NUMBER IS
V_SAL MEMBER.SAL%TYPE;
BEGIN
UPDATE MEMBER SET SAL = SAL * 1.1 WHERE MEMBER_ID = P_ID;
SELECT SAL INTO V_SAL FROM MEMBER WHERE MEMBER_ID = P_ID;
RETURN V_SAL;
END;
BEGIN
v_sal :=change_sal(p_id);
RETURN v_sal;
END;

*****************************************************************************8
授予权限,与回收
grant select on member to devf2;
revoke select on member from devf2;

–select member_id,name,sal,res52(sal) from member;

SELECT * FROM User_Objects;

CREATE OR REPLACE PACKAGE member_admin
IS
FUNCTION get_sal(P_ID NUMBER) RETURN NUMBER;
PROCEDURE print_sal(P_ID NUMBER);
PROCEDURE print_max_sal;
g_max_sal MEMBER.sal%TYPE;
END;

CREATE OR REPLACE PACKAGE BODY member_admin
IS
v_temp MEMBER.sal%TYPE;

PROCEDURE print_max_sal
IS
BEGIN
dbms_output.put_line(‘g_max_sal = ‘||g_max_sal);
END;

FUNCTION get_sal(p_id NUMBER) RETURN NUMBER
IS
BEGIN
SELECT sal INTO v_temp FROM MEMBER WHERE member_id=p_id;
RETURN v_temp;
END;

PROCEDURE print_sal(P_ID NUMBER)
IS
BEGIN
dbms_output.put_line(‘该员工的薪资是’||get_sal(p_id));
END;

*****************************************************************************8

BEGIN
SELECT MAX (sal) INTO g_max_sal FROM MEMBER;

END;

*****************************************************************************8
*****************************************************************************8
*****************************************************************************8

–12>a package example
CREATE OR REPLACE PACKAGE my_package IS
—public
g_num NUMBER :=20;
PROCEDURE show_g_num ;
PROCEDURE update_num ;
function fun01(num number) return number;
END;

CREATE OR REPLACE PACKAGE BODY my_package
IS
v_count number default 1;

PROCEDURE show_g_num
IS
BEGIN
dbms_output.put_line(g_num);
v_count:=v_count+1;
g_num:=g_num+2;
END;

PROCEDURE update_num
is
begin
dbms_output.put_line(v_count);
dbms_output.put_line(g_num);
end;

function fun01(num number)
return number
is
begin
return num*10;
end;

END;
*****************************************************************************8
*****************************************************************************8
包packeage的 调用:
方法1:plsql command 窗口定义
SQL> begin
2 my_package.g_num :=my_package.g_num*my_package.g_num;
3 dbms_output.put_line(my_package.g_num);
4 end;
5 /

方法2:plsql中sqlwindow的输出
调用procedure
begin
my_package.show_g_num;
end;
调用方法:
begin
dbms_output.put_line(my_package.fun01(20));
end;

*****************************************************************88888888

create or replace package pack01 is
procedure pr1;
end;

create or replace package body pack01 is
procedure pr2; –提前声明
procedure pr3; –提前声明

procedure pr1
is
begin
dbms_output.put_line(‘pr1’);
pr2;
end;

procedure pr2
is
begin
dbms_output.put_line(‘pr2’);
pr3;
end;

procedure pr3
is
begin
dbms_output.put_line(‘pr3’);
pr2;
end;
end;
*****************************************************************88888888
*****************************************************************88888888
自己实例:
create or replace package pack_cur
is
cursor c1 is select member.member_id from member;
procedure proc1_3rows;
procedure proc4_6rows;
end;

create or replace package body pack_cur
is
v_empno member.member_id%type;
procedure proc1_3rows is
begin
open c1;
loop
fetch c1 into v_empno;
dbms_output.put_line(‘Id: ‘||(v_empno));
exit when c1%rowcount >=3;
end loop;
end proc1_3rows;

procedure proc4_6rows is
begin
loop
fetch c1 into v_empno;
dbms_output.put_line(‘Id: ‘||(v_empno));
exit when c1%rowcount >=6;
end loop;
close c1;
end proc4_6rows;
end pack_cur;

begin
pack_cur.proc4_6rows;
end;

*****************************************************************88888888

CREATE OR REPLACE PROCEDURE a
IS
BEGIN
dbms_output.put_line(‘a’);
END;

CREATE OR REPLACE PROCEDURE a(p NUMBER)
IS
BEGIN
dbms_output.put_line(p);
END;

SELECT * FROM User_Source;
SELECT * FROM User_Errors;

*****************************************************************************8

–<10.overloading
CREATE OR REPLACE PACKAGE pack1 IS
FUNCTION proc(p1 VARCHAR2) RETURN VARCHAR2;
FUNCTION proc(p1NUMBER) RETURN NUMBER;
END;

CREATE OR REPLACE PACKAGE BODY pack1 IS
FUNCTION proc (p1 VARCHAR2) RETURN VARCHAR2
IS
BEGIN
RETURN ‘varchar2’;
END;

FUNCTION proc (p1NUMBER) RETURN NUMBER
IS
BEGIN
RETURN 100;
END;
END;

*****************************************************************************8

–13> package function
CREATE OR REPLACE PACKAGE pack2 IS
FUNCTION compuMax(p_id NUMBER) RETURN NUMBER;
FUNCTION compuMax(p_id VARCHAR2) RETURN VARCHAR2;
END;

CREATE OR REPLACE PACKAGE BODY pack2 IS
FUNCTION compuMax(p_id NUMBER) RETURN NUMBER
IS
BEGIN
RETURN p_id;
END;

FUNCTION compuMax(p_id VARCHAR2) RETURN VARCHAR2
IS
BEGIN
RETURN p_id;
END;
END;

*****************************************************************************8

–13>
CREATE OR REPLACE PACKAGE pack5 IS
FUNCTION f01 RETURN VARCHAR2;
FUNCTION f02 RETURN VARCHAR2;
END;

CREATE OR REPLACE PACKAGE BODY pack5 IS
FUNCTION f02 RETURN VARCHAR2 ;
FUNCTION f01 RETURN VARCHAR2
IS
BEGIN
dbms_output.put_line(‘—–f01—’);
dbms_output.put_line(f02);
RETURN ‘f01 working’;
END;

FUNCTION f02 RETURN VARCHAR2
IS
BEGIN
dbms_output.put_line(‘—–f02—’);
RETURN ‘f02 working’;
END;
END;

SELECT * FROM MEMBER;
SELECT * FROM dept;

*****************************************************************************8

–14>Restrictions
–14.1>
CREATE OR REPLACE PACKAGE pack3 IS
FUNCTION compuMax(p_id NUMBER) RETURN NUMBER;
END;

CREATE OR REPLACE PACKAGE BODY pack3 IS
FUNCTION compuMax(p_id NUMBER) RETURN NUMBER
IS
v_max MEMBER.SAL%TYPE;
BEGIN
SELECT MAX(sal) INTO v_max FROM MEMBER WHERE DEPT_ID=p_id;
COMMIT;
RETURN v_max;
END;
END;
SELECT NAME ,sal FROM MEMBER WHERE sal =pack3.compuMax(20);

*****************************************************************************8

–14.2>
/*
a query statement may not execute a dml statement.
eg:
1>select member_id,sal from member where sal > pack4.change_m(10);
*/
CREATE OR REPLACE PACKAGE pack4 IS
FUNCTION change_m(m_id NUMBER) RETURN NUMBER;
END;

CREATE OR REPLACE PACKAGE BODY pack4 IS
FUNCTION change_m(m_id NUMBER) RETURN NUMBER
IS
v_sal MEMBER.SAL%TYPE;
BEGIN
UPDATE MEMBER SET sal=sal*1.1 WHERE member_id=m_id;
SELECT sal INTO v_sal FROM MEMBER WHERE member_id=m_id;
RETURN v_sal;
END;
END;

*****************************************************************************8

–14.3>
/*
update member set sal = (select pack4.change_m from
*/
CREATE OR REPLACE PACKAGE pack6 IS
FUNCTION f000 RETURN VARCHAR2;
PROCEDURE f000 (p VARCHAR2) ;
END;

CREATE OR REPLACE PACKAGE BODY pack6 IS
FUNCTION f000 RETURN VARCHAR2
IS
BEGIN
RETURN ‘f000’;
END;

PROCEDURE f000 (p VARCHAR2) ;
IS
BEGIN
dbms_output.put_line(p);
END;
END;

*****************************************************************************8
*****************************************************************************8

–16.1 >trigger :a simple example[statement]
CREATE OR REPLACE TRIGGER trig01_a
BEFORE INSERT OR UPDATE OR DELETE ON test
BEGIN
dbms_output.put_line(‘before-statement-trigger is working ! ‘);
END;

CREATE OR REPLACE TRIGGER trig01_b
AFTER INSERT OR UPDATE OR DELETE ON test
BEGIN
dbms_output.put_line(‘after-statement-trigger is working ! ‘);
END;

select * from test;
insert into test values(40,’fffff’);
delete from test;



书上例子:
CREATE OR REPLACE TRIGGER secure_emp
BEFORE INSERT OR UPDATE OR DELETE ON employees
BEGIN
IF (TO_CHAR (SYSDATE,’DY’) IN (‘SAT’,’SUN’)) OR
(TO_CHAR (SYSDATE, ‘HH24’) NOT BETWEEN ‘08’ AND ‘18’)
THEN
IF DELETING THEN
RAISE_APPLICATION_ERROR (-20502,’You may delete from
EMPLOYEES table only during business hours.’);
ELSIF INSERTING THEN
RAISE_APPLICATION_ERROR (-20500,’You may insert into
EMPLOYEES table only during business hours.’);
ELSIF UPDATING THEN
RAISE_APPLICATION_ERROR (-20503,’You may update
SALARY only during business hours.’);
ELSE
RAISE_APPLICATION_ERROR (-20504,’You may update
EMPLOYEES table only during normal hours.’);
END IF;
END IF;
END;

*****************************************************************************8

–16.2 >trigger :a simple example[row]
CREATE OR REPLACE TRIGGER trig02
BEFORE INSERT ON test
FOR EACH ROW
BEGIN
dbms_output.put_line(‘row-trigger is working ! ‘);
–COMMIT;
END;

*****************************************************************************8

–16.3>trigger :auto rollback ,decide by timing and handle position
CREATE OR REPLACE TRIGGER trig03
AFTER INSERT OR UPDATE OR DELETE ON dept
BEGIN
INSERT INTO test VALUES(11,’11’);
raise_application_error(-20020,’—-exception—’);
/*
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(‘it”s handled’);
*/
END;

BEGIN
INSERT INTO dept (dept_id) VALUES (15);
dbms_output.put_line(‘finished’);
COMMIT;
END;

*****************************************************************************8

–16.4>eg:of columns on tables
CREATE OR REPLACE TRIGGER trig04
BEFORE UPDATE OF sal ON MEMBER –只针对update有效
BEGIN
dbms_output.put_line(‘—–trig04 is working—-‘);
END;

*****************************************************************************8

–16.5> before or after
CREATE OR REPLACE TRIGGER trig05
BEFORE INSERT ON test
FOR EACH ROW
DECLARE
v_max NUMBER;
BEGIN
SELECT COUNT(*) INTO v_max FROM test;
dbms_output.put_line(v_max);
END;

INSERT INTO test VALUES (1,’001’);

*****************************************************************************8

–16.6>create view
CREATE OR REPLACE VIEW dept_emp AS
SELECT d.dept_id,dept_name,member_id,NAME
FROM MEMBER m ,dept d
WHERE m.dept_id = d.dept_id;

select * from dept_emp;
insert into dept_emp values(60,’ss’,120,’test’);

*********************************************************************************888

CREATE OR REPLACE TRIGGER tr_instead_of_dept_emp
INSTEAD OF INSERT ON dept_emp
–FOR EACH ROW
BEGIN
INSERT INTO dept (dept_id,dept_name) VALUES (:NEW.dept_id,:NEW.dept_name);
INSERT INTO MEMBER (member_id,NAME) VALUES(:NEW.member_id,:NEW.NAME);
END;

SELECT * FROM User_Triggers;

*****************************************************************************8

–17.1>schema trigger
CREATE OR REPLACE TRIGGER logon_trig
AFTER logon ON SCHEMA
BEGIN
INSERT INTO e VALUES (USER, SYSDATE, ‘Logging on’);
END;

CREATE OR REPLACE TRIGGER logoff_trig
BEFORE logoff ON SCHEMA
BEGIN
INSERT INTO log_trig_table VALUES (USER, SYSDATE, ‘Logging off’);
END;

*****************************************************************************8

–17.2>call example
CREATE OR REPLACE TRIGGER call_test
BEFORE INSERT OR UPDATE OR DELETE ON log_trig_table
CALL call_test_temp

CREATE OR REPLACE PROCEDURE call_test_temp IS
v_temp VARCHAR2(20) DEFAULT ‘lg cns china’;
BEGIN
dbms_output.put_line(v_temp);
END;

*****************************************************************************8

–17.3>mutate table
CREATE OR REPLACE TRIGGER check_salary
BEFORE INSERT OR UPDATE OF sal ON MEMBER
FOR EACH ROW
DECLARE
v_minsalary MEMBER.sal%TYPE;
v_maxsalary MEMBER.sal%TYPE;
BEGIN
SELECT MIN(sal),
MAX(sal)
INTO v_minsalary,
v_maxsalary
FROM MEMBER
WHERE jikwi = :NEW.jikwi;
IF :NEW.sal < v_minsalary
OR :NEW.sal > v_maxsalary THEN
raise_application_error(-20505,’Out of range’);
END IF;
END;

–shoule be
CREATE OR REPLACE PROCEDURE add_member
(
p_id MEMBER.member_id%TYPE,
p_name MEMBER.NAME%TYPE,
p_sal MEMBER.sal%TYPE
) IS
v_min MEMBER.sal%TYPE;
v_max MEMBER.sal%TYPE;
BEGIN
SELECT MAX(sal),
MIN(sal)
INTO v_max,
v_min
FROM MEMBER;
IF p_sal NOT BETWEEN v_min AND v_max THEN
raise_application_error(-20505,’Out of range’);
ELSE
INSERT INTO MEMBER (member_id, NAME, sal) VALUES (p_id, p_name, p_sal);
END IF;
END;

DECLARE
TABLE

*****************************************************************************8
/DEPT_EMP’,’DEPT两个表之间的参照关系:/

select * from user_dependencies
where referenced_name in (‘DEPT_EMP’,’DEPT’);
;

–18.1>alter member add (001 varchar2(20));
CREATE OR REPLACE FUNCTION get_max RETURN NUMBER
IS
v_max MEMBER.Sal%TYPE;
BEGIN
SELECT MAX(sal) INTO v_max FROM MEMBER;
RETURN v_max;
END;

CREATE OR REPLACE PROCEDURE get_max_pro
IS
BEGIN
dbms_output.put_line(get_max);
END;

SELECT * FROM User_Triggers,User_Objects
WHERE User_Triggers.Trigger_Name = User_Objects.Object_Name
AND User_Objects.Object_Type=’TRIGGER’;

SELECT * FROM user_objects WHERE status=’VALID’;
SELECT * FROM user_objects WHERE status=’INVALID’;
SELECT * FROM User_Dependencies WHERE referenced_owner=’A1’;

SELECT *
FROM USER_OBJECTS
WHERE OBJECT_NAME IN (‘MEMBER’,’GET_MAX’,’GET_MAX_PRO’);
select name,type,referenced_name,referenced_type
from user_dependencies
where referenced_name in(‘MEMBER’,’get_max’);

SELECT * FROM tab WHERE tname NOT LIKE ‘%$%’;

*****************************************************************************8

–18.2>create dblink;
CREATE DATABASE LINK mylink
CONNECT TO nanhai IDENTIFIED BY nanhai
USING ‘orcl’;tnsnames OR sid;
SELECT * FROM MEMBER@mylink;
SELECT SYSDATE FROM dual;

SELECT obj ect_name ,status
FROM User_Objects
WHERE object_name IN (‘MEMBER’,’DEPT’,’DEPT_EMP’);

*****************************************************************************8

–18.3>package depend..
CREATE OR REPLACE PACKAGE p18 IS
PROCEDURE p1 ;
PROCEDURE p2;
END;

CREATE OR REPLACE PACKAGE BODY p18 IS
PROCEDURE p1
IS
BEGIN
dbms_output.put_line(‘…….’);
END;
PROCEDURE p2
IS
BEGIN
NULL;
END;
END;

BEGIN
p18.p1;
END;

SELECT obj ect_name,status,TIMESTAMP FROM User_Objects
WHERE object_name=’P18’;

CREATE OR REPLACE PROCEDURE pr01
IS
BEGIN
pr02;
END;

CREATE OR REPLACE PROCEDURE pr02
IS
BEGIN
NULL;
NULL;
END;
PR01 VALID 2008-01-11:16:07:36
PR02 VALID 2008-01-11:16:06:07
1 PR01 VALID 2008-01-11:16:08:52
2 PR02 VALID 2008-01-11:16:08:16
SELECT obj ect_name,status,TIMESTAMP FROM User_Objects
WHERE object_name=’PR02’ OR obj ect_name=’PR01’;

BEGIN
pr01;
END;

*****************************************************************************8

DECLARE
v_sal NUMBER ;
v_id NUMBER :=102;
BEGIN
EXECUTE IMMEDIATE ‘select sal from member where member_id=:2’
INTO v_sal
USING v_id;
dbms_output.put_line(v_sal);
END;
BEGIN
FOR i IN 1..100000 LOOP
INSERT INTO dy VALUES(i);
END LOOP;
COMMIT;
END;

*****************************************************************************8

DECLARE
v_num NUMBER :=1;
BEGIN
LOOP
EXECUTE IMMEDIATE ‘INSERT INTO dy VALUES(:001)’
USING v_num;
v_num:=v_num+1;
EXIT WHEN v_num >100000;
END LOOP;
END;

*****************************************************************************8

 create or replace procedure pro_temp(v_col1 varchar2,v_col2 varchar2) is
  v_num number;
  begin
  select count(*) into v_num from user_tables where table_name=’T_TEMP’;  
  –create temporary table
  if v_num<1 then
  execute immediate CREATE GLOBAL TEMPORARY TABLE T_TEMP (
  COL1 VARCHAR2(10),
  COL2 VARCHAR2(10)
  ) ON COMMIT delete ROWS;
  end if; 
  –insert data
  execute immediate ‘insert into t_temp values(‘v_col1’,’v_col2’);  
  execute immediate select col1 from t_temp’ into v_num;
  dbms_output.put_line(v_num);
   execute immediate delete from t_temp;
  commit;
  execute immediate ‘drop table t_temp;
  end pro_temp; 

sql 查询 记录 为0 (没有记录) 则返回结果用0 代替
case count(*) when 0 then 0 else max(f1)

*****************************************************************************8

oracle 查询 最大 字段
怎么查询表中某一字段最大值所在行的数据
SQL> select * from 001;

    ID     SEQ_ID NAME

     1          1 A
     1          2 A
     1          3 A
     2          1 B
     2          2 B
     3          1 C
     3          2 C
     3          3 C
     3          4 C

9 rows selected

SQL>
SQL> SELECT *
2 FROM 001 A
3 WHERE A.SEQ_ID = (SELECT MAX(B.SEQ_ID) FROM 001 B WHERE B.ID = A.ID)
4 /

    ID     SEQ_ID NAME

     1          3 A
     2          2 B
     3          4 C

TOP N中的TOP1,(依需要选用rank,dense_rank,row_number)
SELECT ID, SEQ_ID, NAME
FROM (SELECT ID,
SEQ_ID,
NAME,
RANK() OVER(PARTITION BY ID ORDER BY SEQ_ID DESC NULLS LAST) DRN
FROM TA)
WHERE DRN = 1
SQL> SELECT ID, SEQ_ID, NAME
2 FROM (SELECT ID,
3 SEQ_ID,
4 NAME,
5 RANK() OVER(PARTITION BY ID ORDER BY SEQ_ID DESC NULLS LAST) DRN
6 FROM 001)
7 WHERE DRN =1
8 /

    ID     SEQ_ID NAME

     1          3 A
     2          2 B
     3          4 C

某字段值最大的那条记录的另一个字段的值
查询 最大 记录 字段
eg1: SELECT c_a FROM tb_a WHERE c_b = (SELECT MAX(c_b) FROM tb_a)

eg2:
SELECT a.c_a
FROM tb_a a
WHERE NOT EXISTS (SELECT 1 FROM tb_a WHERE c_b > a.c_b)

*****************************************************************************8

trigger示例
create or replace trigger tri_wwm
after update of event_Seq on TB_high_LEVEL_EVENT referencing new as new old as old for each row
begin
if :old.Lower_Report_Operate_Flag=’Y’ then

insert into TB_LOW_LEVEL_EVENT
  (EVENT_SEQ,
   UPPER_EVENT_DEAL_STATUS,
   UPPER_DEALER_NAME,
   UPPER_ONDUTY_DEAL_PROCESS,
   UPPER_ONDUTY_TIME_COUNT,
   UPPER_ACCEPTOR_NAME,
   CREATE_DATE)
values
  (:new.EVENT_SEQ, '1', '1', '1', 1, '1', sysdate);

end if;

end;

*****************************************************************************8

查询所有表,以及各个字段的sql

SELECT t.table_name, c.column_name
FROM user_all_tables t, user_tab_columns c
WHERE t.table_name = c.table_name

将行信息转换成列信息(行列互换sql)
SELECT id, ltrim(MAX(sys_connect_by_path(mc, ‘;’)), ‘;’) add_mc
FROM (SELECT id,
mc,
row_number() over(PARTITION BY id ORDER BY id) rn_by_id,
row_number() over(ORDER BY id) + id rn
FROM test)
START WITH rn_by_id = 1
CONNECT BY rn - 1 = PRIOR rn
GROUP BY id
ORDER BY id;

zhouwf0726 | 27 七月, 2006 12:01

–该测试脚本可以直接运行

–现在想把数据库中数据按照固定字段分组相加,这里总结了三种方法。

–创建测试表、添加测试数据

create table test(id varchar2(10),mc varchar2(50));
insert into test values(‘1’,’11111’);
insert into test values(‘1’,’22222’);
insert into test values(‘2’,’11111’);
insert into test values(‘2’,’22222’);
insert into test values(‘3’,’11111’);
insert into test values(‘3’,’22222’);
insert into test values(‘3’,’33333’);
commit;

–方法一:

SELECT t.table_name, c.column_name
FROM user_all_tables t, user_tab_columns c
WHERE t.table_name = c.table_name

将行信息转换成列信息(行列互换sql)
SELECT id, ltrim(MAX(sys_connect_by_path(mc, ‘;’)), ‘;’) add_mc
FROM (SELECT id,
mc,
row_number() over(PARTITION BY id ORDER BY id) rn_by_id,
row_number() over(ORDER BY id) + id rn
FROM test)
START WITH rn_by_id = 1
CONNECT BY rn - 1 = PRIOR rn
GROUP BY id
ORDER BY id;

;

set serveroutput on size 1000000
declare
union_mc varchar2(200);
begin
for cur_a in(select distinct id from test) loop
for cur_b in(select mc from test where id=cur_a.id) loop
union_mc:=union_mc||cur_b.mc;
end loop;
dbms_output.put_line(cur_a.id||chr(9)||union_mc);
union_mc := ”;
end loop;
end;
/

–方法二:

CREATE OR REPLACE function link(v_id varchar2)
return varchar2
is
union_mc varchar2(200);
begin
for cur in (select mc from test where id=v_id) loop
union_mc := union_mc||cur.mc;
end loop;
union_mc := rtrim(union_mc,1);
return union_mc;
end;
/

select id,link(id) from test group by id;

–方法三:

/从Oracle 9i开始,开发者可以创建用户自定义的合计函数,除了PL/SQL外,还可以使用任何Oralce所支持的语言(如C++或者Java)来创建合计函数。TYPE头定义必须包含ODCIAggregateInitialize、ODCIAggregateIterate、ODCIAggregateMerge和ODCIAggregateTerminate这四个接口函数。/

/Initialize函数对数据组各个需要处理的字段各运行一次。自然的,我需要为每一个值准备一个新的清单,所以需要初始化持久变量list,这里初始化值为null。/

/Iterate函数处理返回的行,所以实际上是由它来创建返回的值的清单。先测试list是否为空,如果为空,就把list直接设置为所引入的value值;如果list变量非空,则给list添加一个逗号后再插入value值,list的最大允许字符数32767。/

/Terminate函数在数据组的每个行的感兴趣字段数据被处理后执行。在这个函数中我只需简单的返回清单变量即可。/

/Merge函数,用来返回成功标记的。/

/创建自己的合计函数扩展了Oracle统计和文本处理能力。/

create or replace type t_cat as object
(
union_mc VARCHAR2(200),
static function ODCIAggregateInitialize(sctx IN OUT t_cat) return number,
member function ODCIAggregateIterate(self IN OUT t_cat,value IN varchar2) return number,
member function ODCIAggregateTerminate(self IN t_cat,returnValue OUT varchar2, flags IN number) return number,
member function ODCIAggregateMerge(self IN OUT t_cat,ctx2 IN t_cat) return number
);

create or replace type body t_cat is
static function ODCIAggregateInitialize(sctx IN OUT t_cat )
return number is
begin
sctx := t_cat(”);
return ODCIConst.Success;
end;

member function ODCIAggregateIterate(self IN OUT t_cat, value IN varchar2)
return number is
begin
self.union_mc := self.union_mc || value;
return ODCIConst.Success;
end;

member function ODCIAggregateTerminate(self IN t_cat, returnValue OUT varchar2, flags IN number) return number is
begin
returnValue := self.union_mc;
return ODCIConst.Success;
end;

member function ODCIAggregateMerge(self IN OUT t_cat , ctx2 IN t_cat ) return number is
begin
return ODCIConst.Success;
end;
end;
/

/如果你的Oracle服务器没有配置成支持并行处理的方式,可以去掉参数PARALLEL_ENABLE/

create or replace function catstr(v_mc varchar2) return varchar2 PARALLEL_ENABLE AGGREGATE USING t_cat;
/

select id,catstr(mc) from test group by id;

http://zhouwf0726.itpub.net/post/9689/161638

查询所有表的表名,列名
查询所有表结构,表,字段,字段类型(含备注说明)

SELECT com.table_name,
upper(tc.comments),
com.COLUMN_NAME,
col.DATA_TYPE,
col.DATA_LENGTH,
p.POSITION,
col.NULLABLE,
com.COMMENTS
FROM ALL_COL_COMMENTS com,
ALL_TAB_COLUMNS col,
ALL_CONS_COLUMNS p,
all_tab_comments tc
WHERE com.table_name = col.table_name
AND com.column_name= col.column_name
–AND com.table_name = ‘ATT_MON_ATT’
AND com.owner = col.owner
AND com.table_name = p.table_name(+)
AND com.column_name= p.column_name(+)
AND com.owner = p.owner(+)
AND p.position(+) IS NOT NULL
AND col.owner =’LGESPM’ –此处为用户
and col.OWNER = tc.owner
and col.TABLE_NAME= tc.table_name
and col.TABLE_NAME like ‘SPMS_SHOP_CHECK%’
ORDER BY com.table_name,col.column_id

查询 当前用户 所有表 及 字段 和 备注注释
SELECT t.table_name,
c.column_name,
p.comments,
c.DATA_TYPE
FROM user_all_tables t,
user_tab_columns c,
user_col_comments p
WHERE t.table_name = c.table_name
AND t.table_name = p.table_name
AND c.COLUMN_NAME = p.column_name
ORDER BY t.table_name ASC,c.COLUMN_ID asc

*****************************************************************************8
oracle 树查询 语句
详细出处参考:http://www.jb51.net/article/19182.htm

格式:
SELECT column
FROM table_name
START WITH column=value
CONNECT BY PRIOR 父主键=子外键

select lpad(’ ‘,4*(level-1))||name name,job,id,super from emp
start with super is null
connect by prior id=super

例子:
原始数据:select no,q from a_example2
NO NAME


001 a01
001 a02
001 a03
001 a04
001 a05
002 b01
003 c01
003 c02
004 d01
005 e01
005 e02
005 e03
005 e04
005 e05
需要实现得到结果是:
001 a01;a02;a03;a04;a05
002 b01
003 c01;c02
004 d01
005 e01;e02;e03;e04;e05

思路:
1、ORACLE8.1之后有个connect by 子句,取出整棵树数据。
create table a_example1
(
no char(3) not null,
name varchar2(10) not null,
parent char(3)
)
insert into a_example1
values(‘001’,’老王’,null)
insert into a_example1
values(‘101’,’老李’,null)
insert into a_example1
values(‘002’,’大王1’,’001’)
insert into a_example1
values(‘102’,’大李1’,’101’)
insert into a_example1
values(‘003’,’大王2’,’001’)
insert into a_example1
values(‘103’,’大李2’,’101’)
insert into a_example1
values(‘003’,’小王1’,’002’)
insert into a_example1
values(‘103’,’小李1’,’102’)
NO  NAME PARENT
001 老王
101 老李
002 大王1 001
102 大李1 101
003 大王2 001
103 大李2 101
003 小王1 002
103 小李1 102
//按照家族树取数据
select * from a_example1
select level,sys_connect_by_path(name,’/’) path
from a_example1
start with /name = ‘老王’ and/ parent is null
connect by parent = prior no
结果:
1 /老王
2 /老王/大王1
3 /老王/大王1/小王1
2 /老王/大王2
1 /老李
2 /老李/大李1
3 /老李/大李1/小李1
2 /老李/大李2
按照上面思路,我们只要将原始数据做成如下结构:
NO NAME
001 a01
001 a01/a02
001 a01/a02/a03
001 a01/a02/a03/a04
001 a01/a02/a03/a04/a05
002 b01
003 c01
003 c01/c02
004 d01
005 e01
005 e01/e02
005 e01/e02/e03
005 e01/e02/e03/e04
005 e01/e02/e03/e04/e05
最后按NO分组,取最大的一个值即为所需的结果。
NO NAME
001 a01/a02/a03/a04/a05
002 b01
003 c01/c02
004 d01
005 e01/e02/e03/e04/e05
SQL语句:
select no,max(sys_connect_by_path(name,’;’)) result from
(select no,name,rn,lead(rn) over(partition by no order by rn) rn1
from (select no,name,row_number() over(order by no,name desc) rn from a_example2)
)
start with rn1 is null connect by rn1 = prior rn
group by no
语句分析:
1、SELECT no, NAME, row_number() over(ORDER BY no, NAME DESC) rn
FROM a_example2

按照NO升序排序,同时按照NAME降序排序,产生伪列,目的是要形成树结构
NO  NAME RN
001 a03 1
001 a02 2
001 a01 3
002 b01 4
003 c02 5
003 c01 6
004 d01 7
005 e05 8
005 e04 9
005 e03 10
005 e02 11
005 e01 12
2、SELECT no, NAME, rn, lead(rn) over(PARTITION BY no ORDER BY rn) rn1
FROM (SELECT no, NAME, row_number() over(ORDER BY no, NAME DESC) rn
FROM a_example2)
生成家族谱,即子节点与父节点有对应关系,对应关系通过rn和 rn1。其中lead为上一条记录的RN值
NO  NAME RN  RN1  001 a03 1 2 –
说明:针对NO=001来说,其下一条记录的RN=2 001 a02 2 3 –说明:针对NO=001来说,其下一条记录的RN=3 001 a01 3  –说明:针对NO=001来说,其下一条记录的RN IS NULL
002 b01 4 003 c02 5 6 003 c01 6 004 d01 7 005 e05 8 9 005 e04 9 10 005 e03 10 11 005 e02 11 12 005 e01 12
3、SELECT no, sys_connect_by_path(NAME, ‘;’) RESULT
FROM (SELECT no, NAME, rn, lead(rn) over(PARTITION BY no ORDER BY rn) rn1
FROM (SELECT no, NAME, row_number() over(ORDER BY no, NAME DESC) rn
FROM a_example2))
START WITH rn1 IS NULL
CONNECT BY rn1 = PRIOR rn

正式生成树
NO   RESULT
001 ;a01
001 ;a01;a02
001 ;a01;a02;a03
002 ;b01
005 ;e01
005 ;e01;e02
005 ;e01;e02;e03
005 ;e01;e02;e03;e04
005 ;e01;e02;e03;e04;e05
003 ;c01
003 ;c01;c02
004 ;d01
将上面结果按照NO分组,取result最大值即可,所以将上述语句改为
select no,max(sys_connect_by_path(name,’;’)) result from
(select no,name,rn,lead(rn) over(partition by no order by rn) rn1
from (select no,name,row_number() over(order by no,name desc) rn from a_example2)
)
start with rn1 is null connect by rn1 = prior rn
group by no
得到所需结果。
详细出处参考:http://www.jb51.net/article/19182.htm

*****************************************************************************8
Oracle 分析函数的使用

Oracle 分析函数使用介绍
分析函数是oracle816引入的一个全新的概念,为我们分析数据提供了一种简单高效的处理方式.在分析函数出现以前,我们必须使用自联查询,子查询或者内联视图,甚至复杂的存储过程实现的语句,现在只要一条简单的sql语句就可以实现了,而且在执行效率方面也有相当大的提高.下面我将针对分析函数做一些具体的说明.

今天我主要给大家介绍一下以下几个函数的使用方法
1. 自动汇总函数rollup,cube,
2. rank 函数, rank,dense_rank,row_number
3. lag,lead函数
4. sum,avg,的移动增加,移动平均数
5. ratio_to_report报表处理函数
6. first,last取基数的分析函数

基础数据
06:34:23 SQL> select * from t;

BILL_MONTH AREA_CODE NET_TYPE LOCAL_FARE


200405 5761 G 7393344.04
200405 5761 J 5667089.85
200405 5762 G 6315075.96
200405 5762 J 6328716.15
200405 5763 G 8861742.59
200405 5763 J 7788036.32
200405 5764 G 6028670.45
200405 5764 J 6459121.49
200405 5765 G 13156065.77
200405 5765 J 11901671.70
200406 5761 G 7614587.96
200406 5761 J 5704343.05
200406 5762 G 6556992.60
200406 5762 J 6238068.05
200406 5763 G 9130055.46
200406 5763 J 7990460.25
200406 5764 G 6387706.01
200406 5764 J 6907481.66
200406 5765 G 13562968.81
200406 5765 J 12495492.50
200407 5761 G 7987050.65
200407 5761 J 5723215.28
200407 5762 G 6833096.68
200407 5762 J 6391201.44
200407 5763 G 9410815.91
200407 5763 J 8076677.41
200407 5764 G 6456433.23
200407 5764 J 6987660.53
200407 5765 G 14000101.20
200407 5765 J 12301780.20
200408 5761 G 8085170.84
200408 5761 J 6050611.37
200408 5762 G 6854584.22
200408 5762 J 6521884.50
200408 5763 G 9468707.65
200408 5763 J 8460049.43
200408 5764 G 6587559.23

BILL_MONTH AREA_CODE NET_TYPE LOCAL_FARE


200408 5764 J 7342135.86
200408 5765 G 14450586.63
200408 5765 J 12680052.38

40 rows selected.

Elapsed: 00:00:00.00

  1. 使用rollup函数的介绍

    Quote:
    下面是直接使用普通sql语句求出各地区的汇总数据的例子
    06:41:36 SQL> set autot on
    06:43:36 SQL> select area_code,sum(local_fare) local_fare
    06:43:50 2 from t
    06:43:51 3 group by area_code
    06:43:57 4 union all
    06:44:00 5 select ‘合计’ area_code,sum(local_fare) local_fare
    06:44:06 6 from t
    06:44:08 7 /

AREA_CODE LOCAL_FARE


5761 54225413.04
5762 52039619.60
5763 69186545.02
5764 53156768.46
5765 104548719.19
合计 333157065.31

6 rows selected.

Elapsed: 00:00:00.03

下面是使用分析函数rollup得出的汇总数据的例子
06:44:09 SQL> select nvl(area_code,’合计’) area_code,sum(local_fare) local_fare
06:45:26 2 from t
06:45:30 3 group by rollup(nvl(area_code,’合计’))
06:45:50 4 /

AREA_CODE LOCAL_FARE


5761 54225413.04
5762 52039619.60
5763 69186545.02
5764 53156768.46
5765 104548719.19
333157065.31

6 rows selected.

Elapsed: 00:00:00.00

从上面的例子我们不难看出使用rollup函数,系统的sql语句更加简单,耗用的资源更少,从6个consistent gets降到4个consistent gets,如果基表很大的话,结果就可想而知了.

  1. 使用cube函数的介绍

    Quote:
    为了介绍cube函数我们再来看看另外一个使用rollup的例子
    06:53:00 SQL> select area_code,bill_month,sum(local_fare) local_fare
    06:53:37 2 from t
    06:53:38 3 group by rollup(area_code,bill_month)
    06:53:49 4 /

AREA_CODE BILL_MONTH LOCAL_FARE


5761 200405 13060433.89
5761 200406 13318931.01
5761 200407 13710265.93
5761 200408 14135782.21
5761 54225413.04
5762 200405 12643792.11
5762 200406 12795060.65
5762 200407 13224298.12
5762 200408 13376468.72
5762 52039619.60
5763 200405 16649778.91
5763 200406 17120515.71
5763 200407 17487493.32
5763 200408 17928757.08
5763 69186545.02
5764 200405 12487791.94
5764 200406 13295187.67
5764 200407 13444093.76
5764 200408 13929695.09
5764 53156768.46
5765 200405 25057737.47
5765 200406 26058461.31
5765 200407 26301881.40
5765 200408 27130639.01
5765 104548719.19
333157065.31

26 rows selected.

Elapsed: 00:00:00.00

系统只是根据rollup的第一个参数area_code对结果集的数据做了汇总处理,而没有对bill_month做汇总分析处理,cube函数就是为了这个而设计的.
下面,让我们看看使用cube函数的结果

06:58:02 SQL> select area_code,bill_month,sum(local_fare) local_fare
06:58:30 2 from t
06:58:32 3 group by cube(area_code,bill_month)
06:58:42 4 order by area_code,bill_month nulls last
06:58:57 5 /

AREA_CODE BILL_MONTH LOCAL_FARE


5761 200405 13060.43
5761 200406 13318.93
5761 200407 13710.27
5761 200408 14135.78
5761 54225.41
5762 200405 12643.79
5762 200406 12795.06
5762 200407 13224.30
5762 200408 13376.47
5762 52039.62
5763 200405 16649.78
5763 200406 17120.52
5763 200407 17487.49
5763 200408 17928.76
5763 69186.54
5764 200405 12487.79
5764 200406 13295.19
5764 200407 13444.09
5764 200408 13929.69
5764 53156.77
5765 200405 25057.74
5765 200406 26058.46
5765 200407 26301.88
5765 200408 27130.64
5765 104548.72
200405 79899.53
200406 82588.15
200407 84168.03
200408 86501.34
333157.05

30 rows selected.

Elapsed: 00:00:00.01

可以看到,在cube函数的输出结果比使用rollup多出了几行统计数据.这就是cube函数根据bill_month做的汇总统计结果

1 rollup 和 cube函数的再深入

Quote:
从上面的结果中我们很容易发现,每个统计数据所对应的行都会出现null,
我们如何来区分到底是根据那个字段做的汇总呢,
这时候,oracle的grouping函数就粉墨登场了.
如果当前的汇总记录是利用该字段得出的,grouping函数就会返回1,否则返回0

1 select decode(grouping(area_code),1,’all area’,to_char(area_code)) area_code,
2 decode(grouping(bill_month),1,’all month’,bill_month) bill_month,
3 sum(local_fare) local_fare
4 from t
5 group by cube(area_code,bill_month)
6* order by area_code,bill_month nulls last
07:07:29 SQL> /

AREA_CODE BILL_MONTH LOCAL_FARE


5761 200405 13060.43
5761 200406 13318.93
5761 200407 13710.27
5761 200408 14135.78
5761 all month 54225.41
5762 200405 12643.79
5762 200406 12795.06
5762 200407 13224.30
5762 200408 13376.47
5762 all month 52039.62
5763 200405 16649.78
5763 200406 17120.52
5763 200407 17487.49
5763 200408 17928.76
5763 all month 69186.54
5764 200405 12487.79
5764 200406 13295.19
5764 200407 13444.09
5764 200408 13929.69
5764 all month 53156.77
5765 200405 25057.74
5765 200406 26058.46
5765 200407 26301.88
5765 200408 27130.64
5765 all month 104548.72
all area 200405 79899.53
all area 200406 82588.15
all area 200407 84168.03
all area 200408 86501.34
all area all month 333157.05

30 rows selected.

Elapsed: 00:00:00.01
07:07:31 SQL>

可以看到,所有的空值现在都根据grouping函数做出了很好的区分,这样利用rollup,cube和grouping函数,我们做数据统计的时候就可以轻松很多了.

  1. rank函数的介绍

介绍完rollup和cube函数的使用,下面我们来看看rank系列函数的使用方法.

问题2.我想查出这几个月份中各个地区的总话费的排名.

Quote:
为了将rank,dense_rank,row_number函数的差别显示出来,我们对已有的基础数据做一些修改,将5763的数据改成与5761的数据相同.
1 update t t1 set local_fare = (
2 select local_fare from t t2
3 where t1.bill_month = t2.bill_month
4 and t1.net_type = t2.net_type
5 and t2.area_code = ‘5761’
6* ) where area_code = ‘5763’
07:19:18 SQL> /

8 rows updated.

Elapsed: 00:00:00.01

我们先使用rank函数来计算各个地区的话费排名.
07:34:19 SQL> select area_code,sum(local_fare) local_fare,
07:35:25 2 rank() over (order by sum(local_fare) desc) fare_rank
07:35:44 3 from t
07:35:45 4 group by area_codee
07:35:50 5
07:35:52 SQL> select area_code,sum(local_fare) local_fare,
07:36:02 2 rank() over (order by sum(local_fare) desc) fare_rank
07:36:20 3 from t
07:36:21 4 group by area_code
07:36:25 5 /

AREA_CODE LOCAL_FARE FARE_RANK


5765 104548.72 1
5761 54225.41 2
5763 54225.41 2
5764 53156.77 4
5762 52039.62 5

Elapsed: 00:00:00.01

我们可以看到红色标注的地方出现了,跳位,排名3没有出现
下面我们再看看dense_rank查询的结果.

07:36:26 SQL> select area_code,sum(local_fare) local_fare,
07:39:16 2 dense_rank() over (order by sum(local_fare) desc ) fare_rank
07:39:39 3 from t
07:39:42 4 group by area_code
07:39:46 5 /

AREA_CODE LOCAL_FARE FARE_RANK


5765 104548.72 1
5761 54225.41 2
5763 54225.41 2
5764 53156.77 3 这是这里出现了第三名
5762 52039.62 4

Elapsed: 00:00:00.00

在这个例子中,出现了一个第三名,这就是rank和dense_rank的差别,
rank如果出现两个相同的数据,那么后面的数据就会直接跳过这个排名,而dense_rank则不会,
差别更大的是,row_number哪怕是两个数据完全相同,排名也会不一样,这个特性在我们想找出对应没个条件的唯一记录的时候又很大用处

1 select area_code,sum(local_fare) local_fare,
2 row_number() over (order by sum(local_fare) desc ) fare_rank
3 from t
4* group by area_code
07:44:50 SQL> /

AREA_CODE LOCAL_FARE FARE_RANK


5765 104548.72 1
5761 54225.41 2
5763 54225.41 3
5764 53156.77 4
5762 52039.62 5

在row_nubmer函数中,我们发现,哪怕sum(local_fare)完全相同,我们还是得到了不一样排名,我们可以利用这个特性剔除数据库中的重复记录.

这个帖子中的几个例子是为了说明这三个函数的基本用法的. 下个帖子我们将详细介绍他们的一些用法.

a. 取出数据库中最后入网的n个用户
select user_id,tele_num,user_name,user_status,create_date
from (
select user_id,tele_num,user_name,user_status,create_date,
rank() over (order by create_date desc) add_rank
from user_info
)
where add_rank <= :n;

b.根据object_name删除数据库中的重复记录
create table t as select obj#,name from sys.obj$;
再insert into t1 select * from t1 数次.
delete from t1 where rowid in (
select row_id from (
select rowid row_id,row_number() over (partition by obj# order by rowid ) rn
) where rn <> 1
);

c. 取出各地区的话费收入在各个月份排名.
SQL> select bill_month,area_code,sum(local_fare) local_fare,
2 rank() over (partition by bill_month order by sum(local_fare) desc) area_rank
3 from t
4 group by bill_month,area_code
5 /

BILL_MONTH AREA_CODE LOCAL_FARE AREA_RANK


200405 5765 25057.74 1
200405 5761 13060.43 2
200405 5763 13060.43 2
200405 5762 12643.79 4
200405 5764 12487.79 5
200406 5765 26058.46 1
200406 5761 13318.93 2
200406 5763 13318.93 2
200406 5764 13295.19 4
200406 5762 12795.06 5
200407 5765 26301.88 1
200407 5761 13710.27 2
200407 5763 13710.27 2
200407 5764 13444.09 4
200407 5762 13224.30 5
200408 5765 27130.64 1
200408 5761 14135.78 2
200408 5763 14135.78 2
200408 5764 13929.69 4
200408 5762 13376.47 5

20 rows selected.
SQL>

  1. lag和lead函数介绍

取出每个月的上个月和下个月的话费总额
1 select area_code,bill_month, local_fare cur_local_fare,
2 lag(local_fare,2,0) over (partition by area_code order by bill_month ) pre_local_fare,
3 lag(local_fare,1,0) over (partition by area_code order by bill_month ) last_local_fare,
4 lead(local_fare,1,0) over (partition by area_code order by bill_month ) next_local_fare,
5 lead(local_fare,2,0) over (partition by area_code order by bill_month ) post_local_fare
6 from (
7 select area_code,bill_month,sum(local_fare) local_fare
8 from t
9 group by area_code,bill_month
10* )
SQL> /
AREA_CODE BILL_MONTH CUR_LOCAL_FARE PRE_LOCAL_FARE LAST_LOCAL_FARE NEXT_LOCAL_FARE POST_LOCAL_FARE


5761 200405 13060.433 0 0 13318.93 13710.265
5761 200406 13318.93 0 13060.433 13710.265 14135.781
5761 200407 13710.265 13060.433 13318.93 14135.781 0
5761 200408 14135.781 13318.93 13710.265 0 0
5762 200405 12643.791 0 0 12795.06 13224.297
5762 200406 12795.06 0 12643.791 13224.297 13376.468
5762 200407 13224.297 12643.791 12795.06 13376.468 0
5762 200408 13376.468 12795.06 13224.297 0 0
5763 200405 13060.433 0 0 13318.93 13710.265
5763 200406 13318.93 0 13060.433 13710.265 14135.781
5763 200407 13710.265 13060.433 13318.93 14135.781 0
5763 200408 14135.781 13318.93 13710.265 0 0
5764 200405 12487.791 0 0 13295.187 13444.093
5764 200406 13295.187 0 12487.791 13444.093 13929.694
5764 200407 13444.093 12487.791 13295.187 13929.694 0
5764 200408 13929.694 13295.187 13444.093 0 0
5765 200405 25057.736 0 0 26058.46 26301.881
5765 200406 26058.46 0 25057.736 26301.881 27130.638
5765 200407 26301.881 25057.736 26058.46 27130.638 0
5765 200408 27130.638 26058.46 26301.881 0 0
20 rows selected.

利用lag和lead函数,我们可以在同一行中显示前n行的数据,也可以显示后n行的数据.

  1. sum,avg,max,min移动计算数据介绍

计算出各个连续3个月的通话费用的平均数
1 select area_code,bill_month, local_fare,
2 sum(local_fare)
3 over ( partition by area_code
4 order by to_number(bill_month)
5 range between 1 preceding and 1 following ) “3month_sum”,
6 avg(local_fare)
7 over ( partition by area_code
8 order by to_number(bill_month)
9 range between 1 preceding and 1 following ) “3month_avg”,
10 max(local_fare)
11 over ( partition by area_code
12 order by to_number(bill_month)
13 range between 1 preceding and 1 following ) “3month_max”,
14 min(local_fare)
15 over ( partition by area_code
16 order by to_number(bill_month)
17 range between 1 preceding and 1 following ) “3month_min”
18 from (
19 select area_code,bill_month,sum(local_fare) local_fare
20 from t
21 group by area_code,bill_month
22* )
SQL> /

AREA_CODE BILL_MONTH LOCAL_FARE 3month_sum 3month_avg 3month_max 3month_min


5761 200405 13060.433 26379.363 13189.6815 13318.93 13060.433
5761 200406 13318.930 40089.628 13363.2093 13710.265 13060.433
5761 200407 13710.265 41164.976 13721.6587 14135.781 13318.93
40089.628 = 13060.433 + 13318.930 + 13710.265
13363.2093 = (13060.433 + 13318.930 + 13710.265) / 3
13710.265 = max(13060.433 + 13318.930 + 13710.265)
13060.433 = min(13060.433 + 13318.930 + 13710.265)
5761 200408 14135.781 27846.046 13923.023 14135.781 13710.265
5762 200405 12643.791 25438.851 12719.4255 12795.06 12643.791
5762 200406 12795.060 38663.148 12887.716 13224.297 12643.791
5762 200407 13224.297 39395.825 13131.9417 13376.468 12795.06
5762 200408 13376.468 26600.765 13300.3825 13376.468 13224.297
5763 200405 13060.433 26379.363 13189.6815 13318.93 13060.433
5763 200406 13318.930 40089.628 13363.2093 13710.265 13060.433
5763 200407 13710.265 41164.976 13721.6587 14135.781 13318.93
5763 200408 14135.781 27846.046 13923.023 14135.781 13710.265
5764 200405 12487.791 25782.978 12891.489 13295.187 12487.791
5764 200406 13295.187 39227.071 13075.6903 13444.093 12487.791
5764 200407 13444.093 40668.974 13556.3247 13929.694 13295.187
5764 200408 13929.694 27373.787 13686.8935 13929.694 13444.093
5765 200405 25057.736 51116.196 25558.098 26058.46 25057.736
5765 200406 26058.460 77418.077 25806.0257 26301.881 25057.736
5765 200407 26301.881 79490.979 26496.993 27130.638 26058.46
5765 200408 27130.638 53432.519 26716.2595 27130.638 26301.881

20 rows selected.

  1. ratio_to_report函数的介绍

    Quote:
    1 select bill_month,area_code,sum(local_fare) local_fare,
    2 ratio_to_report(sum(local_fare)) over
    3 ( partition by bill_month ) area_pct
    4 from t
    5* group by bill_month,area_code
    SQL> break on bill_month skip 1
    SQL> compute sum of local_fare on bill_month
    SQL> compute sum of area_pct on bill_month
    SQL> /

BILL_MONTH AREA_CODE LOCAL_FARE AREA_PCT


200405 5761 13060.433 .171149279
5762 12643.791 .165689431
5763 13060.433 .171149279
5764 12487.791 .163645143
5765 25057.736 .328366866
**** —————- ———-
sum 76310.184 1

200406 5761 13318.930 .169050772
5762 12795.060 .162401542
5763 13318.930 .169050772
5764 13295.187 .168749414
5765 26058.460 .330747499
**** —————- ———-
sum 78786.567 1

200407 5761 13710.265 .170545197
5762 13224.297 .164500127
5763 13710.265 .170545197
5764 13444.093 .167234221
5765 26301.881 .327175257
**** —————- ———-
sum 80390.801 1

200408 5761 14135.781 .170911147
5762 13376.468 .161730539
5763 14135.781 .170911147
5764 13929.694 .168419416
5765 27130.638 .328027751
**** —————- ———-
sum 82708.362 1

20 rows selected.

6 first,last函数使用介绍

Quote:
取出每月通话费最高和最低的两个用户.
1 select bill_month,area_code,sum(local_fare) local_fare,
2 first_value(area_code)
3 over (order by sum(local_fare) desc
4 rows unbounded preceding) firstval,
5 first_value(area_code)
6 over (order by sum(local_fare) asc
7 rows unbounded preceding) lastval
8 from t
9 group by bill_month,area_code
10* order by bill_month
SQL> /

BILL_MONTH AREA_CODE LOCAL_FARE FIRSTVAL LASTVAL


200405 5764 12487.791 5765 5764
200405 5762 12643.791 5765 5764
200405 5761 13060.433 5765 5764
200405 5765 25057.736 5765 5764
200405 5763 13060.433 5765 5764
200406 5762 12795.060 5765 5764
200406 5763 13318.930 5765 5764
200406 5764 13295.187 5765 5764
200406 5765 26058.460 5765 5764
200406 5761 13318.930 5765 5764
200407 5762 13224.297 5765 5764
200407 5765 26301.881 5765 5764
200407 5761 13710.265 5765 5764
200407 5763 13710.265 5765 5764
200407 5764 13444.093 5765 5764
200408 5762 13376.468 5765 5764
200408 5764 13929.694 5765 5764
200408 5761 14135.781 5765 5764
200408 5765 27130.638 5765 5764
200408 5763 14135.781 5765 5764

20 rows selected.

————=-=—————======—=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

OLAP函数语法的总结over(…)

ORACLE OLAP 函数
最近这个东东用得特别多,总结了一下 。

语法: FUNCTION_NAME(,,…)
OVER
()

OLAP函数语法四个部分:
1、function本身 用于对窗口中的数据进行操作;
2、partitioning clause 用于将结果集分区;
3、order by clause 用于对分区中的数据进行排序;
4、windowing clause 用于定义function在其上操作的行的集合,即function所影响的范围。

一、order by对窗口的影响
不含order by的:
SQL> select deptno,sal,sum(sal) over()
2 from emp;
不含order by时,默认的窗口是从结果集的第一行直到末尾。
含order by的:
SQL> select deptno,sal,
2 sum(sal) over(order by deptno) as sumsal
3 from emp;
当含有order by时,默认的窗口是从第一行直到当前分组的最后一行。

二、用于排列的函数
SQL> select empno, deptno, sal,
2 rank() over
3 (partition by deptno order by sal desc nulls last) as rank,
4 dense_rank() over
5 (partition by deptno order by sal desc nulls last) as dense_rank,
6 row_number() over
7 (partition by deptno order by sal desc nulls last) as row_number
8 from emp;

三、用于合计的函数

SQL> select deptno,sal,
2 sum(sal) over (partition by deptno) as sumsal,
3 avg(sal) over (partition by deptno) as avgsal,
4 count(*) over (partition by deptno) as count,
5 max(sal) over (partition by deptno) as maxsal
6 from emp;

四、开窗语句

1、rows窗口: “rows 5 preceding”

适用于任何类型而且可以order by多列。

SQL> select deptno,ename,sal,
2 sum(sal) over (order by deptno rows 2 preceding) sumsal
3 from emp;

rows 2 preceding:将当前行和它前面的两行划为一个窗口,因此sum函数就作 用在这三行上面
SQL> select deptno,ename,sal,
2 sum(sal) over
3 (partition by deptno order by ename rows 2 preceding) sumsal
4 from emp
5 order by deptno,ename;
加了partiton by分区后之后,rows 2 preceding(窗口)只在当前分区内生效,不会影响分区之外的行。
SQL> select ename,sal,hiredate,
2 first_value(ename)over
3 (order by hiredate asc rows 5 preceding) first_ename,
4 first_value(hiredate) over
5 (order by hiredate asc rows 5 preceding) first_hiredate
6 from emp
7 order by hiredate asc;
order by hiredate asc rows 5 preceding: order by之后,取当前行的前5行+当前行作为窗口(共6行)。
2、”range unbounded preceding”

range unbounded preceding会把当前行之前的所有行都包含进来,但当partition by时:

SQL> select deptno,ename,sal,
2 sum(sal) over
3 (partition by deptno order by deptno range unbounded preceding) sumsal
4 from emp;
SQL> select deptno,ename,sal,
2 sum(sal) over
3 (order by deptno range unbounded preceding) sumsal
4 from emp;
这SQL句子和下面这SQL是等价的:

select deptno,ename,sal,
sum(sal) over (order by deptno) sumsal
from emp;

因为order by的默认窗口总是从结果集的第一行开始到它分组的最后一行。
而partiton by的默认窗口总是从分区的第一行开始。
3、range窗口: “range 100 preceding”

这个子句只适用于number和date,而且只能order by一列。
如果over()里asc排列,意思是[number-100,number]这样一个闭区间是它的窗口。
如果over()里desc排列,意思是[number,number+100]这样一个闭区间是它的窗口。
4、窗口总结

1、unbounded preceding:从当前分区的第一行开始,到当前行结束。
2、current row:从当前行开始,也结束于当前行。
3、[numeric expression] preceding:对于rows来说从当前行之前的第[numeric expression]行开始,到当前行结束。对range来说从小于数值
表达式的值开始,到当前行结束。
4、[numeric expression] following:与[numeric expression] preceding相反。

[ Last edited by DQ on 2005-3-4 at 14:15 ]

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
ORACLE创建、修改计划任务(2010-08-13 18:09)转载标签:杂谈 分类:技术
begin
sys.dbms_job.submit(job => :job,
what => ‘calculate_tag_score_smsbill;’,–分号必须加
next_date => to_date(‘13-08-2010 11:26:13’, ‘dd-mm-yyyy hh24:mi:ss’), –开始执行时间
interval => ‘sysdate+1/8640’); –字符型,执行间隔,这里是10秒一次
commit;
end;

begin
sys.dbms_job.change(job => 81,
what => ‘stat_user_tag;’,
next_date => to_date(‘12-08-2010 09:59:17’, ‘dd-mm-yyyy hh24:mi:ss’),
interval => ‘sysdate+1’);
commit;
end;

*****************************************************************************8

*****************************************************************************8
oracle JOB 的创建列子
创建
variable job_feeid_create NUMBER;
begin
sys.dbms_job.submit(:job_feeid_create,’wlk_check_fee;’,sysdate,’TRUNC(SYSDATE+1)’);
commit;
end;
在命令控制台中这样就可以建产一个作业了。sysdate表示当前作业将来执行的时间,sysdate+1表示调用频率。
描述 INTERVAL参数值
每天午夜12点 ‘TRUNC(SYSDATE + 1)’
每天早上8点30分 ‘TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)’
每星期二中午12点 ‘NEXT_DAY(TRUNC(SYSDATE ), ”TUESDAY” ) + 12/24’
每个月第一天的午夜12点 ‘TRUNC(LAST_DAY(SYSDATE ) + 1)’
每个季度最后一天的晚上11点 ‘TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), ‘Q’ ) -1/24’
每星期六和日早上6点10分 ‘TRUNC(LEAST(NEXT_DAY(SYSDATE, ”SATURDAY”), NEXT_DAY(SYSDATE, “SUNDAY”))) + (6×60+10)/(24×60)’

运行

begin
dbms_job.run(:job_feeid_create);
end;

查询作业记录
select * from user_jobs

具体讲解:
1.确保Oracle的工作模式允许启动任务队列管理器
Oracle定时执行“Job Queue”的后台程序是SNP进程,而要启动SNP进程,首先要确保整个系统的模式是可以启动SNP进程的,这需要以 DBA的身份去执行如下命令:
svrmgrl>; alter system enable restricted session;
或sql>; alter system disenable restricted session;
利用如上命令更改系统的会话方式为disenable restricted,为SNP的启动创造条件。

  2.确保Oracle的系统已经配置了任务队列管理器的启动参数 
        SNP的启动参数位于Oracle的初始化文件中,该文件放在$ORACLE_HOME/dbs路径下,如果Oracle的SID是myora8的话,则初始化文件就是   initmyora8.ora,在文件中对SNP启动参数的描述部分如下: 
        job_queue_process=n 
        job_queue_interval=N 
        第一行定义SNP进程的启动个数为n。系统缺省值为0,正常定义范围为0~36,根据任务的多少,可以配置不同的数值。 
        第二行定义系统每隔N秒唤醒该进程一次。系统缺省值为60秒,正常范围为1~3600秒。事实上,该进程执行完当前任务后,就进入睡眠状 态,睡眠一段时间后,由系统的总控负责将其唤醒。 
        如果该文件中没有上面两行,请按照如上配置添加。配置完成后,需要重新启动数据库,使其生效。注意:如果任务要求执行的间隔很短的 话,N的配置也要相应地小一点。 
   3.将任务加入到数据库的任务队列中 
          用Oracle的dbms_job包中的存储过程,将任务加入到任务队列中: 

dbms_job.submit( job out binary_integer,
what       in   archar2,
next_date     in   date,
interval     in   varchar2,
no_parse     in   boolean)

其中:
●job:输出变量,是此任务在任务队列中的编号;
●what:执行的任务的名称及其输入参数;
●next_date:任务执行的时间;
●interval:任务执行的时间间隔。
下面详细讨论一下dbms_job.submit中的参数interval。严格地讲,interval是指上一次执行结束到下一次开始执行的时间间隔,当interval设置为null 时,该job执行结束后,就被从队列中删除。假如我们需要该job周期性地执行,则要用‘sysdate+m’表示。
将任务加入到任务队列之前,要确定执行任务的数据库用户,若用户是scott, 则需要确保该用户拥有执行包dbms_job的权限;若没有,需要以 DBA的身份将权利授予scott用户:
svrmgrl>; grant execute on dbms_job to scott;

 4.将要执行的任务写成存储过程或其他的数据库可执行的pl/sql程序段 

        例如,我们已经建立了一个存储过程,其名称为my_job,在sql/plus中以scott用户身份登录,执行如下命令: 

sql>; variable n number;
sql>; begin
dbms_job.submit(:n‘my_job;’,sysdate,
‘sysdate+1/360’);
commit;
end;
/
系统提示执行成功。
Sql>; print :n;
系统打印此任务的编号,例如结果为300。
如上,我们创建了一个每隔4分钟执行一次的任务号为300的任务。可以通过Oracle提供的数据字典user_jobs察看该任务的执行情况:

sql>; select job,next_date,next_sec,failures,broken from user_jobs;
执行结果如下:
job next_date next_sec failures broken
300 2000/10/10 11:45:15 0 N

     这表示任务号为300的任务,下一次将在2000/10/10 11:45:15执行,此任务的执行失败记录为0次。注意:当执行job出现错误时,Oracle将其记录在日志里,失败次数每次自动加1。当执行失败次数达到16时,Oracle就将该job标志为broken。此后,Oracle不再继续执行它,直到用户调用过程dbms_job.broken,重新设置为not broken,或强制调用dbms_job.run来重新执行它。 
     除了以上我们讨论的submit存储过程之外,Oracle还提供了其他许多存储过程来操作任务。例如:dbms_job.change 、 dbms_job.what、dbms_job.interval可以用来修改提交的任务。要想删除该任务,只需运行dbms_job.remove(n)即可,其中n为任务号。 

下方为实例2:

创建oracle job
oracle job简介
主要的使用情景
定时在后台执行相关操作:如每天晚上0点将一张表的数据保存到另一张表中,2:定时备份数据库等

熟化说万事开头难,这里我只简单记述一个创建一个简单的job
步骤如下:
1、创建一张表g_test
create table G_TEST
(
ID NUMBER(12),
C_DATE DATE
)
2、创建一个sequence
create sequence G_SEQ
minvalue 1
maxvalue 999999999999999999999999999
start with 141
increment by 1
cache 20;

3、创建一个存储过程
create or replace procedure prc_g_test is
begin
insert into g_test values(g_seq.nextval,sysdate);
end prc_g_test;

4、创建job,
使用Submit()过程,工作被正常地计划好。
这个过程有五个参数:job、what、next_date、interval与no_parse。

PROCEDURE Submit ( job OUT binary_ineger,
What IN varchar2,
next_date IN date,
interval IN varchar2,
no_parse IN booean:=FALSE)

job参数是由Submit()过程返回的binary_ineger。这个值用来唯一标识一个工作。
what参数是将被执行的PL/SQL代码块。
next_date参数指识何时将运行这个工作。
interval参数何时这个工作将被重执行。
no_parse参数指示此工作在提交时或执行时是否应进行语法分析——TRUE
指示此PL/SQL代码在它第一次执行时应进行语法分析,
而FALSE指示本PL/SQL代码应立即进行语法分析。

在command window窗口中执行下面脚本
variable job1 number;
begin
sys.dbms_job.submit(job => :job,
what => ‘prc_g_test;’,
next_date => to_date(‘22-10-2008 10:06:41’, ‘dd-mm-yyyy hh24:mi:ss’),
interval => ‘sysdate+1/1440’);–每天1440分钟,即一分钟运行test过程一次
commit;
end;
/


在plSQL中我的做法是:

declare
job number;
begin
sys.dbms_job.submit(job,’prc_g_test;’,sysdate,’sysdate+1/1440’);
end;

删除job:
exec dbms_job.remove(jobno);


5、查看创建的job
查看相关job信息
1、相关视图
dba_jobs
all_jobs
user_jobs
dba_jobs_running 包含正在运行job相关信息。
如:
select * from dba_jobs

6、运行JOB
说明:Run()过程用来立即执行一个指定的工作。这个过程只接收一个参数:
SQL> begin
2 dbms_job.run(:job);
3 end;
4 /


在plSQL中我的做法是:
begin
dbms_job.run(3017);

end;

7、删除JOB
SQL> begin
2 dbms_job.remove(:job);–:job可以用dba_jobs.job的值代替如:1198
3 end;
4 /

说明:在sqlplus命令行直接定义变量要variable!!!!

*****************************************************************************8
使用dbms_output.putline();
使用set serveroutput on

*****************************************************************************8
ORACLE默认创建2个用户 SYS,密码:change_on_install
SYSTEM,密码:manager
一般登陆时可以输入:D:>sqlplus “/as sysdba”
或:D:>sqlplus user/password

在以SYSDBA身份登陆时可以修改其他用户的密码,比如:
SQL> alter user user01 identified by user10;
用户已更改。
这个是把USER01用户密码修改为USER10

*****************************************************************************8
oracle中查看用户权限
1.查看所有用户:
select * from dba_users;
select * from all_users;
select * from user_users;

2.查看用户或角色系统权限(直接赋值给用户或角色的系统权限):
select * from dba_sys_privs;
select * from user_sys_privs;

3.查看角色(只能查看登陆用户拥有的角色)所包含的权限

sql>select * from role_sys_privs;

4.查看用户对象权限:
select * from dba_tab_privs;
select * from all_tab_privs;
select * from user_tab_privs;

5.查看所有角色:
select * from dba_roles;

6.查看用户或角色所拥有的角色:
select * from dba_role_privs;
select * from user_role_privs;

7.查看哪些用户有sysdba或sysoper系统权限(查询时需要相应权限)

select * from V$PWFILE_USERS

注意:

1、以下语句可以查看Oracle提供的系统权限

select name from sys.system_privilege_map

2、查看一个用户的所有系统权限(包含角色的系统权限)

Sql代码
select privilege from dba_sys_privs where grantee=’IPSBR’
union
select privilege from dba_sys_privs where grantee in (select granted_role from dba_role_privs where grantee=’IPSBR’ );

select privilege from dba_sys_privs where grantee=’IPSBR’
union
select privilege from dba_sys_privs where grantee in (select granted_role from dba_role_privs where grantee=’IPSBR’ );

session

*****************************************************************************8
Oracle 数据库用户(user)的创建、删除以及授予权限


———–Oracle 数据库用户创建学习

–创建用户,如同在网吧开机子一样,保护自身系统的安全性的同时,有简化了自己的操作(系统用户有很多繁杂的表)
–默认用户
/*
用户名 密码
sys 安装时确认
system manager
scott tiger
注:Oracle10g 后的版本sys和system都是安装时设定的,而scott是默认锁定的
*/
create user user_name identified by password;
–详解:
/*
创建一个用户名称为user_name,密码为password的用户;
注:密码必须由字母开头
如果以数字或其他符号开头会出现错误:ORA-00988: 口令缺失或无效
如果以下划线“_”开头会出现错误:ORA-00911: 无效字符

*/

drop user user_name [cascade];
–详解
/*
drop user user_name;
仅仅删除用户
drop user user_name cascade;
删除用户的同时,删除此用户名下所有的
使用cascade参数可以删除该用户的全部objects。
1、如果用户的schema中有表,则在删除表的时候自动删除与该表相关的主键和外键。
2、如果用户的schema中有表,则在删除表的时候自动删除与该表相关的索引。
3、删除用户时,下列在其他用户中的objects不会被删除,只会被置为无效
4、其他用户建立的基于被删除用户的物化视图不会被删除,只是不能在刷新了。
5、用户模式下的所有触发器全部被删除
6、被删除用户建立的其他用户不会被删除
*/

–赋予用户权限(c初始用户没有权限,连进入该用户都不可能)
grant connect,resource,dba to user_name;
–一般授予以上权限就可以了
–1、三个常用的系统权限的赋予语句:
–格式:grant 系统权限 to { public | role | username };
grant create session to lisi;
–创建会话权限,可以进入用户进行相关数据库操作
grant create table to lisi;
–创建表的权限
grant unlimited tablespace to lisi;
–使用表空间的权限
grant create session to public;
–对所有用户授予创建会话权限,public代表所有用户
–删除以上权限,不做解释
revoke create session from lisi;
revoke create table from lisi;
revoke unlimited tablespace from lisi;
–2、创建常用的对象权限

–示例
–创建用户,并制定表空间
create user username identified by password
default tablespace test_data
temporary tablespace test_temp;
–给用户授予权限
grant
create session, create any table, create any view ,create any index, create any procedure,
alter any table, alter any procedure,
drop any table, drop any view, drop any index, drop any procedure,
select any table, insert any table, update any table, delete any table
to username;

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Kilper/archive/2010/08/07/5795482.aspx

*****************************************************************************8
Oracle 转义字符
转义字符 &
在plsql里边执行:
update userinfo set pageurl=’myjsp?page=1&pagesize=10’ where id=’test’
这条sql语句往数据库的pageurl字段放进去了一个url地址,但是执行的时候却并非那么理想,因为这其中有一个oracle的特殊字符,需要进行转义,那就是字符’&’.

怎么处理上例中的特殊字符?
两个办法:
1) update userinfo set pageurl=’myjsp?page=1’||’&’||’pagesize=10’ where id=’test’
2) update userinfo set pageurl=’myjsp?page=1’||chr(38)||’pagesize=10’ where id=’test’

其中||是连字符, chr(38)跟ASCII的字符转码是一致的。
plsql中还可以set define off来关闭特殊字符,还可以用show define来查看有些特殊定义的字符。

转义字符 %

处理手法如&

转义字符 ’ 单引号 在PL/SQL 里 两个单引号等于一个单引号

双引号 = chr(34)

*****************************************************************************8
查询Oracle中某些表或者某张表的信息(备注、主键、owner等)2009年02月13日 星期五 11:38查询某张或者某些表的整体信息:

/first/
select distinct a.table_name,
b.comments,
A.OWNER,
a.tablespace_name,
null as is_used
from all_tables a, all_tab_comments b
where a.table_name = b.table_name
and a.table_name like ‘%YOUR_TABLE_SPECIAL_PART%’
and a.tablespace_name = ‘YOUR_TABSPACE_NAME’

/second/
select distinct a.table_name,
b.comments,
c.constraint_name,
d.column_name,
A.OWNER,
a.tablespace_name,
null as is_used
from all_tables a,
all_tab_comments b,
all_constraints c,
all_cons_columns d
where a.table_name = b.table_name
and b.table_name = c.table_name
and c.table_name = d.table_name and c.constraint_name = d.constraint_name
and a.table_name like ‘%%YOUR_TABLE_SPECIAL_PART%%’ and c.constraint_type = ‘P’
and a.tablespace_name = ‘YOUR_TABSPACE_NAME’

*****************************************************************************8

根据表明,查询列名 以及 字段数量
最近正在研究JVM,发现函数参数的索引下标是Byte类型,这样不是只能写255个参数吗?
试了一下,写了一个有300个参数的函数,果然编译不通过。显示参数过多。
但是印象中没有在任何一本书中看到参数个数有限制啊!

*****************************************************************************8

Error: ORA-02069: global_names parameter must be set to TRUE for this operation
Cause:
You tried to execute an operation that requires a remote mapping. This can not be done because the parameter called GLOBAL_NAMES is not set to TRUE.

Action:
The options to resolve this Oracle error are:

  1. Try setting the GLOBAL_NAMES parameter to TRUE with the following statement:

Code:

ALTER SESSION SET GLOBAL_NAMES = TRUE;

*****************************************************************************8
请教 怎么修改 Global_names 的参数值为 TRUE

SQL> show parameter global_name;

NAME TYPE VALUE


global_names boolean FALSE
SQL> alter system set global_names=true scope=both;
alter system set global_names=true scope=both
*
ERROR 位于第 1 行:
ORA-32001: 已请求写入 SPFILE, 但是在启动时未指定 SPFILE

SQL> conn system/manager@portal
已连接。
SQL> alter system set global_names=true scope=both;
alter system set global_names=true scope=both
*
ERROR 位于第 1 行:
ORA-32001: 已请求写入 SPFILE, 但是在启动时未指定 SPFILE

SQL> alert system set global_name = true scope = both;
SP2-0734: 未知的命令开头 “alert syst…” - 忽略了剩余的行。
SQL> alter system set open_links=4 scope=both;
alter system set open_links=4 scope=both
*
ERROR 位于第 1 行:
ORA-02095: 无法修改指定的初始化参数

SQL> alter system set job_queue_processes=10 scope=both;
alter system set job_queue_processes=10 scope=both
*
ERROR 位于第 1 行:
ORA-32001: 已请求写入 SPFILE, 但是在启动时未指定 SPFILE

SQL>SHOW PARAMETER SPFILE
没有的话是指定了IFILE了
SQL>SHOW PARAMETER IFILE(这个参数里应该有内容的)

在INIT.ORA里曾加一行
GLOBAL_NAMES=TRUE

THEN RESTART DATABASE

你没有使用spfile,而这个参数不能动态修改的,所以你只能在你的init.ora文件中修改这个参数,要重启动database的

*****************************************************************************8
ORA-02069:解决方法
今天遇到了ORA-02069: global_names parameter must be set to TRUE for this operation

查了METALINK原因是不能在通过DBLINK操作远程表的DML语句中使用本地函数

原文如下:

Because of a limitation, it is not possible to use a local function when doing a dml operation on a remote tableITPUB个人空间w zxR/^#t^
When this is attempted, the ora-2069 is raised.

解决方法

1、使用 global_names=true个人觉得麻烦还要修改DBLINK名

2、把函数放到远端数据库去,这个比较可行。

*****************************************************************************8
创建DB_link
create database link SSS connect to dcf IDENTIFiED BY dcfl123 USING ‘ds392’
SSS: db_link 的名字
dcf: 用户名
dcf123: 密码
ds392: 为TNS配置的名称

*****************************************************************************8

*****************************************************************************8

*****************************************************************************8
plsql 默认字体:
main Fount: Courier New 常规 10
藏青色 西方

*****************************************************************************8
sbSql.append(” decode(‘”+bcm1103t.getJno()+”’,’null’,”,”,”,’”+bcm1103t.getJno()+”’), \n”);

*****************************************************************************8
oracle字符替换
文章分类:数据库

select REGEXP_REPLACE( ‘ABC5DD6D ‘, ‘5|6’, ‘x’) x from dual;

SELECT COUNT(*) FROM dual WHERE REGEXP_LIKE(‘abcdef’,’a|x’)

Oracle提供了一个字符替换函数translate,不同于replace函数的是,translate函数是字符级别的替换,而不是字符串的替换。

其语法如下:

TRANSLATE ( expr , from_string , to_string )

简单的说就是对expr内容,用to_string中的字符逐一替换from_string 中的字符,举例说明如下:

SQL> select translate(‘123456789’,’456’,’abc’) from dual;

TRANSLATE

123abc789

SQL> select translate(‘123456789’,’456’,’ab’) from dual;

TRANSLAT

123ab789

SQL> select translate(‘123456789’,’4564’,’a’) from dual;

TRANSLAT

123a789

SQL> select translate(‘123456789’,’4564’,’abcd’) from dual;

TRANSLATE

123abc789

可以看到translate函数是以字符为单位逐一替换的,从第二、三个例子可以看出,如果第三个参数to_string的长度小于第二个参数 from_string,那么from_string的后边超出的部分都被替换为空值。从第三、四个例子可见,如果某一个字符多次出现,则以第一次替换的内容为准。

以此可以实现的一个有用的功能是统计一个字符串中某个字符出现的次数:

select length(translate(‘expl’,’x’||’expl’,’x’)) from dual

官方文档10g Release 2 (10.2) B14200-02 提供了一个例子如下:

Examples

The following statement translates a book title into a string that could be used (for example) as a filename. The from_string contains four characters: a space, asterisk, slash, and apostrophe (with an extra apostrophe as the escape character). The to_string contains only three underscores. This leaves the fourth character in the from_string without a corresponding replacement, so apostrophes are dropped from the returned value.

SELECT TRANSLATE(‘SQL*Plus User”s Guide’, ’ */”’, ‘_‘) FROM DUAL;

SQL_Plus_Users_Guide

字符串别的替换相当简单:
select replace(‘/jsp/spms/sampleplan/samplePlanMng.jsp’,’spms’,’cpfr’) from dual;

/jsp/spms/sampleplan/samplePlanMng.jsp =》
/jsp/cpfr/sampleplan/samplePlanMng.jsp

UPDATE sys_menu_inf t
SET t.menu_url = REPLACE(t.menu_url,’spms’, ‘cpfr’)
*****************************************************************************8

Oracle DBA常用SQL
一、查询数据库配置

查询数据库名字、创建日期
select name,created,log_mode,open_mode from v$database

查询主机名、实例名及版本
select host_name,instance_name,version from v$instance

查看详细版本信息
select * from v$version

查看控制文件
select * from v$controlfile

查看重做日志配置信息
select group#,members,bytes,status,archived from v$log

查看重做日志(成员)文件存放的具体位置
select * from v$logfile

查看数据库备份和恢复策略及归档文件位置
archive log list
执行此语句需sysdba权限

查询表空间情况
select tablespace_name, block_size, status, contents, logging from dba_tablespaces

查询表空间存储文件
select file_id, file_name, tablespace_name, status, bytes from dba_data_files

查询用户情况
select username,created from dba_users

二、与重做日志相关的命令

查看重做日志组信息:
select * from v logselectfromv l o g 查 看 重 做 日 志 组 成 员 信 息 : s e l e c t ∗ f r o m v logfile

重做日志切换命令
alter system switch logfile

创建新的日志组
alter database add logfile (‘c:\1.log’,’d:\3.log’);
删除日志组
alter database drop logfile group 组号

添加日志组成员
alter database add logfile member ‘c:\redo01b.log’ to group 1,’d:\redo02b.log’ to group 2
删除日志组成员
alter database drop logfile member ‘c:\redo01b.log’

初始化联机重做日志
alter database clear [unarchived] logfile group 组号
若崩溃的重做日志已不能归档,可以使用unarchived关键字避免对它们进行归档。

3、其它常见问题
查看表占用的空间:
select owner,table_name,
NUM_ROWS,
BLOCKS*001/1024/1024 “Size M”,
EMPTY_BLOCKS,
LAST_ANALYZED
from dba_tables
where table_name=’XXX’;
Here: 001 is the value of db_block_size ;
XXX is the table name you want to check

查看系统允许的最大会话数:
select * from v$parameter where name like ‘proc%’;
或者:
show parameter processes

查看曾经到达的最大会话数记录(SESSIONS_HIGHWATER)
select * from v$license;

请问如何分辨某个用户是从哪台机器登陆ORACLE的?
SELECT machine , terminal FROM V$SESSION;

查看系统的数据字典
select * from dictionary

查看数据字典的字段备注
select column_name,comments from dict_columns where table_name=’XXXX’;
备注内容不是很全,但总比没有强

查看系统被锁的事务
select * from v$locked_object;

获取正在使用数据库的用户
select username from v$session;

查询用户系统权限
select * from dba_sys_privs where grantee=’HR’

修改表使用的表空间
alter table YOUT_TABLE_NAME move NEW_TABLESPACE_NAME;

修改索引使用的表空间
alter index YOUR_INDEX_NAME rebuild tablespace NEW_TABLESPACE_NAME;

如何解锁?
ALTER SYSTEM KILL SESSION ‘SID,SERIR#’;

Oracle产生随机数的函数
dbms_random.random

查看数据库字符状况?
SELECT * FROM NLS_DATABASE_PARAMETERS;
SELECT * FROM V$NLS_PARAMETERS;

查询表空间信息?
SELECT * FROM DBA_DATA_FILES;

如何给表、列加注释?
comment on table 表 is ‘表注释’;
comment on column 表.列 is ‘列注释’;

如何在字符串里加回车
select ‘我的博客:’||chr(10)||’wallimn.javaeye.com’ from dual

怎幺可以快速做一个和原表一样的备份表?
create table new_table as (select * from old_table);

怎幺在sqlplus下修改procedure?
select line,trim(text) t from user_source
where name =’A’ order by line;

EXP 如何加query参数?
EXP USER/PWD FILE=A.DMP TABLES(BSEMPMS)
QUERY=‘“WHERE EMP_NO=\’S09394\’\”;

如果修改表名?
alter table old_table_name rename to new_table_name;

*****************************************************************************8

相当于alias(别名),比如把user1.table1在user2中建一个同义词table1
create synonym table1 for user1.table1;
这样当你在user2中查select * from table1时就相当于查select * from user1.table1;
优点自己总结吧。

例如:
在oracle中对用户的管理是使用权限的方式来管理的,
也就是说,如果我们想使用数据库,我们就必须得有权限,
但是如果是别人将权限授予了我们,我们也是能对数据库进行操作的,
但是我们必须要已授权的表的名称前键入该表所有者的名称,所以这就是比较麻烦的,
遇到这种情况,我们该怎么办呢?创建个同义词吧!这样我们就可以直接使用同义词来使用表了。

*****************************************************************************8
同义词可分为两种:1)公有同义词。2)私有同义词。
create public synonym 同义词名称 for 数据库对象名;—-公有同义词
create synonym 同义词名称 from 数据库对象;—–私有同义词

*****************************************************************************8
创建了dblink以后就能直接用了,而不必再去创建同义词了,使用方法如下:

select * from pub_employee@连接名

如果查不到数据或者报错的话,那么肯定是数据库链接创建的还有问题了

*****************************************************************************8
Oracle的同义词(2008-09-08 11:41:06)转载标签: 杂谈 分类: Oracle
Oracle中创建同义词语句:
create synonym table_name for user.table_name;
其中第一个user_table和第二个user_table可以不一样。
此外如果要创建一个远程的数据库上的某张表的同义词,需要先创建一个Database Link(数据库连接)来扩展访问,然后在使用如下语句创建数据库同义词:create synonym table_name for table_name@DB_Link;

当然,你可能需要在user用户中给当前用户(user2)授权: grant select/delete/update on user2

创建好同义词之后,你可以对它进行DML(insert,update,delete)操作,当然select语句时肯定支持的。删除同义词:drop synonym table_name;这里的table_name是指同义词的表名。

同义词拥有如下好处:节省大量的数据库空间,对不同用户的操作同一张表没有多少差别;扩展的数据库的使用范围,能够在不同的数据库用户之间实现无缝交互;同义词可以创建在不同一个数据库服务器上,通过网络实现连接。

待研究:不同用户对通一张表操作时,使用锁对多用户的影响,能否使用锁,事务进行操作

查看所有同义词:

  select * from dba_synonyms

在oracle中创建同义词
2008年01月26日 星期六 20:52

我们都知道,在oracle中对用户的管理是使用权限的方式来管理的,也就是说,如果我们想使用数据库,我们就必须得有权限,但是如果是别人将权限授予了我们,我们也是能对数据库进行操作的,但是我们必须要已授权的表的名称前键入该表所有者的名称,所以这就是比较麻烦的,遇到这种情况,我们该怎么办呢?创建个同义词吧!这样我们就可以直接使用同义词来使用表了。

创建同义词的具体语法是:create [public] SYNONYM synooym for object;其中synooym表示要创建的同义词的名称,object表示表,视图,序列等我们要创建同义词的对象的名称。

CREATE PUBLIC SYNONYM public_emp FOR jward.emp; – jward 用户名

删除同义词
使用DROP SYNONYM语句删除不再需要的同义词 要想删除私有同义词 就省略 PUBLIC 关键字要想删除公共同义词就要包括PUBLIC 关键字

DROP SYNONYM emp; –删除名为emp 的私有同义词
DROP PUBLIC SYNONYM public_emp; –删除名为public_emp的公有同义词

Oracle同义词建立方法

作者: ckernel 发布日期: 2006-10-19 查看数:
问题描述:
有两个oralce数据库
SID分别为 A B
A中a用户下含有表objects
B中含有b用户
使在B中用b用户登录后执行
select * from objects
能显示出A中a.objects的全部内容

问题解答:
用b用户登录到B中,执行:
create public synonym objects for a.objects@A
此时执行select * from objects 就能显示出a.objects的全部内容

需要注意的一点:
B中不能含有table b.objects否则语句可以执行,但是执行select操作时显示的仍然为b.objects的内容,
需要先把b.objects删除掉,重新建立synonym即可。

*****************************************************************************8

 <statement name="cudMessageKo">

MERGE INTO MESSAGE_KO A
USING (SELECT ${message}  AS MESSAGE,
              ${code}     AS CODE
         FROM DUAL) B
ON (A.CODE = B.CODE)
WHEN MATCHED THEN
   UPDATE
   SET MESSAGE = B.MESSAGE
WHEN NOT MATCHED THEN
  INSERT(
          CODE,
          MESSAGE
        )
  VALUES(
          B.CODE,
          B.MESSAGE
        )

参考Oracle 的SQL Reference,可以看到Merge Statement的语法如下:
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;

作用:merge into 解决用B表跟新A表数据,如果A表中没有,则把B表的数据插入A表;当处理大数据量是,该方法的效率很高。
语法:
MERGE INTO [your table-name] [rename your table here]
USING ( [write your query here] )[rename your query-sql and using just like a table]
ON ([conditional expression here] AND […]…)
WHEN MATHED THEN [here you can execute some update sql or something else ]
WHEN NOT MATHED THEN [execute something else here ! ]

实例:

例如:SQL>
merge into acct a
using subs b
on (a.msid = b.msid)
when MATCHED then
update set a.areacode = b.areacode
when NOT MATCHED then
insert
(msid, bill_month, areacode)
values
(b.msid, ‘200702’, b.areacode);

*****************************************************************************8
SELECT t.approver_id,
a.user_name approver_nm,
t.appr_row_no appr_row_no
FROM cdms_appr_dtl t,
sys_user_inf a
WHERE t.doc_app_no = docAppNoANDt.apprrowno=(SELECTMAX(t.apprrowno)+1nextrownoFROMcdmsapprdtltWHEREt.docappno= d o c A p p N o A N D t . a p p r r o w n o = ( S E L E C T M A X ( t . a p p r r o w n o ) + 1 n e x t r o w n o F R O M c d m s a p p r d t l t W H E R E t . d o c a p p n o = {docAppNo}
AND t.approver_id = ${approverId})
AND t.approver_id = a.user_id(+)

*****************************************************************************8
Oracle的instr函数
文章分类:数据库
1.instr

在Oracle/PLSQL中,instr函数返回要截取的字符串在源字符串中的位置。

语法如下:instr( string1, string2 [, start_position [, nth_appearance ] ] )

string1 源字符串,要在此字符串中查找。

string2 要在string1中查找的字符串.

start_position 代表string1 的哪个位置开始查找。此参数可选,如果省略默认为1. 字符串索引从1开始。如果此参数为正,从左到右开始检索,如果此参数为负,从右到左检索,返回要查找的字符串在源字符串中的开始索引。

nth_appearance 代表要查找第几次出现的string2. 此参数可选,如果省略,默认为 1.如果为负数系统会报错。

注意:

如果String2在String1中没有找到,instr函数返回0.

应用于:

Oracle 8i, Oracle 9i, Oracle 10g, Oracle 11g
举例说明:

select instr(‘abc’,’a’) from dual; – 返回 1
select instr(‘abc’,’bc’) from dual; – 返回 2
select instr(‘abc abc’,’a’,1,2) from dual; – 返回 5
select instr(‘abc’,’bc’,-1,1) from dual; – 返回 2
select instr(‘abc’,’d’) from dual; – 返回 0

注:也可利用此函数来检查String1中是否包含String2,如果返回0表示不包含,否则表示包含。

*****************************************************************************8
oracle截取字符串

select k(字段,1,INSTR(字段,’/’)-1)
from dual

例如
select Substr(‘sdhfuiasdh/asdfsadf’,1,INSTR(‘sdhfuiasdh/asdfsadf’,’/’)-1)
from dual

执行
SELECT CASE
WHEN INSTR(WH_CD, ‘+’, 1, 1) > 0
THEN SUBSTR(WH_CD, 1, INSTR(WH_CD, ‘+’, 1, 1) - 1)
ELSE WH_CD
END AS WH_CD
FROM T_RCV_ISSUE

结果:MR-PS,MR-WS,MR-WS,MR-PS

select t.model_suffix,
substr(t.model_suffix, 1, INSTR(t.model_suffix, ‘.’) - 1) model,
substr(t.model_suffix,
INSTR(t.model_suffix, ‘.’) + 1,
length(t.model_suffix)) suffix
from aaa_test2 t;

*****************************************************************************8
CREATE OR REPLACE VIEW V_CDMS_MASTER_SNSHOP AS
SELECT SNSHOP.SHOP_CD,
SNSHOP.SHOP_DESC,
SNBRANCH.BRANCH_CD SN_BRANCH_CD,
SNBRANCH.BRANCH_NM SN_BRANCH_NM,
SNDIV.CD_CODE SN_DIV_CD,
SNDIV.DESC_LOC SN_DIV_NM,
SHIP.CUST_CD SHIP_TO,
SHIP.SHORT_NAME SHIP_TO_NM,
SHIP.FULL_NAME SHIP_TO_FULLNM,
BILL.CUST_CD BILL_TO,
BILL.SHORT_NAME BILL_TO_NM,
BILL.FULL_NAME BILL_TO_FULLNM,
DEPT.DIV_CD,
DEPT.DEPT_CD,
DEPT.DEPT_NAME,
SNSHOP.PARENT_DC
FROM CDMS_BRANCH_SN SNBRANCH,
CDMS_SHOP_SN SNSHOP,
CDMS_CCUST SHIP,
CDMS_CCUST BILL,
CDMS_COMM_CD SNDIV,
CDMS_DEPARTMENT DEPT
WHERE SNBRANCH.BRANCH_CD = SNSHOP.BRANCH_CD
AND SNSHOP.SHIP_TO = SHIP.CUST_CD
AND SHIP.CUST_CD = SHIP.SHIP_TO
AND BILL.CUST_CD = BILL.BILL_TO
AND SHIP.BILL_TO = BILL.CUST_CD
AND SNDIV.CD_CLASS = ‘SN_DIV’
AND SNDIV.CD_CODE = SNBRANCH.BRANCH_DIV_CD
AND SHIP.DEPT_CD = DEPT.DEPT_CD
AND NVL(SNSHOP.USE_FLAG,’Y’) = ‘Y’;

*****************************************************************************8

ORA-01691 unable to extend lob segment
表空间不够,需要扩容

*****************************************************************************8

创建同义词 步骤:
想要在cdms用户下,使用Lgespm用户 下的表

01.首先在需要真实查询的用户Lgespm下的数据库 为待查询的CDMS数据库 增加权限

– Grant/Revoke object privileges
grant select on SPMS_PRPS_MASTER to CDMS;

  1. 在待查询的数据库增加同义词
    – Create the synonym
    create or replace synonym CDMS_PRPS_MASTER
    for LGESPM.SPMS_PRPS_MASTER;

*****************************************************************************8
SQL 按月统计(2009-08-12 23:32:40)转载标签: sql按月统计oracleit 分类: Oracle
前提:
created_date 是 表 A 的一个日期字段
1、按月分组统计 (1\2\3\4等自然月统计)
select sum(quantity) from A group by trunc(created_date,‘mm’);
用 trunc 函数 将日期转化为 每个月的第一天(或者说是忽略月(mm)后面得日期);

2、如果 需求是要 按 每个月 的25号来划分的话(实际经常碰到)
select sum(quantity) from A
group by trunc(created_date+(add_months(created_date,1)-created_date-20),’mm’);
20 的作用是 每个月按20号 分割月之间 如果是按每个月的15号分割
那么 20 的位置就是15;
蓝色字体的意思是求得 所给日期 created_date 所在月的天数;
减去20 是求得 还需要 再加上 多少天就到下个月了;
*****************************************************************************8
sql 按字段日期拆分
一个表里面的数据 有一个

id 开始时间 结束时间

1 2009-12-01 11:31:40 2009-12-05 11:31:46
sql 怎么拆分成
1 2009-12-01 11:31:40
1 2009-12-02 11:31:40
1 2009-12-03 11:31:40
1 2009-12-04 11:31:40
1 2009-12-05 11:31:40

回答人的补充 2009-12-15 14:40

declare @Day int,@i int,@BeginTime Datetime,@EndTime Datetime
set @BeginTime=’2009-11-11’ –这里换成你的开始时间
set @EndTime=’2009-11-15’ –这里换成你的结束时间
select @Day=datediff(d,@BeginTime,@EndTime)
set @i=0
while @i<@Day+1
begin
select Dateadd(d,@i,@BeginTime)
set @i = @i +1
end

拆分转置:
原始:’aassa 2222 333’
转置之后:’aassa’
‘2222’
‘333’

SELECT DISTINCT REGEXP_SUBSTR (REPLACE(‘aassa 2222 333’, ’ ‘, ‘,’),’[^,]+’,1,LEVEL) as “token”
FROM DUAL
CONNECT BY REGEXP_SUBSTR (REPLACE(‘aassa 2222 333’, ’ ‘, ‘,’),’[^,]+’,1,LEVEL) IS NOT NULL
order by 1

*****************************************************************************8
SELECT *,
IF(b.id <= HOUR(a.StartTime) OR (b.id > HOUR(a.StartTime) AND b.id < HOUR(a.StopTime))
,CAST(CONCAT(DATE(a.StartTime),’ ‘,b.id + 1,’:00:00’) AS DATETIME)
,IF(b.id = HOUR(a.StopTime),(a.StopTime),CAST(CONCAT(DATE(a.StartTime),’ ‘,b.id,’:00:00’) AS DATETIME))) AS newstop,

   IF(b.id <= HOUR(a.StartTime),a.StartTime,IF(b.id > HOUR(a.StartTime) AND b.id < HOUR(a.StopTime),
   CAST(CONCAT(DATE(a.StartTime),' ',b.id,':00:00') AS DATETIME),IF(b.id = HOUR(a.StopTime),
   CAST(CONCAT(DATE(a.StartTime),' ',b.id,':00:00') AS DATETIME),b.id))) AS newstart

FROM ttf a
LEFT JOIN zz.lsb1 b ON b.id BETWEEN HOUR(a.StartTime)
AND HOUR(a.StopTime)

*****************************************************************************8
One Row:001 2003.10.11 ~ 2004,02.05
===》
N Rows:
001 2003.10
001 2003.11
001 2003.12
001 2004.01
001 2004.02
001 2004.03

年份,期间,查询,行转列
解决方法:
查询日期期间所有日期
oracle:
SELECT to_char(a.everyDay,’YYYYMM’) yyyymm
FROM (
SELECT add_months(to_date(‘200611’,’yyyymm’), LEVEL-1) AS everyDay
FROM dual
CONNECT BY LEVEL <= Months_between(to_date(‘200711’,’yyyymm’) , to_date(‘200611’,’yyyymm’) )+1
)a
;

SELECT TO_CHAR(ADD_MONTHS(TO_DATE(‘201404’, ‘YYYYMM’), ROWNUM - 1),’YYYYMM’) MONTH_ID
FROM DUAL
CONNECT BY ROWNUM <=
months_between(to_date(‘201504’, ‘yyyymm’),to_date(‘201404’, ‘yyyymm’)) + 1
;

SELECT ROWNUM
,TO_CHAR(ADD_MONTHS(TO_DATE( ‘201403’,’YYYYMM’),DECODE(ROWNUM,0,0,-(11-ROWNUM))),’MM’) format_month
,TO_CHAR(ADD_MONTHS(TO_DATE( ‘201403’,’YYYYMM’),DECODE(ROWNUM,0,0,-(11-ROWNUM))),’YYYYMM’) full_format_month
FROM TB_COM_CODE
WHERE ROWNUM < 12
ORDER BY 1
1 1 05 201305
2 2 06 201306
3 3 07 201307
4 4 08 201308
5 5 09 201309
6 6 10 201310
7 7 11 201311
8 8 12 201312
9 9 01 201401
10 10 02 201402
11 11 03 201403
DB2:
WITH n(level, mdate) AS
(SELECT 1, to_char(date(‘2009-01-01’),’YYYY-MM-DD’) as mdate
FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT n.level + 1, to_char(ADD_MONTHS(n.mdate,1),’YYYY-MM-DD’)
FROM SYSIBM.SYSDUMMY1 as nplus1, n
WHERE MONTHS_BETWEEN(date(‘2011-11-01’),date(n.mdate))>0
)
SELECT level, to_char(mdate,’YYYYMM’) FROM n;

select 001,substr(日期,‘YYYY.MM’),count(*)
where * = 001 and ***date between ‘2003.10.11’ and 2004.02.05
group by 001,substr(日期,‘YYYY.MM’)

将一行数据根据空格拆分成多行
SELECT TMP.SUBSTITUDE_PART_NO SUBSTITUDE_PART_NO
FROM (SELECT DISTINCT REGEXP_SUBSTR(REPLACE(‘011133005106 011133005106 194712007830 192512018870 R193616000010’, ’ ‘, ‘,’), ‘[^,]+’, 1, LEVEL) AS SUBSTITUDE_PART_NO
FROM DUAL
CONNECT BY REGEXP_SUBSTR(REPLACE(‘011133005106 011133005106 194712007830 192512018870 R193616000010’, ’ ‘, ‘,’), ‘[^,]+’, 1, LEVEL) IS NOT NULL
ORDER BY 1) TMP;

结果:
011133005106
192512018870
194712007830
R193616000010

*****************************************************************************8
年月日:日期期间:
SELECT *
FROM (SELECT TO_DATE(‘20061101’, ‘yyyymmdd’) + LEVEL - 1 AS EVERYDAY
FROM DUAL
CONNECT BY LEVEL <= (TO_DATE(‘20071201’, ‘yyyymmdd’) - TO_DATE(‘20061101’, ‘yyyymmdd’) + 1));


日期期间 整月
select * from ( select to_date(‘20061101’,’yyyymmdd’) + level - 1 as everyDay from dual
connect by level <=
(last_day(to_date(‘20061101’,’yyyymmdd’)) - to_date(‘20061101’,’yyyymmdd’) +1));

日期期间
SELECT ROWNUM
,TO_CHAR(ADD_MONTHS(TO_DATE( ‘201403’,’YYYYMM’),DECODE(ROWNUM,0,0,-(11-ROWNUM))),’MM’) format_month
,TO_CHAR(ADD_MONTHS(TO_DATE( ‘201403’,’YYYYMM’),DECODE(ROWNUM,0,0,-(11-ROWNUM))),’YYYYMM’) full_format_month
FROM TB_COM_CODE
WHERE ROWNUM < 12
ORDER BY 1

日期期间:
获取某个月的所有天数
SELECT TO_CHAR(trunc(add_months(last_day(SYSDATE), -1) + 1) + ROWNUM - 1, ‘YYYYMMDD’) dt_id
FROM DUAL
CONNECT BY ROWNUM <= last_day(SYSDATE) - trunc(add_months(last_day(SYSDATE), -1) + 1) + 1;


http://www.baidu.com/s?bs=sql+%C8%D5%C0%FA&f=8&wd=oralce+sql+%C8%D5%C0%FA

*****************************************************************************8
WITH n(level, empid, name) AS
(SELECT 1, empid, name
FROM emp
WHERE name = ‘Goyal’
UNION ALL
SELECT n.level + 1, nplus1.empid, nplus1.name
FROM emp as nplus1, n
WHERE n.empid = nplus1.mgrid)
SELECT level, name FROM n;

WITH n(level, mdate) AS
(SELECT 1, to_char(date(‘2009-01-01’),’YYYY-MM-DD’) as mdate
FROM SYSIBM.SYSDUMMY1
UNION ALL
SELECT n.level + 1, to_char(ADD_MONTHS(n.mdate,1),’YYYY-MM-DD’)
FROM SYSIBM.SYSDUMMY1 as nplus1, n
WHERE MONTHS_BETWEEN(date(‘2011-11-01’),date(n.mdate))>0
)
SELECT level, to_char(mdate,’YYYYMM’) FROM n;

select to_char(date(‘2008-01-08’),’YYYYMM’) from SYSIBM.SYSDUMMY1;
select date(‘2008-05-08’)-date(‘2008-01-08’) from SYSIBM.SYSDUMMY1;

select MONTHS_BETWEEN(date(‘2011-11-08’),date(‘2009-01-12’)) from SYSIBM.SYSDUMMY1;

select ADD_MONTHS(‘2008-05-08’,5)from SYSIBM.SYSDUMMY1;
select ADD_MONTHS(‘20080508’,5)from SYSIBM.SYSDUMMY1;

*****************************************************************************8
SELECT ‘LG-SU660’ model_name
,MAX(temp3.max_value) AS max_value
,MAX(temp3.sw_confirm) AS sw_confirm
,MAX(temp3.bug_clear) AS bug_clear
FROM (SELECT t.maturity_level_index || ‘(’ || MIN(t.maturity_week) || ‘W)’ AS max_value
,” AS sw_confirm
,” AS bug_clear
FROM svms_mgr.tb_maturity_index t
WHERE t.maturity_level_index =
(SELECT MAX(t.maturity_level_index)
FROM svms_mgr.tb_maturity_index t
WHERE 1 = 1
AND t.model_name = ‘LG-SU660’ AND t.buyer_id = ‘41’ )
AND t.model_name = ‘LG-SU660’ AND t.buyer_id = ‘41’
GROUP BY t.maturity_level_index
UNION ALL
SELECT ” AS max_value
,t.maturity_level_index || ‘(’ || temp2.week || ‘W)’ AS sw_confirm
,” AS bug_clear
FROM svms_mgr.tb_maturity_index t
,(SELECT temp.td_event
,temp.step
,MAX(t2.maturity_week) AS week
FROM (SELECT t.td_event
,MAX(t.td_step) AS step
FROM svms_mgr.tb_maturity_index t
WHERE 1 = 1
AND t.model_name = ‘LG-SU660’ AND t.buyer_id = ‘41’
GROUP BY t.td_event) temp
,svms_mgr.tb_maturity_index t2
WHERE 1 = 1
AND temp.td_event = ‘SW’
AND temp.td_event = t2.td_event
AND t2.td_step = temp.step
GROUP BY temp.td_event
,temp.step) temp2
WHERE temp2.td_event = t.td_event
AND temp2.step = t.td_step
AND temp2.week = t.maturity_week
UNION ALL
SELECT ” AS max_value
,” AS sw_confirm
,’0 (’ || CASE COUNT(*)
WHEN 0 THEN
0
ELSE
MIN(t.maturity_week)
END || ‘W)’ AS bug_clear
FROM svms_mgr.tb_maturity_index t
WHERE 1 = 1
AND t.model_name = ‘LG-SU660’ AND t.buyer_id = ‘41’
AND t.in_flow_total = ‘0’) temp3

*****************************************************************************8
当查询结果为0 ,则也显示一行记录,对应值为零
SELECT ” AS max_value
,” AS sw_confirm
,’0 (’ || CASE COUNT(*)
WHEN 0 THEN
0
ELSE
MIN(t.maturity_week)
END || ‘W)’ AS bug_clear
FROM svms_mgr.tb_maturity_index t
WHERE 1 = 1
AND t.model_name = ‘LG-SU660’ AND t.buyer_id = ‘41’
AND t.in_flow_total = ‘0’

*****************************************************************************8
DEVy_11=CSTMT.E Laptime : 23
DEVy_11={call PKG_OSMS_GEN_KPI.MAIN( ‘201145’
DEVy_11= , ‘10001211’,’admin’
DEVy_11= , ‘sqlType:Types.VARCHAR’
DEVy_11= , ‘sqlType:Types.VARCHAR’
DEVy_11= )}
[FRM_DAO_007] devonframework.persistent.autodao.procedure.LStandardStoredProcedure-execute(LCommonDao dao, CallableStatement cstmt) ? Error occurred while executing Stored Procedure or getting results. : java.sql.SQLException: ORA-06550: 第 1 行, 第 7 列:
PLS-00306: 调用 ‘MAIN’ 时参数个数或类型错误
ORA-06550: 第 1 行, 第 7 列:
PL/SQL: Statement ignored

  {call PKG_OSMS_GEN_KPI.MAIN( ?
                             , ?,?
                             , ?  
                             , ?
                             )} 

parameter : [201145, 10001211, admin, null, null]

osms.smReport.weeklyRpt.biz.WeeklyReportBiz.createWeeklyReportDo()=>Error occurred while executing Stored Procedure or getting results. : java.sql.SQLException: ORA-06550: 第 1 行, 第 7 列:
PLS-00306: 调用 ‘MAIN’ 时参数个数或类型错误
ORA-06550: 第 1 行, 第 7 列:
PL/SQL: Statement ignored

*****************************************************************************8
【TRUNC】使用TRUNC函数完成对时间的截取
上一篇 / 下一篇 2010-03-30 23:27:10 / 个人分类:SQL

查看( 553 ) / 评论( 1 ) / 评分( 0 / 0 )
使用TRUNC函数可以完成时间的截取功能。

1.设置一下时间的显示样式
sec@secooler> alter session set NLS_DATE_FORMAT=’YYYY-MM-DD HH24:MI:SS’;

Session altered.

2.以系统时间为例,查看当前时间
sys@secooler> select sysdate from dual;

SYSDATE

2010-03-31 00:22:48

3.不使用参数表示截取到日
sys@secooler> select trunc(sysdate) trunc_default from dual;

TRUNC_DEFAULT

2010-03-31 00:00:00

4.截取到年
以下八种方法都可以完成截取到年的功能。
sys@secooler> select trunc(sysdate,’YEAR’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

sys@secooler> select trunc(sysdate,’SYYYY’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

sys@secooler> select trunc(sysdate,’YYYY’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

sys@secooler> select trunc(sysdate,’SYEAR’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

sys@secooler> select trunc(sysdate,’YYY’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

sys@secooler> select trunc(sysdate,’YYY’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

sys@secooler> select trunc(sysdate,’YY’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

sys@secooler> select trunc(sysdate,’Y’) trunc_year from dual;

TRUNC_YEAR

2010-01-01 00:00:00

5.截取到月
以下四种方法都可以完成截取到月的功能。
sys@secooler> select trunc(sysdate,’MONTH’) trunc_mounth from dual;

TRUNC_MOUNTH

2010-03-01 00:00:00

sys@secooler> select trunc(sysdate,’MON’) trunc_mounth from dual;

TRUNC_MOUNTH

2010-03-01 00:00:00

sys@secooler> select trunc(sysdate,’MM’) trunc_mounth from dual;

TRUNC_MOUNTH

2010-03-01 00:00:00

sys@secooler> select trunc(sysdate,’RM’) trunc_mounth from dual;

TRUNC_MOUNTH

2010-03-01 00:00:00

6.截取到日
以下三种方法都可以完成截取到日的功能。
sys@secooler> select trunc(sysdate,’DDD’) trunc_day from dual;

TRUNC_DAY

2010-03-31 00:00:00

sys@secooler> select trunc(sysdate,’DD’) trunc_day from dual;

TRUNC_DAY

2010-03-31 00:00:00

sys@secooler> select trunc(sysdate,’J’) trunc_day from dual;

TRUNC_DAY

2010-03-31 00:00:00

7.截取到小时
以下三种方法都可以完成截取到小时的功能。
sys@secooler> select trunc(sysdate,’HH’) trunc_hour from dual;

TRUNC_HOUR

2010-03-31 00:00:00

sys@secooler> select trunc(sysdate,’HH12’) trunc_hour from dual;

TRUNC_HOUR

2010-03-31 00:00:00

sys@secooler> select trunc(sysdate,’HH24’) trunc_hour from dual;

TRUNC_HOUR

2010-03-31 00:00:00

8.截取到分钟
sys@secooler> select trunc(sysdate,’MI’) trunc_minute from dual;

TRUNC_MINUTE

2010-03-31 00:22:00

9.trunc应用–解决因时分秒不同导致无返回记录的问题
sys@secooler> create table t (x date,y timestamp);

Table created.

sys@secooler> insert into t values (sysdate,sysdate);

1 row created.

sys@secooler> update t set y=sysdate;

1 row updated.

sys@secooler> commit;

Commit complete.

sys@secooler> select * from t;

X Y


2010-03-31 00:31:20 31-MAR-10 12.31.28.000000 AM

此时我们如果直接查询x与y相等的记录是没有返回结果的。
sys@secooler> select * from t where x = y;

no rows selected

如果我们同时使用trunc截取到天,结果将不同
sys@secooler> select * from t where trunc(x,’DD’)=trunc(y,’DD’);

X Y


2010-03-31 00:31:20 31-MAR-10 12.31.28.000000 AM

10.小结
在Oracle数据中日期的操作相对复杂,如果可以善加利用与日期相关的函数,便会达到事半功倍的效果。

Good luck.

secooler
10.03.30

– The End –

*****************************************************************************8
根据某个表数据修改数据
update spms_shop_dtl d
set d.shop_grade =
(select t.shop_level_new
from shop_level_update_2012 t
where d.shop_cd = t.shop_cd)
where d.shop_cd in (select a.shop_cd from shop_level_update_2012 a);

修改channel_grade
UPDATE spms_shop_dtl t
SET t.channel_grade = (SELECT t2.channel_grade FROM test03 t2 WHERE t2.shop_cd = t.shop_cd)
WHERE t.shop_cd IN (SELECT t3.shop_cd FROM test03 t3);
*****************************************************************************8
UPDATE spms_shop_dtl t
SET t.channel_grade = ”
WHERE NOT EXISTS (SELECT t2.shop_cd FROM test03 t2 WHERE t2.shop_cd = t.shop_cd)
AND t.shop_cd IN (SELECT t1.shop_cd
FROM spms_shop_mst t1,
spms_shop_dtl t2
WHERE t1.shop_cd = t2.shop_cd
AND t1.com_cd = t2.com_cd
AND t1.use_flag = ‘Y’)

*****************************************************************************8
job 备份
begin
sys.dbms_job.submit(job => :job,
what => ‘pro_plan_job;’,
next_date => to_date(‘06-03-2012 17:33:11’, ‘dd-mm-yyyy hh24:mi:ss’),
interval => ‘sysdate+2/1440’);
commit;
end;

/

begin
sys.dbms_job.submit(job => :job,
what => ‘PK_EZS_AG_DATA.main();’,
next_date => to_date(‘06-03-2012 17:39:56’, ‘dd-mm-yyyy hh24:mi:ss’),
interval => ‘sysdate+10/1440’);
commit;
end;
/

*****************************************************************************8
比如现在有一人员表 (表名:peosons)
若想将姓名、身份证号、住址这三个字段完全相同的记录查询出来
select p1.*
from persons p1,persons p2
where p1.id<>p2.id
and p1.cardid = p2.cardid and p1.pname = p2.pname and p1.address = p2.address

可以实现上述效果.

几个删除重复记录的SQL语句

1.用rowid方法

2.用group by方法

3.用distinct方法

1。用rowid方法

据据oracle带的rowid属性,进行判断,是否存在重复,语句如下:

查数据:

 select * from table1 a where rowid !=(select max(rowid) 
 from table1 b where a.name1=b.name1 and a.name2=b.name2......)

删数据:

delete  from table1 a where rowid !=(select max(rowid) 
from table1 b where a.name1=b.name1 and a.name2=b.name2......)

2.group by方法

查数据:

  select count(num), max(name) from student –列出重复的记录数,并列出他的name属性
  group by num
  having count(num) >1 –按num分组后找出表中num列重复,即出现次数大于一次

删数据:

  delete from student
  group by num
  having count(num) >1
  这样的话就把所有重复的都删除了。

3.用distinct方法 -对于小的表比较有用

create table table_new as select distinct * from table1 minux
truncate table table1;
insert into table1 select * from table_new;

查询及删除重复记录的方法大全

1、查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断
select * from people
where peopleId in (select peopleId from people group by peopleId having count(peopleId) > 1)

2、删除表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断,只留有rowid最小的记录
delete from people
where peopleId in (select peopleId from people group by peopleId
having count(peopleId) > 1)
and rowid not in (select min(rowid) from people group by peopleId having count(peopleId )>1)

3、查找表中多余的重复记录(多个字段)
select * from vitae a
where (a.peopleId,a.seq) in (select peopleId,seq from vitae group by peopleId,seq having count(*) > 1)

4、删除表中多余的重复记录(多个字段),只留有rowid最小的记录
delete from vitae a
where (a.peopleId,a.seq) in (select peopleId,seq from vitae group by peopleId,seq having count(*) > 1)
and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)>1)

5、查找表中多余的重复记录(多个字段),不包含rowid最小的记录
select * from vitae a
where (a.peopleId,a.seq) in (select peopleId,seq from vitae group by peopleId,seq having count(*) > 1)
and rowid not in (select min(rowid) from vitae group by peopleId,seq having count(*)>1)

(二)
比方说
在A表中存在一个字段“name”,
而且不同记录之间的“name”值有可能会相同,
现在就是需要查询出在该表中的各记录之间,“name”值存在重复的项;
Select Name,Count() From A Group By Name Having Count() > 1
如果还查性别也相同大则如下:
Select Name,sex,Count() From A Group By Name,sex Having Count() > 1

(三)
方法一
declare @max integer,@id integer
declare cur_rows cursor local for select 主字段,count() from 表名 group by 主字段 having count() >; 1
open cur_rows
fetch cur_rows into @id,@max
while @@fetch_status=0
begin
select @max = @max -1
set rowcount @max
delete from 表名 where 主字段 = @id
fetch cur_rows into @id,@max
end
close cur_rows
set rowcount 0

方法二
"重复记录"有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,
比如Name字段重复,而其他字段不一定重复或都重复可以忽略。

1、对于第一种重复,比较容易解决,使用
select distinct * from tableName就可以得到无重复记录的结果集。
如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除
select distinct * into #Tmp from tableName
drop table tableName
select * into tableName from #Tmp
drop table #Tmp
发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决。

2、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下
假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集
select identity(int,1,1) as autoID, * into #Tmp from tableName
select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID
select * from #Tmp where autoID in(select autoID from #tmp2)
  最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)

(四)
查询重复
select * from tablename where id in (
select id from tablename
group by id
having count(id) > 1
)

例子
delete from w_m_mjout where ksid in
(select ksid from tableName group by ksid HAVING COUNT(ksid)>1)
and rowid not in (select min(ROWID) from tableName group by ksid HAVING COUNT(ksid)>1)

*****************************************************************************8
查询重复信息:
select t.*
from mob_ag_basic_promoter_inf t
where t.rowId <> (select min(t2.rowId)
from mob_ag_basic_promoter_inf t2
where t2.agent_promoter_code = t.agent_promoter_code
and t2.agent_code = ‘ASD’)

删除重复信息:(适合较大数据量)
delete from mob_ag_basic_shop_inf t
where t.agent_shop_code in (select t1.agent_shop_code
from mob_ag_basic_shop_inf t1
where t1.agent_code = ‘ASD’
group by t1.agent_shop_code
having count(1) > 1)
and rowId not in (select min(rowId)
from mob_ag_basic_shop_inf t2
where t2.agent_code = ‘ASD’
group by t2.agent_shop_code
having count(1) > 1)
;
*****************************************************************************8
Oracle截取字符串和查找字符串
oracle 截取字符(substr),检索字符位置(instr) case when then else end语句使用 收藏
常用函数:substr和instr
1.SUBSTR(string,start_position,[length]) 求子字符串,返回字符串
解释:string 元字符串
start_position 开始位置(从0开始)
length 可选项,子字符串的个数
For example:
substr(“ABCDEFG”, 0); //返回:ABCDEFG,截取所有字符
substr(“ABCDEFG”, 2); //返回:CDEFG,截取从C开始之后所有字符
substr(“ABCDEFG”, 0, 3); //返回:ABC,截取从A开始3个字符
substr(“ABCDEFG”, 0, 100); //返回:ABCDEFG,100虽然超出预处理的字符串最长度,但不会影响返回结果,系统按预处理字符串最大数量返回。
substr(“ABCDEFG”, 0, -3); //返回:EFG,注意参数-3,为负值时表示从尾部开始算起,字符串排列位置不变。

2.INSTR(string,subString,position,ocurrence)查找字符串位置
解释:string:源字符串
subString:要查找的子字符串
position:查找的开始位置
ocurrence:源字符串中第几次出现的子字符串
For example:
INSTR(‘CORPORATE FLOOR’,’OR’, 3, 2)中,源字符串为’CORPORATE FLOOR’, 目标字符串为’OR’,起始位置为3,取第2个匹配项的位置;返回结果为 14 ‘

*****************************************************************************8
Oracle 函数大全(字符串函数,数学函数,日期函数,逻辑运算函数,其他函数)
关键词: Oracle函数 字符串函数 数学函数 日期函数 逻辑运算函数

SQL中的单记录函数
1.ASCII
返回与指定的字符对应的十进制数;
SQL> select ascii(’A’) A,ascii(’a’) a,ascii(’0’) zero,ascii(’ ’) space from dual;
A A ZERO SPACE


65 97 48 32

2.CHR
给出整数,返回对应的字符;
SQL> select chr(54740) zhao,chr(65) chr65 from dual;
ZH C


赵 A
3.CONCAT
连接两个字符串;
SQL> select concat(’010-’,’88888888’)||’转23’ 高乾竞电话 from dual;

高乾竞电话

010-88888888转23
4.INITCAP
返回字符串并将字符串的第一个字母变为大写;
SQL> select initcap(’smith’) upp from dual;

UPP

Smith

5.INSTR(C1,C2,I,J)
在一个字符串中搜索指定的字符,返回发现指定的字符的位置;
C1 被搜索的字符串
C2 希望搜索的字符串
I 搜索的开始位置,默认为1
J 出现的位置,默认为1
SQL> select instr(’oracle traning’,’ra’,1,2) instring from dual;

INSTRING

9

6.LENGTH
返回字符串的长度;
SQL> select name,length(name),addr,length(addr),sal,length(to_char(sal)) from gao.nchar_tst;
NAME LENGTH(NAME) ADDR LENGTH(ADDR) SAL LENGTH(TO_CHAR(SAL))


高乾竞 3 北京市海锭区 6 9999.99 7

7.LOWER
返回字符串,并将所有的字符小写
SQL> select lower(’AaBbCcDd’)AaBbCcDd from dual;

AABBCCDD

aabbccdd

8.UPPER
返回字符串,并将所有的字符大写
SQL> select upper(’AaBbCcDd’) upper from dual;

UPPER

AABBCCDD

9.RPAD和LPAD(粘贴字符)
RPAD 在列的右边粘贴字符
LPAD 在列的左边粘贴字符
SQL> select lpad(rpad(’gao’,10,’’),17,’’)from dual;

LPAD(RPAD(’GAO’,1

**gao**
不够字符则用*来填满

10.LTRIM和RTRIM
LTRIM 删除左边出现的字符串
RTRIM 删除右边出现的字符串
SQL> select ltrim(rtrim(’ gao qian jing ’,’ ’),’ ’) from dual;

LTRIM(RTRIM(’

gao qian jing

11.SUBSTR(string,start,count)
取子字符串,从start开始,取count个
SQL> select substr(’13088888888’,3,8) from dual;

SUBSTR(’

08888888

12.REPLACE(’string’,’s1’,’s2’)
string 希望被替换的字符或变量
s1 被替换的字符串
s2 要替换的字符串
SQL> select replace(’he love you’,’he’,’i’) from dual;

REPLACE(’H

i love you

13.SOUNDEX
返回一个与给定的字符串读音相同的字符串
SQL> create table table1(xm varchar(8));
SQL> insert into table1 values(’weather’);
SQL> insert into table1 values(’wether’);
SQL> insert into table1 values(’gao’);
SQL> select xm from table1 where soundex(xm)=soundex(’weather’);

XM

weather
wether

14.TRIM(’s’ from ’string’)
LEADING 剪掉前面的字符
TRAILING 剪掉后面的字符
如果不指定,默认为空格符
15.ABS
返回指定值的绝对值
SQL> select abs(100),abs(-100) from dual;
ABS(100) ABS(-100)


100 100

16.ACOS
给出反余弦的值
SQL> select acos(-1) from dual;

ACOS(-1)

3.1415927

17.ASIN
给出反正弦的值
SQL> select asin(0.5) from dual;

ASIN(0.5)

.52359878

18.ATAN
返回一个数字的反正切值
SQL> select atan(1) from dual;

ATAN(1)

.78539816

19.CEIL
返回大于或等于给出数字的最小整数
SQL> select ceil(3.1415927) from dual;

CEIL(3.1415927)

4

20.COS
返回一个给定数字的余弦
SQL> select cos(-3.1415927) from dual;

COS(-3.1415927)

-1
21.COSH
返回一个数字反余弦值
SQL> select cosh(20) from dual;

COSH(20)

242582598

22.EXP
返回一个数字e的n次方根
SQL> select exp(2),exp(1) from dual;
EXP(2) EXP(1)


7.3890561 2.7182818

23.FLOOR
对给定的数字取整数
SQL> select floor(2345.67) from dual;

FLOOR(2345.67)

2345

24.LN
返回一个数字的对数值
SQL> select ln(1),ln(2),ln(2.7182818) from dual;
LN(1) LN(2) LN(2.7182818)


0 .69314718 .99999999

25.LOG(n1,n2)
返回一个以n1为底n2的对数
SQL> select log(2,1),log(2,4) from dual;
LOG(2,1) LOG(2,4)


0 2

26.MOD(n1,n2)
返回一个n1除以n2的余数
SQL> select mod(10,3),mod(3,3),mod(2,3) from dual;
MOD(10,3) MOD(3,3) MOD(2,3)


1 0 2

27.POWER
返回n1的n2次方根
SQL> select power(2,10),power(3,3) from dual;
POWER(2,10) POWER(3,3)


1024 27

28.ROUND和TRUNC
按照指定的精度进行舍入
SQL> select round(55.5),round(-55.4),trunc(55.5),trunc(-55.5) from dual;
ROUND(55.5) ROUND(-55.4) TRUNC(55.5) TRUNC(-55.5)


56 -55 55 -55

29.SIGN
取数字n的符号,大于0返回1,小于0返回-1,等于0返回0
SQL> select sign(123),sign(-100),sign(0) from dual;
SIGN(123) SIGN(-100) SIGN(0)


1 -1 0

0 A
100+ B
其他: C
sign(100)+100:
1:101
-1:99
0:100

30.SIN
返回一个数字的正弦值
SQL> select sin(1.57079) from dual;

SIN(1.57079)

1

31.SIGH
返回双曲正弦的值
SQL> select sin(20),sinh(20) from dual;
SIN(20) SINH(20)


.91294525 242582598

32.SQRT
返回数字n的根
SQL> select sqrt(64),sqrt(10) from dual;
SQRT(64) SQRT(10)


8 3.1622777

33.TAN
返回数字的正切值
SQL> select tan(20),tan(10) from dual;
TAN(20) TAN(10)


2.2371609 .64836083

34.TANH
返回数字n的双曲正切值
SQL> select tanh(20),tan(20) from dual;
TANH(20) TAN(20)


1 2.2371609

35.TRUNC
按照指定的精度截取一个数
SQL> select trunc(124.1666,-2) trunc1,trunc(124.16666,2) from dual;
TRUNC1 TRUNC(124.16666,2)


100 124.16

36.ADD_MONTHS
增加或减去月份
SQL> select to_char(add_months(to_date(’199912’,’yyyymm’),2),’yyyymm’) from dual;

TO_CHA

200002
SQL> select to_char(add_months(to_date(’199912’,’yyyymm’),-2),’yyyymm’) from dual;

TO_CHA

199910

37.LAST_DAY
返回日期的最后一天
SQL> select to_char(sysdate,’yyyy.mm.dd’),to_char((sysdate)+1,’yyyy.mm.dd’) from dual;
TO_CHAR(SY TO_CHAR((S


2004.05.09 2004.05.10
SQL> select last_day(sysdate) from dual;

LAST_DAY(S

31-5月 -04

38.MONTHS_BETWEEN(date2,date1)
给出date2-date1的月份
SQL> select months_between(’19-12月-1999’,’19-3月-1999’) mon_between from dual;

MON_BETWEEN

9
SQL>selectmonths_between(to_date(’2000.05.20’,’yyyy.mm.dd’),to_date(’2005.05.20’,’yyyy.mm.dd’)) mon_betw from dual;

MON_BETW

-60

39.NEW_TIME(date,’this’,’that’)
给出在this时区=other时区的日期和时间
SQL> select to_char(sysdate,’yyyy.mm.dd hh24:mi:ss’) bj_time,to_char(new_time
2 (sysdate,’PDT’,’GMT’),’yyyy.mm.dd hh24:mi:ss’) los_angles from dual;
BJ_TIME LOS_ANGLES


2004.05.09 11:05:32 2004.05.09 18:05:32

40.NEXT_DAY(date,’day’)
给出日期date和星期x之后计算下一个星期的日期
SQL> select next_day(’18-5月-2001’,’星期五’) next_day from dual;

NEXT_DAY

25-5月 -01
41.SYSDATE
用来得到系统的当前日期
SQL> select to_char(sysdate,’dd-mm-yyyy day’) from dual;

TO_CHAR(SYSDATE,’

09-05-2004 星期日
trunc(date,fmt)按照给出的要求将日期截断,如果fmt=’mi’表示保留分,截断秒
SQL> select to_char(trunc(sysdate,’hh’),’yyyy.mm.dd hh24:mi:ss’) hh,
2 to_char(trunc(sysdate,’mi’),’yyyy.mm.dd hh24:mi:ss’) hhmm from dual;
HH HHMM


2004.05.09 11:00:00 2004.05.09 11:17:00

42.CHARTOROWID
将字符数据类型转换为ROWID类型
SQL> select rowid,rowidtochar(rowid),ename from scott.emp;
ROWID ROWIDTOCHAR(ROWID) ENAME


AAAAfKAACAAAAEqAAA AAAAfKAACAAAAEqAAA SMITH
AAAAfKAACAAAAEqAAB AAAAfKAACAAAAEqAAB ALLEN
AAAAfKAACAAAAEqAAC AAAAfKAACAAAAEqAAC WARD
AAAAfKAACAAAAEqAAD AAAAfKAACAAAAEqAAD JONES

43.CONVERT(c,dset,sset)
将源字符串 sset从一个语言字符集转换到另一个目的dset字符集
SQL> select convert(’strutz’,’we8hp’,’f7dec’) “conversion” from dual;

conver

strutz

44.HEXTORAW
将一个十六进制构成的字符串转换为二进制

45.RAWTOHEXT
将一个二进制构成的字符串转换为十六进制

46.ROWIDTOCHAR
将ROWID数据类型转换为字符类型

47.TO_CHAR(date,’format’)
SQL> select to_char(sysdate,’yyyy/mm/dd hh24:mi:ss’) from dual;

TO_CHAR(SYSDATE,’YY

2004/05/09 21:14:41

48.TO_DATE(string,’format’)
将字符串转化为ORACLE中的一个日期

49.TO_MULTI_BYTE
将字符串中的单字节字符转化为多字节字符
SQL> select to_multi_byte(’高’) from dual;

TO

50.TO_NUMBER
将给出的字符转换为数字
SQL> select to_number(’1999’) year from dual;

YEAR

1999

51.BFILENAME(dir,file)
指定一个外部二进制文件
SQL>insert into file_tb1 values(bfilename(’lob_dir1’,’image1.gif’));

52.CONVERT(’x’,’desc’,’source’)
将x字段或变量的源source转换为desc
SQL> select sid,serial#,username,decode(command,
2 0,’none’,
3 2,’insert’,
4 3,
5 ’select’,
6 6,’update’,
7 7,’delete’,
8 8,’drop’,
9 ’other’) cmd from v$session where type!=’background’;
SID SERIAL# USERNAME CMD


1 1 none
2 1 none
3 1 none
4 1 none
5 1 none
6 1 none
7 1275 none
8 1275 none
9 20 GAO select
10 40 GAO none

53.DUMP(s,fmt,start,length)
DUMP函数以fmt指定的内部数字格式返回一个VARCHAR2类型的值
SQL> col global_name for a30
SQL> col dump_string for a50
SQL> set lin 200
SQL> select global_name,dump(global_name,1017,8,5) dump_string from global_name;
GLOBAL_NAME DUMP_STRING


ORACLE.WORLD Typ=1 Len=12 CharacterSet=ZHS16GBK: W,O,R,L,D

54.EMPTY_BLOB()和EMPTY_CLOB()
这两个函数都是用来对大数据类型字段进行初始化操作的函数

55.GREATEST
返回一组表达式中的最大值,即比较字符的编码大小.
SQL> select greatest(’AA’,’AB’,’AC’) from dual;

GR

AC
SQL> select greatest(’啊’,’安’,’天’) from dual;

GR

56.LEAST
返回一组表达式中的最小值
SQL> select least(’啊’,’安’,’天’) from dual;

LE

57.UID
返回标识当前用户的唯一整数
SQL> show user
USER 为”GAO”
SQL> select username,user_id from dba_users where user_id=uid;
USERNAME USER_ID


GAO 25

58.USER
返回当前用户的名字
SQL> select user from dual;

USER

GAO

59.USEREVN
返回当前用户环境的信息,opt可以是:
ENTRYID,SESSIONID,TERMINAL,ISDBA,LABLE,LANGUAGE,CLIENT_INFO,LANG,VSIZE
ISDBA 查看当前用户是否是DBA如果是则返回true
SQL> select userenv(’isdba’) from dual;

USEREN

FALSE
SQL> select userenv(’isdba’) from dual;

USEREN

TRUE
SESSION
返回会话标志
SQL> select userenv(’sessionid’) from dual;

USERENV(’SESSIONID’)

152
ENTRYID
返回会话人口标志
SQL> select userenv(’entryid’) from dual;

USERENV(’ENTRYID’)

0
INSTANCE
返回当前INSTANCE的标志
SQL> select userenv(’instance’) from dual;

USERENV(’INSTANCE’)

1
LANGUAGE
返回当前环境变量
SQL> select userenv(’language’) from dual;

USERENV(’LANGUAGE’)

SIMPLIFIED CHINESE_CHINA.ZHS16GBK
LANG
返回当前环境的语言的缩写
SQL> select userenv(’lang’) from dual;

USERENV(’LANG’)

ZHS
TERMINAL
返回用户的终端或机器的标志
SQL> select userenv(’terminal’) from dual;

USERENV(’TERMINA

GAO
VSIZE(X)
返回X的大小(字节)数
SQL> select vsize(user),user from dual;
VSIZE(USER) USER


6 SYSTEM

60.AVG(DISTINCT|ALL)
all表示对所有的值求平均值,distinct只对不同的值求平均值
SQLWKS> create table table3(xm varchar(8),sal number(7,2));
语句已处理。
SQLWKS> insert into table3 values(’gao’,1111.11);
SQLWKS> insert into table3 values(’gao’,1111.11);
SQLWKS> insert into table3 values(’zhu’,5555.55);
SQLWKS> commit;
SQL> select avg(distinct sal) from gao.table3;

AVG(DISTINCTSAL)

3333.33
SQL> select avg(all sal) from gao.table3;

AVG(ALLSAL)

2592.59

61.MAX(DISTINCT|ALL)
求最大值,ALL表示对所有的值求最大值,DISTINCT表示对不同的值求最大值,相同的只取一次
SQL> select max(distinct sal) from scott.emp;

MAX(DISTINCTSAL)

5000

62.MIN(DISTINCT|ALL)
求最小值,ALL表示对所有的值求最小值,DISTINCT表示对不同的值求最小值,相同的只取一次
SQL> select min(all sal) from gao.table3;

MIN(ALLSAL)

1111.11

63.STDDEV(distinct|all)
求标准差,ALL表示对所有的值求标准差,DISTINCT表示只对不同的值求标准差
SQL> select stddev(sal) from scott.emp;

STDDEV(SAL)

1182.5032
SQL> select stddev(distinct sal) from scott.emp;

STDDEV(DISTINCTSAL)

1229.951

64.VARIANCE(DISTINCT|ALL)
求协方差
SQL> select variance(sal) from scott.emp;

VARIANCE(SAL)

1398313.9

65.GROUP BY
主要用来对一组数进行统计
SQL> select deptno,count(*),sum(sal) from scott.emp group by deptno;
DEPTNO COUNT(*) SUM(SAL)


10 3 8750
20 5 10875
30 6 9400

66.HAVING
对分组统计再加限制条件
SQL> select deptno,count(),sum(sal) from scott.emp group by deptno having count()>=5;
DEPTNO COUNT(*) SUM(SAL)


20 5 10875
30 6 9400
SQL> select deptno,count(),sum(sal) from scott.emp having count()>=5 group by deptno ;
DEPTNO COUNT(*) SUM(SAL)


20 5 10875
30 6 9400

67.ORDER BY
用于对查询到的结果进行排序输出
SQL> select deptno,ename,sal from scott.emp order by deptno,sal desc;
DEPTNO ENAME SAL


10 KING 5000
10 CLARK 2450
10 MILLER 1300
20 SCOTT 3000
20 FORD 3000
20 JONES 2975
20 ADAMS 1100
20 SMITH 800
30 BLAKE 2850
30 ALLEN 1600
30 TURNER 1500
30 WARD 1250
30 MARTIN 1250
30 JAMES 950

*****************************************************************************8

根据中文拼音顺序排序:
select sys_id code, sys_short_nm val
from mob_shop_sys
where use_yn = ‘Y’
order by nlssort(sys_short_nm, ‘NLS_SORT=SCHINESE_PINYIN_M’)
*****************************************************************************8
create or replace trigger TG_UPDATE_MOB_SHOP_HIST
after update or insert or delete on mob_shop_mapping
for each row
declare
begin
if /updating or /deleting then

   insert into mob_shop_mapping_hist(COM_CD,
                        SHOP_CD,
                        PS_ID,
                        PR_ID,
                        PROD_CD,
                        SHOP_TP,
                        create_date,
                        create_emp,
                        USE_YN)
     values (:old.COM_CD,
             :old.SHOP_CD,
             :old.PS_ID,
             :old.PR_ID,
             :old.PROD_CD,
             :old.SHOP_TP,
             sysdate,
             :old.create_emp,
             'N' );

elsif inserting then

 insert into mob_shop_mapping_hist(COM_CD,
                        SHOP_CD,
                        PS_ID,
                        PR_ID,
                        PROD_CD,
                        SHOP_TP,
                        create_date,
                        create_emp,
                        USE_YN)
     values (:NEW.COM_CD,
             :NEW.SHOP_CD,
             :NEW.PS_ID,
             :NEW.PR_ID,
             :NEW.PROD_CD,
             :NEW.SHOP_TP,
             sysdate,
             :NEW.create_emp,
             'Y' );

end if;
end TG_UPDATE_MOB_SHOP_HIST;

*****************************************************************************8
关于rownum:

在查询中,我们可以注意到,
类似于“select xx from table where rownum < n”(n>1)这样的查询是有正确含义的,
而“select xx from table where rownum = n”这样的查询只在n=1的时候成立,
“select xx from table where rownum > n”(n>1)这样的查询只能得到一个空集。
另外“select xx from table where rownum > 0”这个查询会返回所有的记录。

它的特点是按顺序标记,而且是逐次递加的,换句话说就是只有有rownum=1的记录,才可能有rownum=2的记录。

为什么当条件为rownum = n或者rownum >= n时明明有数据却只能得到一个空集呢?假设我们的查询条件为rownum = 2,
那么在查询出的第一条记录的时候,oracle标记此条记录rownum为1,结果发现和rownum=2的条件不符,于是结果集为空。

*****************************************************************************8
使用imp导入数据库是出现ora-01695错误,此错误时由于表空间小所导致,解决办法如下四种:
1。 加空间。增加原表空间大小
ALTER DATABASE DATAFILE ‘/dev/vg01/file.dbf’
RESIZE 999M;
2。 exp compress=n
3。create table first, and then imp ignore=y
4。consider out of line lob and put lob in dedicated tablespace.

*****************************************************************************8
根据条件删除多条记录:
delete from as_shop_dtl t3
where (t3.com_code, t3.cust_cd, t3.china_product) in
(select t1.com_code, t1.cust_cd, t1.china_product
from as_shop_dtl t1, aaa_test5 t2
where t1.cust_cd = t2.shop_cd)

*****************************************************************************8
执行package:
批量执行多个procedure:
执行procedure:

  1. 编写1.txt文件:
    execute PR_SPMS_CALL_MONTHLY_SUMMARY(‘201205’);
    execute PR_SPMS_CALL_DAILY_ACTSAL(‘20120508’);
    spool d:/1.log
    spool off

  2. 在plsqldev common window
    执行 @d:/1.txt

@D:/insert menu.txt

  1. 执行结果:
    PL/SQL procedure successfully completed

PL/SQL procedure successfully completed
Started spooling to d:\1.log
Stopped spooling to d:\1.log

*****************************************************************************8

如何查询 procedure是否正在运行?

select * from v$access where object=’存储过程名称’

*****************************************************************************8
SELECT ROLE_ID,
CREATE_EMP,
MENU_ID,
MENU_NAME_CN,
MENU_REMARK,
MENU_NAME_EN,
MENU_NAME_KR,
HIGH_MENU_ID,
MENU_LEVEL,
ORD_MENU_ID
FROM (SELECT distinct a.ROLE_ID,
a.CREATE_EMP,
a.MENU_ID,
b.MENU_NAME_CN,
b.MENU_REMARK,
b.MENU_NAME_EN,
b.MENU_NAME_KR,
b.HIGH_MENU_ID,
b.MENU_LEVEL,
b.ORD_MENU_ID
FROM sys_role_menu_inf a, sys_menu_inf b
WHERE a.USE_YN = ‘Y’
AND a.ROLE_ID = ${roleId}
AND a.MENU_ID = b.menu_id)
START WITH HIGH_MENU_ID = ‘M0000’
CONNECT BY PRIOR MENU_ID = HIGH_MENU_ID
ORDER SIBLINGS BY decode(length(ORD_MENU_ID),1,’0’||ORD_MENU_ID,ORD_MENU_ID)
*****************************************************************************8

BEGIN

DELETE as_mob_shop A
 WHERE (com_code, cust_cd, promoter, china_product) IN
       (SELECT com_cd, shop_cd, pr_id, prod_cd 
          FROM mob_shop_mapping_hist@DL_MKT_EZSELOUT B
         WHERE B.CREATE_DATE >= TRUNC(run_time)
           AND B.CREATE_DATE < TRUNC(run_time + 1)
           AND B.use_yn = 'N');

EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
PR_PROCESS_ERROR(‘PR_SHOP_MAPPING’,
‘AS_MOB_SHOP’,
‘DELETE’,
SQLCODE,
SUBSTR(SQLERRM, 1, 2000));
RETURN;
END;

*****************************************************************************8
PL/SQL笔记
PL/SQL块中只能直接嵌入SELECT,DML(INSERT,UPDATE,DELETE)以及事务控制语句(COMMIT,ROLLBACK,SAVEPOINT),而不能直接嵌入DDL语句(CREATE,ALTER,DROP)和DCL语句(GRANT,REVOKE)
1.检索单行数据

1.1使用标量变量接受数据
v_ename emp.ename%type;
v_sal emp.sal%type;
select ename,sal into v_ename,v_sal from emp where empno=&no;
1.2使用记录变量接受数据
type emp_record_type is record(
ename emp.ename%type,sal emp.sal%type);
emp_record emp_record_type;
select ename,sal into emp_record from emp where empno=&no;
1.3嵌入SELECT语句注意事项:
使用SELECT INTO语句时,必须要返回一条数据,并且只能返回一条数据

no_date_found:
select into没有返回数据
too_many_rows:
select into返回多条数据

where子句使用注意事项:
使用的变量名不能与列名相同,否则触发TOO_MANY_ROWS例外.

2.操纵数据
2.1使用VALUES子句插入数据
v_deptno dept.deptno%type;
v_dname dept.dname%type;
v_deptno:=no;
v_dname:=’&name’;
insert into dept (deptno,dname) values(v_deptno,v_dname);
2.2使用子查询插入数据
v_deptno emp.deptno%type:=&no;
insert into employee select * from emp where deptno=v_deptno;

2.3更新数据
使用表达式更新列值
v_deptno dept.deptno%type:=no;
v_loc dept.loc%type:=’&loc’;
update dept set loc=v_loc where deptno=v_deptno;
2.4使用子查询更新列值
v_ename emp.ename%type:=’&name’;
update emp set (sal,comm) = (select sal,comm from emp where ename=v_ename) where job = (select job from emp where ename=v_ename)
2.5删除数据
使用变量删除数据
v_deptno dept.deptno%type:=&no;
delete from dept where deptno=v_deptno;

2.6使用子查询删除数据
v_ename emp.ename%type:=’&name’;
delete from emp where deptno=(select deptno from emp where ename=v_ename);

3.SQL游标
游标是指向上下文区的指针,包括隐含游标(SQL游标)和显式游标两种类型
SQL游标用于处理SELECT INTO ,INSERT,UPDATE以及DELETE语句.
显式游标用于处理多行的SELECT语句
SQL游标包括:SQL%FOUND,SQL%NOTFOUND,SQL%ROWCOUNT,SQL%ISOPEN等四种属性

3.1 SQL%ISOPEN:执行时,会隐含的打开和关闭游标.因此该属性的值永远都是FALSE

3.2 SQL%FOUND:用于确定SQL语句执行是否成功.当SQL有作用行时,为TRUE,否则为FALSE
v_deptno emp.deptno%type:=&no;
update emp set sal=sal*1.1 where deptno=v_deptno;
if sql%found then dbms_output.put_line(‘执行成功’); else dbms_output.putline(‘失败’); endif

3.3 sql%notfound:确定SQL语句执行是否成功,当SQL有作用行时,为false,否则为true

3.4 sql%rowcount:返回SQL语句所作用的总计行数
v_deptno emp.deptno%type:=&no;
update emp set sal=sal*1.1 where deptno=v_deptno;
dbms_output.put_line(‘修改了’||sql%rowcount||’行’);

4.事务控制语句
事务控制语句包括COMMIT,ROLLBACK以及SAVEPOINT等三种语句

v_sal emp.sal%type:=&salary;
v_ename emp.ename%type:=’&name’;
update emp set sal=v_sal where ename=v_ename;
commit;
exception
when others then
rollback;
insert into temp values(1);
savepoint a1;
insert into temp values(2);
savepoint a2;
insert into temp values(3);
savepoint a3;
rollback to a2;
commit;

5.控制结构
条件分支语句

5.1简单条件判断
v_sal number(6,2);
select sal into v_sal from emp where lower(ename)=lowe(‘&&name’);
if v_sal<2000 then update emp set sal=v_sal+200 where lower(ename)=lower(‘&name’)
end if
5.2二重条件分支
v_comm number(6,2);
select comm into v_comm from emp where empno=&&no;
if v_comm<>0 then update emp set comm=v_comm+100 where empno=&no;
else update emp set comm=200 where empno=&no;
end if
5.3多重条件分支
v_job varchar2(10);
v_sal number(6,2);
select job,sal into v_job,v_sal from emp where empno=&&no;
if v_job=’president’ then update emp set sal=v_sal+1000 where empno=&no;
elseif v_job=’manager’ then update emp set sal=v_sal+500 where empno=&no;
else update emp set sal=v_sal+200 where empno=&no;
end if;

5.4 CASE语句:
在CASE语句中使用单一选择符进行等值比较
declare
v_deptno emp deptno%type;
begin
v_deptno:=&no;
case v_deptno
when 10 then update emp set comm=100 where deptno=v_deptno;
when 20 then update emp set comm=80 where deptno=v_deptno;
when 30 then update emp set comm=50 where deptno=v_deptno;
else
dbms_output.put_line(“不存在’);
end case;
end;
5.5 在CASE语句中使用多种条件比较
declare
v_sal emp.sal%type;
v_ename emp.ename%type;
begin
select ename,sal into v_ename,v_sal from emp where empno=&no;
case
when v_sal<1000 then update emp set comm=100 where ename=v_ename;
when v_sal<2000 then update emp set comm=80 where ename=v_ename;
when v_sal<6000 tehn update emp set comm=50 where ename=v_ename;
end case;
end;

5.6循环语句
有基本循环,WHILE循环,FOR循环

基本循环:一定要包含EXIT语句,定义循环控制变量
create table temp(cola int);
declare
i int:=1;
begin
loop
insert into temp values(i);
exit when i=10;
i:=i+1;
end loop;
end;
5.7 WHILE循环:定义循环控制变量,并在循环体内改变循环控制变量的值
declare
i int:=1;
begin
while i<=10 loop
insert into temp values(i);
i:=i+1;
end loop;
end;
5.8 for循环:使用FOR循环时,ORACLE会隐含定义循环控制变量.
for counter in[reverse]
lower_bound..upper_bound loop
statement1;
statement2;
…….
end loop;
5.9 counter是循环控制变量,并且该变量由ORACLE隐含定义,不需要显示定义;lower_bound和upper_bound分别对应循环控制变量的上下界值.默认情况下,FOR循环,每次会自动增一,指定REVERSE选项时,每次循环控制变量会减一
begin
for i in reverse 1..10 loop
insert into temp values(i);
end loop;
end;

5.10嵌套循环和标号:通过在嵌套循环中使用标号,可以区分内层循环和外层循环,并且可以在内层循环中直接退出外层循环
declare
result int;
begin
<>
for i in 1..100 loop
<>
for j in 1..100 loop
result:=i*j;
exit outer when result=1000;
exit when result=500;
end loop inner;
dbms_ouput.put_line(result);
end loop outer;
dbms_output.put_line(result);
end;

6.顺序控制语句
PL/SQL不仅提供了条件分支语句和循环控制语句,而且还提供了顺序控制语句GOTO和NULL.一般情况下不使用

6.1 GOTO:用于跳转到特定标号处去执行语句.
GOTO LABEL_NAME;

declare
i int :=1;
begin
loop
insert into temp values(i);
if i=10 then
goto end_loop
end if;
i:=i+1;
end loop;
<>
dbms_output.put_line(‘循环结束’);
end;

6.2 null:不会执行任何操作,并且会直接将控制传递到下一条语句.
declare
v_sal emp.sal%type;
v_ename emp.ename%type;
begin
select ename,sal into v_ename,v_sal from emp where empno=&no;
if v_sal<3000 then update emp set comm=sal*0.1 where ename=v_ename;
else
null;
end if;
end;

7.复合数据类型
7.1定义PL/SQL记录

自定义PL/SQL记录:需要定义PL/SQL记录类型和记录变量,identifier用于指定记录变量名
type type_name is record(
field_declaration[,
field_declaration]…
);
identifier type_name;

declare
type emp_record_type is record(
name emp.ename%type,
salary em.sal%type,
dno emp.deptno%type);
emp_record emp_record_type;

使用%rowtype属性定义记录变量:可以基于表或视图定义记录变量
当使用%ROWTYPE属性定义记录变量时,记录成员个数,名称,类型与表或视图列的个数,名称,类型完全相同.
dept_record dept%rowtype;
emp_record emp%rowtype;

在select into 语句中使用PL/SQL 记录
在select into 语句中使用记录变量
set serveroutput on
declare
  type emp_record_type is record(
       name emp.ename%type,
       salary em.sal%type,
       dno emp.deptno%type);
  emp_record emp_record_type;
begin
  select ename,sal,deptno into emp_record from emp where empno=&no;
  dbms_output.put_line(emp_record.name);
end;
7.2在select into 语句中使用记录成员
declare 
  type emp_record_type is record(
       name emp.ename%type,
       salary emp.sal%type,
       dna emp.deptno%type);
  emp_record emp_record_type;
begin
  select ename,sal into emp_record.name,emp_record.salary from emp where empno=&no;
  dbms_output.put_line(emp_record.name);
end;

7.3在insert语句中使用PL/SQL记录
在VALUES子句中使用记录变量
declare 
  dept_record dept%rowtype;
begin
  dept_record.deptno:=50;
  dept_record.dname:='administrator';
  dept_record.loc:='beijing';
  insert int dept values dept_record;
end;
在VALUES子句中使用记录成员
declare
  dept_record dept%rowtype;
begin
  dept_record.deptno:=60;
  dept_record.dname:='sales';
  insert into dept (deptno,dname) values (dept_record.deptno,dept_record.dname);
end;
7.4在UPDATE语句中使用PL/SQL记录
在SET子句中使用记录变量
declare
  dept_record dept%rowtype;
begin
  dept_record.deptno:=30;
  dept_record.dnama:='sales';
  dept_record.loc:='shanghai';
  update dept set row=dept_record where deptno=30;

end;
在SET子句中使用记录成员
declare
dept_record dept%rowtype;
begin
dept_record.loc:=’guangzhou’;
update dept set loc=dept_record.loc where deptno=10;
end;

7.5在DELETE语句中使用PL/SQL记录:只能在DELETE语句中的WHERE子句中使用记录成员
declare
dept_record dept%rowtype;
begin
dept_record.deptno:=50;
delete from dept where deptno=dept_record.deptno;
end;

8.pl/sql集合
处理单行单列数据,可以使用标量变量,处理单行多列的数据,可以使用PL/SQL记录
处理单列多行数据,可以使用PL/SQL集合

PL/SQL集合类型类似于高级语言数组的一种复合数据类型
包括:索引表(PL/SQL表),嵌套表(NESTED TABLE),变长数组(VARRAY)三种

8.1 索引表:PL/SQL表 元素个数没有限制,并且下标可以是负值
定义索引表:
type type_name is table of element_type [not null] index by key_type;
identifier type_name;

在索引表中使用BINARY_INTEGER和PLS_INTEGER
set serveroutput on
declare
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
begin
select ename into ename_table(-1) from emp where empno=&no;
dbms_output.put_line(‘雇员名:’||ename_table(-1));
end;
在索引表中使用VARCHAR2
set serveroutput on
declare
type area_table_type is table of number index by varchar2(10);
area_table area_table_type;
begin
area_table(‘北京’):=1;
area_table(‘上海’):=2;
area_table(‘广州’):=3;
dbms_output.put_line(‘第一个元素:’||area_table.first);
dbms_output.put_line(‘最后一个元素:’||area_table.last);
end;
8.2 嵌套表:元素个数从1开始,并且元素个数没有限制
定义嵌套表:
type type_name is table of element_type;
identifier type_name;

  declare
    type ename_table_type is table of emp.ename%type;
    ename_table ename_table_type:=ename_table_type('A','A');

在PL/SQL块中使用嵌套表:使用嵌套表变量时,必须首先使用构造方法初始化嵌套表变量,然后才能在块内引用嵌套表元素
declare
type ename_talbe_type is table of emp.ename%type;
ename_talbe ename_table_type;
begin
ename_table:=ename_table_type(‘mary’,’mary’,’mary’);
select ename into ename_table(2) from emp where empno=&no;
dbms_output.put_line(‘雇员名:’||ename_table(2));
end;

在表列中使用嵌套表:
在表列中使用嵌套表类型,必须首先使用CREATE TYPE命令建立嵌套表类型.
当使用嵌套表类型作为表列的数据类型时,必须要为嵌套表列指定专门的存储表
create type phone_type is table of varchar2(20);
/
create table employee(
id number(4),name varchar2(10),sal number(6,2),
phone phone_type
)nested table phone store as phone_table;
8.3 在PL/SQL块中为嵌套表列插入数据
当定义嵌套表类型时,ORACLE自动为该类型生成相应的构造方法.当为嵌套表列插入数据时,需要使用嵌套表的构造方法
begin
insert into employee values(1,’scott’,800,phone_type(‘0471-3456788’,’13804711111’));
end;
在PL/SQL块中检索嵌套表列的数据
当在PL/SQL块中检索嵌套表列的数据时,需要定义嵌套表类型的变量接受其数据.
set serveroutput on
declare
phone_table phone_type;
begin
select phone into phone_table from employee where id=1;
for i in 1..phone_table.count loop
dbms_output.put_line(‘电话:’||phone_table(i));
end loop;
end;

8.4 在pl/sql块中更新嵌套表列的数据
更新嵌套表列的数据时,首先需要定义嵌套表变量,并使用构造方法初始化变量,然后才可在执行部分使用UPDATE语句更新数据
declare
phone_table phone_type:=phone_type(‘0471-3456788’,’13804711111’,’0471-2233066’,’13056278568’);
begin
update employee set phone=phone_talbe where id=1;
end;

8.5变长数组(varray)
VARRAY也是一种用于处理PL/SQL数组的数据类型, 它也可以做为表列的数据类型使用.
元素下标以1开始,并且元素的最大个数是有限制的
定义VARRAY的语法:
type type_name is varray(size_limite) of element_type [not mull];
identifier type_name;
当使用VARRAY元素时,必须要使用其构造方法初始化VARRAY元素.
declare
type ename_table_type is varrar(20) of emp.ename%type;
ename_talbe ename_table_type:=ename_table_type(‘A’,’A’);
8.6 在PL/SQL块中使用VARRAY
必须首先使用其构造方法来初始化VARRAY变量,然后才能在PL/SQL块内引用VARRAY元素
declare
type ename_table_type is varray(20) of emp.ename%type;
ename_table ename_table_type:=ename_table_type(‘mary’);
begin
select ename into ename_table(1) from emp where empno=&no;
dbms_output.put_line(‘雇员名:’||ename_table(1));
end;
在表列中使用varray
要在表列中引用该数据类型,则必须使用CREATE TYPE命令建立VARRAY类型
create type phone_type is varray(20) of varchar2(20);
/
create table employee(
id number(4),name varchar2(10),
sal number(6,2),phone phone_type);
在PL/SQL块中操纵VARRAY列的方法与操纵嵌套表列的方法完全相同.嵌套表列元素个数没有限制,而VARRAY列的元素个数是有限制的.

PL/SQL记录表
PL/SQL变量处理单行单列数据
PL/SQL记录处理单行多列数据
PL/SQL集合处理多行单列数据
PL/SQL记录表处理多行多列数据

8.7 PL/SQL记录表结合了PL/SQL记录和PL/SQL集合的优点
declare
type emp_talbe_type is table of emp%rowtype index by binary_integer;
emp_table emp_table_type;
begin
select * into emp_table(1) from emp where empno=&no;
dbms_output.put_line(‘雇员姓名:’||emp_table(1).ename);
dbms_output.put_line(‘雇员姓名:’||emp_table(1).sal);
end;
8.8 多级集合
多级集合是指嵌套了集合类型的集合类型
在PL/SQL块中使用多级VARRAY:实现多维数组功能
定义二维VARRAY(10,10):
declare
type a1_varray_type is varray(10) of int;–定义一维VARRAY
type na1_varray_type is varray(10) of a1_varray_type;–定义二维VARRAY集合
–初始化二维集合变量
nv1 nal_varray_type:=nal_varray_type(
a1_varray_type(58,100,102),
a1_varray_type(55,6,73),
a1_varray_type(2,4);
begin
dbms_output.put_line(‘显示二维数组所有元素’);
for i in 1..nv1.count loop
for j in 1..nv1(i).count loop
dbms_output.put_line(‘nvl(‘||i||’,’||j||’)=’||nvl(i)(j));
end loop;
end loop;
end;
在PL/SQL块中使用多级嵌套表
如果多维数组的元素个数没有限制,那么可以在嵌套表类型中嵌套另一个嵌套表类型

8.9 二维嵌套表
declare
type a1_table_type is table of int;–定义一维嵌套表
type nal_table_type is table of a1_table_type;–定义二维嵌套表集合
–初始化二维集合变量
nvl nal_table_type:=nal_table_type(
a1_table_type(2,4),
a1_table_type(5,73));
begin
dbms_output.put_line(‘显示二维数组所有元素’);
for i in 1..nvl.count loop
for j in 1..nvl(i).count loop
dbms_output.put_line(‘nvl(‘||i||’,’||j||’)=’||nvl(i)(j));
end loop;
end loop;
end
在PL/SQL块中使用多级索引表
二维索引表:
declare
type a1_table_type is table of int index by binary_integer;
type nal_table_type is table of al_table_type index by binary_integer;
nvl nal_table_type;
begin
nvl(1)(1):=10;
nvl(1)(2):=5;
nvl(2)(1):=100;
nvl(2)(2):=50;
dbms_output.put_line(‘显示二维数组所有元素’);
for i in 1..nvl.count loop
for j in 1..nvl(i).count loop
dbms_output.put_line(‘nvl(‘||i||’,’||j||’)=’||nvl(i)(j));
end loop;
end loop;
end;

8.10集合方法:ORACLE提供的用于操纵集合变量的内置函数或过程,其中EXISTS,COUNT,LIMIT,FIRST,NEXT,FRIOR和NEXT是函数
而EXTEND,TRIM和DELETE则是过程
集合方法只能在PL/SQL语句中使用,不能在SQL语句中使用.
集合方法EXTEND和TRIM只适用于嵌套表和VARRAY,而不适合于索引表
1.EXISTS:用于确定集合元素是否存在
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
begin
if ename_table.exists(1) then
ename_table(1):=’SCOTT’;
else
dbms_output.put_line(‘必须初始化集合元素’);
end if;
end;
2.COUNT:用于返回当前集合变量中的元素总个数.
declare
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
begin
ename_table(-5):=’scott’;
ename_table(1):=’smith’;
ename_table(5):=’mary’;
ename_table(10):=’blake’;
dbms_output.put_line(‘集合元素总个数:’||ename_table.count);
end;
3.LIMIT:用于返回集合元素的最大个数.因为嵌套表和索引表的余数个数没有限制,返回NULL
对于VARRAY来说,该方法返回VARRAY所允许的最大元素个数
declare
type ename_table_type is varray(20) of emp.ename%type;
ename_table ename_table_type:=ename_table_type(‘mary’);
begin
dbms_output.put_line(‘集合元素的最大个数:’||ename_table.limit);
end;
4.FIRST和LAST:FIRST用于返回集合变量第一个元素的下标,而LAST方法则用于返回集合变量最后一个元素的下标
declare
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
begin
ename_table(-5):=’scott’;
ename_table(1):=’smith’;
ename_table(5):=’mary’;
ename_table(10):=’blake’;
dbms_output.put_line(‘第一个元素:’||ename_table.first);
dbms_output.put_line(‘最后一个元素:’||ename_table.last);
end;
5.FRIOR和NEXT:PRIOR返回当前集合元素的前一个元素的下标,而NEXT方法则用于返回当前集合元素的后一个元素的下标
declare
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
begin
ename_table(-5):=’scott’;
ename_table(1):=’smith’;
ename_table(5):=’mary’;
ename_table(10):=’blake’;
dbms_output.put_line(‘元素5的前一个元素:’||ename_table.prior(5));
dbms_output.put_line(‘元素5的后一个元素:’||ename_table.next(5));
end;
6.EXTEND:用于扩展集合变量的尺寸,并为它们增加元素.只适用于嵌套表和VARRAY.
三种调用格式:EXTEND,EXTEND(N),EXTEND(N,I):添加N个元素,值与第I个元素相同
declare
type ename_table_type is varray(20) of varchar2(10);
ename_table ename_table_type;
begin
ename_table:=ename_table_type(‘mary’);
ename_table.extend(5,1);
dbms_output.put_line(‘元素个数:’||ename_table.count);
end;
7.TRIM:用于从集合尾部删除元素,有TRIM和TRIM(N)两种调用格式.
只适用于嵌套表和VARRAY
declare
type ename_table_type is table of varchar2(10);
ename_table ename_table_type;
begin
ename_table:=ename_table_type(‘a’,’a’,’a’,’a’,’a’);
ename_table.trim(2);
dbms_table.put_line(‘元素个数:’||ename_table.count);
end;
8.DELETE:删除结合元素,但该方法只适用于嵌套表和索引表,不适用于VARRAY.
有DELETE,DELETE(N),DELETE(M,N)三种调用方式.
DETELE(M,N)删除集合变量从M到N之间的所有元素
declare
type ename_table_type is table of emp.ename%type index by binary_integer;
ename_table ename_table_type;
begin
ename_table(-5):=’scott’;
ename_table(1):=’smith’;
ename_table(5):=’mary’;
ename_table(10):=’blake’;
ename_table.delete(5);
dbms_output.put_line(‘元素总个数:’||ename_table.count);
end;

8.11集合赋值
使用嵌套表和VARRAY时,通过执行INSERT,UPDATE,FETCH,SELECT赋值语句,可以将一个集合的数据赋值给另一个集合.
当给嵌套表赋值时,还可以使用SET,MULTISET UNION,MULTISET INTERSECT,MULTISET EXCEPT等集合操作符
SET:用于取消嵌套表中的重复值.
MULTISET UNION:取得两个嵌套表的并集(DISTINCT)
MULTISET INTERSECT:用于取得两个嵌套表的交集.
NULTISET EXCEPT:用于取得两个嵌套表的差集

1.将一个集合的数据赋值个另一个集合
源集合和目标集合的数据类型必须完全一致.
declare
type name_varray_type is varray(4) of varchar2(10);
name_array1 name_varray_type;
name_array2 name_varray_type;
begin
name_array1:=name_varray_type(‘scott’,’smith’);
name_array2:=name_varray_type(‘a’,’a’,’a’,’a’);
dbms_output.put_line(‘name_array2的原数据:’);
for i in 1..name_array2.count loop
dbms_output.put_line(’ ‘||name_array2(i));
end loop;
dbms_output.new_line;
name_array2:=name_array1;
dbms_output.put(‘name_array2的新数据:’);
for i in 1..name_array2.count loop
dbms_output.put(’ ‘||name_array2(i));
end loop;
dbms_output.new_line;
end;

2.给集合赋NULL值:清空集合变量的所有数据(集合方法DETELE,TRIM也可以)
declare
type name_varray_type is varray(4) of varchar2(10);
name_array name_varray_type;
name_empty name_varray_type;
begin
name_array:=name_varray_type(‘scott’,’smith’);
dbms_output.put_line(‘name_array的原有元素个数:’||name_array.count);
name_array:=name_empty;
if name_array is null then
dbms_output.put_line(‘name_array的现有元素个数:0’);
end if;
end;
3.使用集合操作符给嵌套表赋值

1.使用SET操作符:用于取消特定嵌套表中的重复值.

declare
type nt_table_type is table of number;
nt_table nt_table_type:=nt_table_type(2,4,3,1,2);
result nt_table_type;
begin
result:=set(nt_table);
dbms_output.put(‘result:’);
for i in 1..result.count loop
dbms_output.put(’ ‘||result(i));
end loop;
dbms_output.new_line;
end;
2.使用MULTISET UNION操作符:取得两个嵌套表的并集.结果集中会包含重复值
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 MULTISET union nt2;
dbms_output.put(‘result:’);
for i in 1..result.count loop
dbms_output.put(’ ‘||result(i));
end loop;
dbms_output.new_line;
end;
3.使用MULTISET UNION DISTINCT操作符:用于取得两个嵌套表的并集,并取消重复结果.
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 multiset union distinct nt2;
dbms_output.put(‘result:’);
for i in 1..result.count loop
dbms_output.put(’ ‘||result(i));
end loop;
dbms_output.new_line;
end;

4.使用MULTISET INTERSECT操作符:用于取得两个嵌套表的交集
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 multiset intersect nt2;
dbms_output.put(‘result:’);
for i in 1..result.count loop
dbms_output.put(’ ‘||result(i));
end loop;
dbms_output.new_line;
end;

5.使用MULTISET EXCEPT操作符:取得两个嵌套表的差集.在NT1中存在,但在NT2中不存在
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(3,4,5);
result nt_table_type;
begin
result:=nt1 multiset except nt2;
dbms_output.put(‘result:’);
for i in 1..result.count loop
dbms_output.put(’ ‘||result(i));
end loop;
dbms_output.new_line;
end;
8.4比较集合
函数cardinality用于返回嵌套表变量的元素个数
操作符SUBMULTISET OF用于确定一个嵌套表是否为另一个嵌套表的子集
操作符MEMBER OF用于检测特定数据是否为嵌套表元素
操作符IS A SET用于检测嵌套表是否包含重复的元素值
操作符IS EMPTY用于检测嵌套表是否为NULL.

1.检测集合是否为NULL
declare
type name_table_type is table of varchar2(10);
name_table name_table_type;
begin
if name_table is empty then
dbms_output.put_line(‘name_table未初始化’);
end if;
end;
2.比较嵌套表是否相同
使用比较符=和!=检测两个嵌套表是否相同.不能比较VARRAY和索引表
declare
type name_table_type is table of varchar2(10);
name_table1 name_table_type;
name_table2 name_table_type;
begin
name_table1:=name_table_type(‘scott’);
name_table2:=name_table_type(‘smith’);
if name_table1=name_table2 then
dbms_output.put_line(‘两个嵌套表完全相同’);
else
dbms_output.put_line(‘两个嵌套表数值不同’);
end if;
end;
3.在嵌套表上使用集合操作符
在嵌套表上使用ANSI集合操作符CARDINALITY,MEMBER OF, IS A SET.不适用于VARRAY和索引表
使用函数CARDINALITY
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,1);
begin
dbms_output.put_line(‘元素个数:’||cardinality(nt1));
end;
使用操作符SUBMULTISET OF:用于确定一个嵌套表是否为另一个嵌套表的子集.
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3);
nt2 nt_table_type:=nt_table_type(1,2,3,4);
begin
if nt1 submultiset of nt2 then
dbms_output.put_line(‘nt1是nt2的子集);
end if;
end;
使用操作符MEMBER OF :用于检测特定数据是否为嵌套表的元素.
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,5);
v1 number:=&v1;
begin
if v1 MEMBER OF nt1 then
dbms_output.put_line(‘v1是nt1的元素’);
end if;
end;
使用操作符IS A SET:用于检测嵌套表是否包含重复的元素值
declare
type nt_table_type is table of number;
nt1 nt_table_type:=nt_table_type(1,2,3,5);
begin
if nt1 is a set then
dbms_output.put_line(‘嵌套表NT1无重复值’);
end if;
end;

8.5批量绑定
当在select,insert,update,delete语句上处理批量数据时,通过批量绑定,可以极大的加快数据处理速度,提高应用程序性能
批量绑定是使用BULK COLLECT子句和FORALL语句来完成的
BULK COLLECT 子句用于取得批量数据,该子句只能用于SELECT语句,FETCH语句和DML返回子句
FORALL只适用于执行批量的DML操作
1.不使用批量绑定
declare
type id_table_type is table of number(6) index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
start_time number(10);
end_time number(10);
begin
for i in 1..5000 loop
id_table(i):=i;
name_table(i);=’name’||to_char(i);
end loop;
start_time:=dbms_utility.get_time;
for i in 1..id_table.count loop
insert into demo values(id_table(i),name_table(i));
end loop;
end_time:=dbms_utility.get_time;
dbms_output.put_line(‘总计时间(秒):’||to_char((end_time-start_time)/100));
end;
2.使用批量绑定
declare
type id_table_type is table of number(6) index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
start_time number(10);
end_time number(10);
begin
for i in 1..5000 loop
id_table(i):=i;
name_table(i);=’name’||to_char(i);
end loop;
start_time:=dbms_utility.get_time;
forall i in 1..id_table.count
insert into demo values(id_table(i),name_table(i));
end_time:=dbms_utility.get_time;
dbms_output.put_line(‘总计时间(秒):’||to_char((end_time-start_time)/100));
end;

8.6 FORALL语句
执行批量insert,update,delete操作时,使用forall语句,FORALL不是循环语句
oracle9i当使用FORALL语句时,必须具有连续的元素
oracle10g通过使用indices of和values of子句,可以使用不连续的集合元素.
forall三种执行语法:
forall index in lower_bound..upper_bound sql_statement;
forall index in indices of collection [between lower_bond.and.upper_bound] sql_statement;
forall index in values of index_collection sql_statement;
1.在insert语句上使用批量绑定
declare
type id_table_type is table of number(6) index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
begin
for i in 1..10 loop
id_table(i):=i;
name_table(i):=’name’||to_char(i);
end loop;
forall i in 1..id_table.count
insert into demo values(id_table(i),name_table(i));
end;
2.在update语句上使用批量绑定
declare
type id_table_type is table of number(6) index by binary_integer;
type name_table_type is table of varchar2(10) index by binary_integer;
id_table id_table_type;
name_table name_table_type;
begin
for i in 1..5 loop
id_table(i):=i;
name_table(i):=’n’||to_char(i);
end loop;
forall i in 1..id_table.count
update demo set name=name_table(i) where id=id_table(i);
end;
3.在DELETE语句上使用批量绑定
declare
type id_table_type is table of number(6) index by binary_integer;
id_table id_table_type;
begin
for i in 1..3 loop
id_table(i):=i;
end loop;
forall i in 1..id_table.count
delete from demo where id=id_table(i);
end;
4.在FORALL语句中使用部分集合元素
declare
type id_table_type is table of number(6) index by binary_integer;
id_table id_table_type;
begin
for i in 1..10 loop
id_table(i):=11-i;
end loop;
forall i in 8..10
insert into demo (id) values (id_table(i));
end;
5.在FORALL语句上使用INDECES OF子句:用于跳过NULL集合元素
declare
type id_table_type is table of number(6);
id_table id_table_type;
begin
id_table:=id_table_type(1,null,3,null,5);
forall i in indices of id_table
delete from demo where id=id_table(i);
end;

6.在FORALL语句上使用VALUES OF子句
create table new_demo as select * from demo where 1=0
declare
type id_table_type is table of demp.id%type;
type name_table_type is table of demo.name%type;
id_table id_table_type;
name_table name_table_type;
type index_pointer_type is table of pls_integer;
index_pointer index_pointer_type;
begin
select * bulk collect into id_table,name_table from demo;
index_pointer:=index_pointer_type(6,8,10);
forall i in values of index_pointer
insert into new_demo values(id_table(i),name_table(i));
end;
7.使用SQL%BULK_ROWCOUNT属性:专门为FORALL语句提供,用于取得在执行批量绑定操作时第i个元素所作用的行数
declare
type dno_table_type is table of number(3);
dno_table dno_table_type:=dno_table_type(10,20);
begin
forall i in 1..dno_table.count
update emp set sal=sal*1.1 where deptno=dno_table(i);
dbms_output.put_line(‘第2个元素更新的行数:’||sql%bulk_rowcount(2));
end;

8.7 BULK COLLECT子句
用于取得批量数据,只适用于select into 语句,fetch into 语句和DML返回子句
可将批量数据存放到PL/SQL集合变量中
1.在select into 语句中使用BULK COLLECT 子句:可以一次将SELECT语句的多行结果检索到集合变量中
declare
type emp_table_type is table of emp%rowtype index by binary_integer;
emp_table emp_table_type;
begin
select * bulk collect into emp_table from emp where deptno=&no;
for i in 1..emp_table.count loop
dbms_output.put_line(‘雇员姓名:’||emp_table(i).ename);
end loop;
end;
2.在DML的返回语句中使用BULK COLLECT子句
为了取得DML操作所改变的数据,可以使用RETURNING子句.
declare
type ename_table_type is table of emp.ename%type;
ename_table ename_table_type;
begin
delete from emp where deptno=&no;
returning ename bulk collect into ename_table;
dbms_output.put(‘雇员名’);
for i in 1..ename_table.count loop
dbms_output.put(ename_table(i)|| ’ ‘);
end loop;
dbms_output.new_line;
end;

9.使用游标
9.1当在PL/SQL块中执行查询语句SELECT和数据操纵语句DML时,ORACLE会为其分配上下文区(CONTEXT AREA),游标指上下文区指针
对于数据操纵语句和单行SELECT INTO语句来说,ORACLE会为他们分配隐含游标.
使用显示游标处理多行数据,也可使用SELECT..BULK COLLECT INTO 语句处理多行数据.
1.显示游标
定义游标
cursor cursor_name is select_statement;
2.打开游标:执行对应的SELECT语句并将SELECT语句的结果暂时存放到结果集中.
open cursor_name;
3.提取数据
打开游标后,SELECT语句的结果被临时存放到游标结果集中,使用FETCH语句只能提取一行数据
通过使用FETCH..BULK COLLECT INTO语句每次可以提取多行数据
fetch cursor_name into variable1,varibale2,…;
fetch cursor_name bulk collect into collect1,collect2,…[limit rows];
4.关闭游标
close cursor_name;

9.2显示游标属性
用于返回显示游标的执行信息,包括%isopen,%found,%notfound,%rowcount
1.%isopen:确定游标是否打开 if cl%isopen then … else open c1; end if;
2.%found:检查是否从结果集中提取到了数据
loop
fetch c1 into var1,var2;
if c2%found then … else exit;
end loop;
3.%notfound
loop
fetch c1 into var1,var2;
exit when c2%notfound;

end loop;
4.%rowcount:返回当前行为止已经提取到的实际行数
loop
fetch c1 into my_ename,my_deptno;
if c1%rowcount>10 then

end if;

end loop;

9.3显示游标使用示例
1.在显示游标中使用fetch..into语句:只能处理一行数据,除非用循环语句
declare
cursor emp_cursor is select ename,sal from emp where deptno=10;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename||’: ‘||v_sal);
end loop;
close emp_cursor;
end;
2.在显示游标中,使用FETCH..BALK COLLECT INTO语句提取所有数据
declare
cursor emp_cursor is select ename from emp where deptno=10;
type ename_table_type is table of varchar2(10);
ename_table ename_table_type;
begin
open emp_cursor;
fetch emp_cursor bulk collect into ename_table;
for i in 1..ename_table.count loop
dbms_output.put_line(ename_table(i));
end loop;
close emp_cursor;
end;
3.在显示游标中使用FETCH..BULK COLLECT INTO ..LIMIT语句提取部分数据
declare
type name_array_type is varray(5) of varchar2(10);
name_array name_array_type;
cursor emp_cursor is select ename from emp;
rows int:=5;
v_count int:=0;
begin
open emp_cursor;
loop
fetch emp_cursor bulk collect into name_array limit rows;
dbms_output.pur(‘雇员名’);
for i in 1..(emp_currsor%rowcount-v_count) loop
dbms_output.put(name_array(i)||’ ‘);
end loop;
dbms_output.new_line;
v_count:=emp_cursor%rowcount;
exit when emp_cursor%notfound;
end loop;
close emp_cursor;
end;
4.使用游标属性
declare
cursor emp_cursor is select ename from emp where deptno=10;
type ename_table_type is table of varchar2(10);
ename_table ename_table_type;
begin
if not emp_cursor%isopen then
open emp_cursor;
end if;
fetch emp_cursor bulk collect into ename_table;
dbms_output.put_line(‘提取的总计行数:’||emp_cursor%rowcount);
close emp_cursor;
end;
5.基于游标定义记录变量
declare
cursor emp_cursor is select ename,sal from emp;
emp_record emp_cursor%rowtype;
begin
open emp_cursor;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line(‘雇员名:’||emp_record.ename||’,雇员工资:’||emp_record.sal);
end loop;
end;

9.4参数游标
定义参数游标时,游标参数只能指定数据类型,而不能指定长度.
cursor cursor_name(parameter_name datatype) is select_statment;
declare
cursor emp_cursor(no number) is select ename from emp where deptno=no;
v_ename emp.ename%type;
begin
open emp_cursor(10);
loop
fetch emp_cursor into v_ename;
exit when emp_cursor%notfound;
dbms_output.put_line(v_ename);
end loop;
close emp_cursor;
end;
9.5使用游标更新或删除数据
要通过游标更新或删除数据,在定义游标时必须要带有FOR UPDATE子句
cursor cursor_name(parameter_name datetype) is select_statement for update [of column_reference] [nowait];
for update子句用于在游标结果集数据上家行共享锁,防止其他用户在相应行执行DML操作
of子句确定哪些表要加锁,没有OF子句,则在所引用的全部表上加锁
nowait子句用于指定不等待锁
必须在UPDATE后DELETE语句中引用WHERE CURRENT OF子句
update table_name set column=.. where current of cursor_name;
delete table_name where current of cursor_name;

1.使用游标更新数据
declare
cursor emp_cursor is select ename,sal from emp for update;
v_ename emp.ename%type;
v_sal emp.sal%tyep;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_oldsal;
exit when emp_cursor%notfound;
if v_oldsal<2000 then
update emp set sal=sal+100 where current of emp_cursor;
end if;
end loop;
close emp_cursor;
end;
2.使用游标删除数据
declare
cursor emp_cursor is select ename,sal,deptno from emp for update;
v_ename emp.ename%type;
v_oldsal emp.sal%type;
v_deptno emp.deptno%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_oldsal,v_deptno;
exit when emp_cursor%notfound;
if v_deptno=30 then
delete from emp where current of emp_cursor;
end if;
end loop;
close emp_cursor;
end;
3.使用OF子句在特定表上加行共享锁
declare
cursor emp_cursor is select ename,sal,dname,emp.deptno from emp,dept where emp.deptno=dept.deptno
for update of emp.deptno;
emp_record emp_cursor%type;
begin
open emp_cursor;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
if emp_record.deptno=30 then
update emp set sal=sal+100 where current of emp_cursor;
end if;
dbms_output.put_line(‘雇员名:’||emp_record.ename||’,工资:’||emp_record.sal||’,部门名:’||emp_record.dname);
end loop;
close emp_cursor;
end;
4.使用nowait子句
通过在FOR UPDATE子句中指定NOWAIT语句,可以避免等待锁.若已经被作用行加锁,则提示错误信息
declare
cursor emp_cursor is select ename,sal from emp for update nowait;
v_ename emp.ename%type;
v_oldsal emp.sal%type;
begin
open emp_cursor;
loop
fetch emp_cursor into v_ename,v_sal;
exit when emp_cursor%notfound;
if v_oldsal<2000 then
update emp set sal=sal+100 where current of emp_cursor;
end if;
end loop;
close emp_cursor;
end;

9.6游标FOR循环
使用FOR循环时,ORACLE会隐含的打开游标,提取游标数据并关闭游标
for record_name in cursor_name loop
statement1;
statement2;

end loop;
每循环一次提取一次数据,在提取了所有数据后,自动退出循环并隐含的关闭游标
1.使用游标FOR循环
declare
cursor emp_cursor is select ename,sal from emp;
begin
for emp_record in emp_cursor loop
dbms_output.put_line(‘第’||emp_curosr%rowcount||’个雇员: ‘||emp_record.ename);
end loop;
end;
2.在游标FOR循环中直接使用子查询
begin
for emp_record in (select ename,sal from emp) loop
dbms_output.put_line(emp_record.ename);
end loop;
end;
9.7使用游标变量
PL/SQL的游标变量中存放着指向内存地址的指针.

1.游标变量使用步骤
包括定义游标变量,打开游标,提取游标数据,关闭游标等四个阶段
1.1定义ref cursor类型和游标变量
type ref_type_name is ref cursor [return return_type];
cursor_varibale ref_type_name;
当指定RETURN子句时,其数据类型必须是记录类型,不能在包内定义游标变量
1.2打开游标
open cursor_variable for select_statement;
1.3提取游标数据
fetch cursor_varibale into variable1,variable2,…;
fetch cursor_varibale bulk collect into collect1,collect2,…[limit rows]
1.4关闭游标变量
close cursor_varibale;
2.游标变量使用示例
2.1在定义FEF CURSOR类型时不指定RETURN子句
在打开游标时可以指定任何的SELECT语句
declare
type emp_cursor_type is ref cursor;
emp_cursor emp_cursor_type;
emp_record emp%rowtype;
begin
open emp_cursor for select * from emp where deptno=10;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line(‘第’||emp_curosr%rowcount||’个雇员: ‘||emp_record.ename);
end loop;
close emp_cursor;
end;
2.2在定义REF CURSOR类型时指定RETURN子句
在打开游标时SELECT语句的返回结果必须与RETURN子句所指定的记录类型相匹配.
declare
type emp_record_type is record(name varchar2(10),salary number(6,2));
type emp_cursor_type is ref cursor return emp_record_type;
emp_cursor emp_cursor_type;
emp_record emp_record_type;
begin
open emp_cursor for select ename,sal from emp where deptno=20;
loop
fetch emp_cursor into emp_record;
exit when emp_cursor%notfound;
dbms_output.put_line(‘第’||emp_curosr%rowcount||’个雇员: ‘||emp_record.ename);
end loop;
close emp_cursor;
end;

9.7使用CURSOR表达式
CURSOR表达式用于返回嵌套游标
结果集不仅可以包含普通数据,而且允许包含嵌套游标的数据
cursor(subquery)
declare
type refcursor is ref cursor;
cursor dept_cursor(no number) is select a.dname,cursor(select ename,sal from emp where deptno=a.deptno)
from dept a where a.deptno=no;
empcur refcursor;
v_dname dept.dname%type;
v_ename emp.ename%type;
v_sal emp.sal%type;
begin
open dept_cursor(&no);
loop
fetch dept_cursor into v_danme,empcur;
exit when dept_cursor%notfound;
dbms_output.put_line(‘部门名:’||v_dname);
loop
fetch empcur into v_ename,v_sal;
exit when empcur%notfound;
dbms_output.put_line(‘雇员名:’||v_ename||’,工资:’||v_sal);
end loop;
end loop;
close dept_cursor;
end;

10开发子程序:过程和函数
过程:执行特定操作
函数:用于返回特定数据

10.1过程
语法:create [or replace] procedure procedure_name(argument1 [model] datatype1,arguement2 [mode2],…)
is [as]
pl/sql block;
1.建立过程:不带任何参数
create or replace procecdure out_time
is
begin
dbms_output.put_line(systimestemp);
end;
2.调用过程
set serveroutput on
exec out_time
set serveroutput on
call out_time();
3.建立过程:带有IN参数
create or replace procedure add_employee
(eno number,name varchar2,sal number,job varchar2 default ‘clerk’,dno number)
is
e_integrity exception;
pragma exception_init(e_integrity,-2291);
begin
insert into imp(empno,ename,sal,job,deptno) valres(eno,name,sal,job,dno);
exception
when dup_val_on_index then
raise_application_error(-20000,’雇员号不能重复’);
when e_integrity then
raise_application_error(-20001,’部门不存在’);
end;
exec add_employee(1111,’clark’,2000,’manager’,10)
4.建立过程:带有OUT参数
create or replace procedure query_employee
(eno number,name out varchar2,salary out number)
is
begin
select ename,sal into name,salary from emp where empno=eno;
exception
when no_date_found then
raise_application_error(-20000,’该雇员不存在’);
end;
当在应用程序中调用该过程时,必须要定义变量接受输出参数的数据
sql>var name varchar2(10)
var salary number
exec query_employee(7788,:name,:salary)
print name salary

5.建立过程:带有IN OUT参数(输入输出参数)
create or replace procedure compute
(num1 in out number,num2 in out number)
is
v1 number;
v2 number;
begin
v1:num1/num2;
v2:mod(num1,num2);
num1:=v1;
num2:=v2;
end;
sql>var n1 number
var n2 number
exec :n1:=100
exec :n2:=30
exec ecmpute(:n1,:n2)
print n1 n2
6.为参数传递变量和数据
位置传递,名称传递,组合传递三种
1.位置传递:在调用子程序时按照参数定义的顺序为参数指定相应的变量或数值
exec add_dept(40,’sales’,’new york’);
exec add_dept(10);
2.名称传递:在调用子程序时指定参数名,并使用关联符号=>为其提供相应的数值或变量
exec add_dept(dname=>’sales’,dno=>50);
exec add_dept(dno=>30);
3.组合传递:同时使用位置传递和名称传递
exec add_dept(50,loc=>’new york’);
exec add_dept(60,dname=>’sales’,loc=>’new york’);
7.查看过程原代码
oracle会将过程名,源代码以及其执行代码存放到数据字典中.执行时直接按照其执行代码执行
可查询数据字典(user_source)
select text from user_source where name=’add_dept’;

删除过程
drop procedure add_dept;

10.2函数
用于返回特定函数
语法:create [or replace] function function_name
(argument1 [mode1] datatype1,
argument2 [mode2] datatype2,
…..)
return datatype –函数头部必须要带有RETURN子句,至少要包含一条RETURN语句
is|as pl/sql block;

1.建立函数:比带任何参数
create or replace function get_user
return varchar2
is
v_user varchar2(100);
begin
select username into v_user from user_users;
return v_user;
end;
2.使用变量接受函数返回值
sql>var v1 varchar2(100)
exec :v1:=get_user
print v1
在SQL语句中直接调用函数
select get_user from dual;
使用DBMS_OUTPUT调用函数
set serveroutput on
exec dbms_output.put_line(‘当前数据库用户:’||ger_user)

3.建立函数:带有IN参数
create or replace function get_sal(name in varchar2)
return number
as
v_sal emp.sal%type;
begin
select sal into v_sal from emp where upper(ename)=upper(name);
return v_sal;
exception
when no_data_found then
raise_application_error(-20000,’该雇员不存在’);
end;
4.建立函数:带有out参数
create or replace function get_info(name varchar2,title out varchar2)
return varchar2
as
deptname dept.dname%type;
begin
select a.job,b.dname into title,deptname from emp a,dept b and a.deptno=b.deptno
and upper(a.ename)=upper(name);
return deptname
exception
when no_data_found then
raise_application_error(-20000,’该雇员不存在’);
end;
sql>var job varchar2(20)
var dname varchar2(20)
exec :dname:=get_info(‘scott’,:job)
print danme job
5.建立函数:带有IN OUT参数
create or replace function result(num1 number,num2 in out number)
return number
as
v_result number(6);
v_remainder number;
begin
v_result:=num1/num2;
v_remainder:=mod(num1,num2);
num2:=v_remainder;
return v_result;
exception
when zero_divide then
raise_application_error(-20000,’不能除0’);
end;
sql>var result1 number
var result2 number
exec :result2:=30
exec :result1:=result(100,:result2)
print result result2
6.函数调用限制
SQL语句中只能调用存储函数(服务器端),而不能调用客户端的函数
SQL只能调用带有输入参数,不能带有输出,输入输出函数
SQL不能使用PL/SQL的特有数据类型(boolean,table,record等)
SQL语句中调用的函数不能包含INSERT,UPDATE和DELETE语句
7.查看函数院源代码
oracle会将函数名及其源代码信息存放到数据字典中user_source
set pagesize 40
select text from user_source where name=’result’;
8.删除函数
drop function result;

10.3管理子程序
1.列出当前用户的子程序
数据字典视图USER_OBJECTS用于显示当前用户所包含的所有对象.(表,视图,索引,过程,函数,包)
sql>col object_name format a20
select object_name,created,status from user_objects where object_type in (‘procedure’,’function’)

2.列出子程序源代码
select text from user_source where name=’raise_salsry’;
3.列出子程序编译错误
使用SHOW ERRORS命令确定错误原因和位置
show errors procedure raise_salary

使用数据字典视图USER_ERRORS确定错误原因和位置
col text format a50
select line||’/’||position as “line/col”,text error from user_errors where name=’raise_salary’;
4.列出对象依赖关系
使用数据字典视图USER_DEPENDENCIES确定直接依赖关系
select name,type from user_dependencies where referenced_name=’emp’;
使用工具视图DEPTREE和IDEPTREE确定直接依赖和间接依赖关系
先运行SQL脚本UTLDTREE.SQL来建立这两个视图和过程DEPTREE_FILL,然后调用DEPTREE_FILL填充这两个视图
sql>@%oracle_home%\rdbms\admin\utldtree
exec deptree_fill(‘TABLE’,’scott’,’emp’)
执行后会将直接或间接依赖于SCOTT.EMP表的所有对象填充到视图DEPTREE和IDEPTREE中.
select nested_level,name,type from deptree;
select * from ideptree
5.重新编译子程序
当修改了被引用对象的结构时,就会将相关依赖对象转变为无效(INVALID)状态。
alter table emp add remark varchar2(10);
select object_name,object_type from user_objects where status=’invalid’;
为了避免子程序的运行错误,应该重新编译这些存储对象
alter procedure add_employee compile;
alter view dept10 compile;
alter function get_info compile;

11.开发包
包用于逻辑组合相关的PL/SQL类型,项和子程序,由包规范和包体组成
1.建立包规范:包规范是包与应用程序之间的接口,用于定义包的公用组件,包括常量,变量,游标,过程,函数等
create [or replace] package package_name
is|as
public type and item declarations
subprogram specificationsend package_name;
create or replace package emp_package is
g_deptno number(3):=30;
procedure add_employee(eno number,name varchar2,salary number,dno number default g_deptno);
procedure fire_employee(eno number);
function get_sal(eno number) return number;
end emp_package;
2.建立包体:用于实现包规范所定义的过程和函数
create [or replace] package body package_name
is|as
private type and item declarations
subprogram bodies
end package_name;
create or repalce package body emp_package is
function validate_deptno(v_deptno number)
return boolean
is
v_temp int;
begin
select 1 into v_temp from dept where deptno=v_deptno;
return true;
exception
when no_date_found then
return false;
end;

procedure add_employee(eno number,name varchar2,salary number,dno number default g_deptno)
is
begin
  if validate_deptno(dno) then
     insert into emp(empno,ename,sal,deptno) values(eno,name,salsry,dno);
  else
     raise_application_error(-20010,'不存在该部门');
  end if;
exception
  when dup_val_on_index then
     raise_application_error(-20012,'该雇员已存在');
end;

procedure fire_employee(eno number) is
begin
  delete from emp where empno=eno;
  if sql%notfound then 
     raise_application_error(-20012,'该雇员不存在');
  end if;
end;

function get_sal(eno number) return number
is
  v_sal emp.sal%type;
begin
  select sal into v_sal from emp where empno=eno;
  return v_sal;
exception
  when no_data_found then
    raise_application_error(-20012,'该雇员不存在');
end;

end emp_package;
3.调用包组件
3.1在同一个包内调用包组件
create or replace package body emp_package is

procedure add_employee(eno number,name vauchar2,salary number,dno number default g_deptno)
is
begin
if validate_deptno(dno) then
insert into emp(empno,ename,sal,deptno) values(eno,name,salary,dno);
else
raise_application_error(-20010,’该部门不存在’)
end if;
exception
when dup_val_on_index then
raise_application_error(-20011,’该雇员已存在’)
end;
………
3.2调用包公用变量
exec emp_package.g_deptno:=20
3.3调用包公用过程
exec emp_package.add_employee(1111,’mary’,2000)
3.4调用包公用函数
var salary number
exec :salary:=emp_package.get_sal(7788)
print salary
3.5以其他用户身份调用包公用组件
conn system/manager
exec scott.emp_package.add_employee(1115,’scott’,1200)
exec scott.emp_package.fire_employee(1115)
3.6调用远程数据库包的公用组件
exec emp_package.add_employee@orasrv(1116,’scott’,1200)

4.查看源代码:存放在数据字典USER_SCOURCE中
select text from user_source where name=’emp-package’ and type=’package’;
5.删除包
drop package emp_package;

6.使用包重载
重载(overload)是指多个具有相同名称的子程序
1.建立包规范
同名的过程和函数必须具有不同的输入参数,同名函数返回值的数据类型必须完全相同
create or replace package overload is
function get_sal(eno number) return number;
function get_sal(name varchar2) return number;
procedure file_employee(eno number);
procedure file_employee(name varchar2);
end;
2.建立包体
必须要给不同的重载过程和重载函数提供不同的实现代码
create or replace package body overload is

function get_sal(eno number) return number
is 
  v_sal emp.sal%type;
begin
  select sal into v_sal from emp where empno=eno;
  return v_sal;
exception
  when no_data_found then
    raise_application_error(-20020,'该雇员不存在');
end;
function get_sal(name varchar2) return  number
is
  v_sal emp.sal%type;
begin
  select sal into v_sal from emp where upper(ename)=upper(name);
  return v_sal;
exception
  when no_data_found then
    raise_application_error(-20020,'该雇员不存在');
end;
procedure fire_employee(eno number) is
begin
  delete from emp where empno=no;
  if sql%notfound then
    raise_application_error(-20020,'该雇员不存在');
  end if;
end;
procedure fire_employee(name varchar2) is
begin
  delete from emp where upper(ename)=upper(name);
  if sql%notfound then
    raise_application_error(-20020,'该雇员不存在');
  end if;
end;

end;

3.调用重载过程和重载函数
var sal1 number
var sal2 number
exec :sal1:=overload.get_sal(‘scott’)
exec :sal2:=overload.get_sal(7685)
exec overload.fire_employee(7369)
exec overload.fire_employee(‘scott’)
7.使用包构造过程
类似于高级语言中的构造函数和构造方法
1.建立包规范
包的构造过程用于初始化包的全局变量.
create or replace package emp_package is
minsal number(6,2);
maxsal number(6,2);
procedure add_employee(eno number,name varchar2,salary number,dno number);
procedure upd_sal(eno number,salary number);
procedure upd_sal(name varchar2,salary number);
end;

2.建立包体
包的构造过程没有任何名称,它是实现了包的其他过程后,以BEGIN开始,END结束的部分
create or replace package body emp_package is

procedure add_employee(eno number,name varchar2,salary number,dno number)
is
begin
if salary between minsal and maxsal then
  insert into emp (empno,ename,sal,deptno) values(eno,name,salary,dno);
else
  raise_application_error(-20001,'工资不在范围内');
end if;
exception
  when dup_val_on_index then
    raise_application_error(-20002,'该雇员已经存在');
end;

procedure upd_sal(eno number,salary number) is
begin
  if salary between minsal and maxsal then
     update emp set sal=salary where empno =eno;
     if sql%notfound then
       raise_application_error(-20003,'不存在雇员号');
     end if;
  else
     raise_application_errpr(-20001,'工资不在范围内');
  end if;

end;
procedure upd_sal(name varchar2,salary number) is
begin
if salary between minsal and maxsal then
update emp set sal=salary where upper(ename)=upper(name);
if sql%notfound then
raise_application_error(-20004,’不存在该雇员名’);
end if;
else
raise_application_error(-20001,’工资不在范围内’);
end if;
end;
begin
select mi(sal),max(sal) into minsal,maxsal from emp ;
end;
调用包公用组件:构造过程只调用一次
exec emp_package.add_employee(1111,’mary’,3000,20)
exec emp_package.upd_sal(‘mary’,2000)

8.使用纯度级别
在SQL中引用包的公用函数,该公用函数不能包含DML语句(insert,update,delete),也不能读写远程包的变量
为了对包的公用函数加以限制,在定义包规范时,可以使用纯度级别(purity level)限制公用函数
语法:pragma restrict_references (function_name,wnds[,wnps][,rnds][,rnps]);
wnds:用于限制函数不能修改数据库数据(禁止DML)
wnps:用于限制函数不能修改包变量(不能给包变量赋值)
rnds:用于限制函数不能读取数据库数据(禁止SELECT操作)
rnps:用于限制函数不能读取包变量(不能将包变量赋值给其他变量)
1.建立包规范
create or replace package purity is
minsal number(6,2);
maxsal number(6,2);
function max_sal return number;
function min_sal return number;
pragma restrict_references(max_sal,wnps);–不能修改
pragma restrict_references(min_sal,wnps);
end;

2.建立包体
create or replace package body purity is
function max_sal return number
is
begin
return maxsal;
end;

function min_sal return number
is
begin
return minsal;
end;

begin
select min(sal),max(sal) into minsal,maxsal from emp;
end;
3.调用包的公用函数
var minsal number
var maxsal number
exec :minsal:=purity.minsal()
exec :maxsal:=purity.maxsal()
print minsal maxsal

12.触发器
存放在数据库中,并被隐含执行的存储过程.
可基于表和视图的DML(INSERT,UPDATE,DELETE),系统事件(启动,关闭,登陆数据库)和DDL操作建立触发器.
触发器由触发事件,触发条件,触发操作三部分组成
1.1触发事件
启动和关闭数据库,ORACLE错误消息,用户登录和断开会话,特定表或视图的DML操作,在任何方案上的DDL语句

1.2.触发条件(可选)
指使用WHEN子句指定一个BOOLEAN表达式,返回为TRUE时,触发

1.3.触发操作
指包含SQL语句和其他执行代码的PL/SQL块.
触发器的代码大小不能超过32K.(可使用CALL语句调用存储过程)
出发器只能包含SELECT,INSERT,UPDATE,DELETE语句,不能包含DDL语句(CREATE,ALTER,DROP)和事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)

2.建立DML触发器
当建立DML触发器时,需要指定触发时机(BEFORE,AFTER),触发事件(INSERT,UPDATE,DELETE),表名,触发类型,触发条件,操作.
2.1触发时机
指定触发器的触发时间,之前(BEFORE),之后(AFTER)
2.2触发事件
指定导致触发器执行的DML操作,也即INSERT,UPDATE,DELTE操作
2.3表名
必须指定DML操作所对应的表
2.4触发类型
指定触发事件发生后,需要执行几次触发操作,默认执行一次触发器代码
如果指定行触发类型,则会在每个被作用行上执行一次触发器代码
2.5触发条件
指定执行触发器代码的条件
当编写DML触发器时,只允许在行触发器上指定触发条件
2.6触发操作
指定触发器执行代码.(若使用PL/SQL,JAVA,或外部存储过程,可直接使用CALL调用相应过程)
2.7DML触发器触发顺序
DML触发器在单行数据上的触发顺序
对于单行数据而言,无论是语句触发器,还是行触发器,触发器代码实际只被执行一次,顺序为:
before语句,before行,dml操作,after行,after语句

DML触发器在多行数据上的触发顺序
对于多行数据而言,语句触发器只被执行一次,而行触发器在每个作用行上都执行一次

3.语句触发器
当执行DML操作时会自动执行触发器的相应代码.
使用语句触发器时,不能记录列数据的变化
语法:create [or replace] trigger trigger_name
timing event1 [or event2 or event3]
on table_name
pl/sql block
3.1建立BEFORE语句触发器
create or replace trigger tr_sec_emp
before insert or update or delete on emp
begin
if to_char(sysdate,’DY’,’nls_date_language=AMERICAN’) IN (‘SAT’,’SUN’) THEN
raise_application_error(-20001,’不能在休息日改变雇员信息’);
end if;
end;
3.2使用条件谓词:inserting,updating,deleting是该操作时返回TRUE,否则FALSE
create or replace trigger tr_sec_emp
before insert or update or delete on emp
begin
if to_char(sysdate,’DY’,’nls_date_language=AMERICAN’) IN (‘SAT’,’SUN’) THEN
CASE
WHEN INSERTING THEN
raise_application_error(-20001,’不能在休息日增加雇员’);
WHEN UPDATING THEN
raise_application_error(-20002,’不能在休息日更新雇员’);
WHEN DELETING THEN
raise_application_error(-20003,’不能在休息日解雇雇员’);
end case;
end if;
end;

4.建立AFTER语句触发器
为了审计DML操作,或者在DML操作之后执行汇总运算.(计算INSERT,UPDATE,DELETE的操作次数)
create table audit_table(name varchar2(20),ins int,upd int,del int,starttime date,endtime date);

create or replace trigger tr_audit_emp
after insert or update or delete on emp
declare
v_temp int;
begin
select count(*) into v_temp from audit_table where name=’emp’;
if v_temp=0 then
insert into audit_table values(‘emp’,0,0,0,sysdate,null);
end if;
case
when inserting then update audit_table set ins=ins+1,endtime=sysdate where name=’emp’;
when updating then update audit_table set upd=upd+1,endtime=sysdate where name=’emp’;
when deleting then update audit_table set del=del+1,endtime=sysdate where name=’emp’;
end case;
end;
5.行触发器
执行DML操作时,每作用一行就触发一次的触发器.审计数据变化时,可以使用行触发器
create [or replace] trigger trigger_name
timing event1 [or event2 or event3]
on table_name
[referencing old as old |new as new]
for each row
[when condition]
pl/sql block;
5.1建立BEFORE行触发器
create or relpace trigger tr_emp_sal
before update of sal on emp
for each row
begin
if :new.sal<:old.sal then
raise_application_error(-20010,’工资只涨不降’);
end if ;
end;
5.2建立AFTER行触发器
为了审计DML操作数据变化,则应该使用AFTER行触发器
create table audit_emp_change(name varchar2(10),oldsal number(6,2),newsal number(6,2),time date);

create or replace trigger tr_sal_change
after update of sal on emp
for each row
declare
v_temp int;
begin
select count(*) into v_temp from audit_emp_change where name=:old.ename;
if v_temp=0 then
insert into audit_emp_change values(:old.ename,:old.sal,:new,sal,sysdate);
else
update audit_emp_change set oldsal=:old.sal,newsal=:new.sal,time=sysdate where name=:old.ename;
end if;
end;
5.3限制行触发器
使用行触发器时,默认情况下会在每个被作用行上执行一次触发器代码,为了使得在特定条件下执行行触发器代码,就需要使用WHEN子句对触发器加以限制
create or replace trigger tr_sal_change
after update of sal on emp
for each row
when (old.job=’salesman’)
declare
v_temp int;
begin
select count(*) into v_temp from audit_emp_change where name=:old.ename;
if v_temp=0 then
insert into audit_emp_change values(:old.ename,:old.sal,:new.sal,sysdate);
else
update audit_emp_change set oldsal=:old.sal,newsal=:new.sal,time=sysdate where name=:old.ename;
end if;
end;
5.4DML触发器使用注意事项
编写DML触发器时,不能从触发器所对应的基表中读取数据.建立时不会出现错误,但在执行相应触发操作时会显示错误信息

6.使用DML触发器
DML触发器可以用于实现数据安全保护,数据审计,数据完整性,参照完整性,数据复制等
6.1控制数据安全
在服务器级控制数据安全是通过授予和收回对象权限来完成的.
conn scott/tiger
grant select,insert,update,delete on emp to smith;
create or replace trigger tr_emp_time
before insert or update or delete on emp
begin
if to_char(sysdate,’hh24’) not between ‘9’ and ‘17’ then
raise_application_error(-20101,’非工作时间’);
end if;
end;
6.2实现数据审计
审计可以用于监视非法和可疑的数据库活动.ORACLE数据库本身提供了审计功能
对EMP表上的DML操作进行审计
audit insert,update,delete on emp by access;
只能审计SQL操作,写入到数据字典中,而不会记载数据变化.为了审计SQL操作引起的数据变化,使用DML触发器
create or replace trigger tr_sal_change
after update of sal on emp
for each row
declare
v_temp int;
begin
select count(*) into v_temp from audit_emp_change where name=:old.ename;
if v_temp=0 then
insert into audit_emp_change values(:old.ename,:old.sal,:new.sal,sysdate);
else
update audit_emp_change set oldsal=:old.sal,newsal=:new.sal,time=sysdate where name=:old.ename;
end if;
end;
6.3实现数据完整性
数据完整性用于确保数据库数据满足特定的商业逻辑或企业规则.
CHECK约束:alter table emp add constraint ck_sal check (sal>=800);
create or replace trigger tr_check_sal
before update of sal on emp
for each row
when (new.sal

时间

2001/01/07 23:51:21
2001/01/07 23:52:22
2001/01/07 23:53:24
删除JOB
SQL> begin
2 dbms_job.remove(:job1);
3 end;
4 /
PL/SQL 过程已成功完成。
=======================================

a、利用dbms_job.run()立即执行该job
sql>begin
sql>dbms_job.run(:jobno) 该jobno为submit过程提交时返回的job number
sql>end;
sql>/
b、利用dbms_job.broken()重新将broken标记为false
sql>begin
sql>dbms_job.broken (:job,false,next_date)
sql>end;
sql>/
========================================
SQL> create table a(a date);
Table created
创建一个过程
SQL> create or replace procedure test as
2 begin
3 insert into a &#118alues(sysdate);
4 end;
5 /
Procedure created
提交作业
SQL> declare
2 job1 number; //定义一个数字型变量
3 begin
4 dbms_job.submit(:job1,’test;’,sysdate,’sysdate+1/1440’); //按分钟算一天1440分钟
5 end;
6 /
PL/SQL procedure successfully completed

job1

4
SQL> commit;
Commit complete
运行作业
SQL> begin
2 dbms_job.run(4);
3 end;
4 /
PL/SQL procedure successfully completed
删除作业
SQL> begin
2 dbms_job.remove(4);
3 end;
4 /
PL/SQL procedure successfully completed
SQL> commit;
Commit complete

job change//修改作业
execute dbms_job.change(186,null,null,’sysdate+3’);
execute dbms_job.change(186,’scott.test(update)’);
DBA_JOBS
===========================================
字段(列) 类型 描述
JOB NUMBER 任务的唯一标示号
LOG_USER VARCHAR2(30) 提交任务的用户
PRIV_USER VARCHAR2(30) 赋予任务权限的用户
SCHEMA_USER VARCHAR2(30) 对任务作语法分析的用户模式
LAST_DATE DATE 最后一次成功运行任务的时间
LAST_SEC VARCHAR2(8) 如HH24:MM:SS格式的last_date日期的小时,分钟和秒
THIS_DATE DATE 正在运行任务的开始时间,如果没有运行任务则为null
THIS_SEC VARCHAR2(8) 如HH24:MM:SS格式的this_date日期的小时,分钟和秒
NEXT_DATE DATE 下一次定时运行任务的时间
NEXT_SEC VARCHAR2(8) 如HH24:MM:SS格式的next_date日期的小时,分钟和秒
TOTAL_TIME NUMBER 该任务运行所需要的总时间,单位为秒
BROKEN VARCHAR2(1) 标志参数,Y标示任务中断,以后不会运行
INTERVAL VARCHAR2(200) 用于计算下一运行时间的表达式
FAILURES NUMBER 任务运行连续没有成功的次数
WHAT VARCHAR2(2000) 执行任务的PL/SQL块
CURRENT_SESSION_LABEL RAW MLSLABEL 该任务的信任Oracle会话符
CLEARANCE_HI RAW MLSLABEL 该任务可信任的Oracle最大间隙
CLEARANCE_LO RAW MLSLABEL 该任务可信任的Oracle最小间隙
NLS_ENV VARCHAR2(2000) 任务运行的NLS会话设置
MISC_ENV RAW(32) 任务运行的其他一些会话参数

描述 INTERVAL参数值
每天午夜12点 ‘TRUNC(SYSDATE + 1)’
每天早上8点30分 ‘TRUNC(SYSDATE + 1) + (8*60+30)/(24*60)’
每星期二中午12点 ‘NEXT_DAY(TRUNC(SYSDATE ), ”TUESDAY” ) + 12/24’
每个月第一天的午夜12点 ‘TRUNC(LAST_DAY(SYSDATE ) + 1)’
每个季度最后一天的晚上11点 ‘TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), ‘Q’ ) -1/24’
每星期六和日早上6点10分 ‘TRUNC(LEAST(NEXT_DAY(SYSDATE, ”SATURDAY”), NEXT_DAY(SYSDATE, “SUNDAY”))) + (6×60+10)/(24×60)’

*****************************************************************************8
job查询:
select * from user_jobs;

创建
variable job number;
begin
sys.dbms_job.submit(job => :job,
what => ‘PK_EZS_AG_DATA.main();’,
next_date => to_date(‘20120818 09:01:00’, ‘yyyy-mm-dd hh24:mi:ss’),
interval => ‘sysdate+10/1440’);
commit;
end;
/

删除
exec dbms_job.remove(29);

停止一个JOB
SQL> exec dbms_job.broken(1,true)

启动job
SQL> exec dbms_job.broken(1,false)

执行job:
exec dbms_job.run(4);
*****************************************************************************8
alter system set job_queue_processes = 10
(根據需要可以調整為不同的值,一般10個左右就夠的了。

*****************************************************************************8
ora-00054:resource busy and acquire with nowait specified解决方法

当某个数据库用户在数据库中插入、更新、删除一个表的数据,或者增加一个表的主键时或者表的索引时,常常会出现ora-00054:resource busy and acquire with nowait specified这样的错误。

主要是因为有事务正在执行(或者事务已经被锁),所有导致执行不成功。

1、用dba权限的用户查看数据库都有哪些锁

select t2.username,t2.sid,t2.serial#,t2.logon_time
from v lockedobjectt1,v l o c k e d o b j e c t t 1 , v session t2
where t1.session_id=t2.sid order by t2.logon_time;

如:testuser 339 13545 2009-3-5 17:40:05
知道被锁的用户testuser,sid为339,serial#为13545

2、根据sid查看具体的sql语句,如果sql不重要,可以kill

select sql_text from v sessiona,v s e s s i o n a , v sqltext_with_newlines b
where DECODE(a.sql_hash_value, 0, prev_hash_value, sql_hash_value)=b.hash_value
and a.sid=&sid order by piece;

查出来的sql,如: begin :id := sys.dbms_transaction.local_transaction_id; end;

3、kill该事务
alter system kill session ‘339,13545’;

4、这样就可以执行其他的事务sql语句了

如增加表的主键:
alter table test
add constraint PK_test primary key (test_NO);

=====================================================================cmd进入:
1. D:\oracle\ora92\bin>
2. sqlplus /nolog
3. conn sys/sys as sysdba

sqlplus进入:
username:sys
password:sys
HostString: test as sysdba



用户管理
创建用户,设定权限

  1. create user fusp identified by fusp default tablespace users temporary tablespace temp;
  2. grant dba to fusp; –dba,recource,connect –赋权限
  3. alter system set resource_limit=true scope=both; –期限,密码等
  4. disconnect;
  5. conn fusp/fusp;
  6. show user;

创建profile
create profile px_test limit
sessions_per_user 3
idle_time 10; –单位:分钟

创建用户
create user dd identified by dd
default tablespace users
temporary tablespace temp
profile px_test;



创建的dba用户,都会存放到dba_users表中
修改用户的默认表空间:
alter user fusp default tablespace users;

查询:
select username,DEFAULT_TABLESPACE from dba_users;




启动:
SQL> startup
ORACLE instance started.

    Total System Global Area  143727516 bytes
    Fixed Size                   453532 bytes
    Variable Size             109051904 bytes
    Database Buffers           33554432 bytes
    Redo Buffers                 667648 bytes
    Database mounted.
    Database opened.

看数据库归档模式
SQL> archive log list;
Database log mode No Archive Mode
Automatic archival Disabled
Archive destination D:\oracle\ora92\RDBMS
Oldest online log sequence 15
Current log sequence 17

查看归档相关初始化参数
show parameter archive


创建spfile
1. startup pfile=D:\oracle\admin\test\pfile\init.ora
2. create pfile from spfile;(根据提示将相应的文件拷贝)


更改存档路径
1. startup; –启动oracle
2. alter system set log_archive_start = true scope = spfile; –修改数据库
3. show parameter archive –查看归档参数参数
4. alter system set log_archive_dest_1=’location=D:\oracle\admin\test\temp’ scope =spfile; –更改log_archive_dest_1的存档路径
5. shutdown –关闭
6. startup; –启动
7. show parameter archive –再次查看一下归档参数

把归档日志文件切换:
1. alter system switch logfile;

创建表空间:
create tablespace exam datafile ‘D:\oracle\admin\test\temp\example1.dbf’ size 10M;

修改表空间:
alter tablespace exam add datafile ‘D:\oracle\admin\test\temp\example2.dbf’ size 5M;

查看表空间大小:
select tablespace_name,sum(bytes/1024/1024)
from dba_data_files group by tablespace_name;

查询动态表空间
select * from v$tablespace;

区管理方式
Select tablespace_name,extent_management from dba_tablespaces;

表空间类型
Select tablespace_name,status,contents from dba_tablespaces;

数据文件自动扩展
Select file_name, AUTOEXTENSIBLE,status,bytes/1024/1024 from dba_data_files where tablespace_name= ‘USERS’;

查看日志
select * from v logfile;selectfromv l o g f i l e ; s e l e c t ∗ f r o m v log;

添加group
alter database add logfile ‘d:\temp\aa.log’ size 5M;
alter database add logfile group 5 ‘d:\temp\aa1.log’ size 5M;

添加成员member
alter database add logfile member ‘d:\temp\aa2.log’ to group 4;

控制文件位置:
1.查看初始化参数 :init.ora
2 打开文件找到control_files:*

生成本地Tablespace
create tablespace example02 datafile ‘c:\’ ????????????????????????????


修改表空间状态 (读和写 在线与下线)
变:
alter tablespace exam read only;
alter tablespace exam read write;
查:
select tablespace_name,status,contents
from dba_tablespaces;


变:
alter tablespace exam offline;
alter tablespace exam online;
查:
select name,status from v$datafile;


创建临时表空间:
create temporary tablespace temptablespace tempfile ‘d:\temp\temptablespace.dbf’ size 5M
extent management local uniform size 100k;

付少苹
查询表数据文件实际大小
select file_name,bytes/1024/1024 from dba_data_files ;

查询表空间空闲
select tablespace_name,sum(bytes/1024/1024)
from dba_free_space group by tablespace_name;

查询 临时表空间 实际大小
select tablespace_name,file_name,bytes/1024/1024 from dba_temp_files;

设置行长
set linesize 100;

设置 格式
col tablespace_name format a50;


查看表空间大小:
select tablespace_name,sum(bytes/1024/1024)
from dba_data_files
where tablespace_name=’EXAM’
group by tablespace_name;

修改表空间大小
alter database datafile ‘D:\oracle\admin\test\temp\example2.DBF’ resize 20M;

自动变更表空间大小
alter database datafile ‘D:\oracle\admin\test\temp\example2.DBF’ autoextend on next 1M maxsize 20M;


删除表空间:
drop tablespace example02;
including contents and datafiles;(连带数据文件一起删除)


查询表空间tablesapce:
select tablespace_name,status from dba_tablespaces;
select * from v$tablespace;

查询块segment:
select segment_name,tablespace_name from dba_segments where segment name=’DEPT’;

查询extent:
select segment_name,extent_id from dba_extents where segment_name=’DEPT’;









DBA基础操作:

创建表:
create table employee
(
empno char(5),
ename varchar2(10),
job varchar2(20),
deptno char(2)
)
–storage(initial 200k next 200k minextents 2,maxextents 100)
tablespace exam;

变更表:
alter table employee storage(next 300k maxextents 150);

alter table employee allocate extent(size 600k);

alter table employee deallocate unused;

添加column:
alter table employee add column(sal number(5));

删除里column:
1.alter table employee drop column job;

2.alter table employee set unused column job; –需要先将其置为不用,然后再进行删除,提高性能
alter table employee drop unused columns;

创建临时表:
1. create global temporary table temp1 –事务提交时,数据被删除
(a number, b number)
on commit delete rows;

  1. create global temporary table temp2 –session结束时将其删除,与事务无关
    (a number, b number)
    on commit preserve rows;


删除表数据:
Truncate table employee; –不可恢复;

删除表
drop table employee;

删除表连带相关约束
drop table dept cascade constraints;


查看该用户下,所有的表:
select table_name from user_tables;

***********************************************************************8
导出数据库:
在cmd化境下:
exp scott/tiger file=d:/test1.dmp log=d:/test1.log tables=dept –tables
exp scott/tiger file=d:/test1.dmp log=d:/test1.log owner=scott –user
exp scott/tiger file=d:/test1.dmp log=d:/test1.log tablespaces=users –tablespaces
exp scott/tiger file=d:/test1.dmp log=d:/test1.log full=y –all

导入数据库:
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log tables=dept row=y
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log fromuser=scott touser=scott
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log tablespaces=users
imp userid=scott/tiger file=d:/test1.dmp log=d:/test1.log full=y

查询Server端 字符集
select userenv(‘language’) from dual;

oracle解决temp01.dbf文件过大的方法2009-09-09 09:25第一步删除原来的文件
SQL>alter database tempfile ‘d:\oracle\oradata\ynrmdb\temp01.dbf’ drop ;
Database altered.
第二步添加新的临时文件
SQL>alter tablespace temp add tempfile
2’d:\oracle\oradata\ynrmdb\temp01.dbf’
3 size 2048M reuse autoextend on next 100M;
Tablespace altered.
SQL> select d.file_name, d.file_id, d.tablespace_name, d.bytes from dba_temp_files d;
第三步查看当前临时文件
FILE_NAME FILE_ID TABLESPACE_NAME BYTES


D:\ORACLE\ORADATA\YNRMDB\TEMP01.DBF 1 TEMP 2147483648

=============================================================================================================
Oracle数据导入导出imp/exp就相当于oracle数据还原与备份。exp命令可以把数据从远程数据库服务器导出到本地的dmp文件,imp命 令可以把dmp文件从本地导入到远处的数据库服务器中。 利用这个功能可以构建两个相同的数据库,一个用来测试,一个用来正式使用。

执行环境:可以在SQLPLUS.EXE或者DOS(命令行)中执行,
DOS中可以执行时由于 在oracle 8i 中 安装目录\ora81\BIN被设置为全局路径,
该目录下有EXP.EXE与IMP.EXE文件被用来执行导入导出。
oracle用java编写,SQLPLUS.EXE、EXP.EXE、IMP.EXE这两个文件有可能是被包装后的类文件。
SQLPLUS.EXE调用EXP.EXE、IMP.EXE所包裹的类,完成导入导出功能。

下面介绍的是导入导出的实例。
数据导出:
1 将数据库TEST完全导出,用户名system 密码manager 导出到D:\daochu.dmp中
exp system/manager@TEST file=d:\daochu.dmp full=y

2 将数据库中system用户与sys用户的表导出
exp system/manager@TEST file=d:\daochu.dmp owner=(system,sys)

3 将数据库中的表inner_notify、notify_staff_relat导出
exp aichannel/aichannel@TESTDB2 file= d:\data\newsmgnt.dmp tables=(inner_notify,notify_staff_relat)

4 将数据库中的表table1中的字段filed1以”00”打头的数据导出
exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\” where filed1 like ‘00%’\”

上面是常用的导出,对于压缩,既用winzip把dmp文件可以很好的压缩。
也可以在上面命令后面 加上 compress=y 来实现。

数据的导入
1 将D:\daochu.dmp 中的数据导入 TEST数据库中。
imp system/manager@TEST file=d:\daochu.dmp
imp aichannel/aichannel@HUST full=y file=file= d:\data\newsmgnt.dmp ignore=y
上面可能有点问题,因为有的表已经存在,然后它就报错,对该表就不进行导入。
在后面加上 ignore=y 就可以了。

2 将d:\daochu.dmp中的表table1 导入
imp system/manager@TEST file=d:\daochu.dmp tables=(table1)

基本上上面的导入导出够用了。不少情况要先是将表彻底删除,然后导入。

注意:
操作者要有足够的权限,权限不够它会提示。
数据库时可以连上的。可以用tnsping TEST 来获得数据库TEST能否连上。

附录一:
给用户增加导入数据权限的操作
第一,启动sql*puls
第二,以system/manager登陆
第三,create user 用户名 IDENTIFIED BY 密码 (如果已经创建过用户,这步可以省略)
第四,GRANT CREATE USER,DROP USER,ALTER USER ,CREATE ANY VIEW ,
DROP ANY VIEW,EXP_FULL_DATABASE,IMP_FULL_DATABASE,
DBA,CONNECT,RESOURCE,CREATE SESSION TO 用户名字
第五, 运行-cmd-进入dmp文件所在的目录,
imp userid=system/manager full=y file=*.dmp
或者 imp userid=system/manager full=y file=filename.dmp

执行示例:
F:\Work\Oracle_Data\backup>imp userid=test/test full=y file=inner_notify.dmp

屏幕显示
Import: Release 8.1.7.0.0 - Production on 星期四 2月 16 16:50:05 2006
(c) Copyright 2000 Oracle Corporation. All rights reserved.

连接到: Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production

经由常规路径导出由EXPORT:V08.01.07创建的文件
已经完成ZHS16GBK字符集和ZHS16GBK NCHAR 字符集中的导入
导出服务器使用UTF8 NCHAR 字符集 (可能的ncharset转换)
. 正在将AICHANNEL的对象导入到 AICHANNEL
. . 正在导入表 “INNER_NOTIFY” 4行被导入
准备启用约束条件…
成功终止导入,但出现警告。

附录二:
Oracle 不允许直接改变表的拥有者, 利用Export/Import可以达到这一目的.
先建立import9.par,
然后,使用时命令如下:imp parfile=/filepath/import9.par
例 import9.par 内容如下:
FROMUSER=TGPMS
TOUSER=TGPMS2 (注:把表的拥有者由FROMUSER改为TOUSER,FROMUSER和TOUSER的用户可以不同)
ROWS=Y
INDEXES=Y
GRANTS=Y
CONSTRAINTS=Y
BUFFER=409600
file==/backup/ctgpc_20030623.dmp
log==/backup/import_20030623.log

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

========================================================================================================

*****************************************************************************8

–example6.1.1>cursor ‘s row set is allowed null;
DECLARE
CURSOR query_member
IS
SELECT name FROM MEMBER WHERE member_id=300;
BEGIN
OPEN query_member;
END;

*****************************************************************************8

–example6.1.2>it’s will be fetch,even if null;
DECLARE
CURSOR query_employee
IS
SELECT NAME FROM MEMBER WHERE member_id=300;
v_name MEMBER.NAME%TYPE;
BEGIN
OPEN query_employee;
FETCH query_employee INTO v_name ;
dbms_output.put_line(v_name);
END;

*****************************************************************************8

–example6.1.3>you should be familiar with the loop syntax .
DECLARE
CURSOR query_member IS SELECT * FROM MEMBER;
member_row MEMBER%ROWTYPE;
BEGIN
OPEN query_member;
LOOP
FETCH query_member INTO member_row ;
EXIT WHEN query_member%NOTFOUND OR query_member%ROWCOUNT > 2;
dbms_output.put_line(‘name is ‘||member_row.NAME);
END LOOP;
CLOSE query_member;
END;

*****************************************************************************8

–example6.2.1>a general syntax ,with conditions.
DECLARE
CURSOR query_employee IS SELECT first_name||last_name
FROM employees GROUP BY first_name||last_name ;
v_name VARCHAR2(20) ;
BEGIN
IF NOT query_employee%ISOPEN THEN
OPEN query_employee;
END IF ;

LOOP
FETCH query_employee INTO v_name ;
EXIT WHEN query_employee%NOTFOUND ;
dbms_output.put_line(‘name is ‘||v_name);
END LOOP;
CLOSE query_employee;
END;

*****************************************************************************8

–example6.2.2>explicit cursor attribute - %rowcount
DECLARE
CURSOR query_employee IS SELECT first_name||last_name FROM employees WHERE
employee_ID=5;
v_name VARCHAR2(20) ;
BEGIN
IF NOT query_employee%ISOPEN THEN
OPEN query_employee;
END IF ;
DBMS_OUTPUT.put_line(query_employee%Rowcount);
CLOSE query_employee;
END;

*****************************************************************************8

–example 6.3> for ..loop syntax
DECLARE
CURSOR member_cur IS SELECT NAME ,sal FROM MEMBER;
BEGIN
FOR member_rec IN member_cur LOOP
dbms_output.put(‘name =’|| member_rec.name|| ’ ‘);
dbms_output.put_line(‘sal = ‘||member_rec.sal);
END LOOP;
END;

*****************************************************************************8

–example 7.1>Cursors with parameters
DECLARE
CURSOR query_dept(dno NUMBER) IS
SELECT NAME,sal FROM MEMBER
WHERE dept_id=dno;
BEGIN
FOR r1 IN query_dept(10) LOOP
dbms_output.put_line(r1.NAME);
END LOOP;
END;

*****************************************************************************8

–example 8.1>using a no_data_found exception
DECLARE
v_name MEMBER.NAME%TYPE;
BEGIN
SELECT NAME INTO v_name FROM MEMBER
WHERE member_id = 100000;
Dbms_Output.put_line(v_name);
EXCEPTION
WHEN no_data_found THEN
Dbms_Output.put_line(‘the user doesn”t exist’);
END;

*****************************************************************************8

–example 8.2>using a too_many_rows exception
DECLARE
v_name MEMBER.Name%TYPE;
BEGIN
SELECT NAME INTO v_name FROM MEMBER WHERE dept_id=20;
EXCEPTION

WHEN too_many_rows THEN
dbms_output.put_line(‘too many rows’);
WHEN OTHERS THEN
dbms_output.put_line(‘others’);
END;

*****************************************************************************8

–example 8.3>confusion
BEGIN
DELETE FROM employees WHERE employee_id=&ID;
IF SQL%ROWCOUNT > 0 THEN
Dbms_Output.put_line(‘yes’);
ELSE
Dbms_Output.put_line(‘no’);
END IF;
END;

*****************************************************************************8

–example 8.4>using a invalid_cursor exception
DECLARE
v_name employees.first_name%TYPE;
CURSOR emp_cursor IS
SELECT first_name FROM employees WHERE employee_id=&ID;
BEGIN
FETCH emp_cursor INTO v_name;
CLOSE emp_cursor;
EXCEPTION
WHEN invalid_cursor THEN
dbms_output.put_line(‘请检查游标’);
END;

*****************************************************************************8

–example8.5>using a DUP_VAL_ON_INDEX exception
BEGIN
INSERT INTO employees (employee_id) VALUES(&ID);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
dbms_output.put_line(‘违反PK 约束’);
END;

*****************************************************************************8

–example8.6>no-pre exception
DECLARE
myexception EXCEPTION;
PRAGMA EXCEPTION_INIT (myexception,-2292);
BEGIN
DELETE FROM dept WHERE dept_id=20;
EXCEPTION
WHEN myexception THEN
dbms_output.put_line(‘该行已被其他表参照’);
WHEN OTHERS THEN
dbms_output.put_line(‘…..’);
END;

*****************************************************************************8

–example 8.7>user-defined exception
–[09:00-18:00] access
DECLARE
myexception EXCEPTION;
BEGIN
IF to_char(SYSDATE,’HH24:MI’) NOT BETWEEN ‘09:00’
AND ‘17:00’ THEN
RAISE myexception;
END IF;
dbms_output.put_line(‘001’);

EXCEPTION
WHEN myexception THEN
dbms_output.put_line(‘bbbb’);
END;

*****************************************************************************8

–example8.8>raise_application_error

BEGIN
IF to_char(SYSDATE,’HH24:MI’) NOT BETWEEN ‘09:00’
AND ‘17:00’ THEN
raise_application_error(‘-20000’,’不允许登陆’);
END IF;
dbms_output.put_line(‘001’);
/*EXCEPTION
WHEN OTHERS THEN
raise_application_error(‘-20030’,’不允许登陆’); */
END;

2.5*7/8=2.5

*****************************************************************************8
–example9.1>no parameter
CREATE OR REPLACE PROCEDURE procedure_no
IS
BEGIN
DBMS_OUTPUT.put_line(‘这是一个没有参数的例子’);
END ;

执行procedure的两种方法:
1:
BEGIN
procedure_no;
END;

2:在comm 上面
SQL> set serveroutput on
SQL> exec procedure_no;


create or replace procedure pp
is
begin
dbms_output.put_line(‘ddddd’);
end;

*****************************************************************************8

–example9.2>in parameter ,where is error .
CREATE OR REPLACE PROCEDURE PROCEDURE_PARAMETER_IN(P_DEPTNO IN
NUMBER) IS
V_MAX MEMBER.SAL%TYPE;
BEGIN
SELECT MAX(SAL) INTO V_MAX FROM MEMBER WHERE DEPT_ID = P_DEPTNO;
IF v_max IS NULL THEN
DBMS_OUTPUT.PUT_LINE(‘该部门目前没有员工’);
ELSE
DBMS_OUTPUT.PUT_LINE(P_DEPTNO || ’ 部门的最大薪资是’ || V_MAX);
END IF;
END;

执行
begin
PROCEDURE_PARAMETER_IN(11);
end;
*****************************************************************************8

–example9.3>out parameter
CREATE OR REPLACE PROCEDURE PROCEDURE_PARAMETER_OUT(P_ENO IN NUMBER,
P_ENAME OUT VARCHAR2)
IS
BEGIN
SELECT NAME INTO P_ENAME FROM MEMBER WHERE MEMBER_ID = P_ENO;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE(‘没有这个员工’);
END;
/*
define call env variable
exec procedure_name(in parameter, :define call env variable);
print define call env variable
*/
方法:
1: 在plsql:command环境下:
var name varchar2(20)
exec procedure_parameter_out(100,:name)
(补充:可以打印参数:print name)
2:
在sql*plus环境下:
SQL> set serveroutput on
SQL> declare v_name member.name%type;
2 begin
3 procedure_parameter_out(100,v_name);
4 dbms_output.put_line(v_name);
5 end;
6 /
3: 在plsql的sqlwindow下
declare v_name member.name%type;
begin
procedure_parameter_out(100,v_name);
dbms_output.put_line(v_name);
end;

*****************************************************************************8

–example9.5>in&out parameter
CREATE OR REPLACE PROCEDURE inout(p_input in OUT NUMBER)
IS
BEGIN
p_input :=p_input*p_input;
END;
/*
define call env variable & value
exec procedure_name(define call env variable);
print define call env variable
*/

调用方法:
方法1:plsql的command窗口下:
SQL> set serveroutput on
SQL> var num number
SQL> exec :num:=3

  PL/SQL procedure successfully completed
  num
  ---------
  3
  SQL> exec inout(:num)
  PL/SQL procedure successfully completed
  num
  ---------
  9

方法2:sql plus环境下:
SQL> declare
2 v_num number;
3 begin
4 v_num :=3;
5 inout(v_num);
6 dbms_output.put_line(v_num);
7 end;
8 /
9
PL/SQL 过程已成功完成。

*****************************************************************************8

–example9.6>parameter assign value
CREATE OR REPLACE PROCEDURE emp_info(p_dpid employees.department_id%TYPE,
p_j obid employees.j ob_id%TYPE DEFAULT 1)
IS
v_lastname employees.last_name%TYPE;
BEGIN
SELECT last_name INTO v_lastname FROM employees
WHERE department_id=p_dpid AND j ob_id=p_j obid;
dbms_output.put_line(‘last_name is ‘||v_lastname);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line(‘没有你要找的信息’);
END;
/*
exec procedure_name(Actual Parameters,Actual Parameters)
exec procedure_name(Formal parameters=>values,Formal parameters=>values)
exec procedure_name(Actual Parameters,Formal parameters=>values)
*/
CREATE OR REPLACE PROCEDURE test01 (
num1 NUMBER DEFAULT 1,
num2 NUMBER DEFAULT 2,
num3 NUMBER DEFAULT 3)
IS
BEGIN
dbms_output.put_line(‘num1 = ‘||num1);
dbms_output.put_line(‘num2 = ‘||num2);
dbms_output.put_line(‘num3 = ‘||num3);
END;
–run
EXEC test01(3,4,5);
EXEC test01(num2=>66,num3=>100,num1=>23);
EXEC test01(num2 => 33);
EXEC test01(11,num2=>44);
EXEC test01(num1=>30);
EXEC test01(1,num2=>44,2); 改正:EXEC test01(1,num2=>44,2);
exec test01(num3=>44,11,2);
BEGIN
FOR i IN 1..9 LOOP
FOR j IN 1..i LOOP
dbms_output.put(i||’*’||j ||’ = ‘||i*j || ’ ‘) ;
END LOOP;
dbms_output.put_line(”);
END LOOP;
END;

*****************************************************************************8

–example9.7>declaring subprograms
CREATE OR REPLACE PROCEDURE subproc (p_eid MEMBER.MEMBER_ID%TYPE)
IS
v_lastname MEMBER.Name%TYPE;
PROCEDURE log_select
IS
BEGIN
INSERT INTO Log_Table VALUES(USER,SYSDATE);
COMMIT;
END log_select;
BEGIN
SELECT NAME INTO v_lastname FROM MEMBER WHERE member_id=p_eid;
dbms_output.put_line(‘last_name’||v_lastname);
log_select;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line(‘没有你要找的信息’);
END;

*****************************************************************************8

CREATE OR REPLACE PROCEDURE add_member (p_eid MEMBER.MEMBER_ID%TYPE)
IS
v_lastname MEMBER.Name%TYPE;
PROCEDURE log_select
IS
BEGIN
INSERT INTO Log_Table VALUES(USER,SYSDATE);
COMMIT;
END log_select;
BEGIN
SELECT NAME INTO v_lastname FROM MEMBER WHERE member_id=p_eid;
dbms_output.put_line(‘last_name’||v_lastname);
log_select;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line(‘没有你要找的信息’);
END;

–9.8>handled exceptions
–9.8.1 raised a unhandle exception
CREATE OR REPLACE PROCEDURE TEST03 IS
BEGIN
INSERT INTO TEST VALUES (10, ‘test03’);
INSERT INTO TEST VALU

ES (11, ‘test03’);
TEST04;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(‘Create a exception ‘);
END;

CREATE OR REPLACE PROCEDURE TEST04 IS
BEGIN
INSERT INTO TEST VALUES (21, ‘test04’);
INSERT INTO TEST VALUES (22, ‘test04’);
RAISE_APPLICATION_ERROR(-20020, ‘raise a exception’);
END;

*****************************************************************************8

–9.8.2
/*the whole can be commit or rollback
called procedure’s exception is handled by itself */
CREATE OR REPLACE PROCEDURE test03
IS
BEGIN
INSERT INTO test VALUES(10,’test03’);
INSERT INTO test VALUES(11,’test03’);
test04;
COMMIT;
INSERT INTO test VALUES(13,’001’);
END;

CREATE OR REPLACE PROCEDURE test04
IS
BEGIN
INSERT INTO test VALUES(21,’t


创建同义词:
tb_sell_budget_state_m 是 chspe_mgr 用户下创建的表
如果希望将该表,在其他用户中使用,并且,希望直接运用,不用每次带上用户名,则需要创建 同义词

同义词执行,应该是在表所在的用户创建,本次,应该在 chspe_mgr 中执行如下语句:

GRANT SELECT, INSERT, UPDATE, DELETE ON TB_SELL_BRA_PL_M_H TO CHIS_APP;
GRANT SELECT, INSERT, UPDATE, DELETE ON TB_SELL_BRA_PL_M_H TO CHIS_MGR;
CREATE OR REPLACE SYNONYM CHIS_APP.TB_SELL_BRA_PL_M_H FOR CHSPE_MGR.TB_SELL_BUDGET_STATE_M;
CREATE OR REPLACE SYNONYM CHIS_MGR.TB_SELL_BRA_PL_M_H FOR CHSPE_MGR.TB_SELL_BUDGET_STATE_M;

tb_sell_budget_state_m

GRANT SELECT, INSERT, UPDATE, DELETE ON TB_SELL_BRA_PL_M_D TO CHIS_APP;
GRANT SELECT, INSERT, UPDATE, DELETE ON TB_SELL_BRA_PL_M_D TO CHIS_MGR;
CREATE OR REPLACE SYNONYM CHIS_APP.TB_SELL_BRA_PL_M_D FOR CHSPE_MGR.TB_SELL_BRA_PL_M_D;
CREATE OR REPLACE SYNONYM CHIS_MGR.TB_SELL_BRA_PL_M_D FOR CHSPE_MGR.TB_SELL_BRA_PL_M_D;

CREATE OR REPLACE SYNONYM CHIS_MGR.TB_SELL_BRA_PL_M_H FOR CHSPE_MGR.TB_SELL_BRA_PL_M_H;

TB_SELL_BRA_PL_M_H

lastMonRemaining

begin
chis_insert_budget_m_proc_test(201307);
chis_insert_budget_m_proc_test(201308);
chis_insert_budget_m_proc_test(201309);
chis_insert_budget_m_proc_test(201310);
chis_insert_budget_m_proc_test(201311);
chis_insert_budget_m_proc_test(201312);
chis_insert_budget_m_proc_test(201401);
chis_insert_budget_m_proc_test(201402);
chis_insert_budget_m_proc_test(201403);
chis_insert_budget_m_proc_test(201404);

end;


将上月数据copy到下月

INSERT INTO tb_sell_sell_in
(ID,
YYYYMM,
BRANCH_NAME,
BILL_TO_CODE,
PRODUCT_CODE,
MODEL_CODE,
SELL_IN_QTY,
SELL_IN_AMT,
AAI_FLAG,
CREATE_TIME,
LAST_UPDATE_TIME,
BRANCH_CODE,
SELL_IN_DATE,
INTERFACE_ID)
SELECT sq_sell_sell_in.nextval,
‘201404’,
BRANCH_NAME,
BILL_TO_CODE,
PRODUCT_CODE,
MODEL_CODE,
SELL_IN_QTY,
SELL_IN_AMT,
AAI_FLAG,
CREATE_TIME,
LAST_UPDATE_TIME,
BRANCH_CODE,
SELL_IN_DATE,
INTERFACE_ID
FROM tb_sell_sell_in t
WHERE t.yyyymm = ‘201403’


INSERT INTO tb_sell_stock_period_calc_st
(ID,
YYYYMM,
PRODUCT_CODE,
ACT_PERIOD,
ACT_YYYYMM,
USE_FLAG,
CREATE_DATE,
CREATE_EMP,
MODIFY_DATE,
MODIFY_EMP)
/*VALUES
(sq_sell_stock_period_calc_st.nextval,
‘201504’,
‘REF’,
1,
‘201503’,
‘Y’,
to_date(‘19-04-2014 14:04:52’, ‘dd-mm-yyyy hh24:mi:ss’),
‘SYSTEM’,
to_date(‘19-04-2014 14:04:52’, ‘dd-mm-yyyy hh24:mi:ss’),
‘SYSTEM’);*/
SELECT sq_sell_stock_period_calc_st.nextval,
‘201412’,
t.cata,
t.mon_12,
to_char(add_months(to_date(‘201412’, ‘YYYYMM’),to_number(t.mon_12)), ‘YYYYMM’),
‘Y’,
SYSDATE,
‘SYSTEM’,
SYSDATE,
‘SYSTEM’
FROM tmp001 t
WHERE 1 = 1;


oracle 模糊查询 下划线
select * from all_tables t
where t.TABLE_NAME like ‘TB_SELL_%_M%’ escape ‘\’
and t.OWNER =’CHSPE_MGR’;


BigDecimal:
(notBudgetSummary.compareTo(BigDecimal.ZERO) < 0 比较大小
budgetRemaining.add(notBudgetSummary); 追加
notBudgetSummary.subtract(selloutAmount); 减
BigDecimal.ZERO; 置为0
multiply 乘机
div 除


select * from TB_SELL_BRA_PL_M_H t
where t.branch_code in (‘40007’,’40044’,’40057’,’40054’,’40099’,’40005’,’40049’,’40008’,’70006’)
and to_char(t.create_date,’YYYYMM’) >= 201401
and to_char(t.create_date,’YYYYMM’) <= 201405
;


select * from user_source t
where t.TEXT like ‘%TB_SELL_BUDGET_STATE_HIS_M3%’
;


oracle 大于 小于 区别
用法:select sign(数值) from dual大于0返回1,等于0返回0,小于0返回-1


update TB_COM_SCREEN t
set t.screen_nm = (
select m.screen_nm from TB_COM_SCREEN m
where ‘sellpaym’||substr(m.screen_path, 8) = t.screen_path
and m.langage_type = t.langage_type
and m.screen_id< ‘500’
)
where t.screen_id >=’584’
and t.screen_id <=’606’
and t.screen_id not in (‘595’,’597’,’599’,’605’)
;


停止oracle的job

博客分类: oracle

  1. 首先确定要停止的JOB号

    在10g中可通过Dba_Jobs_Running进行确认。

    1. Broken你确认的JOB

    注意使用DBMS_JOB包来标识你的JOB为BROKEN。
    SQL> EXEC DBMS_JOB.BROKEN(job#,TRUE);

    注意:当执行完该命令你选择的这个JOB还是在运行着的。

  2. Kill 对应的Oracle Session

    应为BROKEN后该JOB还在运行,如果要求该JOB立刻停止,就需要找到该job的对应SESSION(SID,SERIAL#),然后执行以下命令:

    ALTER SYSTEM KILL SESSION ‘sid,serial#’;

    或者直接KILL对应的操作系统的SESSION,如果使用ALTER SYSTEM KILL SESSION执行很长时间,其实可以使用OS的命令来快速KILL掉SESSION.

    For Windows, at the DOS Prompt: orakill sid spid

    For UNIX at the command line> kill –9 spid

  3. 检查你的JOB是否还在运行

    检查你要停止的JOB是否还在运行,其实多数情况下,应该都已经停止了。尤其执行的第三步的“杀手”命令。如果真的还是没有停止,只好从第一道第三步重新做一下了。

  4. 将Job Queue Processes的数目修改为0

    首先确认当前的Job Queue Processes的数目

    SQL> col value for a10
    SQL> select name,value from v$parameter where name =’job_queue_processes’;

    然后将Job Queue Processes的数目修改为0

    SQL> ALTER SYSTEM SET job_queue_processes = 0;

    保证所有的JOB都会停止。

  5. 修改你要修改的任何东西,甚至是JOB内的内容。

  6. 修改完成后,将job的BROKEN状态停止。

SQL>EXEC DBMS_JOB.BROKEN(job#,FALSE):

  1. 恢复job_queue_processes的原始值

    ALTER SYSTEM SET job_queue_processes = original_value;

    至此整个停止并修改JOB完成.


oracle 创建同义词 并给其他用户授权

2013-02-26 14:43:54| 分类: oracle |举报|字号 订阅
授权:
有一个同义词:c_ship_data_file,在tc1_gctos_file下建立的,现在tc1_gctos要访问,则在tc1_gctos_file用户下执行:
grant all on c_ship_data_file to tc1_gctos;

创建同义词语句:
  create public synonym table_name for user.table_name;

  其中第一个user_table和第二个user_table可以不一样。
  此外如果要创建一个远程的数据库上的某张表的同义词,需要先创建一个Database Link(数据库连接)来扩展访问,然后在使用如下语句创建数据库同义词:create synonym table_name fortable_name@DB_Link;
  当然,你可能需要在user用户中给当前用户(user2)授权: grant select/delete/update on user2
  2.删除同义词:
  drop public synonym table_name;
  3.查看所有同义词:
  select * from dba_synonyms

  同义词拥有如下好处:节省大量的数据库


创建sequence
prompt
prompt Creating sequence SQ_SELL_BUDGET_CALC_LOG
prompt =========================================
prompt
create sequence CHSPE_MGR.SQ_SELL_BUDGET_CALC_LOG
minvalue 1
maxvalue 999999999
start with 3841
increment by 1
cache 20;

将本用户下的sequence赋予其他用户访问
grant SELECT,ALTER on SQ_SELL_BUDGET_CALC_LOG to CHIS_APP;
grant SELECT,ALTER on SQ_SELL_BUDGET_CALC_LOG to CHIS_MGR;

登录到需要使用sequence, 创建同义词,使用户能够直接访问(不必要带用户)
create or replace synonym chis_app.SQ_SELL_BUDGET_CALC_LOG for chspe_mgr.SQ_SELL_BUDGET_CALC_LOG;

select SQ_SELL_BUDGET_CALC_LOG.nextval from dual


oracle 多行转一列,一列转多行  
2011-10-28 16:46:54|  分类: Oracle|举报|字号 订阅

有一个表,表名为tab_test,如下:

一、多行转一列
select id, vnum, to_char(wmsys.wm_concat(vname)) c 
from tab_test group by id,vnum;
执行上述sql后,如下:

二、一列转多行
with a as (select ‘/ABC/AA/AD/ABD/JI/CC/ALSKD/ALDKDJ’ id from dual)
select regexp_substr(id,’[^/]+’,1,rownum) id from a
connect by rownum <= length(regexp_replace(id,’[^/]+’))
执行上述sql后如下:

阅读(8185)| 评论(3)


WMSYS.WM_CONCAT 函數的用法
 (2010-09-10 09:52:07)
转载▼
标签: 
杂谈
分类: 数据库及语言

select t.rank, t.Name from t_menu_item t;

    10 CLARK
    10 KING
    10 MILLER
    20 ADAMS
    20 FORD
    20 JONES
    20 SCOTT
    20 SMITH
    30 ALLEN
    30 BLAKE
    30 JAMES
    30 MARTIN
    30 TURNER
    30 WARD


我们通过 10g 所提供的 WMSYS.WM_CONCAT 函数即可以完成 行转列的效果

    select t.rank, WMSYS.WM_CONCAT(t.Name) TIME From t_menu_item t GROUP BY t.rank;

DEPTNO ENAME


    10 CLARK, KING, MILLER
    20 ADAMS, FORD, JONES, SCOTT, SMITH
    30 ALLEN, BLAKE, JAMES, MARTIN, TURNER, WARD
例子如下:
SQL> create table idtable (id number,name varchar2(30));
Table created
SQL> insert into idtable values(10,’ab’);
1 row inserted
SQL> insert into idtable values(10,’bc’);
1 row inserted
SQL> insert into idtable values(10,’cd’);
1 row inserted
SQL> insert into idtable values(20,’hi’);
1 row inserted
SQL> insert into idtable values(20,’ij’);
1 row inserted
SQL> insert into idtable values(20,’mn’);
1 row inserted
SQL> select * from idtable;
        ID NAME


        10 ab
        10 bc
        10 cd
        20 hi
        20 ij
        20 mn
6 rows selected
SQL> select id,wmsys.wm_concat(name) name from idtable
2 group by id;
        ID NAME


        10 ab,bc,cd
        20 hi,ij,mn
SQL> select id,wmsys.wm_concat(name) over (order by id) name from idtable;
        ID NAME


        10 ab,bc,cd
        10 ab,bc,cd
        10 ab,bc,cd
        20 ab,bc,cd,hi,ij,mn
        20 ab,bc,cd,hi,ij,mn
        20 ab,bc,cd,hi,ij,mn
6 rows selected
SQL> select id,wmsys.wm_concat(name) over (order by id,name) name from idtable;
        ID NAME


        10 ab
        10 ab,bc
        10 ab,bc,cd
        20 ab,bc,cd,hi
        20 ab,bc,cd,hi,ij
        20 ab,bc,cd,hi,ij,mn
6 rows selected
个人觉得这个用法比较有趣.
SQL> select id,wmsys.wm_concat(name) over (partition by id) name from idtable;
        ID NAME


        10 ab,bc,cd
        10 ab,bc,cd
        10 ab,bc,cd
        20 hi,ij,mn
        20 hi,ij,mn
        20 hi,ij,mn
6 rows selected
SQL> select id,wmsys.wm_concat(name) over (partition by id,name) name from idtable;
        ID NAME


        10 ab
        10 bc
        10 cd
        20 hi
        20 ij
        20 mn
6 rows selected
 
ps:
wmsys.wm_concat、sys_connect_by_path、自定义行数实现行列转换:
CREATE TABLE tab_name(ID INTEGER NOT NULL PRIMARY KEY,cName VARCHAR2(20));
CREATE TABLE tab_name2(ID INTEGER NOT NULL,pName VARCHAR2(20));
INSERT INTO tab_name(ID,cName) VALUES (1,’百度’);
INSERT INTO tab_name(ID,cName) VALUES (2,’Google’);
INSERT INTO tab_name(ID,cName) VALUES (3,’网易’);
INSERT INTO tab_name2(ID,pName) VALUES (1,’研发部’);
INSERT INTO tab_name2(ID,pName) VALUES (1,’市场部’);
INSERT INTO tab_name2(ID,pName) VALUES (2,’研发部’);
INSERT INTO tab_name2(ID,pName) VALUES (2,’平台架构’);
INSERT INTO tab_name2(ID,pName) VALUES (3,’研发部’);
COMMIT;
期望结果:
ID             cName                        pName               
1                 百度                     研发部,市场部
2                 Google                 研发部
3                  网易                     研发部,平台架构
方法一:使用wmsys.wm_concat()
SELECT t1.ID,t1.cName,wmsys.wm_concat(t2.pName) FROM tab_name t1,tab_name2 t2 WHERE t1.ID=t2.ID GROUP BY t1.cName,t1.id;
方法二:使用sys_connect_by_path
select id, cName, ltrim(max(sys_connect_by_path(pName, ‘,’)), ‘,’) from (select row_number() over(PARTITION by t1.id ORDER by cName) r,t1.*, t2.pName from tab_name t1, tab_name2 t2 where t1.id = t2.id)
start with r=1 CONNECT by prior r =r-1 and prior id = id group by id ,cName order by id;
方法三:使用自定义函数
create or replace function coltorow(midId INT) RETURN VARCHAR2 is
Result VARCHAR2(1000);
begin
FOR cur IN (SELECT pName FROM tab_name2 t2 WHERE midId=t2.id) LOOP
RESULT:=RESULT||cur.pName||’,’;
END LOOP;
RESULT:=rtrim(RESULT,’,’);
return(Result);
end coltorow;
SELECT t1.*,coltorow(t1.ID) FROM tab_name t1,tab_name2 t2 WHERE t1.ID=t2.ID GROUP BY t1.ID,t1.cname ORDER BY t1.ID;



取两个月期间所跨的月份:
SELECT to_char(t.from_date, ‘YYYYMM’),
to_char(t.end_date, ‘YYYYMM’),
trunc(months_between(t.end_date,t.from_date))+1
FROM tb_loca_bra_pl_h t

oracle如果 用直接减法,在同一年度计算没有问题,但是如果垮了年,就计算错误

201410-201502 = 92 系统会默认按照10进制计算

但是,实际 201410-201502 ==4 实际应该是4
年份计算按照10进制计算,但是月份应该是12进制,,逢十二进一 导致了该问题的发生

而 months_between 会精确到小数点,例如 4.5475
直接取整,


SELECT NVL(MAX(seq), 0) + 1 FROM TB_INTERFACE_LOG

 
修改DB内容:

alter table TB_SP_SAMPLE_DTL modify(ADDRESS3 varchar2(1000));
 
alter table TB_SP_SAMPLE_MST modify(PHONE_NO varchar2(30));

添加column:
alter table employee add column(sal number(5));
alter table TB_SP_SAMPLE_MST add total_amt number;

修改column:
alter table tb_sp_sample_dtl modify(TRANSACT_QTY number);

删除里column:
1.alter table employee drop column job;

修改表名 名字
alter table old_table_name rename to new_table_name;

修改字段名称
alter table TB_SP_SAMPLE_MST rename column salesperson_no to ORIGINAL_ID

查询表结构
所有字段
查询字段详细信息:
SELECT c.column_name,
c.DATA_TYPE,
c.DATA_LENGTH,
c.NULLABLE
FROM user_all_tables t, user_tab_columns c
WHERE t.table_name = c.table_name
AND t.table_name = ‘TB_SP_SAMPLE_DTL’

ORDER BY c.COLUMN_ID ASC

create table t_dept( 
id integer primary key, 
name varchar2(12), 
code varchar2(12) 
); 
在执行下面的语句时 
insert into t_dept values(2,’r&d’,’002’); 
insert into t_dept values(2,’r’||chr(38)||’d’,’002’);   
会出现提示信息,要求输入值 

怎么才能原样插入字符串r&d 

主要是:oracle的特殊字符,需要进行转义,那就是字符’&’. 
转义字符: ’ 
两个办法: 
Sql代码  
insert into t_dept values(2,’r’||’&’||’d’,’002’);   

或者 
Sql代码  
insert into t_dept values(2,’r’||chr(38)||’d’,’002’);   


ORACLE把数值改為千分位显示
发布日期:2012-07-13 18:50:56
我来说两句(0)收藏本文
SQL跑出来数值太多位导致USER看的雾煞煞

 
因此,要求数值资料可否加上千分位,方便阅读
虽说在code上可以把资料转换為千分位显示
但是小弟有点懒惰,不想更动已经写好code
就把SQL语法改成有千分位显示….
如果数值超过6位,就要写999,999,999这是9位数的写法
有小数点的话999,999,999.00这是保留两位小数,為0时显示0,
另外如果要是遇到0.XX时,要想显示小数点前面的0,要这样写999,999,990.00
PS:FM是去空白用
 
SELECT to_char(QTY_1, ‘FM999,999,999,999,999’) AS QTY_1,
       to_char(QTY_2, ‘FM999,999,999,999,999’) AS QTY_2,
       to_char(QTY_3, ‘FM999,999,999,999,999’) AS QTY_3
FROM TEST_DB

PL/SQL Developer 如何显示行号
 (2013-01-12 20:07:24)
转载▼
标签: 
pl/sql
 
developer
 
行号
 
it

一、工具-首选项-用户界面-编辑器-其它-显示行号
二、工具-首选项-窗口类型-SQL窗口-显示隔号(行号)

select * from all_source
where text like ‘%execute immediate%’
and owner <>’SYS’;
MGMT_DB_LL_METRICS;

利用Oracle动态游标实现动态SQL循环遍历
create or replace procedure P_TEST_SQL is  
TYPE ref_cursor_type IS REF CURSOR;  –定义一个动态游标   
tablename varchar2(200) default ‘ess_client’;  
v_sql varchar2(1000);  
mobile varchar2(15);  
usrs ref_cursor_type;  
begin  
  –使用连接符拼接成一条完整SQL   
  v_sql := ‘select usrmsisdn from ‘||tablename||’ where rownum < 11’;  
  –打开游标   
  open usrs for v_sql ;  
  loop  
      fetch usrs into mobile;   
      exit when usrs%notfound;  
      insert into tmp(usrmsisdn) values(mobile);  
  end loop;  
  close usrs;  
  commit;  
end P_TEST_SQL;  

================================================================================================
SELECT ROWNUM
,TO_CHAR(ADD_MONTHS(TO_DATE( ‘201403’,’YYYYMM’),DECODE(ROWNUM,0,0,-(11-ROWNUM))),’MM’) format_month
,TO_CHAR(ADD_MONTHS(TO_DATE( ‘201403’,’YYYYMM’),DECODE(ROWNUM,0,0,-(11-ROWNUM))),’YYYYMM’) full_format_month
FROM TB_COM_CODE
WHERE ROWNUM < 12
ORDER BY 1

================================================================================================
oracle 第几周

最近做报表需要取某天是当年的第几周,用到了oracle的两个取周的函数。
WW:
每年的1月1日作为当年的第一周的第一天(不管当年的1月1日是星期几);
比如:2011/01/01 是周六, 在Oracle中被定义为2011年的第一周的第一天;
SELECT to_char(TO_DATE(‘20110101’,’YYYYMMDD’) ,’yyyyww’) as week FROM DUAL;
IW :

是周算法以周别为“主线” ,每年最多可以有53个周B别,但是每年至少要包含52个周别;

如果一年当中第52周别之后至当年的12月31日之间,还有大于或等于4天的话,则定为当年的第53周,否则剩余这些天数被归为下一年的第1周;
果在不 足52周别的话,则以下一年的时间来补;每周固定的从周一开始作为本周的第1天,到周日作为本周的第7天;
比如:在Oracle中 2011/01/01 依然属于IW周别 2010年的第52周的第6天

附:

SELECT TO_CHAR(TO_DATE(‘20110101’, ‘YYYYMMDD’), ‘iw’) AS WEEK1IW, –oracle求当年的第几周
TO_CHAR(TO_DATE(‘20110101’, ‘YYYYMMDD’), ‘ww’) AS WEEK2WW, –将当年1月1日作为第一周,之后7天为一周,即1月8日为第二周
TO_CHAR(TO_DATE(‘20110101’, ‘YYYYMMDD’), ‘w’) AS WEEK2W, –求日期是本月的第几周
TO_CHAR(TO_DATE(‘20110101’, ‘YYYYMMDD’), ‘yyyy’) AS YEAR, –oracle求当前年
TO_CHAR(TO_DATE(‘20110101’, ‘YYYYMMDD’), ‘mm’) AS MONTH, –oracle求当年的第几月
TO_CHAR(TO_DATE(‘20110101’, ‘YYYYMMDD’), ‘ddd’) AS DAY, –oracle求当年的第几天
TO_CHAR(TO_DATE(‘20110401’, ‘YYYYMMDD’), ‘q’) AS QUARTER – oracle求当年的第几季度
FROM DUAL
;

SELECT TRUNC(TO_DATE(‘20160101’, ‘YYYYMMDD’), ‘iw’) AS WEEKFIRSTDAY FROM DUAL; –取日期所在周的第一天;
SELECT TRUNC(MM.EVERYDAY, ‘iw’),TO_CHAR(MM.EVERYDAY, ‘iw’) AS WEEKFIRSTDAY FROM –取某个期间日期的第一天
(
SELECT *
FROM (SELECT TO_DATE(‘20160101’, ‘yyyymmdd’) + LEVEL - 1 AS EVERYDAY
FROM DUAL
CONNECT BY LEVEL <= (TO_DATE(‘20161231’, ‘yyyymmdd’) - TO_DATE(‘20160101’, ‘yyyymmdd’) + 1))
)MM
;

================================================================================================

WITH PARAMS AS (SELECT ‘2018’ AS NF FROM DUAL)
SELECT TO_CHAR(TO_DATE(PM.NF || ‘-12-28’,’YYYY-MM-DD’),’IYYYIW’) FROM DUAL LEFT JOIN PARAMS PM ON 1=1;

查询某年的 周次,当周第一天,当周最后一天
WITH PARAMS AS (SELECT TRUNC(TO_DATE(‘2016-01-01’,’YYYY-MM-DD’),’YYYY’) AS SD FROM DUAL)
SELECT LEVEL 周次,
DECODE(SIGN(5-DECODE(TO_CHAR(PM.SD,’D’),’1’,’7’,TO_CHAR(PM.SD,’D’))),-1,
NEXT_DAY(PM.SD+(LEVEL-1)*7,2),NEXT_DAY(PM.SD+(LEVEL-1)*7-7,2))
当周第一天,
DECODE(SIGN(5-DECODE(TO_CHAR(PM.SD,’D’),’1’,’7’,TO_CHAR(PM.SD,’D’))),-1,
NEXT_DAY(PM.SD+(LEVEL-1)*7,2),NEXT_DAY(PM.SD+(LEVEL-1)*7-7,2)) + 6
当周最后一天
FROM DUAL D
LEFT JOIN PARAMS PM ON 1=1
CONNECT BY LEVEL<=53;

判断本年度有多少周?
SELECT TO_CHAR(TO_DATE( P_YEAR || ‘1231’,’yyyyMMdd’),’IW’)
INTO V_WEEK
FROM DUAL;
/2.得到循环次数/
IF TO_NUMBER(V_WEEK) <= 52 THEN
V_CNT := 52;
ELSE
V_CNT := 53;
END IF;

查询某天所在周
SELECT TO_CHAR(TO_DATE(‘20150101’,’YYYYMMDD’),’IW’) FROM DUAL;

计算表的字段长度汇总
SELECT t.table_name, sum(c.DATA_LENGTH)
FROM user_all_tables t, user_tab_columns c
WHERE t.table_name = c.table_name
group by t.table_name

    // 记录用户操作

// AddOperaterUtil.addUserInfo(input);
// String sessionEmpNo = SessionHolder.getUserInfo().getEmpNo();

直接查询总记录数作为列显示:
count(1) over (partition by ‘1’) as count

给CHIS_APP用户赋予procedure执行权限
grant execute on PR_GEN_ERROR_MSG to CHIS_APP;

在plsql中测试procedure的执行
begin
chsem_mgr.PR_GEN_ERROR_MSG(‘bbbbb’,’222’,’sssssssssssssssssss’);
end;

查询结果:
select * from CHSEM_MGR.AD_DB_ERROR

赋予CHIS_APP的sequence查询权限:
grant select on seq_ad_sem_dtl to chis_app;
grant select on seq_ad_sem_kwd to chis_app;

赋予CHIS_APP的table的查询/修改/删除权限:
grant select, insert, update, delete on AD_SITE_MST to SPMS_INF;

CREATE OR REPLACE FUNCTION F_GET_CH2SPELL(P_NAME IN VARCHAR2) RETURN VARCHAR2 AS
/转拼音首字母的函数/
V_COMPARE VARCHAR2(100);
V_RETURN VARCHAR2(4000);
CHAR1 VARCHAR2(3);
CHAR2 VARCHAR2(3);
LEN INTEGER;
N1 INTEGER;
N2 INTEGER;

FUNCTION F_NLSSORT(P_WORD IN VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN NLSSORT(P_WORD, ‘NLS_SORT=SCHINESE_PINYIN_M’);
END;
BEGIN
LEN := LENGTH(P_NAME);
FOR I IN 1 .. LEN LOOP
CHAR2 := SUBSTR(P_NAME, i, 1);
N1 := FLOOR(ASCII(CHAR2) / 256);
N2 := MOD(ASCII(CHAR2), 256);

IF N1 = 0 AND N2 <= 129 THEN
  V_RETURN := V_RETURN || CHAR2;
ELSIF N2 <> 127 AND N2 <> 255 AND NOT (N2 >= 0 AND N2 <= 63) THEN
  V_COMPARE := F_NLSSORT(SUBSTR(P_NAME, I, 1));
  IF V_COMPARE >= F_NLSSORT(' 吖 ') AND V_COMPARE <= F_NLSSORT('驁 ') THEN
    V_RETURN := V_RETURN || 'A';
  ELSIF V_COMPARE >= F_NLSSORT('八 ') AND V_COMPARE <= F_NLSSORT('簿 ') THEN
    V_RETURN := V_RETURN || 'B';
  ELSIF V_COMPARE >= F_NLSSORT('嚓 ') AND V_COMPARE <= F_NLSSORT('錯 ') THEN
    V_RETURN := V_RETURN || 'C';
  ELSIF V_COMPARE >= F_NLSSORT('咑 ') AND V_COMPARE <= F_NLSSORT('鵽 ') THEN
    V_RETURN := V_RETURN || 'D';
  ELSIF V_COMPARE >= F_NLSSORT('妸 ') AND V_COMPARE <= F_NLSSORT('樲 ') THEN
    V_RETURN := V_RETURN || 'E';
  ELSIF V_COMPARE >= F_NLSSORT('发 ') AND V_COMPARE <= F_NLSSORT('猤 ') THEN
    V_RETURN := V_RETURN || 'F';
  ELSIF V_COMPARE >= F_NLSSORT('旮 ') AND V_COMPARE <= F_NLSSORT('腂 ') THEN
    V_RETURN := V_RETURN || 'G';
  ELSIF V_COMPARE >= F_NLSSORT('妎 ') AND V_COMPARE <= F_NLSSORT('夻 ') THEN
    V_RETURN := V_RETURN || 'H';
  ELSIF V_COMPARE >= F_NLSSORT('丌 ') AND V_COMPARE <= F_NLSSORT('攈 ') THEN
    V_RETURN := V_RETURN || 'J';
  ELSIF V_COMPARE >= F_NLSSORT('咔 ') AND V_COMPARE <= F_NLSSORT('穒 ') THEN
    V_RETURN := V_RETURN || 'K';
  ELSIF V_COMPARE >= F_NLSSORT('垃 ') AND V_COMPARE <= F_NLSSORT('擽 ') THEN
    V_RETURN := V_RETURN || 'L';
  ELSIF V_COMPARE >= F_NLSSORT('嘸 ') AND V_COMPARE <= F_NLSSORT('椧 ') THEN
    V_RETURN := V_RETURN || 'M';
  ELSIF V_COMPARE >= F_NLSSORT('拏 ') AND V_COMPARE <= F_NLSSORT('瘧 ') THEN
    V_RETURN := V_RETURN || 'N';
  ELSIF V_COMPARE >= F_NLSSORT('筽 ') AND V_COMPARE <= F_NLSSORT('漚 ') THEN
    V_RETURN := V_RETURN || 'O';
  ELSIF V_COMPARE >= F_NLSSORT('妑 ') AND V_COMPARE <= F_NLSSORT('曝 ') THEN
    V_RETURN := V_RETURN || 'P';
  ELSIF V_COMPARE >= F_NLSSORT('七 ') AND V_COMPARE <= F_NLSSORT('裠 ') THEN
    V_RETURN := V_RETURN || 'Q';
  ELSIF V_COMPARE >= F_NLSSORT('亽 ') AND V_COMPARE <= F_NLSSORT('鶸 ') THEN
    V_RETURN := V_RETURN || 'R';
  ELSIF V_COMPARE >= F_NLSSORT('仨 ') AND V_COMPARE <= F_NLSSORT('蜶 ') THEN
    V_RETURN := V_RETURN || 'S';
  ELSIF V_COMPARE >= F_NLSSORT('侤 ') AND V_COMPARE <= F_NLSSORT('籜 ') THEN
    V_RETURN := V_RETURN || 'T';
  ELSIF V_COMPARE >= F_NLSSORT('屲 ') AND V_COMPARE <= F_NLSSORT('鶩 ') THEN
    V_RETURN := V_RETURN || 'W';
  ELSIF V_COMPARE >= F_NLSSORT('夕 ') AND V_COMPARE <= F_NLSSORT('鑂 ') THEN
    V_RETURN := V_RETURN || 'X';
  ELSIF V_COMPARE >= F_NLSSORT('丫 ') AND V_COMPARE <= F_NLSSORT('韻 ') THEN
    V_RETURN := V_RETURN || 'Y';
  ELSIF V_COMPARE >= F_NLSSORT('帀 ') AND V_COMPARE <= F_NLSSORT('咗 ') THEN
    V_RETURN := V_RETURN || 'Z';
  END IF;
END IF;

END LOOP;
RETURN V_RETURN;
END;

字符函数——返回字符值
这些函数全都接收的是字符族类型的参数(CHR 除外)并且返回字符值.除了特别说明的之外,这些函数大部分返回VARCHAR2类型的数值.字符函数的返回类型所受的限制和基本数据库类型所受的限制是相同的,比如: VARCHAR2数值被限制为2000字符(ORACLE 8中为4000字符),而CHAR数值被限制为255字符(在ORACLE8中是2000).当在过程性语句中使用时,它们可以被赋值给VARCHAR2 或者CHAR类型的PL/SQL变量.
CHR
语法: chr(x)
功能:返回在数据库字符集中与X拥有等价数值的字符。CHR和ASCII是一对反函数。经过CHR转换后的字符再经过ASCII转换又得到了原来的字符。
使用位置:过程性语句和SQL语句。
CONCAT
语法: CONCAT(string1,string2)
功能:返回string1,并且在后面连接string2。
使用位置:过程性语句和SQL语句。
INITCAP
语法:INITCAP(string)
功能:返回字符串的每个单词的第一个字母大写而单词中的其他字母小写的string。单词是用.空格或给字母数字字符进行分隔。不是字母的字符不变动。
使用位置:过程性语句和SQL语句。
LTRIM
语法:LTRIM(string1,string2)
功能:返回删除从左边算起出现在string2中的字符的string1。String2被缺省设置为单个的空格。数据库将扫描string1,从最左边开始。当遇到不在string2中的第一个字符,结果就被返回了。LTRIM的行为方式与RTRIM很相似。
使用位置:过程性语句和SQL语句。
NLS_INITCAP
语法:NLS_INITCAP(string[,nlsparams])
功能:返回字符串每个单词第一个字母大写而单词中的其他字母小写的string,nlsparams
指定了不同于该会话缺省值的不同排序序列。如果不指定参数,则功能和INITCAP相同。Nlsparams可以使用的形式是:
‘NLS_SORT=sort’
这里sort制订了一个语言排序序列。
使用位置:过程性语句和SQL语句。
NLS_LOWER
语法:NLS_LOWER(string[,nlsparams])
功能:返回字符串中的所有字母都是小写形式的string。不是字母的字符不变。
Nlsparams参数的形式与用途和NLS_INITCAP中的nlsparams参数是相同的。如果nlsparams没有被包含,那么NLS_LOWER所作的处理和LOWER相同。
使用位置;过程性语句和SQL语句。
NLS_UPPER
语法:nls_upper(string[,nlsparams])
功能:返回字符串中的所有字母都是大写的形式的string。不是字母的字符不变。nlsparams参数的形式与用途和NLS_INITCAP中的相同。如果没有设定参数,则NLS_UPPER功能和UPPER相同。
使用位置:过程性语句和SQL语句。
REPLACE
语法:REPLACE(string,search_str[,replace_str])
功能:把string中的所有的子字符串search_str用可选的replace_str替换,如果没有指定replace_str,所有的string中的子字符串search_str都将被删除。REPLACE是TRANSLATE所提供的功能的一个子集。
使用位置:过程性语句和SQL语句。
RPAD
语法:RPAD(string1,x[,string2])
功能:返回在X 字符长度的位置上插入一个string2中的字符的string1。如果string2的长度要比X字符少,就按照需要进行复制。如果string2多于 X字符,则仅string1前面的X各字符被使用。如果没有指定string2,那么使用空格进行填充。X是使用显示长度可以比字符串的实际长度要长。 RPAD的行为方式与LPAD很相似,除了它是在右边而不是在左边进行填充。
使用位置:过程性语句和SQL语句。
RTRIM
语法: RTRIM(string1,[,string2])
功能: 返回删除从右边算起出现在string1中出现的字符string2. string2被缺省设置为单个的空格.数据库将扫描string1,从右边开始.当遇到不在string2中的第一个字符,结果就被返回了RTRIM的行为方式与LTRIM很相似.
使用位置:过程性语句和SQL语句。
SOUNDEX
语法: SOUNDEX(string)
功能: 返回string的声音表示形式.这对于比较两个拼写不同但是发音类似的单词而言很有帮助.
使用位置:过程性语句和SQL语句。
SUBSTR  截取子串
语法: SUBSTR(string,a[,b])
功能: 返回从a位置开始的b个字符长的string的一个子字符串. 第一个字符的位置是1. 如果a是0,那么它就被认为从第一个字符开始.如果是正数,返回字符是从左边向右边进行计算的.如果b是负数,那么返回的字符是从string的末尾开始从右向左进行计算的.如果b不存在,那么它将缺省的设置为整个字符串.如果b小于1,那么将返回NULL.如果a或b使用了浮点数,那么该数值将在处理进行以前首先被却为一个整数.
使用位置:过程性语句和SQL语句。
TRANSLATE
语法: TRANSLATE(string,from_str,to_str)
功能: 返回将所出现的from_str 中的每个字符替换为to_str中的相应字符以后的string. TRANSLATE是REPLACE所提供的功能的一个超集.如果from_str比to_str长,那么在from_str中而不在to_str中而外的字符将从string中被删除,因为它们没有相应的替换字符. to_str不能为空.Oracle把空字符串认为是NULL,并且如果TRANSLATE中的任何参数为NULL,那么结果也是NULL.
使用位置:过程性语句和SQL语句。
UPPER
语法: UPPER(string)
功能: 返回大写的string.不是字母的字符不变.如果string是CHAR数据类型的,那么结果也是CHAR类型的.如果string是VARCHAR2类型的,那么结果也是VARCHAR2类型的.
使用位置: 过程性语句和SQL语句。
F.2 字符函数——返回数字
这些函数接受字符参数回数字结果.参数可以是CHAR或者是VARCHAR2类型的.尽管实际下许多结果都是整数值,但是返回结果都是简单的NUMBER类型的,没有定义任何的精度或刻度范围.
ASCII
语法: ASCII(string)
功能: 数据库字符集返回string的第一个字节的十进制表示.请注意该函数仍然称作为ASCII.尽管许多字符集不是7位ASCII.CHR和ASCII是互为相反的函数.CHR得到给定字符编码的响应字符. ASCII得到给定字符的字符编码.
使用位置: 过程性语句和SQL语句。
INSTR
语法: INSTR(string1, string2[a,b])
功能: 得到在string1中包含string2的位置. string1时从左边开始检查的,开始的位置为a,如果a是一个负数,那么string1是从右边开始进行扫描的.第b次出现的位置将被返回. a和b都缺省设置为1,这将会返回在string1中第一次出现string2的位置.如果string2在a和b的规定下没有找到,那么返回0.位置的计算是相对于string1的开始位置的,不管a和b的取值是多少.
使用位置: 过程性语句和SQL语句。
INSTRB
语法: INSTRB(string1, string2[a,[b]])
功能: 和INSTR相同,只是操作的对参数字符使用的位置的是字节.
使用位置: 过程性语句和SQL语句。
LENGTH
语法: LENGTH(string)
功能: 返回string的字节单位的长度.CHAR数值是填充空格类型的,如果string由数据类型CHAR,它的结尾的空格都被计算到字符串长度中间.如果string是NULL,返回结果是NULL,而不是0.
使用位置: 过程性语句和SQL语句。
LENGTHB
语法: LENGTHB(string)
功能: 返回以字节为单位的string的长度.对于单字节字符集LENGTHB和LENGTH是一样的.
使用位置: 过程性语句和SQL语句。
NLSSORT
语法: NLSSORT(string[,nlsparams])
功能: 得到用于排序string的字符串字节.所有的数值都被转换为字节字符串,这样在不同数据库之间就保持了一致性. Nlsparams的作用和NLS_INITCAP中的相同.如果忽略参数,会话使用缺省排序.
使用位置: 过程性语句和SQL语句。
http://www.newsmth.net/pc/pccon.php?id=2206&nid=355848

insert into ad_ex_banner_dtl
(id,
ex_banner_id,
dtl_tp,
device_cd,
dept,
media_nm,
position_nm,
inject,
impession,
click,
tot_net_cost,
ctr,
cpm,
cpc,
state_nm,
order_no,
price,
order_date,
click_time,
city_nm,
promotion_plan,
promotion_unit,
promotion_position,
material_nm,
order_tp_nm,
status_nm,
keyword,
mapping_tp_nm,
order_cnt,
order_amt,
order_conv_rate,
order_roi,
payment_cnt,
payment_amt,
payment_conv_rate,
payment_roi)
values
(lpad(seq_ad_ex_banner_dtl.nextval, 10, 0),
‘EX_BANNER_000000005’,
null,
‘PC’,
‘HA’,
‘腾讯’,
‘频道内容页窄通1-640*90-30K’,
‘站外’,
to_number(REPLACE(nvl(trim(‘38400360’),0),’,’,”)),
to_number(REPLACE(nvl(trim(‘2707’),0),’,’,”)),
to_number(REPLACE(substr(nvl(trim(‘3840.05’),0), instr(nvl(trim(‘3840.05’),0), ‘¥’) + 1),’,’,”)),
to_number(REPLACE(substr(nvl(trim(‘0.01’),0), 1, instr(nvl(trim(‘0.01’),0), ‘%’) - 1),’,’,”)),
to_number(REPLACE(nvl(trim(‘0.1’),0),’,’,”)),
to_number(REPLACE(nvl(trim(‘1.42’),0),’,’,”)),
null,
null,
to_number(REPLACE(nvl(trim(null),0),’,’,”)),
to_date(null,’YYYY/MM/DD hh24:mi:ss’),
to_date(null,’YYYY/MM/DD hh24:mi:ss’),
null,
null,
null,
null,
null,
null,
null,
null,
null,
to_number(REPLACE(nvl(trim(null),0),’,’,”)),
to_number(REPLACE(nvl(trim(null),0),’,’,”)),
to_number(REPLACE(substr(nvl(trim(null),0), 1, instr(nvl(trim(null),0), ‘%’) - 1),’,’,”)),
to_number(REPLACE(nvl(trim(null),0),’,’,”)),
to_number(REPLACE(nvl(trim(null),0),’,’,”)),
to_number(REPLACE(nvl(trim(null),0),’,’,”)),
to_number(REPLACE(substr(nvl(trim(null),0), 1, instr(nvl(trim(null),0), ‘%’) - 1),’,’,”)),
to_number(REPLACE(nvl(trim(null),0),’,’,”))
);

select to_number(REPLACE(substr(nvl(trim(‘0.01’),0), 1, instr(nvl(trim(‘0.01’),0), ‘%’) - 1),’,’,”)) from dual;
select instr(nvl(trim(‘0.01’),0), ‘%’) - 1,substr(nvl(trim(‘0.01’),0), 1, instr(nvl(trim(‘0.01’),0), ‘%’) - 1) from dual;
select to_number(REPLACE(substr(nvl(trim(‘0.01’),0), 1, instr(nvl(trim(‘0.01’),0), ‘%’) - 1),’,’,”)) from dual;

select substr(‘1000’,1,instr(‘1000’,’%’)) from dual;

select substr(‘OR:com.lcs.wc.placeholder.Placeholder:860825’,INSTR(‘OR:com.lcs.wc.placeholder.Placeholder:860825’,’:’,1,2) + 1,length(‘OR:com.lcs.wc.placeholder.Placeholder:860825’)),
INSTR(‘OR:com.lcs.wc.placeholder.Placeholder:860825’, ‘:’, 1, 2),
length(‘OR:com.lcs.wc.placeholder.Placeholder:860825’)
From dual;
substr(“ABCDEFG”, 0); //返回:ABCDEFG,截取所有字符
substr(“ABCDEFG”, 2); //返回:CDEFG,截取从C开始之后所有字符
substr(“ABCDEFG”, 0, 3); //返回:ABC,截取从A开始3个字符
substr(“ABCDEFG”, 0, 100); //返回:ABCDEFG,100虽然超出预处理的字符串最长度,但不会影响返回结果,系统按预处理字符串最大数量返回。
substr(“ABCDEFG”, -3); //返回:EFG,注意参数-3,为负值时表示从尾部开始算起,字符串排列位置不变。;

select Substr(‘sdhfuiasdh/asdfsadf’,1,INSTr(‘sdhfuiasdhasdfsadf’,’/’)-1) from dual;


查询一个数据集,默认提供递增数列:
参考两个日期期间的所有日期:
SELECT ‘1’ code,’aaaa’ as name,LEVEL lvl FROM dual CONNECT BY LEVEL <= 5

1 1 aaaa 1
2 1 aaaa 2
3 1 aaaa 3
4 1 aaaa 4
5 1 aaaa 5


oracle行转列(动态行转不定列)
/*物料 需要数量 需要仓库 现存量仓库 现存量仓库数量 批次 
A1 2 C1 C1         20         123 
A1 2 C1 C2         30         111 
A1 2 C1 C2         20         222 
A1 2 C1 C3         10         211 
A2 3 C4 C1         40         321 
A2 3 C4 C4         50         222 
A2 3 C4 C4         60         333 
A2 3 C4 C5         70         223 
我需要把上面的查询结果转换为下面的。
物料 需要数量 需要仓库 C1 C2 C3 C4 C5 
A1 2 C1 20 50 10 0 0 
A2 3 C4 40 0 0 110 70 
*/ 
—————————————————————建表
—————-判断表是否存在
declare num number; 
begin 
    select count(1) into num from user_tables where table_name=’TEST’;
    if num>0 then 
      execute immediate ‘drop table TEST’;
    end if;
end;
—————-建表
CREATE TABLE TEST(
    WL VARCHAR2(10),
    XYSL INTEGER,
    XYCK VARCHAR2(10),
    XCLCK VARCHAR2(10),
    XCLCKSL INTEGER,
    PC INTEGER
);
—————-第一部分测试数据
INSERT INTO TEST VALUES(‘A1’, 2, ‘C1’, ‘C1’ ,        20,         123); 
INSERT INTO TEST VALUES(‘A1’, 2, ‘C1’, ‘C2’ ,        30,         111); 
INSERT INTO TEST VALUES(‘A1’, 2, ‘C1’, ‘C2’ ,        20,         222); 
INSERT INTO TEST VALUES(‘A1’, 2, ‘C1’, ‘C3’ ,        10,         211); 
INSERT INTO TEST VALUES(‘A2’, 3, ‘C4’, ‘C1’ ,        40,         321); 
INSERT INTO TEST VALUES(‘A2’, 3, ‘C4’, ‘C4’ ,        50,         222); 
INSERT INTO TEST VALUES(‘A2’, 3, ‘C4’, ‘C4’ ,        60,         333); 
INSERT INTO TEST VALUES(‘A2’, 3, ‘C4’, ‘C5’ ,        70,         223);
COMMIT;
–select * from test;
—————————————————————行转列的存储过程
CREATE OR REPLACE PROCEDURE P_TEST IS
  V_SQL VARCHAR2(2000);
  CURSOR CURSOR_1 IS SELECT DISTINCT T.XCLCK FROM TEST T ORDER BY XCLCK; 
    
    BEGIN
      V_SQL := ‘SELECT WL,XYSL,XYCK’;
      FOR V_XCLCK IN CURSOR_1
      LOOP
        V_SQL := V_SQL || ‘,’ || ‘SUM(DECODE(XCLCK,”’ || V_XCLCK.XCLCK ||
                 ”’,XCLCKSL,0)) AS ’ || V_XCLCK.XCLCK;
      END LOOP;
      
      V_SQL := V_SQL || ’ FROM TEST GROUP BY WL,XYSL,XYCK ORDER BY WL,XYSL,XYCK’;
      –DBMS_OUTPUT.PUT_LINE(V_SQL);
      V_SQL := ‘CREATE OR REPLACE VIEW RESULT  AS ‘||  V_SQL;
      –DBMS_OUTPUT.PUT_LINE(V_SQL);
      EXECUTE IMMEDIATE V_SQL;
    END;
—————————————————————-结果
—————-执行存储过程,生成视图
BEGIN
  P_TEST;               
END;
—————-结果
SELECT * FROM RESULT T;
WL                                            XYSL XYCK               C1         C2         C3         C4         C5


A1                                               2 C1                 20         50         10          0          0
A2                                               3 C4                 40          0          0        110         70
—————-第二部分测试数据
INSERT INTO TEST VALUES(‘A1’, 2, ‘C1’, ‘C6’ ,        20,         124); 
INSERT INTO TEST VALUES(‘A2’, 2, ‘C1’, ‘C7’ ,        30,         121); 
INSERT INTO TEST VALUES(‘A3’, 2, ‘C1’, ‘C8’ ,        20,         322); 
COMMIT;
—————-报告存储过程,生成视图
BEGIN
  P_TEST;               
END;
—————-结果
SELECT * FROM RESULT T;
WL     XYSL XYCK          C1       C2         C3         C4         C5         C6         C7         C8


A1        2 C1            20       50         10          0          0         20          0          0
A2        2 C1             0        0          0          0          0          0         30          0
A2        3 C4            40        0          0        110         70          0          0          0
A3        2 C1             0        0          0          0          0          0          0         20
————— 删除实体
DROP VIEW RESULT;
DROP PROCEDURE P_TEST;
DROP TABLE TEST;  
分类: Oracle

============================================================================================

oracle 如何创建DBlink?
分享| 2014-05-26 10:04 anlod | 浏览 2747 次
数据库
FC环境临时用户及数据库配置信息:
用户名/密码:aaa/111
SAP_FC_ORACLE=
(DESCRIPTION=
(ADDRESS= (PROTOCOL=TCP) (HOST=10.9.10.11) (PORT=1527) ) (CONNECT_DATA= (SID=prd) )
)

测试用户及数据库配置信息:
用户名/密码:bbb/2222
nclaos_cs = (DESCRIPTION =
(ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP) (HOST = 10.1.91.177)
(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = nclaos) )
)

请将以下两个库创建DBLINK,以便两个库中的数据核对工作
2014-05-26 10:06 #“谁是脑力达人”分类答题赛火热开启!# 提问者采纳
  创建dblink一般有两种方式,不过在创建dblink之前用户必须有创建dblink的权限。想知道有关dblink的权限,以sys用户登录到本地数据库:
  select * from user_sys_privs t
  where t.privilege like upper(‘%link%’);
  1 SYS CREATE DATABASE LINK NO
  2 SYS DROP PUBLIC DATABASE LINK NO
  3 SYS CREATE PUBLIC DATABASE LINK NO
  可以看出在数据库中dblink有三种权限CREATE DATABASE LINK(所创建的dblink只能是创建者能使用,别的用户使用不了),CREATE PUBLIC DATABASE LINK(public表示所创建的dblink所有用户都可以使用),DROP PUBLIC DATABASE LINK。
  在sys用户下,把CREATE PUBLIC DATABASE LINK,DROP PUBLIC DATABASE LINK权限授予给你的用户
  grant CREATE PUBLIC DATABASE LINK,DROP PUBLIC DATABASE LINK to scott;
  然后以scott用户登录本地数据库
  1.创建dblink的第一种方式,是在本地数据库tnsnames.ora文件中配置了要远程访问的数据库。
  create public database link
  to_bylw connect to scott identified by tiger using ‘bylw’;
  其中to_bylw是你创建的dblink名字,bylw是远程数据库的实例名,scott/tiger是登录到远程数据库的用户/密码。然后在本地数据库中通过dblink访问远程数据库’bylw’中scott.tb_test表,sql语句如下所示
  select * from scott.tb_test@to_bylw;
  2.创建dblink的第二种方式,是在本地数据库tnsnames.ora文件中没有配置要访问的远程数据库,
  create database link to_tests
  connect to scott identified by tiger
  using ‘(DESCRIPTION =
  (ADDRESS_LIST =
  (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.5)(PORT = 1521))  )  (CONNECT_DATA =
  (SERVER = DEDICATED)
  (SERVICE_NAME = bylw)  )  )’;  第二种是把第一种配置在tnsnames.ora文件中的信息,直接放在创建dblink语句后面。第一种情况tnsnames.ora文件中信息如下:  bylw =  (DESCRIPTION =
  (ADDRESS_LIST =
  (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.5)(PORT = 1521))  )  (CONNECT_DATA =
是否可以解决您的问题?

赋予创建dblink的权限有三种:
grant create  database link to user ;–只有user用户能使用的
dblinkgrant create public  database link to user ;–所有用户都可以使用的
dblinkgrant drop public  database link to user; –删除dblink的权限看你创建语句是public dblink,所以要DBA用户付给user第二种权限才行。
 
—-创建dblink的一种方式
create database link [name] connect to [user] identified by [passwrod]
   using ‘(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.174.59)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME =osstest)
)
)’;
 

UPDATE psi_sellout_stock_sum_temp xss
SET (da_qu, zhi_she, dept_code, au_code) =
(SELECT z.da_qu, z.zhi_she, a.group_cd1, a.accounting_unit
FROM psi_bill_to a, psi_department D, psi_zhishe_mapping z
WHERE A.group_cd1 = D.dept_cd
AND d.com_cd = ‘LGECH’
AND a.group_cd1 = to_char(z.organization_code)
AND a.site_use_id = xss.bill_to_site_use_id
AND A.bill_to_code = xss.Bill_To_Code
AND rownum = 1)
;

select * from (
SELECT z.da_qu, z.zhi_she, a.group_cd1, a.accounting_unit
FROM psi_sellout_stock_sum_temp xss,
psi_bill_to a,
psi_zhishe_mapping z,
psi_department d
WHERE 1 = 1
AND a.site_use_id = xss.bill_to_site_use_id
AND A.bill_to_code = xss.Bill_To_Code
AND A.group_cd1 = D.dept_cd
AND d.com_cd = ‘LGECH’
AND a.group_cd1 = to_char(z.organization_code)
AND A.bill_to_code = xss.Bill_To_Code
)tmp
where tmp.da_qu is null
;

SELECT a.site_use_id,a.bill_to_code,count(1)
FROM psi_bill_to a, psi_department D, psi_zhishe_mapping z
WHERE A.group_cd1 = D.dept_cd
AND d.com_cd = ‘LGECH’
AND a.group_cd1 = to_char(z.organization_code)
group by a.site_use_id,a.bill_to_code
having count(1)>1 ;

select distinct bill_to_code from psi_sellout_stock_sum_temp xss
where not exists
(SELECT z.da_qu, z.zhi_she, a.group_cd1, a.accounting_unit
FROM psi_bill_to a, psi_department D, psi_zhishe_mapping z
WHERE A.group_cd1 = D.dept_cd
AND d.com_cd = ‘LGECH’
AND a.group_cd1 = to_char(z.organization_code)
AND a.site_use_id = xss.bill_to_site_use_id
AND A.bill_to_code = xss.Bill_To_Code
AND rownum = 1)
;

一、单个IF
1、

if a=… then
………
end if;

2、

if a=… then
……
else
….
end if;

二、多个IF

if a=.. then
……
elsif a=.. then
….
end if;
这里中间是“ELSIF”,而不是ELSE IF 。这里需要特别注意

===================================================================================================
delete FROM TB_PART_FIELD_CONF T
WHERE t.part_type_code NOT IN (‘021LCM’,
‘010’,
‘021PDP’,
‘170’,
‘171’,
‘192’,
‘193’,
‘194’,
‘NTV’,
‘SET’)

;

DECLARE
CURSOR query_employee IS
SELECT T.CODE
FROM tb_code_info t
WHERE t.division = ‘PART_TYPE’
AND T.CODE NOT IN (‘010’,
‘021LCM’,
‘021PDP’,
‘170’,
‘171’,
‘192’,
‘193’,
‘194’,
‘NTV’,
‘SET’);
v_code VARCHAR2(20);
BEGIN
OPEN query_employee;
FETCH query_employee
INTO v_code;
INSERT INTO TB_PART_FIELD_CONF
(part_type_code, Field_Id, Field_Name, Display_SEQ)
SELECT v_code, t.field_id, t.field_name, t.Display_SEQ
FROM TB_PART_FIELD_CONF t
WHERE t.part_type_code = ‘010’;

END;

===========================================================================================

UPDATE tb_object_mst mst
SET mst.lst_mod_user_id = ‘admin’,
mst.lst_mod_nm = ‘administrator’,
mst.lst_mod_dt = SYSDATE
WHERE 1=1
and (mst.object_id, mst.object_no, mst.object_type_code) =
(SELECT rev.object_id, mst1.object_no, mst1.object_type_code
FROM tb_object_mst mst1, tb_object_rev rev
WHERE mst1.object_id = rev.object_id
and rev.revision_id = ‘C903023E0C0B5E3D6305’)

=========================================================================
 
Oracle CONNECT BY的用法
标签: oraclepathinserthexexceptiontable
2011-09-14 17:26 9015人阅读 评论(0) 收藏 举报
 分类:
Oracle(67) 
 Oracle中可以通过START WITH … CONNECT BY …子句来实现SQL的层次查询.
自从Oracle 9i开始,可以通过 SYS_CONNECT_BY_PATH 函数实现将父节点到当前行内容以“path”或者层次元素列表的形式显示出来。

自从Oracle 10g 中,还有其他更多关于层次查询的新特性 。例如,有的时候用户更关心的是每个层次分支中等级最低的内容。
那么你就可以利用伪列函数CONNECT_BY_ISLEAF来判断当前行是不是叶子。如果是叶子就会在伪列中显示“1”,
如果不是叶子而是一个分支(例如当前内容是其他行的父亲)就显示“0”。

在Oracle 10g 之前的版本中,如果在你的树中出现了环状循环(如一个孩子节点引用一个父亲节点),
Oracle 就会报出一个错误提示:“ ORA-01436: CONNECT BY loop in user data”。如果不删掉对父亲的引用就无法执行查询操作。
而在 Oracle 10g 中,只要指定“NOCYCLE”就可以进行任意的查询操作。与这个关键字相关的还一个伪列——CONNECT_BY_ISCYCLE,
如果在当前行中引用了某个父亲节点的内容并在树中出现了循环,那么该行的伪列中就会显示“1”,否则就显示“0”。

The start with .. connect by clause can be used to select data that has a hierarchical relationship
(usually some sort of parent->child, boss->employee or thing->parts). 
It is also being used when an sql execution plan is explained. 

syntax:
select … [start with initial-condition] connect by [nocycle] recurse-condition

level
With level it is possible to show the level in the hierarchical relation of all the data.

–oracle 9i
sys_connect_by_path
With sys_connect_by_path it is possible to show the entire path from the top level down to the ‘actual’ child.

–oracle 10g
connect_by_root
connect_by_root is a new operator that comes with Oracle 10g and enhances the ability to perform hierarchical queries.
connect_by_is_leaf
connect_by_isleaf is a new operator that comes with Oracle 10g and enhances the ability to perform hierarchical queries.
connect_by_iscycle
connect_by_is_cycle is a new operator that comes with Oracle 10g and enhances the ability to perform hierarchical queries.
下面举例说明:
[例1]
创建一个部门表,这个表有4个字段,分别对应部门ID,部门名称,上级部门ID ,本部门直属员工人数。
create table DEP
(  
DEPID      number(10) not null,  
DEPNAME    varchar2(32),  
UPPERDEPID number(10),
NUMOFEMP   number(10)
) ;
下面插入一些数据,结果如下:
hr@MYTEST2> select * from dep;

DEPID DEPNAME UPPERDEPID NUMOFEMP


     0 Dev Center                          2

     1 DevA                     0          3

     2 DevA Team1               1         10

     3 DevA Team2               1          8

     4 DevB                     0          2

     5 DevB Team1               4         12

     6 Test Center                         1

     7 Test Team1               6          5

     8 Test Team2               6          5

9
9 rows selected.
现在根据“CONNECT BY”来实现树状查询:
column depname format a15;
c
column rootdep format a15;
c
column path format a30;

s
select rpad(’ ‘, 2*(level-1), ‘-‘) || depname “DEPNAME”,

connect_by_root depname “ROOTDEP”,

connect_by_isleaf “ISLEAF”,
l
level,
s
sys_connect_by_path(depname, ‘/’) “PATH”
f
from dep
s
start with upperdepid is null

connect by prior depid = upperdepid
/
/
结果如下:

DEPNAME ROOTDEP ISLEAF LEVEL PATH


D
Dev Center Dev Center 0 1 /Dev Center

-DevA Dev Center 0 2 /Dev Center/DevA

—DevA Team1 Dev Center 1 3 /Dev Center/DevA/DevA Team1

—DevA Team2 Dev Center 1 3 /Dev Center/DevA/DevA Team2

-DevB Dev Center 0 2 /Dev Center/DevB

—DevB Team1 Dev Center 1 3 /Dev Center/DevB/DevB Team1
T
Test Center Test Center 0 1 /Test Center

-Test Team1 Test Center 1 2 /Test Center/Test Team1

-Test Team2 Test Center 1 2 /Test Center/Test Team2

下面计算Dev Center和Test Center部门的总人数:
select ROOTDEPID, sum(numofemp) “TOTALEMP”
f
from (select connect_by_root depid “ROOTDEPID”, numofemp from dep
s
start with upperdepid is null

connect by prior depid = upperdepid)
g
group by ROOTDEPID
/
/
结果如下:

ROOTDEPID TOTALEMP


     6         11

     0         37

[例2]
通过CONNECT BY用于十六进度转换为十进制
CREATE OR REPLACE FUNCTION f_hex_to_dec(p_str IN VARCHAR2) RETURN VARCHAR2 IS

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

-- 对象名称: f_hex_to_dec

-- 对象描述: 十六进制转换十进制

-- 输入参数: p_str 十六进制字符串

-- 返回结果: 十进制字符串

-- 测试用例: SELECT f_hex_to_dec('78A') FROM dual;

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

v_return  VARCHAR2(4000);

BEGIN

SELECT SUM(DATA) INTO v_return

  FROM (SELECT (CASE upper(substr(p_str, 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'

                 ELSE substr(p_str, rownum, 1)

               END) * power(16, length(p_str) - rownum) DATA

          FROM dual

        CONNECT BY rownum <= length(p_str));

RETURN v_return;

EXCEPTION

WHEN OTHERS THEN

  RETURN NULL;

END;

说明:
1. CONNECT BY rownum <= length(p_str))对输入的字符串进行逐个遍历
2. 通过CASE语句,来解析十六进制中的A-F对应的10进制值

测试结果如下:
hr@MYTEST2> variable dec varchar2(32);
h
hr@MYTEST2> exec :dec := f_hex_to_dec(‘1FF’);

P
PL/SQL procedure successfully completed.

h
hr@MYTEST2> print dec

D

DEC


5
511

[例3]
通过CONNECT BY生成序列
对于connect by,现在大多数人已经很熟悉了,connect by中的条件就表示了父子之间的连接关系,比如 connect by id=prior pid。

但如果connect by中的条件没表示记录之间的父子关系
那会出现什么情况?
常见的,connect by会在构造序列的时候使用
用select rownum from dual connect by rownum

ID LEVEL


A
A 1
B
B 1
C
C 1

h
hr@MYTEST2> select id,level from t connect by level<3;

I

ID LEVEL


A
A 1
A
A 2
B
B 2
C
C 2
B
B 1
A
A 2
B
B 2
C
C 2
C
C 1
A
A 2
B
B 2
C
C 2

1
12 rows selected.

无需多说,我们很快可以找到其中的规律,假设表中有N条记录
则记F(N,l)为 select id,level from t connect by level

COUNT(*)


2713235
S
SQL> alter session set nls_date_format=’yyyy-mm-dd hh24:mi:ss’;

会话已更改。
S
SQL> select time_fee from dba where rownum<5;
T

TIME_FEE


2011-02-17 19:29:09
2011-02-17 19:29:15
2011-02-17 19:29:18
2011-02-17 19:29:20
S
SQL>
2.1.1 Oracle 11g的Interval
在11g里的Interval创建,这种方法对没有写全的分区会自动创建。 比如我这里只写了1月日期,如果插入的数据有其他月份的,会自动生成对应的分区。
/* Formatted on 2011/03/02 15:41:09 (QP5 v5.115.810.9015) */
CREATE TABLE intervaldave

PARTITION BY RANGE (time_fee)

INTERVAL ( NUMTOYMINTERVAL (1, ‘MONTH’) )
(
(PARTITION part1

VALUES LESS THAN (TO_DATE (‘01/12/2010’, ‘MM/DD/YYYY’)))

AS
SELECT ID, TIME_FEE FROM DAVE;
SQL> select table_name,partition_name from user_tab_partitions where table_name=’INTERVALDAVE’;
T

TABLE_NAME PARTITION_NAME


I
INTERVALDAVE PART1
I
INTERVALDAVE SYS_P24
I
INTERVALDAVE SYS_P25
I
INTERVALDAVE SYS_P26
I
INTERVALDAVE SYS_P33
I
INTERVALDAVE SYS_P27
I
INTERVALDAVE SYS_P28
2.1.2 Oracle 10g 版本
在10g里面,我需要写全所有的分区。
sql> create table pdba (id, time) partition by range (time)

2 (partition p1 values less than (to_date(‘2010-10-1’, ‘yyyy-mm-dd’)),

3 partition p2 values less than (to_date(‘2010-11-1’, ‘yyyy-mm-dd’)),

4 partition p3 values less than (to_date(‘2010-12-1’, ‘yyyy-mm-dd’)),

5 partition p4 values less than (maxvalue))

6 as select id, time_fee from dba;

表已创建。
S
SQL> select table_name,partition_name from user_tab_partitions where table_name=’PDBA’;
T

TABLE_NAME PARTITION_NAME


P
PDBA P1
P
PDBA P2
P
PDBA P3
P
PDBA P4
s
sql> select count(*) from pdba partition (p1);
c

count(*)


1718285
s
sql> select count(*) from pdba partition (p2);
c

count(*)


183667
s
sql> select count(*) from pdba partition (p3);
c

count(*)


188701
s
sql> select count(*) from pdba partition (p4);
c

count(*)


622582
s
sql>

现在分区表已经建好了,但是表名不一样,需要用rename对表重命名一下:
S
SQL> rename dba to dba_old;

表已重命名。
S
SQL> rename pdba to dba;

表已重命名。
S
SQL> select table_name,partition_name from user_tab_partitions where table_name=’DBA’;
T

TABLE_NAME PARTITION_NAME


D
DBA P1
D
DBA P2
D
DBA P3
D
DBA P4
2.2 . 交换分区:Partition exchange method
这种方法只是对数据字典中分区和表的定义进行了修改,没有数据的修改或复制,效率最高。适用于包含大数据量的表转到分区表中的一个分区的操作。尽量在闲时进行操作。
交换分区的操作步骤如下:
创建分区表,假设有2个分区,P1,P2.
创建表A存放P1规则的数据。
创建表B 存放P2规则的数据。
用表A 和P1 分区交换。 把表A的数据放到到P1分区
用表B 和p2 分区交换。 把表B的数据存放到P2分区。
创建分区表:
sql> create table p_dba

2 (id number,time date)

3 partition by range(time)

4 (

5 partition p1 values less than (to_date(‘2010-09-1’, ‘yyyy-mm-dd’)),

6 partition p2 values less than (to_date(‘2010-11-1’, ‘yyyy-mm-dd’))

7 );

表已创建。
注意:我这里只创建了2个分区,没有创建存放其他数据的分区。
创建2个分别对应分区的基表:
SQL> CREATE TABLE dba_p1 as SELECT id,time_fee FROM dba_old WHERE time_fee

COUNT(*)


1536020
S
SQL> select count(*) from dba_p2;
C

COUNT(*)


365932
S
SQL>
讲2个基表与2个分区进行交换:
SQL> alter table p_dba exchange partition p1 with table dba_p1;

表已更改。
S
SQL> alter table p_dba exchange partition p2 with table dba_p2;

表已更改。
查询2个分区:
SQL> select count(*) from p_dba partition(p1);
C

COUNT(*)


1536020
S
SQL> select count(*) from p_dba partition(p2);
C

COUNT(*)


365932

注意:数据和之前的基表一致。

查询原来的2个基表:
S
SQL> select count(*) from dba_p2;
C

COUNT(*)


0
S
SQL> select count(*) from dba_p1;
C

COUNT(*)


0
注意: 2个基表的数据变成成0。
在这里我们看一个问题,一般情况下,我们在创建分区表的时候,都会有一个其他分区,用来存放不匹配分区规则的数据。 在这个例子中,我只创建了2个分区,没有创建maxvalue分区。 现在我来插入一条不满足规则的数据,看结果:
SQL> insert into p_dba values(999999,to_date(‘2012-12-29’,’yyyy-mm-dd’));

insert into p_dba values(999999,to_date(‘2012-12-29’,’yyyy-mm-dd’))
*
*

第 1 行出现错误:
O
ORA-14400: 插入的分区关键字未映射到任何分区
S
SQL> insert into p_dba values(999999,to_date(‘2009-12-29’,’yyyy-mm-dd’));

已创建 1 行。
S
SQL> select * from p_dba where id=999999;
I

ID TIME


999999 29-12月-09
S
SQL> alter session set nls_date_format=’yyyy-mm-dd hh24:mi:ss’;

会话已更改。
S
SQL> select * from p_dba where id=999999;
I

ID TIME


999999 2009-12-29 00:00:00
S
SQL>
通过这个测试可以清楚,如果插入的数据不满足分区规则,会报ORA-14400错误。
2.3 . 使用在线重定义:DBMS_REDEFINITION
在线重定义能保证数据的一致性,在大部分时间内,表都可以正常进行DML操作。只在切换的瞬间锁表,具有很高的可用性。这种方法具有很强的灵活性,对各种不同的需要都能满足。而且,可以在切换前进行相应的授权并建立各种约束,可以做到切换完成后不再需要任何额外的管理操作。
关于DBMS_REDEFINITION的介绍,参考官方连接:
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_redefi.htm#CBBFDJBC
关于用在线重定义创建分区表,参考:
How To Partition Existing Table Using DBMS_Redefinition [ID 472449.1]
http://blog.csdn.net/tianlesoftware/archive/2011/03/02/6218693.aspx
这个功能只在9.2.0.4以后的版本才有,在线重定义表具有以下功能:
(1)修改表的存储参数;
(2)将表转移到其他表空间;
(3)增加并行查询选项;
(4)增加或删除分区;
(5)重建表以减少碎片;
(6)将堆表改为索引组织表或相反的操作;
(7)增加或删除一个列。
使用在线重定义的一些限制条件:
(1) There must be enough space to hold two copies of the table.
(2) Primary key columns cannot be modified.
(3) Tables must have primary keys.
(4) Redefinition must be done within the same schema.
(5) New columns added cannot be made NOT NULL until after the redefinition operation.
(6) Tables cannot contain LONGs, BFILEs or User Defined Types.
(7) Clustered tables cannot be redefined.
(8) Tables in the SYS or SYSTEM schema cannot be redefined.
(9) Tables with materialized view logs or materialized views defined on them cannot be redefined.
(10) Horizontal sub setting of data cannot be performed during the redefinition.
在Oracle 10.2.0.4和11.1.0.7 版本下,在线重定义可能会遇到如下bug:
Bug 7007594 - ORA-600 [12261]
http://blog.csdn.net/tianlesoftware/archive/2011/03/02/6218681.aspx
在线重定义的大致操作流程如下:
(1)创建基础表A,如果存在,就不需要操作。
(2)创建临时的分区表B。
(3)开始重定义,将基表A的数据导入临时分区表B。
(4)结束重定义,此时在DB的 Name Directory里,已经将2个表进行了交换。即此时基表A成了分区表,我们创建的临时分区表B 成了普通表。 此时我们可以删除我们创建的临时表B。它已经是普通表。
下面看一个示例:

创建基本表和索引
sql> conn icd/icd;

已连接。
s
sql> create table unpar_table (

2 id number(10) primary key,

3 create_date date
4 );

表已创建。
s
sql> insert into unpar_table select rownum, created from dba_objects;

已创建72288行。
s
sql> create index create_date_ind on unpar_table(create_date);

索引已创建。
s
sql> commit;

提交完成。

收集表的统计信息
sql> exec dbms_stats.gather_table_stats(‘icd’, ‘unpar_table’, cascade => true);pl/sql 过程已成功完成。

创建临时分区表
sql> create table par_table (id number primary key, time date) partition by range (time)

2 (partition p1 values less than (to_date(‘2004-7-1’, ‘yyyy-mm-dd’)),

3 partition p2 values less than (to_date(‘2005-1-1’, ‘yyyy-mm-dd’)),

4 partition p3 values less than (to_date(‘2005-7-1’, ‘yyyy-mm-dd’)),

5 partition p4 values less than (maxvalue));

表已创建。
进行重定义操作
4.1 检查重定义的合理性
sql> exec dbms_redefinition.can_redef_table(‘icd’, ‘unpar_table’);
pl/sql 过程已成功完成。
4.2 如果4.1 没有问题,开始重定义,这个过程可能要等一会。
这里要注意:如果分区表和原表列名相同,可以用如下方式进行:
SQL> BEGIN
DBMS_REDEFINITION.start_redef_table(
uname => ‘ICD’,
orig_table => ‘unpar_table’,
int_table => ‘par_table’);
END;
/
如果分区表的列名和原表不一致,那么在开始重定义的时候,需要重新指定映射关系:
SQL> EXEC DBMS_REDEFINITION.START_REDEF_TABLE(
‘ICD’,
‘unpar_table’,
‘par_table’,
‘ID ID, create_date TIME’, – 在这里指定新的映射关系
DBMS_REDEFINITION.CONS_USE_PK);
这一步操作结束后,数据就已经同步到这个临时的分区表里来了。
4.3 同步新表,这是可选的操作
SQL> BEGIN
2 dbms_redefinition.sync_interim_table(
3 uname => ‘ICD’,
4 orig_table => ‘unpar_table’,
5 int_table => ‘par_table’);
6 END;
7 /
PL/SQL 过程已成功完成。
4.4 创建索引,在线重定义只重定义数据,索引还需要单独建立。
sql> create index create_date_ind2 on par_table(time);
索引已创建。
4.5 收集新表的统计信息
sql> exec dbms_stats.gather_table_stats(‘icd’, ‘par_table’, cascade => true);
pl/sql 过程已成功完成。
4.6 结束重定义
SQL> BEGIN
2 dbms_redefinition.finish_redef_table(
3 uname => ‘ICD’,
4 orig_table => ‘unpar_table’,
5 int_table => ‘par_table’);
6 END;
7 /
PL/SQL 过程已成功完成。
结束重定义的意义:
基表unpar_table 和临时分区表par_table 进行了交换。 此时临时分区表par_table成了普通表,我们的基表unpar_table成了分区表。
我们在重定义的时候,基表unpar_table是可以进行DML操作的。 只有在2个表进行切换的时候会有短暂的锁表。
删除临时表
SQL> DROP TABLE par_table;
表已删除。
索引重命名
SQL> ALTER INDEX create_date_ind2 RENAME TO create_date_ind;
索引已更改。
验证
sql> select partitioned from user_tables where table_name = ‘UNPAR_TABLE’;

par

yes
sql> select partition_name from user_tab_partitions where table_name = ‘UNPAR_TABLE’;

partition_name

p1
p2
p3
p4
sql> select count() from unpar_table;

count()

72288
sql> select count() from unpar_table partition (p4);

count()

72288
sql>
三. 分区表的其他操作
3.1 添加新的分区
添加新的分区有2中情况:
(1)原分区里边界是maxvalue或者default。 这种情况下,我们需要把边界分区drop掉,加上新分区后,在添加上新的分区。 或者采用split,对边界分区进行拆分。
(2)没有边界分区的。 这种情况下,直接添加分区就可以了。
以边界分区添加新分区示例:
(1)分区表和索引的信息如下:
SQL> create table custaddr
2 (
3 id varchar2(15 byte) not null,
4 areacode varchar2(4 byte)
5 )
6 partition by list (areacode)
7 (
8 partition t_list556 values (‘556’) tablespace icd_service,
9 partition p_other values (default)tablespace icd_service
10 );
表已创建。
SQL> create index ix_custaddr_id on custaddr(id)
2 local (
3 partition t_list556 tablespace icd_service,
4 partition p_other tablespace icd_service
5 );
索引已创建。
(2)插入几条测试数据:
SQL> insert into custaddr values(‘1’,’556’);
已创建 1 行。
SQL> insert into custaddr values(‘2’,’551’);
已创建 1 行。
SQL> insert into custaddr values(‘3’,’555’);
已创建 1 行。
SQL> commit;
提交完成。
SQL> select * from custaddr;
ID AREA


1 556
2 551
3 555
SQL> select * from custaddr partition(t_list556);
ID AREA


1 556
SQL>
(3)删除default分区
sql> alter table custaddr drop partition p_other;
表已更改。
sql> select table_name,partition_name from user_tab_partitions where table_name=’CUSTADDR’;
table_name partition_name


custaddr t_list556
(4)添加新分区
SQL> alter table custaddr add partition t_list551 values(‘551’) tablespace icd_service;
表已更改。
SQL> select table_name,partition_name from user_tab_partitions where table_name=’CUSTADDR’;
TABLE_NAME PARTITION_NAME


CUSTADDR T_LIST556
CUSTADDR T_LIST551
(5)添加default 分区
SQL> alter table custaddr add partition p_other values (default) tablespace icd_service;
表已更改。
SQL> select table_name,partition_name from user_tab_partitions where table_name=’CUSTADDR’;
TABLE_NAME PARTITION_NAME


CUSTADDR T_LIST556
CUSTADDR T_LIST551
CUSTADDR P_OTHER
(6)对于局部索引,oracle会自动增加一个局部分区索引。验证一下:
sql> select owner,index_name,table_name,partitioning_type from dba_part_indexes where index_name=’ix_custaddr_id’;
owner index_name table_name


icd ix_custaddr_id custaddr
sql> select index_owner,index_name,partition_name from dba_ind_partitions where index_name=’ix_custaddr_id’;
index_owner index_name partition_name


icd ix_custaddr_id p_other
icd ix_custaddr_id t_list551
icd ix_custaddr_id t_list556
分区索引自动创建了。
3.2 split 分区拆分
在3.1 中,我们说明了可以使用split的方式来添加分区。 这里我们用split方法继续上面的实验。
sql> alter table custaddr split partition p_other values(‘552’) into (partition t_list552 tablespace icd_service, partition p_other tablespace icd_service);
表已更改。
–注意这里红色的地方,如果是Range类型的,使用at,List使用Values。
SQL> select table_name,partition_name from user_tab_partitions where table_name=’CUSTADDR’;
TABLE_NAME PARTITION_NAME


CUSTADDR T_LIST556
CUSTADDR T_LIST551
CUSTADDR T_LIST552
CUSTADDR P_OTHER
SQL> select index_owner,index_name,partition_name from dba_ind_partitions where index_name=’IX_CUSTADDR_ID’;
index_owner index_name partition_name


icd ix_custaddr_id p_other
icd ix_custaddr_id t_list551
icd ix_custaddr_id t_list552
icd ix_custaddr_id t_list556
注意:分区表会自动维护局部分区索引。全局索引会失效,需要进行rebuild。
3.3 合并分区Merge
相邻的分区可以merge为一个分区,新分区的下边界为原来边界值较低的分区,上边界为原来边界值较高的分区,原先的局部索引相应也会合并,全局索引会失效,需要rebuild。
SQL> alter table custaddr merge partitions t_list552,p_other into partition p_other;
表已更改。
SQL> select index_owner,index_name,partition_name from dba_ind_partitions where index_name=’IX_CUSTADDR_ID’;
index_owner index_name partition_name


icd ix_custaddr_id p_other
icd ix_custaddr_id t_list551
icd ix_custaddr_id t_list556
SQL> select table_name,partition_name from user_tab_partitions where table_name=’CUSTADDR’;
table_name partition_name


custaddr t_list556
custaddr t_list551
custaddr p_other
3.4 . 移动分区
SQL> alter table custaddr move partition P_OTHER tablespace system;
表已更改。
SQL> alter table custaddr move partition P_OTHER tablespace icd_service;
表已更改。
注意:分区移动会自动维护局部分区索引,oracle不会自动维护全局索引,所以需要我们重新rebuild分区索引,具体需要rebuild哪些索引,可以通过dba_part_indexes,dba_ind_partitions去判断。
SQL> Select index_name,status From user_indexes Where table_name=’CUSTADDR’;
INDEX_NAME STATUS


IX_CUSTADDR_ID N/A
3.5. Truncate分区
SQL> select * from custaddr partition(T_LIST556);
ID AREA


1 556
SQL> alter table custaddr truncate partition(T_LIST556);
表被截断。
SQL> select * from custaddr partition(T_LIST556);
未选定行
说明:
Truncate相对delete操作很快,数据仓库中的大量数据的批量数据加载可能会有用到;截断分区同样会自动维护局部分区索引,同时会使全局索引unusable,需要重建
3.6. Drop分区
SQL> alter table custaddr drop partition T_LIST551;
表已更改。
SQL> select table_name,partition_name from user_tab_partitions where table_name=’CUSTADDR’;
TABLE_NAME PARTITION_NAME


CUSTADDR T_LIST556
CUSTADDR P_OTHER
同样会自动维护局部分区索引,同时会使全局索引unusable,需要重建
四. 分区表的索引
分区索引分为本地(local index)索引和全局索引(global index)。局部索引比全局索引容易管理, 而全局索引比较快。
与索引有关的表:
dba_part_indexes 分区索引的概要统计信息,可以得知每个表上有哪些分区索引,分区索引的类型(local/global)
dba_ind_partitions 每个分区索引的分区级统计信息
dba_indexes/dba_part_indexes 可以得到每个表上有哪些非分区索引
Local索引肯定是分区索引,Global索引可以选择是否分区,如果分区,只能是有前缀的分区索引。
分区索引分2类:有前缀(prefix)的分区索引和无前缀(nonprefix)的分区索引:
(1)有前缀的分区索引指包含了分区键,并且将其作为引导列的索引。
如:
create index i_id_global on PDBA(id) global –引导列
2 partition by range(id) –分区键
3 (partition p1 values less than (200),
4 partition p2 values less than (maxvalue)
5 );
这里的ID 就是分区键,并且分区键id 也是索引的引导列。
(2)无前缀的分区索引的列不是以分区键开头,或者不包含分区键列。
如:
create index ix_custaddr_local_id_p on custaddr(id)
local (
partition t_list556 tablespace icd_service,
partition p_other tablespace icd_service
)
这个分区是按照areacode来的。但是索引的引导列是ID。 所以它就是非前缀分区索引。
全局分区索引不支持非前缀的分区索引,如果创建,报错如下:
SQL> create index i_time_global on PDBA(id) global –索引引导列
2 partition by range(time) –分区建
3 (partition p1 values less than (TO_DATE(‘2010-12-1’, ‘YYYY-MM-DD’)),
4 partition p2 values less than (maxvalue)
5 );
partition by range(time)
第 2 行出现错误:
ORA-14038: GLOBAL 分区索引必须加上前缀
4.1 Local 本地索引
对于local索引,当表的分区发生变化时,索引的维护由Oracle自动进行。
注意事项:
(1) 局部索引一定是分区索引,分区键等同于表的分区键。
(2) 前缀和非前缀索引都可以支持索引分区消除,前提是查询的条件中包含索引分区键。
(3) 局部索引只支持分区内的唯一性,无法支持表上的唯一性,因此如果要用局部索引去给表做唯一性约束,则约束中必须要包括分区键列。
(4) 局部分区索引是对单个分区的,每个分区索引只指向一个表分区;全局索引则不然,一个分区索引能指向n个表分区,同时,一个表分区,也可能指向n个索引分区,对分区表中的某个分区做truncate或者move,shrink等,可能会影响到n个全局索引分区,正因为这点,局部分区索引具有更高的可用性。
(5) 位图索引必须是局部分区索引。
(6) 局部索引多应用于数据仓库环境中。
(7) B树索引和位图索引都可以分区,但是HASH索引不可以被分区。
示例:
sql> create index ix_custaddr_local_id on custaddr(id) local;
索引已创建。
和下面SQL 效果相同,因为local索引就是分区索引:
create index ix_custaddr_local_id_p on custaddr(id)
local (
partition t_list556 tablespace icd_service,
partition p_other tablespace icd_service
)
SQL> create index ix_custaddr_local_areacode on custaddr(areacode) local;
索引已创建。
验证2个索引的类型:
SQL> select index_name,table_name,partitioning_type,locality,ALIGNMENT from user_part_indexes where table_name=’CUSTADDR’;
index_name table_name partition locali alignment


ix_custaddr_local_areacode custaddr list local prefixed
ix_custaddr_local_id custaddr list local non_prefixed
因为我们的custaddr表是按areacode进行分区的,所以索引ix_custaddr_local_areacode是有前缀的索引(prefixed)。而ix_custaddr_local_id是非前缀索引。
4.2 Global索引
对于global索引,可以选择是否分区,而且索引的分区可以不与表分区相对应。全局分区索引只能是B树索引,到目前为止(10gR2),oracle只支持有前缀的全局索引。
另外oracle不会自动的维护全局分区索引,当我们在对表的分区做修改之后,如果对分区进行维护操作时不加上update global indexes的话,通常会导致全局索引的INVALDED,必须在执行完操作后 REBUILD。
注意事项:
(1)全局索引可以分区,也可以是不分区索引,全局索引必须是前缀索引,即全局索引的索引列必须是以索引分区键作为其前几列。
(2)全局索引可以依附于分区表;也可以依附于非分区表。
(3)全局分区索引的索引条目可能指向若干个分区,因此,对于全局分区索引,即使只截断一个分区中的数据,都需要rebulid若干个分区甚至是整个索引。
(4)全局索引多应用于oltp系统中。
(5)全局分区索引只按范围或者散列分区,hash分区是10g以后才支持。
(6) oracle9i以后对分区表做move或者truncate的时可以用update global indexes语句来同步更新全局分区索引,用消耗一定资源来换取高度的可用性。
(7) 表用a列作分区,索引用b做局部分区索引,若where条件中用b来查询,那么oracle会扫描所有的表和索引的分区,成本会比分区更高,此时可以考虑用b做全局分区索引。
注意:Oracle只支持2中类型的全局分区索引:
range partitioned 和 Hash Partitioned.
官网的说明如下:
Global Partitioned Indexes
Oracle offers two types of global partitioned index: range partitioned and hash partitioned.
(1)Global Range Partitioned Indexes
Global range partitioned indexes are flexible in that the degree of partitioning and the partitioning key are independent from the table’s partitioning method. They are commonly used for OLTP environments and offer efficient access to any individual record.
The highest partition of a global index must have a partition bound, all of whose values are MAXVALUE. This ensures that all rows in the underlying table can be represented in the index. Global prefixed indexes can be unique or nonunique.
You cannot add a partition to a global index because the highest partition always has a partition bound of MAXVALUE. If you wish to add a new highest partition, use the ALTER INDEX SPLIT PARTITION statement. If a global index partition is empty, you can explicitly drop it by issuing the ALTER INDEX DROP PARTITION statement. If a global index partition contains data, dropping the partition causes the next highest partition to be marked unusable. You cannot drop the highest partition in a global index.
(2)Global Hash Partitioned Indexes
Global hash partitioned indexes improve performance by spreading out contention when the index is monotonically growing. In other words, most of the index insertions occur only on the right edge of an index.
(3)Maintenance of Global Partitioned Indexes
By default, the following operations on partitions on a heap-organized table mark all global indexes as unusable:
ADD (HASH)
COALESCE (HASH)
DROP
EXCHANGE
MERGE
MOVE
SPLIT
TRUNCATE
示例1 全局索引,全局索引对所有分区类型都支持:
sql> create index ix_custaddr_ global_id on custaddr(id) global;
索引已创建。
示例2:全局分区索引,只支持Range 分区和Hash 分区:
(1)创建2个测试分区表:
sql> create table pdba (id number, time date) partition by range (time)
2 (
3 partition p1 values less than (to_date(‘2010-10-1’, ‘yyyy-mm-dd’)),
4 partition p2 values less than (to_date(‘2010-11-1’, ‘yyyy-mm-dd’)),
5 partition p3 values less than (to_date(‘2010-12-1’, ‘yyyy-mm-dd’)),
6 partition p4 values less than (maxvalue)
7 );
表已创建。
SQL> create table Thash
2 (
3 id number primary key,
4 item_id number(8) not null
5 )
6 partition by hash(id)
7 (
8 partition part_01,
9 partition part_02,
10 partition part_03
11 );
表已创建。
(2)创建分区索引
示例2:全局分区索引
SQL> create index i_id_global on PDBA(id) global
2 partition by range(id)
3 (partition p1 values less than (200),
4 partition p2 values less than (maxvalue)
5 );
索引已创建。
–这个是有前缀的分区索引。
SQL> create index i_time_global on PDBA(id) global
2 partition by range(time)
3 (partition p1 values less than (TO_DATE(‘2010-12-1’, ‘YYYY-MM-DD’)),
4 partition p2 values less than (maxvalue)
5 );
partition by range(time)
第 2 行出现错误:
ORA-14038: GLOBAL 分区索引必须加上前缀
SQL> create index i_time_global on PDBA(time) global
2 partition by range(time)
3 (partition p1 values less than (TO_DATE(‘2010-12-1’, ‘YYYY-MM-DD’)),
4 partition p2 values less than (maxvalue)
5 );
索引已创建。
–有前缀的分区索引
SQL> select index_name,table_name,partitioning_type,locality,ALIGNMENT from user_part_indexes where table_name=’PDBA’;
index_name table_name partition locali alignment


i_id_global pdba range global prefixed
i_time_global pdba range global prefixed
SQL> CREATE INDEX ix_hash ON PDBA (id,time) GLOBAL
2 PARTITION BY HASH (id)
3 (PARTITION p1,
4 PARTITION p2,
5 PARTITION p3,
6 PARTITION p4);
索引已创建。
只要索引的引导列包含分区键,就是有前缀的分区索引。
4.3 索引重建问题
(1)分区索引
对于分区索引,不能整体进行重建,只能对单个分区进行重建。语法如下:
Alter index idx_name rebuild partition index_partition_name [online nologging]
说明:
online:表示重建的时候不会锁表。
nologging:表示建立索引的时候不生成日志,加快速度。
如果要重建分区索引,只能drop表原索引,在重新创建:
SQL>create index loc_xxxx_col on xxxx(col) local tablespace SYSTEM;
这个操作要求较大的临时表空间和排序区。
示例:
SQL> select index_name,partition_name from user_ind_partitions where index_name=’I_TIME_GLOBAL’;
INDEX_NAME PARTITION_NAME


I_TIME_GLOBAL P1
I_TIME_GLOBAL P2
SQL> alter index I_TIME_GLOBAL rebuild partition p1 online nologging;
索引已更改。
SQL> alter index I_TIME_GLOBAL rebuild partition p2 online nologging;
索引已更改。
(2)全局索引
Oracle 会自动维护分区索引,对于全局索引,如果在对分区表操作时,没有指定update index,则会导致全局索引失效,需要重建。
SQL> select owner,index_name,table_name,status from dba_indexes where INDEX_NAME=’IX_PDBA_GLOBAL’;
owner index_name table_name status


sys ix_pdba_global pdba valid
删除一个分区:
SQL> alter table pdba drop partition p2;
表已更改。
SQL> select owner,index_name,table_name,status from dba_indexes where INDEX_NAME=’IX_PDBA_GLOBAL’;
owner index_name table_name status


sys ix_pdba_global pdba valid
split 分区:
SQL> alter table pdba split partition P4 at(TO_DATE(‘2010-12-21 00:00:00’,’YYYY-MM-DD HH24:MI:SS’)) into (partition P4, partition P5);
表已更改。
SQL> select owner,index_name,table_name,status from dba_indexes where INDEX_NAME=’IX_PDBA_GLOBAL’;
owner index_name table_name status


sys ix_pdba_global pdba valid
drop 分区时使用update indexes
SQL> alter table pdba drop partition P4 UPDATE INDEXES;
表已更改。
SQL> select owner,index_name,table_name,status from dba_indexes where INDEX_NAME=’IX_PDBA_GLOBAL’;
owner index_name table_name status


sys ix_pdba_global pdba valid
做了几个drop分区操作,全局索引没有失效,有点奇怪。 不过如果在生产环境中,还是小心点。
重建全局索引命令如下:
Alter index idx_name rebuild [online nologging]
示例:
SQL> Alter index ix_pdba_global rebuild online nologging;
索引已更改。
补充一点,分区表存储空间的问题:
SQL> select table_name,partition_name,tablespace_name from user_tab_partitions where table_name=’DBA’;
TABLE_NAME PARTITION_NAME TABLESPACE_NAME


DBA P1 SYSTEM
DBA P2 SYSTEM
DBA P3 SYSTEM
DBA P4 SYSTEM
通过user_tab_partitions 表可以查看到每个分区对应的tablesapce_name. 但是,如果通过all_tables 表,却查不到分区表对应表空间的信息。
分区表:
SQL> select owner,table_name,tablespace_name,cluster_name from all_tables where table_name=’DBA’;
OWNER TABLE_NAME TABLESPACE_NAME CLUSTER_NAME


SYS DBA
普通表:
SQL> select owner,table_name,tablespace_name,cluster_name from all_tables where table_name=’DAVE’;
OWNER TABLE_NAME TABLESPACE_NAME CLUSTER_NAME


SYS DAVE SYSTEM
分类: oracle

============================================================================================================
ORACLE关于锁表查询的部分SQL

–查询表空间名称和大小
SELECT UPPER (F.TABLESPACE_NAME) “表空间名”,
D.TOT_GROOTTE_MB “表空间大小(M)”,
D.TOT_GROOTTE_MB - F.TOTAL_BYTES “已使用空间(M)”,
TO_CHAR (ROUND ((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100, 2), ‘990.99’) “使用比”,
F.TOTAL_BYTES “空闲空间(M)”,
F.MAX_BYTES “最大块(M)”
FROM ( SELECT TABLESPACE_NAME,
ROUND (SUM (BYTES) / (1024 * 1024), 2) TOTAL_BYTES,
ROUND (MAX (BYTES) / (1024 * 1024), 2) MAX_BYTES
FROM SYS.DBA_FREE_SPACE
GROUP BY TABLESPACE_NAME) F,
( SELECT DD.TABLESPACE_NAME,
ROUND (SUM (DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB
FROM SYS.DBA_DATA_FILES DD
GROUP BY DD.TABLESPACE_NAME) D
WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
ORDER BY 4 DESC;

–查看数据库引起锁表的SQL语句:
SELECT A.USERNAME, A.MACHINE, A.PROGRAM, A.SID, A.SERIAL#, A.STATUS, C.PIECE, C.SQL_TEXT
FROM V SESSIONA,V S E S S I O N A , V SQLTEXT C
WHERE A.SID IN
(SELECT DISTINCT T2.SID FROM V LOCKEDOBJECTT1,V L O C K E D O B J E C T T 1 , V SESSION T2 WHERE T1.SESSION_ID = T2.SID)
AND A.SQL_ADDRESS = C.ADDRESS(+)
ORDER BY C.PIECE;

–查看数据库锁的情况必须要有DBA权限,可以使用一下SQL 语句:
SELECT object_id, session_id, locked_mode FROM v$locked_object;

SELECT t2.username, t2.sid, t2.serial#, t2.logon_time
FROM v lockedobjectt1,v l o c k e d o b j e c t t 1 , v session t2
WHERE t1.session_id = t2.sid
ORDER BY t2.logon_time;

–查看被锁的表
SELECT P.SPID,
A.SERIAL#,
C.OBJECT_NAME,
B.SESSION_ID,
B.ORACLE_USERNAME,
B.OS_USER_NAME
FROM V PROCESSP,V P R O C E S S P , V SESSION A,
V$LOCKED_OBJECT B,
ALL_OBJECTS C
WHERE P.ADDR = A.PADDR
AND A.PROCESS = B.PROCESS
AND C.OBJECT_ID = B.OBJECT_ID;

–杀掉进程
ALTER SYSTEM KILL SESSION ‘sid,serial#’;

–查看连接数
SELECT COUNT (*) FROM v$session;

–查看并发连接数
SELECT COUNT(*) FROM V$SESSION WHERE STATUS=’ACTIVE’;

–查看连接的进程
SELECT SID, SERIAL#, USERNAME, OSUSER FROM V$SESSION;

–查看数据库使用的裸设备
SELECT *
FROM dba_data_files
ORDER BY file_name;

SELECT *
FROM dba_temp_files
ORDER BY file_name;

SELECT *
FROM v$controlfile
ORDER BY file_name;

SELECT *
FROM v$logfile;

–具体的方法是查询dba_data_files,dba_temp_files,v controlfilev c o n t r o l f i l e 和 v logfile看这四类文件具体占用的裸设备

–查询所有用户表使用大小的前三十名
select * from (select segment_name,bytes from dba_segments where owner = USER order by bytes desc ) where rownum <= 30;

–以下的SQL语句列出当前数据库建立的会话情况:
select sid,serial#,username,program,machine,status from v$session;

–如果DBA要手工断开某个会话,则执行:
alter system kill session ‘SID,SERIAL#’;
–注意,上例中SID为1到7(USERNAME列为空)的会话,是Oracle的后台进程,不要对这些会话进行任何操作。

–查询表空间有那些表:
select table_name from all_tables where tablespace_name= ‘TEMP’;


UPDATE tb_code_info ta
SET ta.attr3 =
(SELECT tmp.sort_no
FROM (SELECT RANK() OVER(PARTITION BY t.DIVISION ORDER BY t.code_nm) sort_no, t.code
FROM tb_code_info t
WHERE t.com_code = ‘LGEHZ’
AND t.DIVISION = ‘SHIP_CPNY’) tmp
WHERE tmp.code = ta.code)
WHERE ta.com_code = ‘LGEHZ’
AND Ta.DIVISION = ‘SHIP_CPNY’;

=============================================================================================================

ORA-24247: 网络访问被访问控制列表 (ACL) 拒绝

注意:需要在system用户下使用命令
需要先使用 DBMS_NETWORK_ACL_ADMIN.CREATE_ACL 创建访问控制列表(ACL),
再使用 DBMS_NETWORK_ACL_ADMIN.ASSIGN_ACL 将此 ACL 与邮件服务器相关联,
最后使用 DBMS_NETWORK_ACL_ADMIN.ADD_PRIVILEGE 在此 ACL 为用户授与连接邮件服务器的权限。

BEGIN
DBMS_NETWORK_ACL_ADMIN.CREATE_ACL (
  acl          => ‘email_server_permissions.xml’,
  description  => ‘Enables network permissions for the e-mail server’,
  principal    => ‘APPS’,
  is_grant     => TRUE,
  privilege    => ‘connect’);
END;
/

BEGIN
DBMS_NETWORK_ACL_ADMIN.assign_acl (
    acl         => ‘email_server_permissions.xml’,
    host        => ‘123.125.50.132’, –SMTP服务器地址
    lower_port  => 25,
    upper_port  => NULL);
  COMMIT;
END;
/

–drop
BEGIN
  DBMS_NETWORK_ACL_ADMIN.drop_acl(acl => ‘email_server_permissions.xml’);
  COMMIT;
END;
/

–查询
  SELECT host, lower_port, upper_port, acl FROM dba_network_acls;

SELECT acl,
       principal,
       privilege,
       is_grant,
       TO_CHAR(start_date, ‘DD-MON-YYYY’) AS start_date,
       TO_CHAR(end_date, ‘DD-MON-YYYY’) AS end_date
  FROM dba_network_acl_privileges;

=============================================================================================================
ORA-01653:表空间扩展失败的问题
今天发现,原来设备的数据表空间只5M,已经满了,上网去找发现要进行扩展空间。
一、脚本修改方式:
—-查询表空间使用情况—
使用DBA权限登陆
SELECT UPPER(F.TABLESPACE_NAME) “表空间名”,
D.TOT_GROOTTE_MB “表空间大小(M)”,
D.TOT_GROOTTE_MB - F.TOTAL_BYTES “已使用空间(M)”,
TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),’990.99’) “使用比”,
F.TOTAL_BYTES “空闲空间(M)”,
F.MAX_BYTES “最大块(M)”
FROM (SELECT TABLESPACE_NAME,
ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES,
ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES
FROM SYS.DBA_FREE_SPACE
GROUP BY TABLESPACE_NAME) F,
(SELECT DD.TABLESPACE_NAME,
ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB
FROM SYS.DBA_DATA_FILES DD
GROUP BY DD.TABLESPACE_NAME) D
WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
ORDER BY 4 DESC;
表空间名                       表空间大小(M) 已使用空间(M) 使用比 空闲空间(M) 最大块(M)



CCEN                                      10           8.5   85.00         1.5        .94

发现表空间只1.5M的空闲,猜测可能是表空间自动扩展失败的问题(表空间的增长量太高,ORACLE默认是50%),修改表空间文件扩展方式:

SQL>ALTER DATABASE 
    DATAFILE ‘/u01/oracle/oradata/orcl/ccen01.dbf’ AUTOEXTEND 
    ON NEXT 50M MAXSIZE UNLIMITED
问题解决.

查看表空间是否具自动扩展的能力
SELECT T.TABLESPACE_NAME,D.FILE_NAME,
D.AUTOEXTENSIBLE,D.BYTES,D.MAXBYTES,D.STATUS
FROM DBA_TABLESPACES T,DBA_DATA_FILES D
WHERE T.TABLESPACE_NAME =D.TABLESPACE_NAME
ORDER BY TABLESPACE_NAME,FILE_NAME;
二、使用控制台方式:
打开ORACLE的企业管理器,到表空间选择要修改的表空间,双击点开表穿间的编缉界面,点击那只笔的图标,在编辑数据文件界面的存储选项卡上就可以修改“数据文件已满后自动扩展”修改希望的增量,和最大值后点应用进行保存。

==============================================================================================
oracle 迁移至 mysql 部分语句的转换
2014-02-26 16:16 4356人阅读 评论(0) 收藏 举报
版权声明:本文为博主原创文章,未经博主允许不得转载。
前几天吧系统从oracle往mysql上迁移,很多的语句是比较简单的,就是一些函数的修改如to-date等
但是也几个比较棘手的,这里记录下

第一、row_number() over(partition by   
首先要了解下oracle中这个函数的用法,看个例子
select t.*,row_number() over(partition by t.owner order by y.createDate desc) rn from test t
这个语句的意思就是,把test这个表的数据按照owner 分组并且给每个分组的里面的数据加上一个序列号,数据 式如下

id       name      owner   createDate  rn
1         aa            001                              1
2          bb           001                              2
3          cc            001                             3
4          dd            002                             1
5           ee           002                              2
6            ff            003                               1
数据搞得不太正规,但是应该能够看懂它的意思吧,

但是在mysql中是没有这个函数的于是乎,找啊找,总算找了个解决方法,如下
SELECT
    heyf_tmp.*,
    IF(@pdept=heyf_tmp.owner ,@rn:=@rn+1,@rn:=1) AS rn,
    @pdept:=heyf_tmp.owner 
FROM
    (
        SELECT
            yv.*
        FROM
            test yv
        ORDER BY
            yv.owner  ,
            yv.createDate  DESC
    )
    heyf_tmp ,
    (
        SELECT
            @rn :=0 ,
            @pdept := NULL ,
            @rn:=0
    )
    aa
具体是什么意思,不是很清楚,不过先解决问题再说

第二、oracle树形查询

oracle树形查询现成的方法
select distinct t.id as id, t.name 
from test t
                start with id=‘’
               connect by prior id = parentid
但是mysql中是没有这个方法的,于是只能自己定义函数或者过程,我这里用的是过程
如下
CREATE PROCEDURE Pro_GetTreeList(in pid varchar(36))
begin 
   declare lev int;
   set lev=1;
   drop table if exists tmp1;    
   CREATE TABLE tmp1(id VARCHAR(40),name varchar(50),parentid varchar(40) ,levv INT);    
   INSERT tmp1 SELECT id,name,parent_id,1 FROM
test` WHERE parent_id=pid;    
  while  row_count()>0 
    do     set lev=lev+1;     
     INSERT tmp1 SELECT t.id,t.name,t.parent_id,lev from testt join tmp1 a on t.parent_id=a.id AND levv=lev-1;–查出子节点
  end while ;    
  INSERT tmp1 SELECT id,name,parent_id,0 FROM test WHERE id=pid;   –查出当前节点
end
这个存储过程应该都能看懂吧,就不做多解释了

第 、函数中定义类 一维、二维数组,

oracle中可以直接定义的,如
return number  is   newList  :=  NewList((1,2,3),(4,5,6));这样可以直接返回   return newList(1,2)    返回的就是2了,
但是mysql中却不能这样写的,不过也有这样的方法解决:
对于一维的来说,很简单,有函数的elt函数,可以直接return   elt(index,’1’,’2’,’3’);   如果elt(3,’1’,’2’,’3’)  这样返回的就是 3了,

不过对于二维的来说好像没现成的函数用了,我的解决方法是改成个表来做,把数据录入到表中,然后去查表,这丫要给你也是可以实现

第四、 mysql中获取汉字的首个大写字母
mysql中遇到了这样的一个问题,网上找到了方法,转载地址://http://blog.csdn.net/lky5387/article/details/11973721
DROP FUNCTION IF EXISTS getPY;
DELIMITER ;;
CREATE DEFINER=root@% FUNCTION getPY(in_string VARCHAR(65534)) RETURNS mediumtext CHARSET utf8
BEGIN
DECLARE tmp_str VARCHAR(65534) charset gbk DEFAULT ” ; #截取字符串,每次做截取后的字符串存放在该变量中,初始为函数参数in_string 
DECLARE tmp_len SMALLINT DEFAULT 0;#tmp_str的长度
DECLARE tmp_char VARCHAR(2) charset gbk DEFAULT ”;#截取字符,每次 left(tmp_str,1) 返回 存放在该变量中
DECLARE tmp_rs VARCHAR(65534) charset gbk DEFAULT ”;#结果字符串
DECLARE tmp_cc VARCHAR(2) charset gbk DEFAULT ”;#拼音字符,存放单个汉字对应的拼音首字符
SET tmp_str = in_string;#初始化,将in_string赋给tmp_str
SET tmp_len = LENGTH(tmp_str);#初始化长度
WHILE tmp_len > 0 DO #如果被计算的tmp_str长度大于0则进入该while
SET tmp_char = LEFT(tmp_str,1);#获取tmp_str最左端的首个字符,注意这里是获取首个字符,该字符可能是汉字,也可能不是。
SET tmp_cc = tmp_char;#左端首个字符赋 给拼音字符
IF LENGTH(tmp_char)>1 THEN#判断左端首个字符是多字节还是单字节字符,要是多字节则认为是汉字且作以下拼音获取,要是单字节则不处理。
SELECT ELT(INTERVAL(CONV(HEX(tmp_char),16,10),0xB0A1,0xB0C5,0xB2C1,0xB4EE,0xB6EA,0xB7A2,0xB8C1,0xB9FE,0xBBF7,0xBFA6,0xC0AC
,0xC2E8,0xC4C3,0xC5B6,0xC5BE,0xC6DA,0xC8BB,0xC8F6,0xCBFA,0xCDDA ,0xCEF4,0xD1B9,0xD4D1),
‘A’,’B’,’C’,’D’,’E’,’F’,’G’,’H’,’J’,’K’,’L’,’M’,’N’,’O’,’P’,’Q’,’R’,’S’,’T’,’W’,’X’,’Y’,’Z’) INTO tmp_cc; #获得汉字拼音首字符
END IF;
SET tmp_rs = CONCAT(tmp_rs,tmp_cc);#将当前tmp_str左端首个字符拼音首字符与返回字符串拼接
SET tmp_str = SUBSTRING(tmp_str,2);#将tmp_str左端首字符去除
SET tmp_len = LENGTH(tmp_str);#计算当前字符串长度
END WHILE;
RETURN tmp_rs;#返回结果字符串
END;;
DELIMITER ;
第四、 图片clob的修改
系统中的功能是把图片存在blob字段中的,,原来用的是oracle,java中对应的字段是Object,但是mysql中如果这样做却不能独处图片,原因可能是因为在往Object中写数据时出错了,这个号解决,只要把java中对应字段的类型改成byte[]  就行了

第五、mysql中 group_concat  与 find_in_set  用法
在项目中遇到这样的需求,
表event中如下字段                                           表work中如下字段
         id                 ename                                              id            wname              eventid
      1001       事件1                                   1          工作1         1001
      1002       事件2                                   2          工作2         1001,1002
      1003       事件3                                   3          工作3         1001,1003
       现查询了一张work表数据,需要展示id   name   event名称,只用一个sql展示,
       select wname,  (select group_concat(ename) from event where find_in_set(id,eventid) ) as ename  from  work;
这一个sql就可以搞定,find_in_set  用法以逗号分隔开与id进行匹配,返回多条记录,  group_concat为把展示的多行记录做成一列展示并以逗号拼接   
 

Oracle调用webservice说明
1.             用途简介
为什么要在Oracle中访问WebService?在系统实现中,时会直接在数据库端利用触发器、存储过程等方式进行数据传递、分发的业务,而其中可能会涉及一些业务逻辑,为了处理这些业务逻辑,并简单起见,可以直接在触发器或存储过程中调用一些java类或WebService。
2.             准备工作
1、首先保证Oracle为完全安装(本文均以10.2g);
2、下载对应版本的UTL_DBWS(一个工具包dbws-callout-utility-10131.zip),解压后放到oracle安装目录下的/sqlj/lib中;
      3、在命令行中利用loadjava命令(一般安装完jdk或oracle之后就会)将jar包导入oracle对应的用户中:
loadjava -u user/pwd@dbinstance -r -v -f -genmissing dbwsclientws.jar dbwsclientdb102.jar
若为SYS用户,命令为:
loadjava -u sys/change_on_install -r -v -f -genmissing -s -grant public dbwsclientws.jar dbwsclientdb102.jar
3.             步骤说明
前面准备工作做好之后,如果未发现UTL_DBWS(可以在plsql中敲入sys.若未utl_dbws显示,则需要进行初始化),需要运行之前下载的包中dbws-callout-utility-10131\sqlj\lib\ utl_dbws_body.sql及utl_dbws_decl.sql,这样准备工作基本就绪,下面是调用的步骤:
1、 编写sql函数并发布。
create or replace function FUNC_GENERATE_LOGINNAME(xmlstring?VARCHAR2)
return VARCHAR2 
   AS
       l_service utl_dbws.SERVICE;
牋牋牋?l_call utl_dbws.call;
牋牋牋?l_result ANYDATA;
牋牋牋?l_wsdl_url?VARCHAR2(1024);
牋牋牋?l_service_name?VARCHAR2(200);
牋牋牋?l_operation_name?VARCHAR2(200);
牋牋牋?l_input_params UTL_DBWS.anydata_list;
牋牋BEGIN
       l_wsdl_url :=?’http://192.168.21.85:9080/xgxt/services/wfWebService?wsdl‘;
牋牋牋?l_service_name :=?’WorkflowWebServiceService’;
牋牋牋?l_operation_name :=?’saveFormData’;
牋牋牋?l_service := UTL_DBWS.create_service(wsdl_document_location=>URIFACTORY.getURI(l_wsdl_url),service_name=>l_service_name);

牋牋牋?l_call := UTL_DBWS.create_call(service_handle=>l_service,port_name=>NULL,operation_name=>l_operation_name);
牋牋牋?l_input_params(1) := ANYDATA.ConvertVarchar2(xmlstring);
牋牋牋牋牋牋?
牋牋牋?l_result := UTL_DBWS.invoke(call_handle=>l_call,input_params=>l_input_params);
牋牋牋?UTL_DBWS.release_call (call_handle=>l_call);
牋牋牋?UTL_DBWS.release_service (service_handle=>l_service);
牋牋牋?RETURN ANYDATA.AccessVarchar2(l_result);
牋牋EXCEPTION
      WHEN OTHERS THEN
        RETURN substr(sqlerrm,0,2000);
牋牋END FUNC_GENERATE_LOGINNAME;
2、 查看结果(select func_generate_loginname(var)?from dual)
对于其中出现的异常,最可能的就是出现权限不足,可以利用如下语句解决:
begin 
dbms_java.grant_permission(?’XGXT’, ‘SYS:java.lang.RuntimePermission’, ‘getClassLoader’, ” );
dbms_java.grant_permission(?’XGXT’,’SYS:java.lang.IllegalAccessException’,’getClassLoader’, ” );
dbms_java.grant_permission(?’XGXT’, ‘SYS:java.lang.RuntimePermission’, ‘accessClassInPackage.sun.util.calendar’, ” );
dbms_java.grant_permission(?’XGXT’, ‘SYS:java.lang.RuntimePermission’, ‘setFactory’, ” );
dbms_java.grant_permission(?’XGXT’, ‘SYS:java.util.PropertyPermission’, ‘HTTPClient.socket.idleTimeout’, ‘write’ );
dbms_java.grant_permission(?’XGXT’, ‘SYS:java.net.SocketPermission’, ‘localhost’, ‘resolve’ );
dbms_java.grant_permission(?’XGXT’, ‘SYS:java.net.SocketPermission’, ‘192.168.21.203:80’, ‘connect,resolve’ );
dbms_java.grant_permission(?’XGXT’, ‘SYS:java.lang.RuntimePermission’, ‘createClassLoader’, ” );
end;
4.             附
1、以上还只是针对windows服务器,对于unix/linux,主要是一些环境变量需要配置,需要查文档解决。
2、帮助的语句
SELECT owner, status,?count(*)?FROM DBA_OBJECTS
WHERE OBJECT_TYPE=’JAVA CLASS’
GROUP BY owner, status;?
select *?from User_Objects t?where t.object_type?like ‘%JAVA_CLASS%’ and object_name?like ‘%DbwsProxy%’;

SELECT   TEXT牋?FROM   ALL_SOURCE牋?
WHERE   TYPE   =牋?’PACKAGE’   and owner?like ‘%XGXT%’

===========================================================================
APMS webservice对应呢让接口表内容
XXOMDS_APMS_INQUIRY_V

CREATE OR REPLACE PROCEDURE VALIDATE_CSMG_PRC(P_IMEI_NO IN VARCHAR2,
P_MODEL IN VARCHAR2,
P_SUFFIX IN VARCHAR2,
P_TYPE IN VARCHAR2,
O_MODEL OUT VARCHAR2,
O_SUFFIX OUT VARCHAR2,
O_SEQ OUT VARCHAR2,
O_PASS_FLAG OUT VARCHAR2) AS

/**
* O_PASS_FLAG:
* 0 - exception
* 1 - input is null
* 2 - extract XML ERROR
* 3 - imei not in CSMG
* 4 - not master Imei,Dual Imei Model
* 5 - P_MODEL <> CSMG’s model
* 6 - model.suffix not in tm_model
* 7 - buyer not in domestic
* Y - SUCCESS
*/
V_REQ UTL_HTTP.REQ;
V_RESP UTL_HTTP.RESP;
V_VALUE VARCHAR2(4000);
V_XML VARCHAR2(4000);

V_MODEL VARCHAR2(50) := ”;
V_SUFFIX VARCHAR2(50) := ”;
V_ESN VARCHAR2(50) := ”;
V_MSN VARCHAR2(50) := ”;
V_ESNDATE VARCHAR2(50) := ”;
V_BUYER VARCHAR2(1000) := ”;
V_OUTGO_DATE VARCHAR2(50) := ”;
V_ULOCATIONCODE VARCHAR2(50) := ”;
V_BUYERNAME VARCHAR2(1000) := ”;
V_CSN VARCHAR2(50) := ”;

PP_IMEI VARCHAR2(30) := ”;
PP_MODEL VARCHAR2(30) := ”;
PP_SUFFIX VARCHAR2(30) := ”;

N_EXIST_FLAG NUMBER;
V_ERR_YN VARCHAR2(1) := ‘Y’;
V_REASON_DESC VARCHAR2(100);

BEGIN

– ???? ???
V_VALUE := ”;
V_XML := ”;

V_MODEL := ”;
V_SUFFIX := ”;
V_ESN := ”;
V_MSN := ”;
V_ESNDATE := ”;
V_BUYER := ”;
V_OUTGO_DATE := ”;
V_ULOCATIONCODE := ”;
V_BUYERNAME := ”;
V_CSN := ”;

PP_IMEI := UPPER(TRIM(P_IMEI_NO));
PP_MODEL := UPPER(TRIM(P_MODEL));
PP_SUFFIX := UPPER(TRIM(P_SUFFIX));
O_PASS_FLAG := ‘0’;

IF PP_IMEI IS NULL THEN
O_PASS_FLAG := ‘1’;
RETURN;
END IF;

– XML ??
BEGIN
–V_REQ := UTL_HTTP.BEGIN_REQUEST(‘http://csmg.lgmobile.com:9002/svc/popup/model_check.jsp?esn=’ || TRIM(V_IMEI));
V_REQ := UTL_HTTP.BEGIN_REQUEST(‘http://csmg.lgmobile.com:9002/svc/popup/model_check.jsp?esn=’ ||
PP_IMEI);
UTL_HTTP.SET_HEADER(V_REQ, ‘User-Agent’, ‘Mozilla/4.0’);
V_RESP := UTL_HTTP.GET_RESPONSE(V_REQ);

LOOP
  UTL_HTTP.READ_LINE(V_RESP, V_VALUE, TRUE);
  V_XML := V_XML || TRIM(V_VALUE);
END LOOP;

UTL_HTTP.END_RESPONSE(V_RESP);

EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(V_RESP);
WHEN OTHERS THEN
O_PASS_FLAG := ‘2’;
GOTO LAST_CSMG_LOG;
END;

SELECT UPPER(EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/model’)) MODEL,
UPPER(EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/suffix’)) SUFFIX,
UPPER(EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/esn’)) ESN,
EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/msn’) MSN,
EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/esndate’) ESNDATE,
UPPER(EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/buyer’)) BUYER,
EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/esnoutgodate’) OUTGO_DATE,
EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/ULocationcode’) ULOCATIONCODE,
EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/buyername’) BUYERNAME,
EXTRACTVALUE(XMLTYPE(V_XML), ‘/response/auth/csn’) CSN
INTO V_MODEL,
V_SUFFIX,
V_ESN,
V_MSN,
V_ESNDATE,
V_BUYER,
V_OUTGO_DATE,
V_ULOCATIONCODE,
V_BUYERNAME,
V_CSN
FROM DUAL;

IF V_MODEL IS NULL THEN
–imei not in CSMG
O_PASS_FLAG := ‘3’;
GOTO LAST_CSMG_LOG;
END IF;

IF PP_IMEI <> V_ESN THEN
–not master Imei,Dual Imei Model
O_PASS_FLAG := ‘4’;
GOTO LAST_CSMG_LOG;
END IF;

– 2011.01.07 Modify JH.Lee Add Start
IF PP_MODEL = ‘LGKX206’ THEN
IF V_MODEL <> ‘KX206’ THEN
–P_MODEL <> CSMG’s model
O_PASS_FLAG := ‘5’;
GOTO LAST_CSMG_LOG;
END IF;
ELSIF PP_MODEL = ‘GS100CU’ THEN
IF V_MODEL <> ‘GS100’ THEN
–P_MODEL <> CSMG’s model
O_PASS_FLAG := ‘5’;
GOTO LAST_CSMG_LOG;
END IF;
ELSE
IF PP_MODEL <> V_MODEL THEN
–P_MODEL <> CSMG’s model
O_PASS_FLAG := ‘5’;
GOTO LAST_CSMG_LOG;
END IF;
END IF;
– 2011.01.07 Modify JH.Lee Add End

/* 2011.01.07 Modify JH.Lee Comment
IF PP_MODEL <> V_MODEL THEN
–P_MODEL <> CSMG’s model
O_PASS_FLAG := ‘5’;
GOTO LAST_CSMG_LOG;
END IF;
*/

IF NVL(PP_SUFFIX,’@’) <> V_SUFFIX THEN – 2011.01.07 Modify JH.Lee Add
–IF PP_SUFFIX <> V_SUFFIX THEN – 2011.01.07 Modify JH.Lee Comment
SELECT COUNT(1)
INTO N_EXIST_FLAG
FROM TM_MODEL
WHERE COM_CODE = ‘LGECH’
AND MODEL = V_MODEL
AND SUFFIX = V_SUFFIX
AND HOLD_FLAG IN (‘N’, ‘P’)
AND ROWNUM = 1;

IF N_EXIST_FLAG > 0 THEN
  O_PASS_FLAG := 'Y';
  O_MODEL     := V_MODEL;
  O_SUFFIX    := V_SUFFIX;
  V_ERR_YN    := 'N';
  --GOTO LAST_CSMG_LOG;
ELSE
  SELECT COUNT(1)
    INTO N_EXIST_FLAG
    FROM TM_MODEL
   WHERE COM_CODE = 'LGECH'
     AND MODEL = PP_MODEL
     AND SUFFIX = PP_SUFFIX
     AND HOLD_FLAG IN ('N', 'P')
     AND ROWNUM = 1;

  IF N_EXIST_FLAG > 0 THEN
    O_PASS_FLAG := 'Y';
    O_MODEL     := PP_MODEL;
    O_SUFFIX    := PP_SUFFIX;
    V_ERR_YN    := 'N';
    --GOTO LAST_CSMG_LOG;
  ELSE
    O_PASS_FLAG := '6';
    GOTO LAST_CSMG_LOG;
  END IF;
END IF;

ELSE
SELECT COUNT(1)
INTO N_EXIST_FLAG
FROM TM_MODEL
WHERE COM_CODE = ‘LGECH’
AND MODEL = PP_MODEL
AND SUFFIX = PP_SUFFIX
AND HOLD_FLAG IN (‘N’, ‘P’)
AND ROWNUM = 1;

IF N_EXIST_FLAG > 0 THEN
  O_PASS_FLAG := 'Y';
  O_MODEL     := PP_MODEL;
  O_SUFFIX    := PP_SUFFIX;
  V_ERR_YN    := 'N';
  --GOTO LAST_CSMG_LOG;
ELSE
  O_PASS_FLAG := '6';
  GOTO LAST_CSMG_LOG;
END IF;

END IF;

SELECT COUNT(1)
INTO N_EXIST_FLAG
FROM CSMG_BUYER_LIST
WHERE –BUYER_ID = SUBSTR(O_SUFFIX, 2, 3)
instr(V_SUFFIX,BUYER_ID)>0;

IF N_EXIST_FLAG <= 0 AND V_SUFFIX <> ‘*’ THEN
–buyer not in domestic
O_PASS_FLAG := ‘7’;
V_ERR_YN := ‘Y’;
GOTO LAST_CSMG_LOG;
END IF;


<>
–insert CSMG log
SELECT CSMG_VALIDATE_LOG_S.NEXTVAL INTO O_SEQ FROM DUAL;

SELECT desc_loc INTO V_REASON_DESC FROM csmg_validate_desc WHERE cd_class=’CS’ AND cd_code = O_PASS_FLAG;

INSERT INTO CSMG_VALIDATE_LOG
(SEQ,
IMEI_NO,
ERROR_YN,
IN_MODEL,
IN_SUFFIX,
CSMG_MODEL,
CSMG_SUFFIX,
ESN,
MSN,
ESNDATE,
BUYER,
OUTGO_DATE,
ULOCATIONCODE,
BUYERNAME,
CSN,
CREATION_DATE,
REASON,
REASON_DESC,
TRANS_FLAG,
TRANS_TYPE)
VALUES
(O_SEQ,
PP_IMEI,
V_ERR_YN,
P_MODEL,
P_SUFFIX,
V_MODEL,
V_SUFFIX,
V_ESN,
V_MSN,
V_ESNDATE,
V_BUYER,
V_OUTGO_DATE,
V_ULOCATIONCODE,
V_BUYERNAME,
V_CSN,
SYSDATE,
O_PASS_FLAG,
V_REASON_DESC,
‘N’,
P_TYPE);
COMMIT;

–RETURN O_PASS_FLAG;

EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
–RETURN O_PASS_FLAG;
–insert CSMG log
END VALIDATE_CSMG_PRC;
/

oracle11本地访问局域网不行的解决
 
访问局域网Oracle数据库 解决在不能上网的情况下面局域网内无法访问oracle数据库
碰到过3次这种情况,整个研发部门基本是没有办法做事。  www.2cto.com  
早上起床快上班的时候还是不甘心,终于找到方法,
记住设置完之后要重启电脑,而且设置完之后,如果在没因特网的情况下面数据库访问很慢
现在两台电脑 A 和 B  ;
电脑 A 上有 Oracle11G服务端; ip地址 192.168.1.120; 端口1521 ;
 
电脑 A 本机连接数据库 正常,可以登录及操作等 ;
 
电脑 B 配置访问电脑 A 时报错:The Network Adapter could not establish the connection
 
报这种错的话,网上有说法, 说是防火墙没关,或者是 服务端服务没启好等..
 
本人的实际情况解说:
 
因为oracle服务端访问配置是需要配置访问地址监听的,具体见Oracle安装路径:
% product\11.2.0\dbhome_1\NETWORK\ADMIN\listener.ora
 
这个是我的oracle监听服务的配置文件,内容为

listener.ora Network Configuration File: E:\app\rcfeng\product\11.2.0\dbhome_1\network\admin\listener.ora

Generated by Oracle configuration tools.

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = CLRExtProc)
      (ORACLE_HOME = E:\app\rcfeng\product\11.2.0\dbhome_1)
      (PROGRAM = extproc)
      (ENVS = “EXTPROC_DLLS=ONLY:E:\app\rcfeng\product\11.2.0\dbhome_1\bin\oraclr11.dll”)
    )
  )
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
    )
  )
ADR_BASE_LISTENER = E:\app\rcfeng
 
其中
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
是指监听的地址;
由于本机的服务端一般都是自己做测试的时候访问 ;
而为什么我们写localhost:1521 的时候可以访问到,就是因为
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
这一句,我们监听了localhost,所以可以访问到..
 
如果需要被局域网访问的话,我们只需要加入监听访问地址就可以了,如:
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.120)(PORT = 1521))
 
这样局域网的机子就可以访问我们的oracle服务了..完整内容为:
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.120)(PORT = 1521))
    )
  )

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值