Oracle-数据库编程总结【持续更新】

2022年07月22日 15:56 · 阅读(342) ·

开发环境

名称 版本
操作系统 Windows 10 X64
Oracle win64_11gR2_database
PLSQL Developer 12.0.1.1814 (64 bit)

测试表

  1. create table TEST1
  2. (
  3. id NUMBER,
  4. user_name VARCHAR2(1000),
  5. cost_center_name VARCHAR2(150),
  6. amount NUMBER,
  7. cost_center_code VARCHAR2(240)
  8. )

变量赋值(单个和多个)

变量赋值(单个和多个)

赋值为空的情况

  1. declare
  2. v_user_name varchar2(300);
  3. begin
  4. Select user_name
  5. Into v_user_name
  6. From TEST1
  7. Where user_name = 'luoma';
  8. dbms_output.put_line(v_user_name);
  9. Exception
  10. When Others Then
  11. dbms_output.put_line('user_name 为空');
  12. end;
  • 如果没有 Exception,查不到数据会报错
  1. ORA-01403: 未找到任何数据
  2. ORA-06512: line 4

动态 SQL 赋值

  1. declare
  2. l_data_query_sql varchar2(1000);
  3. v_user_name varchar2(300);
  4. begin
  5. end;
  6. l_data_query_sql := 'select user_name from test1 where id = 1';
  7. execute immediate l_data_query_sql
  8. into v_user_name;
  9. dbms_output.put_line(v_user_name);
  10. Exception
  11. When Others Then
  12. dbms_output.put_line('user_name 为空');

定时临时表

  1. with
  2. --定义临时表 t1
  3. t1 as (select * from test_v_hwhao1)
  4. select * from t1

定义公共变量

  1. CREATE OR REPLACE PACKAGE FND_API AUTHID DEFINER AS
  2. -- Global constants representing TRUE and FALSE.
  3. G_TRUE CONSTANT VARCHAR2(1) := 'T';
  4. G_FALSE CONSTANT VARCHAR2(1) := 'F';
  5. END FND_API;

使用

  1. declare
  2. begin
  3. dbms_output.put_line(FND_API.G_TRUE); --输出 T
  4. end;

%Rowtype

Oracle-集合表行类型使用

  1. declare
  2. -- 这里 test1 是上面的测试表名称
  3. l_test_rec test1%Rowtype;
  4. begin
  5. l_test_rec.id := 5;
  6. l_test_rec.user_name := 'luoma5';
  7. l_test_rec.cost_center_name := '成本中心5';
  8. l_test_rec.amount := 11;
  9. l_test_rec.cost_center_code := 'code5';
  10. insert into test1
  11. values l_test_rec;
  12. dbms_output.put_line('OK');
  13. end;

或者类型是一个视图也可以,例如

  1. decalre
  2. -- 这里 test1_v 是一个视图
  3. test1VRow test1_v%Rowtype;
  4. begin
  5. Select *
  6. Into test1VRow
  7. From test1_v
  8. Where config_name = 'abc';
  9. end;

%Type

  1. decalre
  2. -- 这里和定义 user_name VARCHAR2(1000); 相同含义
  3. -- TEST1 表的 user_name 字段
  4. user_name TEST1.user_name%Type;
  5. begin
  6. user_name := '1111';
  7. dbms_output.put_line(l_bank_account_name);
  8. end;

TABLE OF

Oracle-集合表行类型使用

自定义异常

自定义异常

公共变量

  1. CREATE OR REPLACE PACKAGE FND_API AUTHID DEFINER AS
  2. G_EXC_ERROR EXCEPTION;
  3. G_EXC_UNEXPECTED_ERROR EXCEPTION;
  4. G_RET_STS_SUCCESS CONSTANT VARCHAR2(1) := 'S';
  5. G_RET_STS_ERROR CONSTANT VARCHAR2(1) := 'E';
  6. G_RET_STS_UNEXP_ERROR CONSTANT VARCHAR2(1) := 'U';
  7. END FND_API;

异常方法

  1. Procedure Raise_Exception(x_Return_Status Varchar2) Is
  2. Begin
  3. If (x_Return_Status = Fnd_Api.g_Ret_Sts_Unexp_Error) Then
  4. Raise Fnd_Api.g_Exc_Unexpected_Error;
  5. Elsif (x_Return_Status = Fnd_Api.g_Ret_Sts_Error) Then
  6. Raise Fnd_Api.g_Exc_Error;
  7. End If;
  8. End Raise_Exception;

使用方法

  1. declare
  2. begin
  3. dbms_output.put_line('1');
  4. Raise_Exception(Fnd_Api.G_RET_STS_UNEXP_ERROR);
  5. dbms_output.put_line('2');
  6. Exception
  7. when Fnd_Api.g_Exc_Unexpected_Error Then
  8. dbms_output.put_line('自定义异常');
  9. when others then
  10. dbms_output.put_line('其它异常');
  11. end;

pragma autonomous_transaction

正常情况

  1. create or replace procedure p_insert_test is
  2. --自治事务 同一个存储过程的commit才生效
  3. pragma autonomous_transaction;
  4. begin
  5. insert into TEST1(id,user_name,Cost_Center_Name,amount,cost_center_code)
  6. values(6,'luoma6','成本中心6',11.11,'Code6');
  7. commit;
  8. end p_insert_test;

调用,数据添加成功

  1. begin
  2. p_insert_test;
  3. end;
  4. select * from TEST1

异常情况

  1. create or replace procedure p_insert_test is
  2. --自治事务 同一个存储过程的commit才生效
  3. pragma autonomous_transaction;
  4. begin
  5. insert into TEST1(id,user_name,Cost_Center_Name,amount,cost_center_code)
  6. values(7,'luoma7','成本中心7',11.14,'Code7');
  7. commit;
  8. end p_insert_test;
  9. create or replace procedure p_insert is
  10. v_num number;
  11. begin
  12. --调用
  13. p_insert_test;
  14. -- pragma autonomous_transaction; 不会生效
  15. --commit;
  16. v_num:=10/0;
  17. exception
  18. when others then
  19. dbms_output.put_line(sqlerrm);
  20. -- pragma autonomous_transaction; 不会回滚
  21. rollback;
  22. end p_insert;

调用

  1. begin
  2. p_insert;
  3. end;

报错,数据添加失败

  1. ORA-06550: 2 行, 3 列:
  2. PLS-00905: 对象 LUOMA.P_INSERT 无效
  3. ORA-06550: 2 行, 3 列:
  4. PL/SQL: Statement ignored

指定事务回滚

  1. declare
  2. v_num number;
  3. p_savepoint_name Constant Varchar2(30) := 'process_request01';
  4. begin
  5. insert into TEST1(id,user_name,Cost_Center_Name,amount,cost_center_code)
  6. values(7,'luoma7','成本中心7',7,'Code7');
  7. commit;
  8. dbms_output.put_line('luoma7');
  9. --回滚标志
  10. dbms_transaction.savepoint(p_savepoint_name);
  11. insert into TEST1(id,user_name,Cost_Center_Name,amount,cost_center_code)
  12. values(8,'luoma8','成本中心8',8,'Code8');
  13. dbms_output.put_line('luoma8');
  14. v_num:=10/0;
  15. --提交
  16. COMMIT WORK;
  17. exception
  18. when others then
  19. --回滚
  20. dbms_transaction.rollback_savepoint(p_savepoint_name);
  21. dbms_output.put_line('回滚');
  22. end;

输出

  1. luoma7
  2. luoma8
  3. 回滚

执行成功

  1. insert into TEST1(id,user_name,Cost_Center_Name,amount,cost_center_code)
  2. values(7,'luoma7','成本中心7',7,'Code7');

执行失败

  1. insert into TEST1(id,user_name,Cost_Center_Name,amount,cost_center_code)
  2. values(8,'luoma8','成本中心8',8,'Code8');

去除

  1. --v_num:=10/0;

两条都执行成功

动态执行 SQL

  1. CREATE OR REPLACE PROCEDURE PRO_Delete_table(tableName IN VARCHAR2, condition IN VARCHAR2,msg out VARCHAR2)
  2. IS
  3. SQL_excute varchar2(4000);
  4. BEGIN
  5. IF LENGTH(condition)=0 THEN
  6. SQL_excute := 'DELETE FROM '|| tableName;
  7. ELSE
  8. SQL_excute := 'DELETE FROM '|| tableName || ' WHERE 1=1 AND ' || condition;
  9. END IF;
  10. EXECUTE IMMEDIATE SQL_excute;
  11. msg := '执行成功';
  12. DBMS_OUTPUT.PUT_LINE('执行成功,'||SQL_excute);
  13. --添加一个异常处理当没有数据的时候赋一个默认值
  14. exception
  15. when others then
  16. dbms_output.put_line('执行报错,'||SQL_excute);
  17. msg:='执行报错';
  18. END PRO_Delete_table;

调用

  1. DECLARE
  2. tableName VARCHAR2(100) := 'TPS_TAX_EXCEL_PROVISION';
  3. condition VARCHAR2(2000) := 'period between ''2022-01'' and ''2022-12'' and BALANCING_SEG in (''101'')';
  4. msg varchar2(1000);
  5. BEGIN
  6. PRO_Delete_table(
  7. tableName => tableName,
  8. condition => condition,
  9. msg => msg);
  10. dbms_output.put_line(msg);
  11. END;

输出

  1. 执行成功,DELETE FROM TPS_TAX_EXCEL_PROVISION WHERE 1=1 AND period between '2022-01' and '2022-12' and BALANCING_SEG in ('101')
  2. 执行成功

带参数的游标

Oracle-包的创建和使用(游标的简单使用,临时表,动态 sql)

  1. declare
  2. CURSOR csr_api(p_id NUMBER) IS
  3. select * from test1
  4. where id > p_id;
  5. begin
  6. FOR rec_c IN csr_api(3)
  7. LOOP
  8. dbms_output.put_line(rec_c.id || '-' || rec_c.user_name);
  9. END LOOP;
  10. end;

输出

  1. 7-luoma7
  2. 5-luoma5
  3. 4-luoma4

游标是使用时才会查询并赋值的

  • 表 test_v_1
ID NO NAME PARENTNO
1 0 NAME-1 2
2 0 NAME-0 2
3 4 luoma_4 PNO-004
4 4 luoma_5 PNO-005
  • 表 test_v_2
ID NO NAME PARENTNO
-
  1. declare
  2. -- 这里只是定义了游标,并没有执行并返回结果赋值
  3. CURSOR data_cur IS
  4. select * from test_v_1 t1 where exists (select 1 from test_v_2 t2 where t1.ID = t2.ID);
  5. begin
  6. delete test_v_2;
  7. insert Into test_v_2(ID,NO,NAME,PARENTNO)
  8. select ID,NO,NAME,PARENTNO from test_v_1 where ID in('1','2','3','4');
  9. commit;
  10. -- 这里使用了游标,才去执行游标定义查询结果并赋值
  11. FOR item_cur IN data_cur LOOP
  12. dbms_output.put_line('ID:' || item_cur.ID || ',NAME:' || item_cur.NAME);
  13. END Loop;
  14. end;
  • 执行结果
  1. ID:1,NAME:NAME-1
  2. ID:2,NAME:NAME-0
  3. ID:3,NAME:luoma_4
  4. ID:4,NAME:luoma_5

For Update 和 For Update Nowait

For Update Nowait

对查询到的结果进行加锁,如果其它线程操作结果集中的数据,For Update Nowait 不会进行资源等待,会立即报错。

● 开启第一个 SQL Windows,执行下面的 SQL,不提交

  1. select t.ID from cux.cux_ce_config t
  2. where config_name = 'task-error-mail-title'
  3. for update of t.id nowait;

返回

ID
18

● 开启第二个 SQL Windows,执行下面的 SQL,不提交

  1. select t.ID from cux.cux_ce_config t
  2. where config_name = 'task-error-mail-title'
  3. for update of t.id nowait;

报错

  1. ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效

● 提交第一个 SQL Windows
● 再次执行第二个 SQL Windows 中的 SQL,返回结果

ID
18

For Update

对查询到的结果进行加锁,如果其它线程操作结果集中的数据,For Update 会进行资源等待,不会立即报错。

● 开启第一个 SQL Windows,执行下面的 SQL,不提交

  1. select t.ID from cux.cux_ce_config t
  2. where config_name = 'task-error-mail-title'
  3. for update;

返回

ID
18

● 开启第二个 SQL Windows,执行下面的 SQL,不提交

  1. select t.ID from cux.cux_ce_config t
  2. where config_name = 'task-error-mail-title'

不报错,一直在转圈等待中

● 提交第一个 SQL Windows
● 返回第二个 SQL Windows,自动返回结果

ID
18