개발자 끄적끄적

loop, while, cursor 본문

MySQL

loop, while, cursor

햏치 2023. 3. 8. 00:28

<loop>
[begin_label:] LOOP
  statement_list
end loop[end_label]

[label] : LOOP
...
--terminate the loop
if condition then
  leave [label]; - exit
  iterate [label]; -반복
end if
...
end loop;
- leave label : 지정된 label의 반복문을 벗어나게 한다
- iterate label : 지정된 label를 반복하게 한다

ex)1~10까지 출력
create procedure loop_test1()
begin
  declare a int default 0;

start_a : loop
  set a =a+1;
  if a>10 then
    leave start_a;
  end if;
    select a;
  end loop;
end;


<while>
begin_label : while 조건 do
...
end while end_label;


ex)
create procedure while_test1()
begin
  declare cnt int default 0;
  declare str varchar(100) default ' ';
  begin_label : while cnt<10 do
    set cnt = cnt+1;
    set str = concat(str, ' ', cnt);
  end while;
  select str;
end;




<cursor>
- 선택된 데이터를 가지고 있다

<cursor 특징>
- Read-only
- Non-scrollable
- Asensitive(강압적이지 않다->커서에 의해 선택된 상태값이
변경 될 경우 인식하지 못한다)


<커서 선언하기>
declare cursor_name cursor for select_statement;
declare continue handler for not fount set finished=1; ->커서에 데이터가 없는 경우
open cursor_name;
fetch cursor_name into variables list;
...
close cursor_name;
- finished : 일반변수
- fetch : 순환
- fetch cursor_name into variables list;
=> cursor_name의 값을 variables list라는 곳에 순환시켜라
=> for(x of obj) | for(x in obj) 과 비슷

ex)사원 번호와 이름 출력하기
create procedure cursor_test1()

begin
  declare m_no varchar(30);
  declare m_nmae varchar(30);
  declare finished int default 0;
  declare cur cursor for select employeeNumber, lastName from employees;
  declare continue handler for not found set finished=1;

  open cur;
  my_job:loop
    fetch cur into m_no, m_name;
    if finished=1 then
      leave my_job;
      end if;
      select m_no, m_name;
    end loop;
    close cur;
  end;
- "employeeNumber, lastName"에서 fetch cur into "m_no, m_name"의
   갯수와 순서가 반드시 일치해야한다
---------------------------------------------
<loop, while>

#loop문을 사용하여 1~10합계를 구하여 출력
#function
use lecture;
set global log_bin_trust_function_creators=1;

drop function func_loop;
create function func_loop()
returns int
begin
declare hap int default 0;
    declare x int default 0;
    my_loop:loop
    set x = x+1;
    set hap = hap + x;
    if x>=10 then
        leave my_loop;
       end if;
      end loop;
  return hap;
end;

select func_loop();

#procedure
drop procedure pro_loop;
create procedure pro_loop()
begin 
declare hap int default 0;
    declare x int default 0;
   
   my_loop:loop 
     set x = x + 1;
     set hap = hap + x;
    if x=10 then 
      leave my_loop;
    end if;
   end loop;
  
select hap;
end;

call pro_loop();

#while
drop procedure while_test1()
create procedure while_test1()
begin 
declare cnt int default 0;
    declare str varchar(100) default '';
    my_loop:while cnt<=10 do
       set cnt=cnt+1;
       set str=concat(str,'', cnt);
      end while 
     select cnt, str;
end;

call while_test1();

#매개변수로 전달된 정수를 사용하여 정수에 해당하는 구구단을 출력하시오(loop, while)

#function+loop 
drop function func_loop_gugu;
create function func_loop_gugu(dan int)
returns varchar(300)
begin 
declare i int default 0;
    declare str varchar(300) default '';
   here:loop 
     set i = i+1;
     set str = concat(str, dan, '*', i, '=', (dan*i), '');
  if i=9 then 
     leave here;
    end if;
   end loop;
  return str;
 end;

select func_loop_gugu(5);

#function+while 
drop function func_while_gugu;
create function func_while_gugu(dan int)
returns varchar(300)
begin 
declare i int default 0;
    declare str varchar(300) default '';
    here : while i<9 do
      set i = i+1;
      set str = concat(str, dan, '*', i, '=', (dan*i), '');
     end while 
     return str;
end;

select func_while_gugu(5);

#procedure+loop 
drop procedure pro_loop_gugu;
create procedure pro_loop_gugu(dan int, out str varchar(100))
begin 
declare i int default 0;
    set str = '';
    here:loop 
     set str = concat(str, dan, '*', i, '=', (dan*i), '');
     if i=9 then
      leave here;
     end if;
   end loop;
  end;
 
call pro_loop_gugu(5, @str);
select @str;

#procedure+while
drop procedure pro_while_gugu;
create procedure pro_while_gugu(dan int, out str varchar(100))
begin 
declare i int default 0;
    set str = '';
    here:while i<9 do 
     set i=i+1;
     set str = concat(str, dan, '*', i, '=', (dan*i),'');
    end while;
   end;

call pro_while_gugu(5,@str);
select @str;
---------------------------------------------

<cursor>

[cursor 미션] function and procedure
1. 매개변수로 사무실코드(officecode)를 입력받아 해당 사무실 직원의
사번, 이름, 이메일 주소를 조회

2. 고객번호(CustomerNumber)를 입력받아 해당 고객의 주문번호, 수량, 
단가, 금액(수량*단가)를 조회(테이블 : orders, orderdetails)

3. 두개의 날짜를 입력받아 두 날짜 사이에 주문된 주문번호, 주문일,
고객번호를 조회(테이블 : orders)

4. 고객별 금액 합계 조회(테이블:payments)

5. 년도를 입력받아 년도에 해당하는 금액총액과 평균금액을 조회
(테이블:payments)



#cursor
#cursor를 사용하여 사번, 사원명을 출력하는 procedure를 작성
drop procedure cursor_test1;
create procedure cursor_test1()
begin
declare eno int;
    declare ename varchar(100);
    declare stop int default 0;
   
   
    declare cur cursor for
      select employeeNumber, lastNmae
      from classicmodels.employees e ;
     declare continue handler for not found set stop=1;
    
   open cur;
   here:loop
   fetch cur into eno, ename;
   if(stop=1) then
    leave here;
   end if;
   select eno, ename;
  end loop;
 
   close cur;
end;
call cursor_test1();

desc classicmodels.employees ;

/*매개변수로 사무실코드(officecode)를 입력받아 해당 사무실 직원의
사번, 이름, 이메일 주소를 조회*/
#function
drop function cursor_f1;
create function cursor_f1(off_code int)
begin 
declare eName varchar(50) default '';
    declare eNumber int default 0;
    declare eMail varchar(50) default '';
   
    declare cur cursor for 
    select e.employeeNumber, e.email, e.lastName 
    from classicmodels.employees e ;
    where e.officeCode = off_code;
   
    declare continue handler for not found set stop=1;
   
    open cur;
    here:loop 
    fetch cur into eName, eNumber, eMail;
    if(stop=1) then  
     leave here;
    end if 
     select eName, eNumber, eMail;
    end loop;
   
   close cur;
  end;
 call cursor_f1();


#procedure
drop procedure proc_cur_mis1;
create procedure proc_cur_mis1(code varchar(10))
begin 
declare eno int;
    declare ename varchar(50);
    declare em varchar(100);
    declare stop int default 0;
   
declare cur cursor for 
select employeeNumber, lastName, email 
from classicmodels.employees e
where officeCode = 2;
    declare continue handler for not found set stop=1;
   
    open cur;
    here:loop 
    fetch cur into eno, ename, em;
    if(stop=1) then 
      leave here;
    end if;
      select eno, ename, em;
     end loop;
    close cur;
   end;
call proc_cur_mis1(2);

/*고객번호(CustomerNumber)를 입력받아 해당 고객의 주문번호, 수량, 
단가, 금액(수량*단가)를 조회(테이블 : orders, orderdetails)*/
drop procedure if exists proc_cur_mis2;
create procedure proc_cur_mis2(cno int)
begin 
declare ono int;
    declare ea int;
    declare price decimal(10,2);
    declare stop int default 0;
   
    declare cur cursor for
      select o.orderNumber, o2.quantityOrdered, o2.priceEach 
      from classicmodels.orders o join classicmodels.orderdetails o2 
      on o.orderNumber = o2.orderNumber 
      where o.customerNumber = cno;
     declare continue handler for not found set stop=1;
    
     open cur;
       here:while stop=0 do
         fetch cur into ono, ea, price;
         select ono, ea, price, (ea*price);
       end while;
      close cur;
end;
call proc_cur_mis2(181);


drop function cursor_f2;
create function cursor_f2(cus_num int)
begin 
declare eNumber int default 0;
    declare eproduct int default 0;
    declare eprice int default 0;
    declare etot int default 0;
    
    declare cur cursor for  
      select o2.orderNumber, o2.priceEach 
      from classicmodels.orderdetails o2 
      select o.orderNumber
      from classicmodels.orders o 
end;

/*두개의 날짜를 입력받아 두 날짜 사이에 주문된 주문번호, 주문일,
고객번호를 조회(테이블 : orders)*/
drop procedure proc_cur_mis3;
create procedure proc_cur_mis3(snal date, enal date)
begin 
declare ono int;
    declare onal date;
    declare cno int;
    declare stop int default 0;
    declare cur cursor for 
      select o.orderNumber, o.orderDate, o.customerNumber 
      from classicmodels.orders o 
      /*where o.orderDate >= snal and o.orderDate <= enal;*/
      where o.orderDate between snal and enal;
      declare continue handler for not found set stop=1;
     
      open cur;
      here:while stop=0 do 
        fetch cur into ono, onal, cno;
        select ono, onal, cno;
      end while;
      close cur;
end;
call proc_cur_mis3('2003-01-01', '2003-01-31');

/*고객별 금액을 합계 조회(테이블:payments)*/
drop procedure proc_cur_mis4;
create procedure proc_cur_mis4(cn int)
begin 
declare cno int;
declare tot decimal(10,2);
    declare stop int default 0;
   
    declare cur cursor for 
      select customerNumber, sum(amount)
      from classicmodels.payments
      where customerNumber = cn
      group by customerNumber;
    declare continue handler for not found set stop=1;
   
   open cur;
   here:while stop=0 do 
     fetch cur into cno, tot;
     select cno, tot;
   end while;
   close cur;
end;
call proc_cur_mis4(103);

/*년도를 입력받아 년도에 해당하는 금액총액과 평균금액을 조회
(테이블:payments)
*/
drop procedure proc_cur_mis5;
create procedure proc_cur_mis5(y int)
begin 
declare totAmt decimal(10,2) default 0;
    declare avgAmt decimal(10,2) default 0;
    declare stop int default 0;
   
   declare cur cursor for 
     select sum(amount), avg(amount)
     from classicmodels.payments p 
     where year(paymentDate) = y #year를 쓰면 반환값이 '숫자'이다
     group by year(paymentDate);
    declare continue handler for not found set stop=1;
   
   open cur;
   here:while stop=0 do 
     fetch cur into totAmt, avgAmt;
    select totAmt "총액", avgAmt "평균";
    end while;
   close cur;
end;
call proc_cur_mis5(2004);

'MySQL' 카테고리의 다른 글

형변환, 내장형 함수, decode, case, inline view, top, with 구문  (0) 2023.03.08
constraint  (0) 2023.03.08
case  (0) 2023.03.08