The ALL_TABLE_COLUMNS view filters out system-generated hidden columns and invisible columns.
The ALL_TAB_COLS view does not filter out hidden columns and invisible columns.
1 2 3 4 5 6 7 8 9
select* from all_tab_cols t where t.table_name =upper('table_name') and t.owner ='APPS'
selectlistagg(t.column_name, ',') withingroup(orderby t.segment_column_id) from all_tab_cols t where t.table_name =upper('table_name') and t.owner ='APPS';
DBMS_METADATA.GET_DDL ( object_type IN VARCHAR2, --对象类型 name IN VARCHAR2, --对象名称 schema IN VARCHAR2 DEFAULTNULL, --对象所在的Schema,默认为当前用户所在所Schema version IN VARCHAR2 DEFAULT'COMPATIBLE', --对象原数据的版本 model IN VARCHAR2 DEFAULT'ORACLE', --原数据的类型默认为ORACLE transform IN VARCHAR2 DEFAULT'DDL') RETURNCLOB; --对象的原数据默认以CLOB类型返回
GET_DDL 函数使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
select dbms_metadata.get_ddl('TABLE', 'ASO_BI_QOT_APRB_MV', 'APPS') from dual; select dbms_metadata.get_ddl('SEQUENCE', 'RA_TRX_NUMBER_1000_S', 'APPS') from dual; -- 获取所有sequence的定义 select dbms_metadata.get_ddl('SEQUENCE', u.object_name) from user_objects u where object_type='SEQUENCE'; --The output not include terminators. BEGIN DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'SQLTERMINATOR', true); DBMS_METADATA.set_transform_param (DBMS_METADATA.session_transform, 'PRETTY', true); END; / select DBMS_METADATA.get_ddl('TABLE', 'EDI_T') as output from dual;
1 2 3
select DBMS_METADATA.get_dependent_ddl('INDEX','SOM_EDI_856_HEADER','YSC') as output from dual;
select DBMS_METADATA.get_xml('TABLE', 'EDI_T') as output from dual;
createor replace trigger edi_block_dml_on_emp before insertor update ordeleteon edi_emp begin raise_application_error(-20001, 'DML Operation not allowed on EMP'); end;
insertinto edi_emp values (4, 'Babbbb Chen', 9000); -- ORA-20001: DML Operation not allowed on EMP
createtable edi_emp2( empno number primary key, ename varchar2(7), --edi_emp1 is varchar2(30) doj datenotnull, --edi_emp1 is nullable sal number notnull--edi_emp1 is nullable );
-------------------------------------------------------- insertinto edi_emp2 select*from edi_emp1 log errors into err$_edi_emp2('TEST INSERT') reject limit unlimited; -- TEST INSERT is ORA_ERR_TAG$
select*from err$_edi_emp2; select*from edi_emp2; -------------------------------------------------------- update edi_emp2 set sal =null log errors into err$_edi_emp2('TEST UPDATE') reject limit unlimited;
select*from err$_edi_emp2; select*from edi_emp2; --------------------------------------------------------- createor replace trigger edi_row_before_del before deleteon edi_emp2 foreachrow declare lv_number number; begin lv_number :=1/0; end;
deletefrom edi_emp2 log errors into err$_edi_emp2('TEST DELETE') reject limit unlimited;
select*from err$_edi_emp2; select*from edi_emp2;
ORA_ERR_NUMBER$
ORA_ERR_MESG$
ORA_ERR_ROWID$
ORA_ERR_OPTYP$
ORA_ERR_TAG$
EMPNO
ENAME
DOJ
SAL
1400
ORA-01400: cannot insert NULL into (“APPS”.“EDI_EMP2”.“SAL”)
I
TEST INSERT
2
Babb
31-MAR-25
1400
ORA-01400: cannot insert NULL into (“APPS”.“EDI_EMP2”.“DOJ”)
I
TEST INSERT
3
Babb
2000
12899
ORA-12899: value too large for column “APPS”.“EDI_EMP2”.“ENAME” (actual: 17, maximum: 7)
I
TEST INSERT
4
Babbbbbbbbbb Chen
31-MAR-25
4000
1407
ORA-01407: cannot update (“APPS”.“EDI_EMP2”.“SAL”) to NULL
AAnjPPAGSAABjXDAAA
U
TEST UPDATE
1
Babb
31-MAR-25
1476
ORA-01476: divisor is equal to zero ORA-06512: at “APPS.EDI_ROW_BEFORE_DEL”, line 4 ORA-04088: error during execution of trigger ‘APPS.EDI_ROW_BEFORE_DEL’
If you are concerned about the length of time it could take to drop column data from all of the rows in a large table, you can use the ALTER TABLE…SET UNUSED statement. This statement marks one or more columns as unused, but does not actually remove the target column data or restore the disk space occupied by these columns. However, a column that is marked as unused is not displayed in queries or data dictionary views, and its name is removed so that a new column can reuse that name. All constraints, indexes, and statistics defined on the column are also removed.
The ALTER TABLE…DROP UNUSED COLUMNS statement is the only action allowed on unused columns. It physically removes unused columns from the table and reclaims disk space.
1 2 3 4 5 6 7 8 9 10 11 12 13
createtable edi_test( a number, b number, c number );
begin alter_table_column('edi_t', 'name', 'varchar2(30)'); end;
dropprocedure alter_table_column;
1 2 3 4 5 6 7 8 9 10
declare l_tab_name varchar2(30) :='edi_t'; l_id number :=1; l_name varchar2(30) :='Babb'; l_sql_stmt varchar2(100); begin l_sql_stmt :='insert into '|| l_tab_name ||' values (:id, :name)'; execute immediate l_sql_stmt using l_id, l_name; end;
1 2 3 4 5 6 7 8 9 10 11 12 13 14
declare l_tab_name varchar2(30) :='edi_t'; l_id number :=1; l_name varchar2(30) :='Babb Chen'; l_sql_stmt varchar2(100); l_updated_name varchar2(30); begin l_sql_stmt :='update '|| l_tab_name || ' set name = :1 where id = :2 returning name into :3'; execute immediate l_sql_stmt using l_name, l_id returning into l_updated_name; dbms_output.put_line(l_updated_name); end;
createor replace procedure edi_update_sal(p_empno number, p_sal varchar2, p_name out varchar2, p_job out varchar2) is l_sql_stmt varchar2(100); begin l_sql_stmt :='update edi_t set sal = :1 where empno = :2 returning ename, job into :3, :4'; execute immediate l_sql_stmt using p_sal, p_empno returning into p_name, p_job; end;
declare l_sql_block varchar2(100); l_name varchar2(30); l_job varchar2(30); begin l_sql_block :='begin edi_update_sal(:empno,:sal,:name,:job); end;'; execute immediate l_sql_block usingin7369, 9999, out l_name, out l_job; dbms_output.put_line(l_name ||':'|| l_job); end;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
declare type ref_cursor isrefcursor; emp_rec_cur ref_cursor; emp_rec edi_t%rowtype; l_sql_stmt varchar2(100); begin l_sql_stmt :='select * from edi_t where deptno = :1'; open emp_rec_cur for l_sql_stmt using10; loop fetch emp_rec_cur into emp_rec; exit when emp_rec_cur%notfound; dbms_output.put_line(emp_rec.empno ||'-'|| emp_rec.ename); end loop; close emp_rec_cur; end;
1 2 3 4 5 6 7 8 9 10 11
declare begin execute immediate 'update edi_t set mgr = :1 where empno = :2' usingnull, 7369; --PLS-00457: expressions have to be of SQL types end;
declare begin execute immediate 'update edi_t set mgr = :1 where empno = :2' using'', 7369; end;
declare lv_count number; begin update edi_t set n = n +10 returning count(1) into lv_count; dbms_output.put_line('Rows Effected: '|| lv_count); rollback; --Rows Effected: 10 end;
declare lv_number number; begin insertinto edi_t values (100) returning count(1) into lv_number; --PL/SQL: ORA-00934: group function is not allowed here dbms_output.put_line(lv_number); rollback; end;
declare lv_number number; begin insertinto edi_t values (100) returning n into lv_number; dbms_output.put_line(lv_number); rollback; end; --100
createor replace trigger edi_truncate_trg before truncateon schema begin if ora_dict_obj_name ='EDI_T'and ora_dict_obj_type ='TABLE'then raise_application_error(-20001, 'Truncate not allowed'); end if; end;
truncatetable edi_t; --ORA-20001: Truncate not allowed --Can delete deletefrom edi_t;
createview edi_emp_dept_v as select e.empno, e.ename, e.job, e.mgr, e.hiredate, e.sal, e.deptno, d.dname from edi_emp e, edi_dept d where e.deptno = d.deptno;
insertinto edi_emp_dept_v(EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, DEPTNO, DNAME) values (1001, 'BABB', 'IT', 'JBN', sysdate, 1000, 60, 'IA'); --ORA-01779: cannot modify a column which maps to a non key-preserved table
--The table has two rows with same NO 1 altertable edi_t addconstraint no_pk primary key(no); --ORA-02437: cannot validate (APPS.NO_PK) - primary key violated
--Insert or update to the 'no' already exists in table will cause unique constraint error insertinto edi_t values(1, 'AAA'); --ORA-00001: unique constraint (APPS.NO_PK) violated update edi_t setno=2where name ='C'; --ORA-00001: unique constraint (APPS.NO_PK) violated
1
select u.uniqueness, u.*from user_indexes u where u.table_name ='EDI_T';
UNIQUENESS
INDEX_NAME
INDEX_TYPE
TABLE_OWNER
TABLE_NAME
TABLE_TYPE
UNIQUENESS
COMPRESSION
PREFIX_LENGTH
TABLESPACE_NAME
INI_TRANS
MAX_TRANS
INITIAL_EXTENT
NEXT_EXTENT
MIN_EXTENTS
MAX_EXTENTS
PCT_INCREASE
PCT_THRESHOLD
INCLUDE_COLUMN
FREELISTS
FREELIST_GROUPS
PCT_FREE
LOGGING
BLEVEL
LEAF_BLOCKS
DISTINCT_KEYS
AVG_LEAF_BLOCKS_PER_KEY
AVG_DATA_BLOCKS_PER_KEY
CLUSTERING_FACTOR
STATUS
NUM_ROWS
SAMPLE_SIZE
LAST_ANALYZED
DEGREE
INSTANCES
PARTITIONED
TEMPORARY
GENERATED
SECONDARY
BUFFER_POOL
FLASH_CACHE
CELL_FLASH_CACHE
USER_STATS
DURATION
PCT_DIRECT_ACCESS
ITYP_OWNER
ITYP_NAME
PARAMETERS
GLOBAL_STATS
DOMIDX_STATUS
DOMIDX_OPSTATUS
FUNCIDX_STATUS
JOIN_INDEX
IOT_REDUNDANT_PKEY_ELIM
DROPPED
VISIBILITY
DOMIDX_MANAGEMENT
SEGMENT_CREATED
NONUNIQUE
NO_PK
NORMAL
APPS
EDI_T
TABLE
NONUNIQUE
DISABLED
APPS_TS_TX_DATA
2
255
131072
131072
1
2147483645
0
10
YES
0
1
5
1
1
1
VALID
6
6
2024-01-09 11:15:27 AM
1
1
NO
N
N
N
DEFAULT
DEFAULT
DEFAULT
NO
NO
NO
NO
NO
VISIBLE
YES
# The Difference between varchar2(10), varchar2(10 byte) and varchar2(10 char)
VARCHAR2(10 byte) will support up to 10 bytes of data, which could be as few as two characters in a multi-byte character sets.
VARCHAR2(10 char) could support as much as 40 bytes of information and will support to up 10 characters of data.
VARCHAR2(10) uses the current value of NLS_LENGTH_SEMANTICS to determine the limit for the string. incase of byte, then it’s 10 bytes. incase of char, then it’s 10 characters.
1 2 3
SELECT* FROM NLS_DATABASE_PARAMETERS WHEREparameter='NLS_LENGTH_SEMANTICS';
select 1 from table 用于判断是否存在满足条件的数据,如果有都返回 1,类似于 select anyCol from table 一般用于判断结果集是否存在。
1 2 3 4 5 6 7
update som_edi_so_import_temp esit set esit.ret_code ='E' where esit.ret_code isnull andnotexists ( select1 from hr_operating_units hou where hou.name = esit.ou_name);
declare l_return varchar2(1); begin select* into l_return from dual where1<>1; end; --ORA-01403: no data found
declare l_return varchar2(1); begin select* into l_return from dual where1<>1; exception when no_data_found then dbms_output.put_line('No Data Found'); end; --No Data Found
declare l_return varchar2(1); begin selectcount(*) into l_return from dual where1<>1; end;
注意,当 SELECT ... INTO ... 触发 ORA-01422: exact fetch returns more than requested number of rows 异常时,会将第一个结果插入,如下虽然产生了异常,后续 l_number 的值为 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
declare l_number number; begin begin select* into l_number from (select1from dual unionselect2from dual); exception when others then dbms_output.put_line(sqlerrm); end; dbms_output.put_line(l_number); end; --ORA-01422: exact fetch returns more than requested number of rows --1
insertall into edi_t1 values(c) into edi_t2 values(c) into edi_t3 values(c) select* from edi_t; select*from edi_t1; select*from edi_t2; select*from edi_t3;
/*insert all when salary <= 2000 then into edi_e_low_sal values (ename, salary) when salary > 2000 and salary <= 4000 then into edi_e_mid_sal values (ename, salary) else into edi_e_high_sal values (ename, salary) select * from edi_e;*/
insertfirst--找到符合条件的就不再继续往下走 when salary <=2000then into edi_e_low_sal values (ename, salary) when salary <=4000then into edi_e_mid_sal values (ename, salary) else into edi_e_high_sal values (ename, salary) select* from edi_e;
报错 ORA-06592: CASE not found while executing CASE statement
case 表达式
end
返回 NULL
Sample Case
1 2 3 4 5 6 7 8 9 10 11 12 13 14
CASE SELECTOR WHEN EXPRESSION 1THEN STATEMENT 1; WHEN EXPRESSION 2THEN STATEMENT 2; ... WHEN EXPRESSION N THEN STATEMENT N; ELSE STATEMENT N+1; ENDCASE;
if som_edi_temp_d_rec.customer_id ='XXX'then case l_edi_shipping_method when'S'then l_freight_terms_code :='10FCA'; when'A'then l_freight_terms_code :='10FCA'; endcase; end if;
CASE WHENSEARCHCONDITION1THEN STATEMENT 1; WHENSEARCHCONDITION2THEN STATEMENT 2; ... WHENSEARCHCONDITION N THEN STATEMENT N; ELSE STATEMENT N+1; ENDCASE;
select name,score, case when score >=90then '优秀' when score between70and89then '良好' when score between60and69then '及格' when score <60then '不及格' end 等级 from test;
createor replace trigger edi_comp_trigger forinsertor update ordeleteon edi_t compound trigger g_var varchar2(50) :='Demo for Compound Trigger'; before statement is l_var varchar2(50) :='Before Statement'; begin dbms_output.put_line(l_var); if inserting then dbms_output.put_line('---Insert'); elsif updating then dbms_output.put_line('---Update'); elsif deleting then dbms_output.put_line('---Delete'); end if; end before statement; before eachrowis l_var varchar2(50) :='Before Each Row'; begin dbms_output.put_line(l_var); end before eachrow; after eachrowis l_var varchar2(50) :='After Each Row'; begin dbms_output.put_line(l_var); end after eachrow; after statement is l_var varchar2(50) :='After Statement'; begin dbms_output.put_line(l_var); end after statement; end; /
update edi_t set sal = sal *2where deptno =10;
/* Before Statement ---Update Before Each Row After Each Row Before Each Row After Each Row Before Each Row After Each Row After Statement */
createor replace trigger edi_comp_trigger for update on edi_t compound trigger type l_log_tab_type istableof edi_t_log%rowtype; l_log_list l_log_tab_type := l_log_tab_type(); before eachrowis l_log_row edi_t_log%rowtype; begin l_log_row.empno := :old.empno; l_log_row.modified_date := sysdate; l_log_row.desc_of_change :='OLD SAL = '|| :old.sal ||', NEW SAL = '|| :new.sal; l_log_list.extend(); l_log_list(l_log_list.last()) := l_log_row; end before eachrow; after statement is begin forall i in1..l_log_list.count insertinto edi_t_log values l_log_list(i); end after statement; end;
update edi_t set sal = sal *2where deptno =10; select*from edi_t_log;
EMPNO
MODIFIED_DATE
DESC_OF_CHANGE
7782
2024-01-09 10:49:51 AM
OLD SAL = 2450, NEW SAL = 4900
7839
2024-01-09 10:49:51 AM
OLD SAL = 5000, NEW SAL = 10000
7934
2024-01-09 10:49:51 AM
OLD SAL = 1300, NEW SAL = 2600
Mutating trigger
Mutating error occurs whenever a ‘row level’ trigger tries to modify or select data from table that is already undergoing change.
createor replace trigger edi_validate_trg before update of sal on edi_t foreachrow declare l_ceo_sal number; begin select sal --select into l_ceo_sal from edi_t where job ='PRESIDENT'; if (:new.sal < l_ceo_sal and :old.job <>'PRESIDENT') or (:old.job ='PRESIDENT') then insertinto edi_t_log values (:new.empno, sysdate, 'OLD SAL = '|| :old.sal ||', NEW SAL = '|| :new.sal); else insertinto edi_t_log values (:new.empno, sysdate, 'Employee salary cannot be more than '|| l_ceo_sal); end if; end;
update edi_t set sal = sal *2where empno =7369; --updating /* ORA-04091: table APPS.EDI_T is mutating, trigger/function may not see it ORA-06512: at "APPS.EDI_VALIDATE_TRG", line 4 ORA-04088: error during execution of trigger 'APPS.EDI_VALIDATE_TRG' */
createor replace trigger edi_validate_trg for update on edi_t compound trigger l_ceo_sal number; before statement is begin select sal into l_ceo_sal from edi_t where job ='PRESIDENT'; end before statement; before eachrowis begin if (:new.sal < l_ceo_sal and :old.job <>'PRESIDENT') or (:old.job ='PRESIDENT') then insertinto edi_t_log values (:new.empno, sysdate, 'OLD SAL = '|| :old.sal ||', NEW SAL = '|| :new.sal); else :new.sal := :old.sal; insertinto edi_t_log values (:new.empno, sysdate, 'Employee salary cannot be more than '|| l_ceo_sal); end if; end before eachrow; end;
update edi_t set sal = sal *10where empno =7369; --updating
declare cursor emp_name_list is select ename from scott.emp; l_name varchar2(100); begin open emp_name_list; loop fetch emp_name_list into l_name; exit when emp_name_list%notfound; dbms_output.put_line(l_name); end loop; close emp_name_list; end;
/* SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER */
declare cursor emp_name_list is select ename from scott.emp; l_name varchar2(100); begin
if not emp_name_list%isopen then open emp_name_list; end if; loop fetch emp_name_list into l_name; exit when emp_name_list%notfound; dbms_output.put_line(l_name ||'-'|| emp_name_list%rowcount); end loop; if emp_name_list%isopen then close emp_name_list; end if; end;
begin deletefrom edi_t; dbms_output.put_line(SQL%ROWCOUNT); if SQL%ISOPEN then dbms_output.put_line('Implicit Cursor is Opened'); else dbms_output.put_line('Implicit Cursor is Closed'); end if; end;
declare l_deptno number; cursor emp_name_list(p_deptno number) is select ename from scott.emp where deptno = p_deptno; l_name varchar2(100); begin dbms_output.put_line('------- EMP from deptno 10 ------'); open emp_name_list(10); loop fetch emp_name_list into l_name; exit when emp_name_list%notfound; dbms_output.put_line(l_name); end loop; close emp_name_list; dbms_output.put_line('------- EMP from deptno 20 ------'); open emp_name_list(20); loop fetch emp_name_list into l_name; exit when emp_name_list%notfound; dbms_output.put_line(l_name); end loop; close emp_name_list; end;
/* ------- EMP from deptno 10 ------ CLARK KING MILLER ------- EMP from deptno 20 ------ SMITH JONES SCOTT ADAMS FORD */
declare type ref_cur_type isrefcursor; rc_emp_list_cur ref_cur_type; l_name varchar2(30); l_dept_row scott.dept%rowtype; begin open rc_emp_list_cur forselect ename from scott.emp; loop fetch rc_emp_list_cur into l_name; exit when rc_emp_list_cur%notfound; dbms_output.put_line(l_name); end loop; close rc_emp_list_cur; open rc_emp_list_cur forselect*from scott.dept; loop fetch rc_emp_list_cur into l_dept_row; exit when rc_emp_list_cur%notfound; dbms_output.put_line(l_dept_row.deptno ||'-'|| l_dept_row.dname); end loop; close rc_emp_list_cur; end;
/* SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER 10-ACCOUNTING 20-RESEARCH 30-SALES 40-OPERATIONS */
declare type ref_cur_type isrefcursorreturn scott.emp%rowtype; rc_emp_list_cur ref_cur_type; l_emp_row scott.emp%rowtype; begin open rc_emp_list_cur forselect*from scott.emp; loop fetch rc_emp_list_cur into l_emp_row; exit when rc_emp_list_cur%notfound; dbms_output.put_line(l_emp_row.ename); end loop; close rc_emp_list_cur; end;
/* SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER */
declare --type ref_cur_type is ref cursor; rc_emp_list_cur sys_refcursor; l_name varchar2(30); l_dept_row scott.dept%rowtype; begin open rc_emp_list_cur forselect ename from scott.emp; loop fetch rc_emp_list_cur into l_name; exit when rc_emp_list_cur%notfound; dbms_output.put_line(l_name); end loop; close rc_emp_list_cur; open rc_emp_list_cur forselect*from scott.dept; loop fetch rc_emp_list_cur into l_dept_row; exit when rc_emp_list_cur%notfound; dbms_output.put_line(l_dept_row.deptno ||'-'|| l_dept_row.dname); end loop; close rc_emp_list_cur; end;
/* SMITH ALLEN WARD JONES MARTIN BLAKE CLARK SCOTT KING TURNER ADAMS JAMES FORD MILLER 10-ACCOUNTING 20-RESEARCH 30-SALES 40-OPERATIONS */
createor replace function edi_t_fn(p_dept_no number) return sys_refcursor is l_emp_list sys_refcursor; begin open l_emp_list forselect ename from scott.emp where deptno = p_dept_no; return l_emp_list; end; /
declare l_ref_cursor sys_refcursor; l_name varchar2(30); begin l_ref_cursor := edi_t_fn(10); --open l_ref_cursor; loop fetch l_ref_cursor into l_name; exit when l_ref_cursor%notfound; dbms_output.put_line(l_name); end loop; close l_ref_cursor; end;
declare cursor emp_list is select empno from edi_emp where deptno =10for update; l_empno number; begin open emp_list; loop fetch emp_list into l_empno; exit when emp_list%notfound; dbms_output.put_line('Updating '|| l_empno); update edi_emp set sal = sal +9999 wherecurrentof emp_list; dbms_output.put_line('Updating count '|| emp_list%rowcount);
createor replace type edi_varchar_list istableof varchar2(30);
createor replace procedure edi_get_emps_use_collection(p_deptno in number, p_out_name_list out edi_varchar_list) as l_varchar_list edi_varchar_list := edi_varchar_list(); begin select ename bulk collectinto l_varchar_list from scott.emp where deptno = p_deptno; p_out_name_list := l_varchar_list; end;
createor replace procedure edi_get_emps_use_ref_cursor(p_deptno in number, p_out_name_list out sys_refcursor) as begin open p_out_name_list for select ename from scott.emp where deptno = p_deptno; end;
createor replace procedure edi_use_ref_cursor(p_in varchar2, p_out_cur out sys_refcursor) as begin if p_in ='ENAME'then open p_out_cur for select ename from scott.emp; elsif p_in ='DNAME'then open p_out_cur for select dname from scott.dept; else open p_out_cur for select'Invalid Input'from dual; end if; end;
drop type edi_varchar_list; dropprocedure edi_get_emps_use_collection; dropprocedure edi_get_emps_use_ref_cursor; dropprocedure edi_use_ref_cursor;
createor replace package edi_t as cursor normal_cur isselect*from scott.emp; end;
declare l_emp scott.emp%rowtype; begin open edi_t.normal_cur; loop fetch edi_t.normal_cur into l_emp; exit when edi_t.normal_cur%notfound; dbms_output.put_line(l_emp.ename); end loop; close edi_t.normal_cur; end;
--Error: PLS-00994: Cursor Variables cannot be declared as part of a package createor replace package edi_t as l_ref_cursor sys_refcursor; end;
--Error: PLS-00994: Cursor Variables cannot be declared as part of a package createor replace package edi_t as type l_ref_cursor_type isrefcursor; l_ref_cursor l_ref_cursor_type; end;
begin --把test_cursor和一个select结合 open test_cursor forselect ename,sal from emp_copy where deptno=&no; --循环取出(fethch) loop fetch test_cursor into v_ename,v_sal; --判断test_cursor是否为空 exit when test_cursor%notfound; dbms_output.put_line('名字:'||v_ename||'工资:'||v_sal); end loop; --关闭游标 close test_cursor; end;
declare -- dynamic cursor type rc isrefcursor; -- static cursor cursor c isselect*from dual; l_cursor rc; begin if (to_char(sysdate,'dd') =30) then -- ref cursor with dynamic sql open l_cursor for'select * from emp'; elsif (to_char(sysdate,'dd') =29) then -- ref cursor with static sql open l_cursor forselect*from dept; else -- ref cursor with static sql open l_cursor forselect*from dual; end if; -- the "normal" static cursor open c; end;
--(2) rownum 和排序 --oracle中的rownum是在取数据的时候产生的序号,所以想对指定排序的数据指定rowmun行数据就必须注意了。可以看出,rownum并不是按照name列来生成的序号。系统是按照记录插入时的顺序给记录排的号,rowid也是顺序分配的。 select rownum,id,name from student orderby name; rownum id name ---------- ------ --------------------------------------------------- 3200003 李三 2200002 王二 1200001 张一 4200004 赵四
--为了解决这个问题,需要使用子查询 select rownum,id,name from (select*from student orderby name); rownum ID NAME ---------- ------ --------------------------------------------------- 1200003 李三 2200002 王二 3200001 张一 4200004 赵四
--(3) 更新表的某一列为 rownum
UPDATE T a SET a.neworder = (SELECT b.newOrder FROM (SELECT rownum over(ORDERBY amount DESC) newOrder, ROWID browid FROM T) b WHERE b.browid = a.rowid)
update test_a t set t.mac = (select b.mac from (select rownum rn, mac from test_a) a, (select rownum rn, mac from test_b) b where a.rn = b.rn and t.mac = a.mac);
-- 2.rowid 的使用
--快速删除重复的记录
deletefrom stu a where rowid notin (selectmax(b.rowid) from stu b where a.no = b.no and a.name = b.name and a.sex = b.sex); --这里 max 使用 min 也可以
deletefrom stu a where rowid < (selectmax(b.rowid) from stu b where a.no = b.no and a.name = b.name and a.sex = b.sex); --这里如果把 max 换成 min 的话,前面的 where 子句中需要把"<"改为">"
deletefrom stu where rowid notin (selectmax(rowid) from stu t groupby t.no, t.name, t.sex); --使用了 group by,减少了显性的比较条件,提高效率
deletefrom stu a where rowid notin (selectmax(b.rowid) from stu b where a.no < b.no and a.name = b.name); --取 name 重复学号大的数据
SELECT column_name FROM table_name ORDERBY CASE --WHEN REGEXP_LIKE(column_name, '^[0-9]+$') THEN TO_NUMBER(column_name) WHEN REGEXP_LIKE(column_name, '^\d+$') THEN TO_NUMBER(column_name) ELSENULL ENDASC, -- Sorts numeric values CASE --WHEN NOT REGEXP_LIKE(column_name, '^[0-9]+$') THEN column_name WHENNOT REGEXP_LIKE(column_name, '^\d+$') THEN column_name ELSENULL ENDASC; -- Sorts non-numeric values
1 2 3
SELECT column_name FROM table_name ORDERBY LPAD(column_name, 20, '0');
-- Retrieve package was drop or replace select* from all_source asoftimestamp to_timestamp('20200902 16:00:00', 'YYYYMMDD HH24:MI:SS') where name =upper('som_edi_custom_utils_pkg') orderby type, line
CREATEOR REPLACE TRIGGER YSC.som_hub_dn_upload_header_bi1 BEFORE INSERTON som_hub_dn_upload_header FOREACHROWWHEN (NEW.header_id isnull) BEGIN SELECT som_hub_dn_upload_header_s.NEXTVAL INTO :NEW.header_id FROM DUAL; END;
CREATEOR REPLACE TRIGGER som_edi_asn_header_ai before INSERTON som_edi_asn_header FOREACHROWWHEN (NEW.header_id isnull) BEGIN SELECT som_edi_asn_h_s.nextval INTO :NEW.header_id FROM DUAL; END;
insertinto som_edi_asn_header ( --HEADER_ID, --use trigger --HEADER_ID, --or use som_edi_asn_h_s.nextval directly DELIVERY_ID, CUSTOMER_PO, ITEM_NO) select--l_header_id, --som_edi_asn_h_s.nextval sh.delivery_id, sh.customer_po, sl.item_no from som_hub_dn_upload_header sh, som_hub_dn_upload_line sl where sh.header_id = sl.header_id and sh.delivery_id = p_delivery_id groupby sh.delivery_id, sh.customer_po, sl.item_no;
insertinto som_edi_asn_line (HEADER_ID, PALLET_NO, CARTON_NO, DEVICE_SERIAL_NUMBER) select--l_header_id, seh.header_id, sl.pallet_id, sl.carton_id, sl.prod_sn, from som_hub_dn_upload_header sh, som_hub_dn_upload_line sl, som_edi_asn_header seh where sh.header_id = sl.header_id and sh.delivery_id = seh.delivery_id and sh.customer_po = seh.customer_po and sl.item_no = seh.item_no and sh.delivery_id = p_delivery_id and nvl(sh.status, 'N') ='N';
begin with t as (select/*+ MATERIALIZE */ som_edi_pkg.get_hub_invoice(sel.so_line_id) hub_invoice, som_edi_pkg.get_qty_per_pallet(sel.invoice_line_id) qty_per_pallet from som_commercial_invoice_headers seh, som_commercial_invoice_lines sel where seh.invoice_header_id = sel.invoice_header_id and seh.invoice_no = p_invoice_no)
selectcount(*) into l_count from t where t.hub_invoice isnull or t.qty_per_pallet isnull;
if l_count <>0then debug('Get HUB Invoice No or Calculate Qty Per Pallet error.');
function get_estimated_invoice_date(p_invoice_no in varchar2, p_invoice_seq in varchar2) returndate is l_return date; begin begin selectmax(case when acceptance_id_count =0and acceptance_date_count =0then ship_date when acceptance_id_count = total_line_count and acceptance_id_count = acceptance_date_count then acceptance_date elsenull end) invoice_date into l_return from (select asn.ship_date, orde.revrec_signature_date as acceptance_date, count(orde.contingency_id) over() as acceptance_id_count, count(orde.revrec_signature_date) over() as acceptance_date_count, count(*) over() as total_line_count from (selectdistinct h.invoice_no, h.invoice_seq, h.ship_date, l.so_line_id from som_edi_856_header h, som_edi_856_line l where h.edi856_id = l.edi856_id) asn, oe_order_lines_all orde where asn.invoice_no = p_invoice_no and asn.invoice_seq = p_invoice_seq and asn.so_line_id = orde.line_id(+)); exception when others then l_return :=null; end;
declare type name_list_type istableof varchar2(100); l_name_list name_list_type := name_list_type(); begin l_name_list.extend(5); l_name_list(1) :=null; l_name_list(2) :='A'; l_name_list(3) :='AA'; l_name_list(4) :='AAA'; l_name_list(5) :='AAAAAAA'; forall i in l_name_list.first..l_name_list.last save exceptions insertinto edi_t values (l_name_list(i)); exception when others then dbms_output.put_line('Error count = '||sql%bulk_exceptions.count); for i in1..sql%bulk_exceptions.count loop dbms_output.put_line('Error index position = '||sql%bulk_exceptions(i).error_index); dbms_output.put_line('Error code = '||sql%bulk_exceptions(i).error_code); dbms_output.put_line('Error message = '|| sqlerrm(-sql%bulk_exceptions(i).error_code)); end loop; end;
--Error count = 2 --Error index position = 1 --Error code = 1400 --Error message = ORA-01400: cannot insert NULL into () --Error index position = 5 --Error code = 12899 --Error message = ORA-12899: value too large for column (actual: , maximum: )
createor replace view som_edi_mes_header_v as select "dbname" as dbname, "head_id" as head_id, "invoice_no" as invoice_no, "exc_seq" as exc_seq, "work_order" as work_order, "part_no" as part_no, "customer" as customer, "qty" as qty, "ctns" as ctns, "pallets" as pallets, "po_no" as po_no, "delivery_no" as delivery_no, "create_time" as create_time, "update_time" as update_time, "country_of_origin" as country_of_origin, "transfer_flag" as transfer_flag, "transfer_time" as transfer_time, "update_by" as update_by, "model_name" as model_name, "ver_no" as ver_no, "tran_create_time" as tran_create_time from ( select'SN'as "dbname", sn.*from "dbo"."ssc_t_edi_head"@mes2edi.sn sn unionall select'SC'as "dbname", sc.*from "dbo"."ssc_t_edi_head"@mes2edi.sc sc );
--dblink 是 Oracle 连接到 SQLServer DB --现在不用在 delivery_no 上加双引号,sev."delivery_no" = '102234' select*from som_edi_mes_header_v sev where sev.delivery_no ='102234'
droptable edi_t; createor replace view edi_t_v as select*from edi_t; --ORA-00942: table or view does not exist
1 2 3 4 5
createor replace force view edi_t_v as select*from edi_t; select*from user_views where view_name ='EDI_T_V'; select u.status, u.*from user_objects u where u.object_name ='EDI_T_V';
STATUS
OBJECT_NAME
SUBOBJECT_NAME
OBJECT_ID
DATA_OBJECT_ID
OBJECT_TYPE
CREATED
LAST_DDL_TIME
TIMESTAMP
STATUS
TEMPORARY
GENERATED
SECONDARY
NAMESPACE
EDITION_NAME
INVALID
EDI_T_V
8462071
VIEW
2024-01-09 11:46:24 AM
2024-01-09 11:46:24 AM
2024-01-09:11:46:24
INVALID
N
N
N
1
1 2 3 4
select*from edi_t_v; --ORA-04063: view "APPS.EDI_T_V" has errors
createtable edi_t asselect*from scott.emp where deptno =10; select*from edi_t_v;
createor replace force view edi_t_v as select*from edi_t;
select text from user_views where view_name ='EDI_T_V'; --select * from edi_t
createtable edi_t asselect*from scott.emp; select text from user_views where view_name ='EDI_T_V'; --select * from edi_t select u.status, u.*from user_objects u where u.OBJECT_NAME ='EDI_T_V'; --INVALID
select*from edi_t_v; --Auto Recompile select text from user_views where view_name ='EDI_T_V'; --select "EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" from edi_t select u.status, u.*from user_objects u where u.OBJECT_NAME ='EDI_T_V'; --VALID
createor replace view edi_t_v as select* from edi_t where dept ='XX' withcheck option; insertinto edi_t_v values (7, 'G', 'XX'); insertinto edi_t_v values (8, 'H', 'YY'); --ORA-01402: view WITH CHECK OPTION where-clause violation update edi_t_v set dept ='YY'where id =1; --ORA-01402: view WITH CHECK OPTION where-clause violation
1 2 3 4 5 6 7 8 9 10 11 12 13 14
createor replace view edi_t_v as select* from edi_t where dept ='XX' withcheck option constraint check_option_constraint; createor replace view edi_t_v2 as select* from edi_t where dept ='YY' with read onlyconstraint read_only_constraint; select*from user_views where view_name in ('EDI_T_V', 'EDI_T_V2'); select*from user_constraints where table_name in ('EDI_T_V', 'EDI_T_V2');
createor replace view edi_t_v as select e.*, d.dname from scott.emp e, scott.dept d where e.deptno = d.deptno; select*from user_dependencies u where u.name ='EDI_T_V';
select (select d.dname from scott.dept d where d.deptno = e.deptno) as dname, round(avg(sal)) from scott.emp e groupby deptno;
DNAME
ROUND(AVG(SAL))
SALES
1567
RESEARCH
2175
ACCOUNTING
2917
1 2 3 4 5
select e.*, d.avg_sal from scott.emp e, (select deptno, avg(sal) avg_sal from scott.emp groupby deptno) d where e.deptno = d.deptno and e.sal > d.avg_sal;
-- Any and In with t as ( select level l from dual connectby level <=10 ) --select * from t where l in (1, 3, 5) --select * from t where l = any(1, 3, 5) --select * from t where l > any(1, 3, 5) select*from t where l <any(1, 3, 5);
L
1
2
3
4
# RANK & DENSE_RANK as Aggreate function and Analytical function
Analytical function
1 2 3 4 5 6
select empno, ename, sal, rank() over(orderby sal desc) rank, dense_rank() over(orderby sal desc) dense_rank from scott.emp;
EMPNO
ENAME
SAL
RANK
DENSE_RANK
7839
KING
5000.00
1
1
7902
FORD
3000.00
2
2
7788
SCOTT
3000.00
2
2
7566
JONES
2975.00
4
3
7698
BLAKE
2850.00
5
4
7782
CLARK
2450.00
6
5
7499
ALLEN
1600.00
7
6
7844
TURNER
1500.00
8
7
7934
MILLER
1300.00
9
8
7521
WARD
1250.00
10
9
7654
MARTIN
1250.00
10
9
7876
ADAMS
1100.00
12
10
7900
JAMES
950.00
13
11
7369
SMITH
800.00
14
12
Aggregate function
1 2 3
selectrank(1600) withingroup(orderby sal desc) rank_of_1600, dense_rank(1600) withingroup(orderby sal desc) dense_rank_of_1600 from scott.emp;
begin dbms_errlog.create_error_log(dml_table_name =>'edi_t_target'); end; /
mergeinto edi_t_target t using edi_t_source s on (t.id = s.id) when matched then update set name = s.name deletewhere s.resigned ='Y' whennot matched then insertvalues (s.id, s.name) log errors into err$_edi_t_target reject limit unlimited;
procedure insert_so(errbuf out varchar2, retcode out varchar2, p_edi_id in number) is begin begin exception when others then retcode :=2; --1 l_error_msg := l_error_msg || dbms_utility.format_error_backtrace || dbms_utility.format_error_stack; debug('error occured in insert_so: '|| l_error_msg);
rollback; --2
update som_edi_temp_h seh set seh.transfer ='E', seh.transfer_date = sysdate, seh.attribute1 = l_error_msg where seh.edi_id = p_edi_id; --3
procedure put_csv(p_value in varchar2, p_separator in varchar2 default',');
end sms_po_requisitions_log_pkg;
-- package body createor replace package body apps.sms_po_requisitions_log_pkg is
procedure put_csv(p_value in varchar2, p_separator in varchar2 default',') is begin /** Test In PL/SQL dbms_output.put : output content to buffer dbms_output.new_line : output buffer to console and newline */ dbms_output.put('"'|| p_value ||'"'|| p_separator); exception when others then raise; end put_csv; end sms_po_requisitions_log_pkg;
--创建存储过程 createor replace procedure p_babb_test(num out number) is begin --select 语句中必须使用 into selectcount(*) into num from scott.emp; end; --调用存储过程 declare a number; begin p_babb_test(a); dbms_output.put_line(a); end; --删除存储过程 dropprocedure p_babb_test;
CREATEOR REPLACE PROCEDURE HelloWorld3 ( p_user_name VARCHAR2, p_val1 VARCHAR2 DEFAULT' Good Moning,', p_val2 VARCHAR2 DEFAULT' Nice to Meet you' ) AS BEGIN dbms_output.put_line('Hello '|| p_user_name || p_val1 || p_val2 ||'!'); END HelloWorld3; / Procedure created.
--指定参数名称调用 --当最后2个参数是有默认的时候,跳過中間的那個。 BEGIN HelloWorld3('Edward'); HelloWorld3('Edward', p_val1 =>' Good Night,'); HelloWorld3('Edward', p_val1 =>' Good Night,', p_val2 =>'Bye'); HelloWorld3('Edward', p_val2 =>' HeiHei '); END; / /* Hello Edward Good Moning, Nice to Meet you! Hello Edward Good Night, Nice to Meet you! Hello Edward Good Night,Bye! Hello Edward Good Moning, HeiHei ! */
--有 group by 会先 group by, 此时什么都不会返回 selectcount(*) from test where1<>1groupby test.name;
--没有数据返回 null selectsum(test.qty)from test where1<>1;
--没有数据什么都不会返回 selectsum(test.qty) from test where1<>1groupby test.name;
--没有数据什么都不会返回 selectsum(test.qty) from test where1<>1groupby test.qty;
--返回 null selectnull+2from dual;
--如果查不到数据min()返回空,此时into不会出错 selectmin(setd.po_line) into l_po_line from som_edi_temp_d setd; --如果查不到数据会产生错误 select setd.po_line into l_po_line from som_edi_temp_d setd;
selectcount(distinct sel.carton_id_value) from som_edi_856_line sel where sel.edi856_id = p_edi856_id and sel.pallet_id_value = p_pallet_id groupby sel.pallet_id_value;
select edi_id from som_edi_temp_h where transfer in ('N', 'Q') and edi_id = nvl(p_edi_id, edi_id) -- and customer_id = nvl(p_customer_id, customer_id) andtrim(cust_po_number) = nvl(trim(p_customer_po), cust_po_number) and edi_type = nvl(p_edi_type, edi_type) orderby edi_id;
SELECT TRUNC(SYSDATE) FROM DUAL; --2012-12-19 SELECT TRUNC(SYSDATE,'MM') FROM DUAL; --2012-12-1 SELECT TRUNC(SYSDATE,'YYYY') FROM DUAL; --2012-1-1 SELECT TRUNC(SYSDATE,'DD') FROM DUAL; --2012-12-19 SELECT TRUNC(SYSDATE,'HH') 或 HH24 FROM DUAL; --2012-12-19 14:00:00 SELECT TRUNC(SYSDATE,'MI') FROM DUAL; --2012-12-19 14:30:00 SELECT TRUNC(SYSDATE,'SS') FROM DUAL; -- 会出现 bad precison specifier,直接用SYSDATE不用TRUNC
selectextract(yearfrom systimestamp) year ,extract(monthfrom systimestamp) month ,extract(dayfrom systimestamp) day from dual union selectextract(yearfrom sysdate) year ,extract(monthfrom sysdate) month ,extract(dayfrom sysdate) day from dual
--number 不能转换为 sysdate select decode('a', null, sysdate, 1) from dual; --ORA-00932: inconsistent datatypes: expected DATE got NUMBER
--varchar 可以转换为日期,但必须是指定格式 select decode('a', null, sysdate, 'a') from dual; --ORA-01858: a non-numeric character was found where a numeric was expected
--尝试将字符串 '1' 转换为日期 select decode('a', null, sysdate, '1') from dual; --ORA-01840: input value not long enough for date format
--'15-JAN-20' 是 Server 指定 Format 格式可以转换为日期 select decode('a', null, sysdate, '15-JAN-20') from dual; --2020/1/15
--'a' 是 varchar,sysdate 总是可以转换为 varchar, 返回 Server 指定 Format 格式 select decode(sysdate, null, 'a', sysdate) from dual; --14-JAN-20
-- null 当作 varchar,sysdate 总是可以转换为 varchar, 返回 Server 指定 Format 格式 select decode(sysdate, null, null, sysdate) from dual; --14-JAN-20
--ORA-01790: expression must have same datatype as corresponding expression select decode(1, 2, null, '2') from dual -- 字符 2 union select2from dual; --数字 2
--use to_number or case statment solve ORA-01790 error select decode(1, 2, to_number(null), 2) from dual union select2from dual; --2
selectcasewhen1=2thennullelse2endfrom dual union select2from dual; --2
decode(null, null, null, null) union
use sql only
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
selectnullfrom dual union select2from dual; --2 --
select decode(null, null, null, null) from dual --no error union select2from dual; --2 --
select to_char(null) from dual --ORA-01790: expression must have same datatype as corresponding expression union select2from dual;
use plsql
1 2 3 4 5 6 7 8 9 10 11 12 13
declare l_number number; begin begin select* into l_number from (select decode(null, null, null, null) from dual unionselect2from dual); --ORA-01790: expression must have same datatype as corresponding expression exception when others then dbms_output.put_line(sqlerrm); end; dbms_output.put_line(l_number); end;
with temp as( select'China' nation ,'Guangzhou' city from dual unionall select'China' nation ,'Shanghai' city from dual unionall select'China' nation ,'Beijing' city from dual unionall select'USA' nation ,'New York' city from dual unionall select'USA' nation ,'Bostom' city from dual unionall select'Japan' nation ,'Tokyo' city from dual ) select nation, listagg(city,',') withingroup(orderby city desc), count(1) from temp groupby nation;
nation citylistagg count(1) ------ -------------------------- -------- China Shanghai,Guangzhou,Beijing 3 Japan Tokyo 1 USA New York,Bostom 2
-- null, '' 不会包含在 listagg 连接的字符串中, 需要进行 nvl 处理 with temp as( select'China' nation ,'Guangzhou' city from dual unionall select'China' nation , null city from dual unionall select'China' nation ,'' city from dual unionall select'USA' nation ,'New York' city from dual unionall select'USA' nation ,'Bostom' city from dual unionall select'Japan' nation ,'Tokyo' city from dual ) select nation, listagg(city,',') withingroup(orderby city desc), count(1) from temp groupby nation;
nation citylistagg count(1) ------ -------------------------- -------- China Guangzhou 3 Japan Tokyo 1 USA New York,Bostom 2
--partitiobn by 不会影响记录条数 with temp as( select'China' nation ,'Guangzhou' city from dual unionall select'China' nation ,'Shanghai' city from dual unionall select'China' nation ,'Beijing' city from dual unionall select'USA' nation ,'New York' city from dual unionall select'USA' nation ,'Bostom' city from dual unionall select'Japan' nation ,'Tokyo' city from dual ) select nation, listagg(city, ',') withingroup(orderby city desc) over (partitionby nation) as citylistagg, count(1) over(partitionby nation) as g_total, --count(1) over(partition by 1) as total count(1) over() as total from temp;
NATION CITYLISTAGG G_TOTAL TOTAL ------ -------------------------- -------- ------ China Shanghai,Guangzhou,Beijing 36 China Shanghai,Guangzhou,Beijing 36 China Shanghai,Guangzhou,Beijing 36 Japan Tokyo 16 USA New York,Bostom 26 USA New York,Bostom 26
Returns
The LEAST function returns a value that is the same datatype as expr1.
Having a NULL value in one of the expressions will return NULL as the least value.
Note
If the datatypes of the expressions are different, all expressions will be converted to whatever datatype expr1 is.
If the comparison is based on a character comparison, one character is considered smaller than another if it has a lower character set value.
1 2 3 4 5
select*from dual where greatest('a', 2, 3, null, sysdate) isnull; -- X
select*from dual where least('a', 2, 3, null, sysdate) isnull; --X
--Remove all CR/LF, trim the left and right spaces, tabs function str_clean(p_str in varchar2) return varchar2 is l_return varchar2(1000); l_tab_space varchar2(10) := chr(9) ||' '; begin /** * Standard ASCII Characters * Decimal Description * 9 Horizontal tab (HT) * 10 Line feed (LF) * 13 Carriage return (CR) */ begin --translate(p_str, 'a' || chr(10) || chr(13), 'a'): a translate to a, chr(10) & chr(13) replace to empty --ltrim(str, l_tab_space): trim left tab and space behavior like translate, such as 'chr(9) chr(9) a' will trim to 'a' --if use trim twice select trim(trim(chr(9) from chr(9) || ' ' || chr(9) || 'a')) from dual; will got 'chr(9) a' select rtrim(ltrim(translate(p_str, 'a'|| chr(10) || chr(13), 'a'), l_tab_space), l_tab_space) into l_return from dual; end;
select lpad('abc', 4, 0) from dual; --0abc select lpad('abcde', 4, 0) from dual; --abcd
select lpad('', 4, 0) from dual; --
select lpad('0', 4, 0) from dual; --0000 select lpad('0', 4) from dual; -- 0
function lpad_str(p_str in varchar2, p_length in number, p_pad_str in varchar2 default' ') return varchar2 is l_return varchar2(4000); begin begin selectcase when length(p_str) >= p_length then substr(p_str, -1* p_length) else lpad(nvl(p_str, p_pad_str), p_length, p_pad_str) end into l_return from dual; exception when others then l_return :=null; end; return l_return; end lpad_str;
select lpad_str('abc', 4, 0) from dual; --0abc select lpad_str('', 4, 0) from dual; --0000
CREATEOR REPLACE PROCEDURE proc_p1(param_value INOUT VARCHAR2) AS BEGIN param_value :='ASSIGNED INSIDE PROCEDURE'; END; /
DECLARE lv_var VARCHAR2(100); BEGIN lv_var :='ASSIGNED IN ANONYMOUS BLOCK'; proc_p1(lv_var); dbms_output.put_line(lv_var); END; / --ASSIGNED INSIDE PROCEDURE
CREATEOR REPLACE PROCEDURE proc_copy(param_value INOUT VARCHAR2) AS x NUMBER; BEGIN param_value :='ASSIGNED INSIDE PROCEDURE'; x :=1/0; END; /
DECLARE lv_var VARCHAR2(100); BEGIN -- To check the proc_copy lv_var :='ASSIGNED IN ANONYMOUS BLOCK'; BEGIN proc_copy(lv_var); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); END; DBMS_OUTPUT.PUT_LINE(lv_var); END; / --ORA-01476: divisor is equal to zero --ASSIGNED IN ANONYMOUS BLOCK
CREATEOR REPLACE PROCEDURE proc_nocopy(param_value INOUT NOCOPY VARCHAR2) AS x NUMBER; BEGIN param_value :='ASSIGNED INSIDE PROCEDURE'; x :=1/0; END; /
DECLARE lv_var VARCHAR2(100); BEGIN lv_var :='ASSIGNED IN ANONYMOUS BLOCK'; BEGIN proc_nocopy(lv_var); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); END; DBMS_OUTPUT.PUT_LINE(lv_var); END; / --ORA-01476: divisor is equal to zero --ASSIGNED INSIDE PROCEDURE
createor replace package body edi_demo_package as procedure p_copy(param_value inout nest_tab_type) as begin null; end; procedure p_no_copy(param_value inout nocopy nest_tab_type) as begin null; end; end; /
createor replace type edi_t_varchar_list istableof varchar2(30);
createor replace function edi_t_get_emp_list return edi_t_varchar_list as l_name_list edi_t_varchar_list := edi_t_varchar_list(); begin for i in (select*from scott.emp) loop dbms_lock.sleep(1); l_name_list.extend(); l_name_list(l_name_list.last()) := i.ename; end loop; return l_name_list; end;
select* fromtable(edi_t_get_emp_list()) where rownum <=3; --Cost 14s
createor replace function edi_t_get_emp_list_p return edi_t_varchar_list pipelined as l_name_list edi_t_varchar_list := edi_t_varchar_list(); begin for i in (select*from scott.emp) loop dbms_lock.sleep(1); pipe row(i.ename); end loop; return; end;
select* fromtable(edi_t_get_emp_list_p()) where rownum <=3; --Cost 3s
with t as ( selectTIMESTAMP'2007-06-15 14:30:00 +00:00'as d from dual unionall selectTIMESTAMP'2007-06-15 09:30:00 -05:00'from dual unionall selectTIMESTAMP'2007-06-15 10:30:00 Canada/Eastern'from dual unionall selectTIMESTAMP'2007-06-15 10:30:00 Canada/Eastern EDT'from dual ) select d as test_time_value, d ATLOCALas session_time_zone_time, d ATTIME ZONE SESSIONTIMEZONE as session_time_zone_time2, d ATTIME ZONE DBTIMEZONE as db_time_zone_time, d ATTIME ZONE '+01:00'as utc_plus_1_time, d ATTIME ZONE '-03:30'as utc_minus_3_30_time, d ATTIME ZONE 'Australia/Sydney'as sydney_time, d ATTIME ZONE 'UTC'AS utc_zone_time, sys_extract_utc(d) as utc_time from t; select to_timestamp_tz('December 12, 2023 4:30 AM 05:00', 'Month dd, yyyy hh:mi AM TZH:TZM'), to_timestamp_tz('December 12, 2023 4:30 AM 05:00', 'Month dd, yyyy hh:mi AM TZH:TZM') ATLOCAL from dual;
# Date and Times Exact Formatting with the FX Modifier
1 2 3 4 5
select to_date( '123', 'yyyy' ) as a, -- three digit year, not four to_timestamp( '2007 12', 'yyyy mm' ) as b, -- extra spaces to_timestamp_tz( '2007/12', 'yyyy-mm' ) as c -- "/" instead of "-" from dual ;
A
B
C
0123-01-01
01-DEC-07 12.00.00.000000000 AM
01-DEC-07 12.00.00.000000000 AM +08:00
1 2 3 4 5
select to_date( '123', 'FXyyyy' ) as a from dual ; --ORA-01862: the numeric value does not match the length of the format item
select to_timestamp( '2007 12', 'FXyyyy mm' ) as b from dual; --ORA-01858: a non-numeric character was found where a numeric was expected
select to_timestamp_tz( '2007/12', 'FXyyyy-mm' ) as c from dual; --ORA-01861: literal does not match format string
# Dates and Times Fill Mode Formatting with the FM Modifier
The Fill Mode modifier, FM, toggles the suppression of blank padding in character format elements like “MONTH” and leading zeros in numeric format elements like “YYYY”.
--The formatting suffixes appear to have problems dealing with some values like zeros and negative years select to_char( timestamp'2007-04-03 02:01:00', 'ssTH' ) as output from dual; --ORA-01877: string is too long for internal buffer
select to_char( timestamp'-1001-01-01 00:00:00', 'syyyySP' ) as output from dual; --ORA-01877: string is too long for internal buffer
createor replace function edi_t_fn(p_deptno in number) return sys.odcivarchar2list as l_name_list sys.odcivarchar2list; begin select s.ename bulk collectinto l_name_list from scott.emp s where s.deptno = p_deptno; return l_name_list; end; /
CHR returns the character having the binary equivalent to n as a VARCHAR2 value in either the database character set or, if you specify USINGNCHAR_CS , the national character set.
For single-byte character sets, if n > 256, then Oracle Database returns the binary equivalent of nmod256 . For multibyte character sets, n must resolve to one entire code point. Invalid code points are not validated, and the result of specifying invalid code points is indeterminate.
This function takes as an argument a NUMBER value, or any value that can be implicitly converted to NUMBER , and returns a character.
Note:Use of the CHR function (either with or without the optional USINGNCHAR_CS clause) results in code that is not portable between ASCII- and EBCDIC-based machine architectures.
NCHR returns the character having the binary equivalent to number in the national character set. The value returned is always NVARCHAR2 . This function is equivalent to using the CHR function with the USINGNCHAR_CS clause.
This function takes as an argument a NUMBER value, or any value that can be implicitly converted to NUMBER , and returns a character.
Bracket expression for specifying a matching list that should match any one of the expressions represented in the list. A non-matching list expression begins with a circumflex (^) and specifies a list that matches any character except for the expressions represented in the list. To specify a right bracket (]) in the bracket expression, place it first in the list (after the initial circumflex (^), if any). To specify a hyphen in the bracket expression, place it first in the list (after the initial circumflex (^), if any), last in the list, or as an ending range point in a range expression.
1 2 3 4
--Find the location of the first character that is not in ][0-9a-z_ ().,;{}''"/- select regexp_instr(']-'|| nchr(160), '[^][0-9a-z_ ().,;{}''"/-]', 1, 1, 0) from dual; --3
with t(n, x, y) as ( select1, dbms_random.value, dbms_random.value from dual unionall select n+1, dbms_random.value, dbms_random.value from t where n <=1000000 ) select4*sum(1-floor(x * x + y * y)) /count(*) as PI from t; --3.13991686008314
with t(n, high) as ( select1, 5from dual unionall select n +1, high +casewhenmod(n +1, 2) =0then-2else5end from t where high <20 ) selectmax(n+1) /2from t;
declare l_char varchar2(20); begin select1into l_char from dual where1<>1; exception when others then -- format_error_backtrace会打印出错行号 dbms_output.put_line('format_error_backtrace: '|| dbms_utility.format_error_backtrace); dbms_output.put_line('format_error_stack: '|| dbms_utility.format_error_stack); dbms_output.put_line('format_call_stack: '|| dbms_utility.format_call_stack); dbms_output.put_line('sqlerrm: '|| sqlerrm); dbms_output.put_line('sqlcode: '|| sqlcode); end;
/* format_error_backtrace: ORA-06512: at line 4 format_error_stack: ORA-01403: no data found format_call_stack: ----- PL/SQL Call Stack ----- object line object handle number name 0x458e9f088 8 anonymous block sqlerrm: ORA-01403: no data found sqlcode: 100 */
--固定数组 declare type type_array is varray(10) of varchar2(20); --一维数组,字符串类型 var_array type_array := type_array('java', 'python', 'php'); begin --数组的长度用count(索引是从1开始的) for i in1 .. var_array.count loop dbms_output.put_line(var_array(i)); end loop; end;
--可变数组 declare type type_array istableof varchar2(20) index by binary_integer; var_array type_array; begin --下标必须是连续的,并且索引从1开始 var_array(1) :='java'; var_array(2) :='php'; for i in1 .. var_array.count loop dbms_output.put_line(var_array(i)); end loop; end;
--类似二维数组 --IS TABLE OF:指定是一个集合的表的数组类型,简单的来说就是一个可以存储一列多行的数据类型。 --INDEX BY BINARY_INTEGER:指索引组织类型。 --BULK COLLECT:指是一个成批聚合类型,简单的来说,它可以存储一个多行多列存储类型,采用BULK COLLECT可以将查询结果一次性地加载到集合中。 declare type type_array istableof som_edi_temp_d%rowtype index by binary_integer; var_array type_array; begin select* bulk collectinto var_array from som_edi_temp_d; for i in1 .. 10 loop dbms_output.put_line('订单id: '|| var_array(i).edi_id ||', 订单类型: '|| var_array(i) .edi_type); end loop; end;
select level as id from dual connectby level <5; /* 1 1 2 2 3 3 4 4 5 5 */ select rownum as id from xmltable('1 to 10'); select level +5as id from dual connectby level <=10-5;
--可以使用 connect by 生成测试数据 insertinto TMP_TABLE select'TMP'|| lpad(rownum, 7, 0), rownum, sysdate from dual connectby level <=1000000;
function calculate_luhn_checksum(p_number in varchar2) return number is l_digit number; l_multiplier number; l_sum_digits number; l_sum number :=0; begin begin for i in1 .. length(p_number) loop l_digit := to_number(substr(p_number, -i, 1)); l_multiplier :=casewhenmod(i, 2) !=0then2else1end; l_sum_digits :=mod(l_digit * l_multiplier, 10) + trunc(l_digit * l_multiplier /10); l_sum := l_sum + l_sum_digits; end loop; l_sum :=mod(10-mod(l_sum, 10), 10); exception when others then raise; end; return l_sum; end calculate_luhn_checksum;
with t as ( select id, data, regexp_substr(data, '(.*?\*){'|| (column_value -1) ||'}([^\*]*)', 1, 1, '', 2) as w, column_value -1as r from edi_t, table(cast(multiset (select level l from dual connectby level <= regexp_count(data, '\*') +1) as sys.odcinumberlist) ) ), t1 as ( select id, data, casewhen r =0then w elsenullendas s, w, r from t ), t2 as ( select id, data, last_value(s ignore nulls) over (orderby id, r) s, w, r from t1 orderby id, r ) select* from t2 --where s = 'RCD' and r = 2;
with t as ( select id, data, regexp_substr(data, '(.*?\*){'|| (l -1) ||'}([^\*]*)', 1, 1, '', 2) as w, l -1as r from edi_t, ( select level l from dual connectby level <= (selectmax(regexp_count(data, '\*') +1) from edi_t) ) where l <= regexp_count(data, '\*') +1 ), t1 as ( select id, data, casewhen r =0then w elsenullendas s, w, r from t ), t2 as ( select id, data, last_value(s ignore nulls) over (orderby id, r) s, w, r from t1 orderby id, r ) select* from t2;
begin execute immediate 'select 1 from som_edi_test_header for update'; selectmax(sh.creation_date) into l_max_creation_date from som_edi_test_header sh; update som_edi_test_header sh set sh.creation_date = l_max_creation_date +interval'1'second--`sh.creation_date = sh.creation_date + interval '1' second` can not be used here, because the programs run concurrently, `sh.creation_date + '1' second` maybe already exists. where sh.header_id = p_header_id and to_char(sh.creation_date, 'yyyymmddhh24miss') in (select to_char(creation_date, 'yyyymmddhh24miss') from som_edi_test_header where header_id != p_header_id); --The current record needs to be excluded here, or condition is always true. commit; select'ASN' ||'_'|| to_char(sh.creation_date, 'yyyymmddhh24miss') ||'.csv' into l_asn_filename from som_edi_test_header sh where sh.header_id = p_header_id; end;
begin begin execute immediate 'select 1 from som_edi_test_header for update';
update som_edi_test_header seh set seh.file_counter = (select nvl(max(sh.file_counter), 0) +1 from som_edi_test_header sh where sh.transfer_flag ='Y' and sh.creation_date >= trunc(sysdate) and sh.creation_date < trunc(sysdate) +interval'1'day) where seh.header_id = p_header_id; --Not commit here, commit after the transfer_flag is 'Y'. Because the where condition includes transfer_flag = 'Y' --If the where not condition includes transfer_flag = 'Y', then an rror(transfer_flag != 'Y') will add up the file_counter, the file_counter will not continuous --commit; select'ASN' ||'_'|| to_char(sh.creation_date, 'yyyymmdd') ||'_'|| sh.file_counter ||'.txt' into l_asn_filename from som_edi_test_header sh where sh.header_id = p_header_id groupby sh.creation_date, sh.file_counter; end; --Logical Code if nvl(retcode, '0') ='0'then update som_edi_test_header sh set sh.file_name = l_asn_filename, sh.transfer_flag ='Y', sh.transfer_date = sysdate where sh.header_id = p_header_id; commit; --Commit Here else rollback; update som_edi_test_header sh set sh.file_name = l_asn_filename, sh.transfer_flag ='N', sh.transfer_date = sysdate where sh.header_id = p_header_id; commit; end if; end;
How to set item propert to Unspecified value. For example, i have radio button with Background color sets to ‘gray’ and i want set it to Unspecified to get transparency effect and i can’t do this. If i set property value to blank forms builder shout “color by this name does not exist”.
Answser: Go to the item in question and press the ‘Inherit’ button in the ‘Property Palette’.
--1. fnd_flex_value_sets 这张表记录了所有值集的名称和值集id select* from fnd_flex_value_sets whereupper(flex_value_set_name) ='NOTES_STATUS';
--2. fnd_flex_values这张表记录了每一个值集对应的可选值 select flex_value from fnd_flex_values where flex_value_set_id in (select flex_value_set_id from fnd_flex_value_sets whereupper(flex_value_set_name) ='NOTES_STATUS'); --flex_value --10 --20
--3. fnd_flex_values_tl对应每一个值集对应的可选值的说明 select description from fnd_flex_values_tl where flex_value_id in (select flex_value_id from fnd_flex_values where flex_value_set_id in (select flex_value_set_id from fnd_flex_value_sets whereupper(flex_value_set_name) ='NOTES_STATUS'));
begin if som_edi_po_insert_pkg.check_is_ok(:new.vendor_id) ='Y'then l_result := fnd_request.set_mode(true); l_req_id := fnd_request.submit_request(application =>'YSC', program =>'SOMP4081', description =>null, start_time =>null, sub_request =>false, argument1 => :new.po_header_id); end if; exception when others then null; end;
--Initialize apps environment in pl/sql developer, not needed if called by ERP Request. --1175:MIS, 50705:SC_OM_SUPERUSER, 660:ONT --select fu.user_id from fnd_user fu where fu.user_name = 'MIS'--1175 --select fr.responsibility_id, fr.application_id from fnd_responsibility fr where fr.responsibility_key = 'SC_OM_SUPERUSER'--50705,660 --fnd_global.APPS_INITIALIZE(user_id => 1175, resp_id => 50705, resp_appl_id => 660); begin begin select fu.user_id into l_user_id from fnd_user fu where fu.user_name ='MIS'; select fr.responsibility_id, fr.application_id into l_responsibility_id, l_application_id from fnd_responsibility fr where fr.responsibility_key ='SC_OM_SUPERUSER'; fnd_global.APPS_INITIALIZE(user_id => l_user_id, resp_id => l_responsibility_id, resp_appl_id => l_application_id); exception when others then l_err_msg :='APPS_INITIALIZE Error: '|| sqlerrm; debug_error; end; l_req_id := fnd_request.submit_request(application =>'YSC', program =>'SOMP4057', description =>null, start_time =>null, sub_request =>false, argument1 => l_file_name); if l_req_id =0then l_err_msg :='Call SOMP4057 Error'; end if; end;
function get_order_salesperson(p_delivery_id in varchar2) return varchar2 is l_return varchar2(100); begin begin select rss.resource_name into l_return from wsh_new_deliveries wnd, wsh_delivery_assignments wda, wsh_delivery_details wdd, oe_order_headers_all ooh, hr_all_organization_units_tl hou, (SELECT JRE.RESOURCE_NAME, JRS.SALESREP_ID, JRS.ORG_ID, JRS.SALESREP_NUMBER FROM JTF_RS_SALESREPS JRS, JTF_RS_RESOURCE_EXTNS JRR, JTF_RS_RESOURCE_EXTNS_TL JRE WHERE JRS.RESOURCE_ID = JRR.RESOURCE_ID AND JRE.LANGUAGE = USERENV('LANG') AND JRR.RESOURCE_ID = JRE.RESOURCE_ID AND JRR.CATEGORY = JRE.CATEGORY AND JRR.CATEGORY IN ('EMPLOYEE', 'OTHER', 'PARTY', 'PARTNER', 'SUPPLIER_CONTACT') ) rss where1=1 and wnd.delivery_id = p_delivery_id and wdd.delivery_detail_id = wda.delivery_detail_id and wnd.delivery_id = wda.delivery_id and wdd.source_header_id = ooh.header_id and ooh.salesrep_id = rss.salesrep_id and rss.org_id = hou.organization_id and hou.language = userenv('LANG') groupby rss.resource_name; exception when others then l_return :=null; end; return l_return; end get_order_salesperson;
Return Material Authorization 退料审查。是处理用户不良产品退货、换货的主要流程。
VMI
Vendor Managed Inventory 供应商管理库存
Incoterm
International Commercial Term 贸易条款
Freight Terms
运输条款
Payment Term
付款条款,一般是按照合同约定多少天付款,如: 0600
SCAC
Standard Carrier Alpha Code The Standard Carrier Alpha Code, a two-to-four letter identification, is used by the transportation industry to identify freight carriers in computer systems and shipping documents such as Bill of Lading, Freight Bill, Packing List, and Purchase Order.