使用 pl/sql 在 table 中查找多个值并在不存在时插入的过程
Procedure to find multiples values in a table and insert if doesnt exist using pl/sql
我有这个 table 这个关系:UNIT --> CHARGE ---> 角色
UNIT_CODE | CHARGE_CODE | ROLE_CODE
0101010001 | 9023409 | AZAAAA
0102010002 | 8023409 | AXAAAB
0103010003 | 7023409 | ACAAAC
0104010004 | 6023409 | AVAAAV
0101010001 | 5023409 | NEWROL
0102010002 | 4023409 | AZAAAA
这个table已经快2.000了rows/line。
所以,情况是这样的:
我必须为特定的 90 unit_code 插入特定的 ROLE_COD (NEWROL
)。但是这个角色申请了具体负责的单位。
示例:我必须插入 role_code = NEWROLE
为此 单位 0101010001
和这个 charge 5023409
所以,我必须检查:
- 如果单位
0101010001
已经存在? - 是
- 如果单位/费用
0101010001 / 5023409
关系已经存在? - 是
- 如果unit/charge/rol
0101010001 / 5023409 / NEWROL
已经存在? - 是
如果 3 个问题的答案是肯定的,我必须检查其他 单位/费用 组合:
0102010002 / 4023409
- 如果单位
0102010002
已经存在? - 是
- 如果单位/费用
0102010002 / 4023409
关系已经存在? - 是
- 如果unit/charge/rol
0102010002 / 4023409 / NEWROL
已经存在? - 否
所以我必须在 table 中插入角色:为此 units/charge 的 NEWROL 并检查其他单位并收费。
注意:这些单位是独一无二的,但有些单位具有 same/multiples 角色或职责。
我必须检查 90 个单位,我需要一个程序来采用 unit_code
和 charge
进行验证并在必要时插入 role_code
。
这是一个纯粹的 SQL 解决方案:
insert into your_table t
select unit_code, charge_code, 'NEWROL'
from
( select unit_code, charge_code from your_table
where (unit_code = '0101010001' and charge_code = 5023409)
or (unit_code = '0102010002' and charge_code = 4023409)
minus
select unit_code, charge_code from your_table
where role_code = 'NEWROL' )
/
子查询 returns (unit_code, charge_code)
的集合没有 role_code='NEWROL'
。如果您确实需要存储过程,可以调整上面的 WHERE 子句以使用 PL/SQL 参数。
这是程序化此查询的一种解决方案。它使用 SQL 类型来传递目标 (unit_code, charge_code)
对:
create or replace type unit_charge_t as object
(unit_code varchar2(10), charge_code number);
/
create or replace type unit_charge_nt as table of unit_charge_t;
/
这是一个简单的概念证明。您需要添加日志记录、异常处理等。
create or replace procedure ins_your_table
(p_recs in unit_charge_nt
, p_new_role in your_table.role_code%type := 'NEWROL')
as
begin
insert into your_table t
select unit_code, charge_code, 'NEWROL'
from
( select unit_code, charge_code from your_table
where (unit_code, charge_code) in (select * from table(p_recs))
minus
select unit_code, charge_code from your_table
where role_code = 'NEWROL' );
dbms_output.put_line('inserted records = '||sql%rowcount);
end ins_your_table;
/
调用示例:
SQL> set serveroutput on
SQL> declare
2 tgt_rows unit_charge_nt
3 := unit_charge_nt ( unit_charge_t('0101010001', 5023409)
4 , unit_charge_t('0102010002', 4023409) );
5 begin
6 ins_your_table(tgt_rows);
7 end;
8 /
inserted records = 1
PL/SQL procedure successfully completed.
SQL>
最大的挑战仍然是将文档中的目标键输入到数据库中。我个人会选择程序员的文本编辑器,例如 NotePad++。这将使使用正则表达式 search'n'replace 将值列表转换为那些类型赋值变得轻而易举。
search: ([0-9]+)\t([0-9]+)
replace: unit_charge_t\('', \z\)
另一种接口是使用外部 table,将 .docx
更改为 .csv
文件。
有许多可能的解决方案;哪个最合适table要看你的具体情况。
我使用这个查询解决了这个问题:
CREATE OR REPLACE PROCEDURE my_procedure
(in_unit_code IN table_1.unit_code%TYPE,
in_charge_code IN table_1.charge_code%TYPE,
in_role_code IN table_1.role_code%TYPE)
AS
BEGIN
trace('my_procedure_p', 'a', 'Role Insert starting');
INSERT INTO table_1 (
unit_code,
charge_code,
role_code
) values (
in_unit_code,
in_charge_code,
in_role_code
);
trace('my_procedure_p', 'a',
'It is inserted correctly. ROLE: ' || in_role_code ||
', UNIT: ' || in_unit_code ||
', CHARGE: ' || in_charge_code ||
' Date: ' || SYSDATE);
COMMIT;
--Note: If the insert is successful i COMMIT, but if records are duplicates i captured with this exception.
EXCEPTION
WHEN dup_val_on_index THEN
ptraza('my_procedure_p', 'a',
'Attention, ROLE: ' || in_role_code ||
' It is already in the table UNIT: ' || in_unit_code ||
', CHARGE: ' || in_charge_code);
END my_procedure;
我这样打电话:
BEGIN
my_procedure('0000000004','CHARGE01','ROLECODE01');
my_procedure('0000000003','CHARGE02','ROLECODE01');
my_procedure('0000000002','CHARGE00','ROLECODE03');
my_procedure('0000000001','CHARGE00','ROLECODE03');
END;
我有这个 table 这个关系:UNIT --> CHARGE ---> 角色
UNIT_CODE | CHARGE_CODE | ROLE_CODE
0101010001 | 9023409 | AZAAAA
0102010002 | 8023409 | AXAAAB
0103010003 | 7023409 | ACAAAC
0104010004 | 6023409 | AVAAAV
0101010001 | 5023409 | NEWROL
0102010002 | 4023409 | AZAAAA
这个table已经快2.000了rows/line。
所以,情况是这样的:
我必须为特定的 90 unit_code 插入特定的 ROLE_COD (NEWROL
)。但是这个角色申请了具体负责的单位。
示例:我必须插入 role_code = NEWROLE
为此 单位 0101010001
和这个 charge 5023409
所以,我必须检查:
- 如果单位
0101010001
已经存在? - 是 - 如果单位/费用
0101010001 / 5023409
关系已经存在? - 是 - 如果unit/charge/rol
0101010001 / 5023409 / NEWROL
已经存在? - 是
- 如果单位
如果 3 个问题的答案是肯定的,我必须检查其他 单位/费用 组合:
0102010002 / 4023409
- 如果单位
0102010002
已经存在? - 是 - 如果单位/费用
0102010002 / 4023409
关系已经存在? - 是 - 如果unit/charge/rol
0102010002 / 4023409 / NEWROL
已经存在? - 否
所以我必须在 table 中插入角色:为此 units/charge 的 NEWROL 并检查其他单位并收费。
注意:这些单位是独一无二的,但有些单位具有 same/multiples 角色或职责。
我必须检查 90 个单位,我需要一个程序来采用 unit_code
和 charge
进行验证并在必要时插入 role_code
。
这是一个纯粹的 SQL 解决方案:
insert into your_table t
select unit_code, charge_code, 'NEWROL'
from
( select unit_code, charge_code from your_table
where (unit_code = '0101010001' and charge_code = 5023409)
or (unit_code = '0102010002' and charge_code = 4023409)
minus
select unit_code, charge_code from your_table
where role_code = 'NEWROL' )
/
子查询 returns (unit_code, charge_code)
的集合没有 role_code='NEWROL'
。如果您确实需要存储过程,可以调整上面的 WHERE 子句以使用 PL/SQL 参数。
这是程序化此查询的一种解决方案。它使用 SQL 类型来传递目标 (unit_code, charge_code)
对:
create or replace type unit_charge_t as object
(unit_code varchar2(10), charge_code number);
/
create or replace type unit_charge_nt as table of unit_charge_t;
/
这是一个简单的概念证明。您需要添加日志记录、异常处理等。
create or replace procedure ins_your_table
(p_recs in unit_charge_nt
, p_new_role in your_table.role_code%type := 'NEWROL')
as
begin
insert into your_table t
select unit_code, charge_code, 'NEWROL'
from
( select unit_code, charge_code from your_table
where (unit_code, charge_code) in (select * from table(p_recs))
minus
select unit_code, charge_code from your_table
where role_code = 'NEWROL' );
dbms_output.put_line('inserted records = '||sql%rowcount);
end ins_your_table;
/
调用示例:
SQL> set serveroutput on
SQL> declare
2 tgt_rows unit_charge_nt
3 := unit_charge_nt ( unit_charge_t('0101010001', 5023409)
4 , unit_charge_t('0102010002', 4023409) );
5 begin
6 ins_your_table(tgt_rows);
7 end;
8 /
inserted records = 1
PL/SQL procedure successfully completed.
SQL>
最大的挑战仍然是将文档中的目标键输入到数据库中。我个人会选择程序员的文本编辑器,例如 NotePad++。这将使使用正则表达式 search'n'replace 将值列表转换为那些类型赋值变得轻而易举。
search: ([0-9]+)\t([0-9]+)
replace: unit_charge_t\('', \z\)
另一种接口是使用外部 table,将 .docx
更改为 .csv
文件。
有许多可能的解决方案;哪个最合适table要看你的具体情况。
我使用这个查询解决了这个问题:
CREATE OR REPLACE PROCEDURE my_procedure
(in_unit_code IN table_1.unit_code%TYPE,
in_charge_code IN table_1.charge_code%TYPE,
in_role_code IN table_1.role_code%TYPE)
AS
BEGIN
trace('my_procedure_p', 'a', 'Role Insert starting');
INSERT INTO table_1 (
unit_code,
charge_code,
role_code
) values (
in_unit_code,
in_charge_code,
in_role_code
);
trace('my_procedure_p', 'a',
'It is inserted correctly. ROLE: ' || in_role_code ||
', UNIT: ' || in_unit_code ||
', CHARGE: ' || in_charge_code ||
' Date: ' || SYSDATE);
COMMIT;
--Note: If the insert is successful i COMMIT, but if records are duplicates i captured with this exception.
EXCEPTION
WHEN dup_val_on_index THEN
ptraza('my_procedure_p', 'a',
'Attention, ROLE: ' || in_role_code ||
' It is already in the table UNIT: ' || in_unit_code ||
', CHARGE: ' || in_charge_code);
END my_procedure;
我这样打电话:
BEGIN
my_procedure('0000000004','CHARGE01','ROLECODE01');
my_procedure('0000000003','CHARGE02','ROLECODE01');
my_procedure('0000000002','CHARGE00','ROLECODE03');
my_procedure('0000000001','CHARGE00','ROLECODE03');
END;