高分求一个存储过程.

bitm 2010-09-21 01:04:55
有一个表名my_tb的表结构是:
id status

我想在插入该表数据时,先判断status的状态值有无为1,2,3的数据,
1:如果状态值1,2,3的3种状态都有数据,那么取status状态值数据最少的status值(该情况该值只可能1,2,3其中一个).
2:如果状态值中只有1,2的状态值,那么只取status值为3.
3:如果状态值中只有2,3的状态值,那么只取status值为1.
4:如果状态值中只有1,3的状态值,那么只取status值为2.
5:如果状态值中只有1的状态值,那么取status(值为2或3其中的任意一个).
6:如果状态值中只有2的状态值,那么取status(值为1或3其中的任意一个).
7:如果状态值中只有3的状态值,那么取status(值为1或2其中的任意一个).

定义个临时变量temp_status,用于将以上查到的status(1,2,3)赋给它。
...全文
160 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
bitm 2010-09-21
  • 打赏
  • 举报
回复
有空帮忙想想,有其人高人也帮想想。。
晚上结贴。

谢谢各位
gelyon 2010-09-21
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 bitm 的回复:]

谢谢,上面的方面可以。

我遇到到新的问题如果我的状态值加到 1 到10。
这样的写法是不是要验证很多逻辑。
还有更加便捷的方法吗?
[/Quote]

恐怕是要验证不同的逻辑啊,你1到10就有很多种排列组合,除此其它方法暂时还没想出来!
bitm 2010-09-21
  • 打赏
  • 举报
回复
谢谢,上面的方面可以。

我遇到到新的问题如果我的状态值加到 1 到10。
这样的写法是不是要验证很多逻辑。
还有更加便捷的方法吗?
gelyon 2010-09-21
  • 打赏
  • 举报
回复

--这个才是最终版:

CREATE OR REPLACE TRIGGER trg_insert_my_tb
BEFORE INSERT ON my_tb
FOR EACH ROW
DECLARE
v_status my_tb.status%TYPE;
cnt1 NUMBER;
cnt2 NUMBER;
cnt3 NUMBER;
BEGIN
BEGIN
select count(*) into cnt1 from my_tb where status = 1;
EXCEPTION WHEN OTHERS THEN
cnt1:=0;
END;
BEGIN
select count(*) into cnt2 from my_tb where status = 2;
EXCEPTION WHEN OTHERS THEN
cnt2:=0;
END;
BEGIN
select count(*) into cnt3 from my_tb where status = 3;
EXCEPTION WHEN OTHERS THEN
cnt3:=0;
END;
IF cnt1=cnt2 AND cnt1=cnt3 AND cnt1=0 THEN
select ceil(dbms_random.value(0,3)) INTO v_status from dual;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3!=0 THEN
BEGIN
IF cnt1<=cnt2 AND cnt1<=cnt3 THEN
v_status:=1;
ELSIF cnt2<=cnt1 AND cnt2<=cnt3 THEN
v_status:=2;
ELSE
v_status:=3;
END IF ;
END;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3=0 THEN
v_status:=3;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3!=0 THEN
v_status:=2;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3!=0 THEN
v_status:=1;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3=0 THEN
select ceil(dbms_random.value(1,3)) into v_status from dual;
ELSIF cnt1=0 AND cnt2=0 AND cnt3!=0 THEN
select ceil(dbms_random.value(0,2)) into v_status from dual;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3=0 THEN
begin
select ceil(dbms_random.value(0,2)) into v_status from dual;
IF v_status=1 THEN --如果为1则取1,否则取3
v_status:=1;
ELSE
v_status:=3;
END IF;
END;
END IF;
:NEW.status:=v_status;
END;
/
gelyon 2010-09-21
  • 打赏
  • 举报
回复

--楼主,我的还有个小问题,就是在随机取值的时候不对,改成我下面这样随机取:
--1、2、3中随即取一个:
SELECT Ceil(dbms_random.value(0,3)) into v_status FROM dual;

--2、3之间随即取一个
select CEIL(dbms_random.value(1,3)) into v_status from dual;

--1、2之间随即取一个
select CEIL(dbms_random.value(0,2)) into v_status from dual;

--1、3之间随即取一个,则外层套一个连续区间
BEGIN
select CEIL(dbms_random.value(0,2)) into v_status from dual;
IF v_status=1 THEN --如果为1则取1,否则取3
v_status:=1;
ELSE
v_status:=3;
END;


你将我上面13楼中trigger里作相应的改动下就OK了

gelyon 2010-09-21
  • 打赏
  • 举报
回复

--这个是最终结果,我测试通过了,具体你再测试下:
CREATE OR REPLACE TRIGGER trg_insert_my_tb
BEFORE INSERT ON my_tb
FOR EACH ROW
DECLARE
v_status my_tb.status%TYPE;
cnt1 NUMBER;
cnt2 NUMBER;
cnt3 NUMBER;
BEGIN
BEGIN
select count(*) into cnt1 from my_tb where status = 1;
EXCEPTION WHEN OTHERS THEN
cnt1:=0;
END;
BEGIN
select count(*) into cnt2 from my_tb where status = 2;
EXCEPTION WHEN OTHERS THEN
cnt2:=0;
END;
BEGIN
select count(*) into cnt3 from my_tb where status = 3;
EXCEPTION WHEN OTHERS THEN
cnt3:=0;
END;
IF cnt1=cnt2 AND cnt1=cnt3 AND cnt1=0 then
select ceil(dbms_random.value(1,3)) INTO v_status from dual;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3!=0 THEN
BEGIN
IF cnt1<=cnt2 AND cnt1<=cnt3 THEN
v_status:=1;
ELSIF cnt2<=cnt1 AND cnt2<=cnt3 THEN
v_status:=2;
ELSE
v_status:=3;
END IF ;
END;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3=0 THEN
v_status:=3;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3!=0 THEN
v_status:=2;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3!=0 THEN
v_status:=1;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3=0 THEN
select ceil(dbms_random.value(2,3)) INTO v_status from dual;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3=0 THEN
select ceil(dbms_random.value(1,3)) INTO v_status from dual;
ELSIF cnt1=0 AND cnt2=0 AND cnt3!=0 THEN
select ceil(dbms_random.value(1,2)) INTO v_status from dual;
END IF;
:NEW.status:=v_status;
END;
bitm 2010-09-21
  • 打赏
  • 举报
回复
正在验证中。thanks a lot.
有思路了
gelyon 2010-09-21
  • 打赏
  • 举报
回复
楼主,你按照此思路改改,我中间那段
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3!=0 THEN
SELECT status INTO v_status FROM (
SELECT status,Count(status) cnt,Row_Number()over(PARTITION BY status ORDER BY Count(status)) rn FROM my_tb GROUP BY status)
WHERE rn=1;

改成:

ELSIF cnt1!=0 AND cnt2!=0 AND cnt3!=0 THEN
BEGIN
IF cnt1<=cnt2 AND cnt1<=cnt3 THEN
v_status:=cnt1;
ELSIF cnt2<=cnt1 AND cnt2<=cnt3 THEN
v_status:=cnt2;
ELSE
v_status:=cnt3;
END IF ;
END;

目的是取最小的作为status
gelyon 2010-09-21
  • 打赏
  • 举报
回复

--上面的忧郁没测试,创建trigger时候有问题,下面的是创建成功了的,你试试
CREATE OR REPLACE TRIGGER trg_insert_my_tb
BEFORE INSERT ON my_tb
FOR EACH ROW
DECLARE
v_status my_tb.status%TYPE;
cnt1 NUMBER;
cnt2 NUMBER;
cnt3 NUMBER;
BEGIN
BEGIN
select count(*) into cnt1 from my_tb where status = 1;
EXCEPTION WHEN OTHERS THEN
cnt1:=0;
END;
BEGIN
select count(*) into cnt2 from my_tb where status = 2;
EXCEPTION WHEN OTHERS THEN
cnt2:=0;
END;
BEGIN
select count(*) into cnt3 from my_tb where status = 3;
EXCEPTION WHEN OTHERS THEN
cnt3:=0;
END;
IF cnt1=cnt2 AND cnt1=cnt3 AND cnt1=0 then
select ceil(dbms_random.value(1,3)) INTO v_status from dual;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3!=0 THEN
SELECT status INTO v_status FROM (
SELECT status,Count(status) cnt,Row_Number()over(PARTITION BY status ORDER BY Count(status)) rn FROM my_tb GROUP BY status)
WHERE rn=1;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3=0 THEN
v_status:=3;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3!=0 THEN
v_status:=2;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3!=0 THEN
v_status:=1;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3=0 THEN
select ceil(dbms_random.value(1,2)) INTO v_status from dual;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3!=0 THEN
select ceil(dbms_random.value(2,3)) INTO v_status from dual;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3=0 THEN
select ceil(dbms_random.value(1,3)) INTO v_status from dual;
END IF;
:NEW.status:=v_status;
END;
/

gelyon 2010-09-21
  • 打赏
  • 举报
回复

--初步写了个,思路跟楼上一样,我用trigger写的,试试,我还没测试过

CREATE OR REPLACE TRIGGER trg_insert_my_tb
BEFORE INSERT ON my_tb
DECLARE
v_status my_tb.status%TYPE;
cnt1 NUMBER;
cnt2 NUMBER;
cnt3 NUMBER;
BEGIN
BEGIN
select count(*) into cnt1 from my_tb where status = 1;
EXCEPTION WHEN OTHERS THEN
cnt1:=0;
END;
BEGIN
select count(*) into cnt2 from my_tb where status = 2;
EXCEPTION WHEN OTHERS THEN
cnt2:=0;
END;
BEGIN
select count(*) into cnt3 from my_tb where status = 3;
EXCEPTION WHEN OTHERS THEN
cnt3:=0;
END;
IF cnt1=cnt2 AND cnt1=cnt3 AND cnt1=0 then
select ceil(dbms_random.value(1,3)) INTO v_status from dual;
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3!=0 THEN
SELECT status INTO v_status FROM (SELECT status,Count(status) cnt,Row_Number()over(PARTITION BY status ORDER BY Count(status)) rn FROM a GROUP BY status) WHERE rn=1);
ELSIF cnt1!=0 AND cnt2!=0 AND cnt3=0 THEN
v_status:=3;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3!=0 THEN
v_status:=2;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3!=0 THEN
v_status:=1;
ELSIF cnt1=0 AND cnt2=0 AND cnt3!=0 THEN
select ceil(dbms_random.value(1,2)) INTO v_status from dual;
ELSIF cnt1!=0 AND cnt2=0 AND cnt3=0 THEN
select ceil(dbms_random.value(2,3)) INTO v_status from dual;
ELSIF cnt1=0 AND cnt2!=0 AND cnt3=0 THEN
select ceil(dbms_random.value(1,3)) INTO v_status from dual;
END IF;
:NEW.status:=v_status;
END;

碧水幽幽泉 2010-09-21
  • 打赏
  • 举报
回复
很简单的, 楼主自己试试吧!
思路是这样的:
1.先定义3个变量cnt1、cnt2、cnt3.
2.其次:
select count(*) into cnt1 from my_tb where status = 1;
select count(*) into cnt2 from my_tb where status = 2;
select count(*) into cnt3 from my_tb where status = 3;
3.最后,只要判断cnt1、cnt2、cnt3是否>0,然后不同情况,取不同的status值(1、2、3)即可.
iqlife 2010-09-21
  • 打赏
  • 举报
回复
不难啊,根据SELECT COUNT() 进行分情况去判断就好了
然后再逐步进行判断,没有什么难度啊,自己先写写。只要逻辑没有问题,语句肯定可以写出来
bitm 2010-09-21
  • 打赏
  • 举报
回复
trigger与procedure 都是可以的吧。
有无哪位牛人帮写下这个过程呀。谢谢了
Diza1986 2010-09-21
  • 打赏
  • 举报
回复
不能理解
gelyon 2010-09-21
  • 打赏
  • 举报
回复
你是想对你心插入的一笔数据,根据你上面的条件,来改变新数据的status吗?
如果这样,根据你的条件,写个before insert trigger,将:new.status改变就可以了
bitm 2010-09-21
  • 打赏
  • 举报
回复
回2楼,

我主要是想根据状态值取数据时能保持平衡。所以要入库时判断该值的数据量做为依据
bitm 2010-09-21
  • 打赏
  • 举报
回复
漏了一个情况,
9:如果状态值1,2,3的3种状态都没有数据,那么取status状态值数据任意一个(该情况该值只可能1,2,3其中一个).
  • 打赏
  • 举报
回复
感觉你这个要求就是status里有123就可以了,没有一点规律的
你就顺便update几个好了

17,081

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧