CREATE PROCEDURE prc_joserph_ring
(p_sodilers IN integer,
p_shift IN integer,
p_msg OUT varchar2)
IS
k integer:=0;
v_idx integer:=0;
Type joserph IS TABLE OF integer INDEX BY BINARY_INTEGER;
v_soilders joserph;
BEGIN
FOR i in 1..p_sodilers LOOP v_soilders(i):=i; END LOOP;
WHILE v_soilders.count>=1 LOOP
IF v_soilders.next(v_idx) is not null then
v_idx :=v_soilders.next(v_idx );
else
v_idx :=v_soilders.first;
end if;
k:=k+1;
if mod(k,p_shift )=0 then
p_msg := p_msg || ',' || v_soilders(v_idx);
v_soilders.delete(v_idx);
end if;
END LOOP;
END;
declare
v_msg varchar2(100);
begin
-- Test statements here
prc_joserph_ring(20,4,v_msg);--20个士兵
DBMS_OUTPUT.put_line(v_msg);
end;
游标实现
CREATE TABLE soilders(--创建表
ind int ,
quit_order int );
DECLARE
v_total integer := &total;
v_step integer := &n;
CURSOR cur_soilder IS
SELECT * FROM soilders WHERE quit_order=0 FOR UPDATE;
k integer :=0; ---报数
j integer:=1; ---退出顺序
v_soilder cur_soilder%ROWTYPE;
BEGIN
DELETE FROM soilders;
FOR i in 1.. v_total LOOP
insert into soilders values(i, 0);
END LOOP;
COMMIT;
WHILE j<=v_total LOOP
OPEN cur_soilder;
LOOP
FETCH cur_soilder INTO v_soilder ;
EXIT WHEN cur_soilder%NOTFOUND;
k:=k+1;
if mod(k,v_step)=0 then
UPDATE soilders SET quit_order = j
WHERE CURRENT OF cur_soilder;
j:=j+1;
end if;
END LOOP;
CLOSE cur_soilder;
commit;
END LOOP;
END;
创建存储过程方便调用
CREATE OR REPLACE PROCEDURE prc_joserph_ring_V2(p_total IN integer,p_step IN integer)
IS
CURSOR cur_soilder IS
SELECT * FROM soilders WHERE quit_order=0 FOR UPDATE;
k integer :=0; ---报数
j integer:=1; ---退出顺序
v_soilder cur_soilder%ROWTYPE;
BEGIN
DELETE FROM soilders;
FOR i in 1.. p_total LOOP
insert into soilders values(i, 0);
END LOOP;
COMMIT;
WHILE j<=p_total LOOP
OPEN cur_soilder;
LOOP
FETCH cur_soilder INTO v_soilder ;
EXIT WHEN cur_soilder%NOTFOUND;
k:=k+1;
if mod(k,v_step)=0 then
UPDATE soilders SET quit_order = j
WHERE CURRENT OF cur_soilder;
j:=j+1;
end if;
END LOOP;
CLOSE cur_soilder;
commit;
END LOOP;
END;