加入收藏 | 设为首页 | 会员中心 | 我要投稿 牡丹江站长网 (https://www.0453zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

Oracle 查找与删除表中重复记录的步骤技巧

发布时间:2021-11-27 12:10:34 所属栏目:教程 来源:互联网
导读:存储过程和存储函数指存储在数据库中供所有用户程序调用的子程序叫存储过程、存储函数。 存储过程没有返回值。存储函数有返回值 创建存储过程 用CREATE PROCEDURE命令建立存储过程和存储函数。 语法: create [or replace] PROCEDURE过程名(参数列表) AS PLS

存储过程和存储函数指存储在数据库中供所有用户程序调用的子程序叫存储过程、存储函数。
存储过程没有返回值。存储函数有返回值
 
创建存储过程
用CREATE PROCEDURE命令建立存储过程和存储函数。
 
语法:
create [or replace] PROCEDURE过程名(参数列表)
AS
PLSQL子程序体;
 
存储过程示例:为指定的职工在原工资的基础上长10%的工资
 
/*
为指定的职工在原工资的基础上长10%的工资,并打印工资前和工资后的工资
*/
SQL> create or replace procedure raiseSalary(empid in number)
as
pSal emp.sal%type;--保存员工当前 工资
begin
--查询该员工的工资
select sal into pSal from emp where empno=empid;
--给该员工涨工资
update emp set sal = sal*1.1 where empno=empid;
--打印涨工资前后的工资
dbms_output.put_line('员工号:' || empid || '涨工资前
' || psal || '涨工资后' || psal*1.1);
end;
1 /
 
Procedure created
--存储过程调用
--方法一
SQL> set serveroutput on
SQL> exec raisesalary(7369);
 
员工号:7369涨工资前
800涨工资后880
 
方法二
set serveroutput on
begin
raisesalary(7369);
end;
/
 
PL/SQL procedure successfully completed
 
 
存储函数
函数(Function)为一命名的存储程序,可带参数,并返回一计算值。函数和过程的结构类似,但必须有一个RETURN子句,用于返回函数值。函数说明要指定函数名、结果值的类型,以及参数类型等。
 
建立存储函数的语法:
 
CREATE [OR REPLACE] FUNCTION函数名(参数列表)
RETURN 函数值类型
AS
PLSQL子程序体;
 
 
示例:查询某职工的年收入。
SQL> /**/
/*
查询某职工的总收入
*/
create or replace function queryEmpSalary(empid in number)
return number
as
pSal number; --定义变量保存员工的工资
pComm number; --定义变量保存员工的奖金
begin
select sal,comm into psal,pcomm from emp where empno = empid;
return psal*12+nvl(pcomm,0);
end;
/
 
Function created
 
l 函数的调用
 
SQL> declare
v_sal number;
begin
v_sal:=queryEmpSalary(7934);
dbms_output.put_line('salary is:'|| v_sal);
end;
/
 
salary is:15600
 
PL/SQL procedure successfully completed
 
SQL> begin
dbms_output.put_line('salary is:'|| queryEmpSalary(7934));
end;
/
 
salary is:15600
 
PL/SQL procedure successfully completed
 
 
触发器
数据库触发器是一个与表相关联的、存储的PL/SQL程序。每当一个特定的数据操作语句(Insert,update,delete)在指定的表上发出时,Oracle自动地执行触发器中定义的语句序列。
 
触发器的类型
语句级触发器
在指定的操作语句操作之前或之后执行一次,不管这条语句影响了多少行。
 
行级触发器(FOR EACH ROW)
触发语句作用的每一条记录都被触发。在行级触发器中使用old和new伪记录变量,识别值的状态。
 
创建触发器
CREATE [or REPLACE] TRIGGER 触发器名
{BEFORE | AFTER}
{DELETE | INSERT | UPDATE [OF列名]}
ON 表名
[FOR EACH ROW [WHEN(条件) ] ]
PLSQL 块
 
示例1:限制非工作时间向数据库插入数据
SQL> create or replace
trigger securityEmp
before insert on emp
declare
begin
if to_char(sysdate,'day')in('星期四','星期六','星期日')
or to_number(to_char(sysdate,'hh24'))not between 8 and 18 then
raise_application_error(-20001,'不能在非工作时间插入数据。');
end if;
end;
/
 
Trigger created
 
触发语句与伪记录变量的值
触发语句
 
:old
 
:new
 
Insert
 
所有字段都是空(null)
 
将要插入的数据
 
Update
 
更新以前该行的值
 
更新后的值
 
delete
 
删除以前该行的值
 
所有字段都是空(null)
 
示例2:确认数据(检查emp表中sal的修改值不低于原值)
SQL> create or replace trigger checkSal
before update of sal on emp
for each row
declare
begin
if :new.sal<:old.sal then
raise_application_error(-20001,'更新后的薪水比更新前小');
end if;
end;
/
 
Trigger created
运行后结果:
SQL> update emp set sal=260 where empno=7499;
 
update emp set sal=260 where empno=7499
 
ORA-20001: 更新后的薪水比更新前小
ORA-06512: 在 "SCOTT.CHECKSAL", line 4
ORA-04088: 触发器 'SCOTT.CHECKSAL'执行过程中出错
 
触发器总结
触发器可用于
• 数据确认
• 实施复杂的安全性检查
• 做审计,跟踪表上所做的数据操作等
 
查询触发器、过程及函数
• Select * from user_triggers;
• Select * from user_source;这时候如果临时表中有重复数据,无论是主键字段businessid有重复,还是一整行有重复都会报出违反唯一主键约束错误。
 
方法:group by XX having count(*)>1,rowid,distinct,temporary table,procedure
 
1、查询表中的重复数据
a.重复一个字段
 
b.重复多个字段
 
c.重复一整行
 
创建测试表:
 
复制代码 代码如下:
 
 
create table cfa (businessid number,customer varchar2(50),branchcode varchar2(10),data_date varchar2(10));
insert into cfa values (1,'Albert','SCB','2011-11-11');
insert into cfa values (2,'Andy','DB','2011-11-12');
insert into cfa values (3,'Allen','HSBC','2011-11-13');
 
---------------以下为重复数据----------------------------------------------
insert into cfa values (1,'Alex','ICBC','2011-11-14');
insert into cfa values (1,'Albert','CTBK','2011-11-15');
insert into cfa values (1,'Albert','SCB','2011-11-11');
 
 
 
对于a的情况,只有businessid重复
 
复制代码 代码如下:
 
 
select * from cfa where businessid in (select businessid from cfa group by businessid having count(businessid)>1);
 
如果是b的情况,businessid 和name同时存在重复
 
复制代码 代码如下:
 
 
select * from cfa where (businessid,customer) in (select businessid,customer from cfa group by businessid,customer having count(*)>1);
 
 
对于c的情况,重复一整行
参考b的方法:
 
复制代码 代码如下:
 
 
select * from cfa where (businessid,customer,branchcode,data_date) in (select * from cfa group by businessid,customer,branchcode,data_date having count(*)>1);
 
2、删除表中的重复数据
a情况,删除表中多余的重复记录,重复记录是根据单个字段(businessid)来判断,只留有rowid最小的记录
 
也可以只保留rowid不是最小记录,需要把代码中的min改为max这里不再赘述。
 
复制代码 代码如下:
 
 
delete from cfa
where businessid in (select businessid
from cfa
group by businessid
having count(businessid) > 1)
and rowid not in (select min(rowid)
from cfa
group by businessid
having count(businessid) > 1);
 
 
或者,使用下面更简单高效的语句
复制代码 代码如下:
 
 
DELETE FROM cfa t
WHERE t.ROWID >
(SELECT MIN(X.ROWID) FROM cfa X WHERE X.businessid = t.businessid);
 
b情况,删除表中多余的重复记录(多个字段),只留有rowid最小的记录
 
复制代码 代码如下:
 
 
delete from cfa
where (businessid,customer) in (select businessid,customer
from cfa
group by businessid,customer
having count(*) > 1)
and rowid not in (select min(rowid)
from cfa
group by businessid,customer
having count(*) > 1);
 
或者,使用下面更简单高效的语句
 
复制代码 代码如下:
 
 
DELETE FROM cfa t
WHERE t.ROWID > (SELECT MIN(X.ROWID)
FROM cfa X
WHERE X.businessid = t.businessid
and x.customer = t.customer);
 
c情况,这种情况就比较简单,使用临时表方法
 
复制代码 代码如下:
 
 
create table cfabak as select distinct * from cfa;
 
truncate table cfa;--如果是生产最好对该表backup
 
Insert into cfa select * from cfabak;
 
commit;

(编辑:牡丹江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!