ms-sql 제어문에 관한 내용

-- 제어문 --
1. if 문
T-SQL 문의 실행에 대한 조건을 설정. IF 키워드와 그 조건 뒤의 T-SQL 문은 조건이 만족되는 경우
(부울 식이 TRUE를 반환하는 경우)에만 실행된다. 선택적인 ELSE 키워드는 IF 조건이 만족되지
않는 경우(부울 식이 FALSE를 반환하는 경우)에 실행되는 대체 T-SQL 문을 사용.


* 한개의 if ~ else 블럭 사용

USE dbsys

IF (SELECT AVG(SAL) FROM EMP WHERE DEPTNO = 10) > (SELECT AVG(SAL) FROM EMP)
BEGIN
PRINT '10번부서의 연봉평균은 전체 평균보다는 높은 편이군요..!!'
END -- BEGIN~END 반드시 써야한다. 없으면 한개의 T-SQL문에만 영향.
ELSE
PRINT '10번부서의 연봉평균은 전체 평균보다는 낮은 편이군요..!!'


* 두개 이상의 if ~ else 블럭 사용

IF (SELECT AVG(SAL) FROM EMP WHERE DEPTNO = 10) >
(SELECT AVG(SAL) FROM EMP)
BEGIN
PRINT '10번부서의 연봉평균은 전체 평균보다는 높은 편이군요..!!'
END
ELSE
IF (SELECT AVG(SAL) FROM EMP WHERE DEPTNO = 50) <
(SELECT AVG(SAL) FROM EMP)
BEGIN
SELECT '10번,50번 둘다 전체연봉평균보다 낮네요..'
END


USE pubs
go

IF (SELECT AVG(price) FROM titles WHERE type = 'mod_cook') < $15
BEGIN
PRINT 'The following titles are excellent mod_cook books:'
PRINT ' '
SELECT SUBSTRING(title, 1, 35) AS Title FROM titles
WHERE type = 'mod_cook'
END
ELSE
IF (SELECT AVG(price) FROM titles WHERE type = 'mod_cook') > $15
BEGIN
PRINT 'The following titles are expensive mod_cook books:'
PRINT ' '
SELECT SUBSTRING(title, 1, 35) AS Title FROM titles
WHERE type = 'mod_cook'
END


2. while 문
SQL 문 또는 문 차단의 반복 실행에 대한 조건을 설정.
문은 지정된 조건이 true인 한, 반복적으로 실행됨.
WHILE 루프의 문 실행은 BREAK와 CONTINUE 키워드를 사용하여 루프 내에서 제어.

* 중첩된 if~else 및 while로 break 및 continue 사용
USE pubs
GO
WHILE (SELECT AVG(price) FROM titles) < $30
BEGIN
UPDATE titles
SET price = price * 2
SELECT MAX(price) FROM titles
IF (SELECT MAX(price) FROM titles) > $50
BREAK
ELSE
CONTINUE
END
PRINT 'Too much for the market to bear'
GO

* 커서가 있는 프로시저 내에서 WHILE 사용
다음 WHILE 생성은 count_all_rows라는 이름의 프로시저의 구역.
다음은 이 WHILE 생성이 커서와 함께 사용되는 함수인
@@FETCH_STATUS의 반환 값을 테스트하는 예제.
@@FETCH_STATUS가 -2, -1 또는 0을 반환하므로 세 가지 경우를
모두 테스트해야한다. 저장 프로시저가 실행된 이후에 커서
결과로부터 행을 삭제한 경우에는 해당 행을 건너뛴다.
성공적으로 반입(0)된 경우, BEGIN...END 루프 내의 SELECT가 실행.
/*
@@FETCH_STATUS 함수의 값
반환값 : 설명
0 : FETCH 문이 성공
-1 : FETCH 문이 실패
-2 : 반입된 행이 없다.
*/

USE pubs
DECLARE tnames_cursor CURSOR
FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
OPEN tnames_cursor
DECLARE @tablename sysname
--SET @tablename = 'authors'
FETCH NEXT FROM tnames_cursor INTO @tablename
WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
SELECT @tablename = RTRIM(@tablename)
EXEC ('SELECT ''' + @tablename + ''' = count(*) FROM '
+ @tablename )
PRINT ' '
END
FETCH NEXT FROM tnames_cursor INTO @tablename
END
CLOSE tnames_cursor
DEALLOCATE tnames_cursor



3. CASE 문
조건 목록을 평가하고 가능한 여러 결과 식 중 하나를 반환.

CASE는 두 가지 형식이 있다.
- 단순 CASE 함수는 특정 식을 일련의 단순 식과 비교하여 결과를 결정.
- 검색된 CASE 함수는 일련의 부울 식을 평가하여 결과를 결정.

두 가지 형식 모두 선택 사항인 ELSE 인수를 지원.

* 단순 CASE : SELECT문 내에서 동등성만 검사하고 다른 비교작업 수행 안함
USE DBSYS
GO
SELECT DEPTNO,
부서명 =
CASE DEPTNO
WHEN 10 THEN '부산의 총무부'
WHEN 40 THEN '서울의 총무부'
WHEN 70 THEN '제주의 총무부'
END
FROM DEPT
WHERE DNAME = '총무부'
ORDER BY 1
GO

* 검색된 CASE : 동등 검사, 부울검사 수행하여 결과를 낸다.
SELECT DEPTNO, AVG(SAL) AS 부서별평균연봉,
"부서별 평균연봉등급" =
CASE
WHEN AVG(SAL) <= 100000 THEN
'평균연봉이 좀 낮은 부서군'
WHEN AVG(SAL) > 100000 AND AVG(SAL) <= 130000 THEN
'평균연봉이 보통인 부서군'
WHEN AVG(SAL) > 130000 AND AVG(SAL) <= 150000 THEN
'평균연봉이 좀 높은 부서군'
ELSE '평균연봉이 꽤 높은 부서군'
END
FROM EMP WHERE DEPTNO IS NOT NULL
GROUP BY DEPTNO
ORDER BY 2 DESC
GO


USE pubs
SELECT SUBSTRING((RTRIM(a.au_fname) + ' '+
RTRIM(a.au_lname) + ' '), 1, 25) AS Name, ta.title_id,
Type =
CASE
WHEN SUBSTRING(ta.title_id, 1, 2) = 'BU' THEN 'Business'
WHEN SUBSTRING(ta.title_id, 1, 2) = 'MC' THEN 'Modern Cooking'
WHEN SUBSTRING(ta.title_id, 1, 2) = 'PC' THEN 'Popular Computing'
WHEN SUBSTRING(ta.title_id, 1, 2) = 'PS' THEN 'Psychology'
WHEN SUBSTRING(ta.title_id, 1, 2) = 'TC' THEN 'Traditional Cooking'
END
FROM titleauthor ta JOIN authors a ON ta.au_id = a.au_id

--------------------------------------------------------------
SUBSTRING 함수 : 문자, 이진, 텍스트, 이미지 식의 일부를 반환

형식 : SUBSTRING ( expression!! , start , length )

USE pubs
SELECT au_lname, SUBSTRING(au_fname, 1, 1)
FROM authors
ORDER BY au_lname

USE pubs
SELECT pub_id, SUBSTRING(logo, 1, 10) AS logo,
SUBSTRING(pr_info, 1, 10) AS pr_info
FROM pub_info
WHERE pub_id = '1756'
--------------------------------------------------------------

-- 흐름 제어 키워드 --

1. BEGIN...END 사용
BEGIN 및 END 문을 사용하여 여러 T-SQL 문을 논리 블록으로 그룹화.
흐름 제어 문이 두 개 이상의 T-SQL 문 블록을 실행해야 하는 곳에서
BEGIN 및 END 문을 사용.

2. GOTO
실행 흐름을 레이블로 변경. GOTO 다음에 이어지는 T-SQL 문을 건너뛰고
레이블에서 처리를 계속 이어간다. GOTO 문과 레이블은 프로시저, 일괄 처리,
명령문 블록 등 어디에서나 사용할 수 있다. GOTO 문은 중첩될 수 있다.

레이블 정의
label :

실행 변경
GOTO label

CREATE TABLE GOTO1
(ID INT, NAME CHAR(12), SAL INT)
GO
-- WHILE 문을 대신해 사용할 수 있는 GOTO 문 작성
DECLARE @NO INT
SET @NO = 0
ADD_ID:
BEGIN
INSERT GOTO1 VALUES(@NO * 4 + 0, 'KIM', 700)
INSERT GOTO1 VALUES(@NO * 4 + 1, 'KANG', 700)
INSERT GOTO1 VALUES(@NO * 4 + 2, 'SEO', 700)
INSERT GOTO1 VALUES(@NO * 4 + 3, 'PARK', 700)
SET @NO = @NO + 1
IF (@NO <> 1000) GOTO ADD_ID
END
GO
-- 4000 개 입력 확인
SELECT COUNT(*) FROM GOTO1


3. RETURN
쿼리나 프로시저를 무조건 종료. RETURN은 즉각적이고 완전하며 프로시저,
일괄 처리, 명령문 블록에서 아무 때나 종료하는 데 사용할 수 있다.
RETURN 다음에 있는 명령문을 실행되지 않는다.


USE dbsys

IF (SELECT AVG(SAL) FROM EMP WHERE DEPTNO = 30) > (SELECT AVG(SAL) FROM EMP)
BEGIN
PRINT '10번부서의 연봉평균은 전체 평균보다는 높은 편이군요..!!'
-- RETURN
PRINT 'RETURN이 될려나?'
END
ELSE
PRINT '10번부서의 연봉평균은 전체 평균보다는 낮은 편이군요..!!'


4. WAITFOR
문 블록, 저장 프로시저 또는 트랜잭션의 실행을 트리거하는 시간, 시간 간격 또는 이벤트를 지정.

WAITFOR { DELAY 'time' | TIME 'time' }
/*
DELAY : 지정된 시간이 경과할 때까지 대기하도록 명령. 최대 24 시간까지 대기.

'time' : 대기할 총 시간입니다. time은 datetime 데이터에서 사용할 수 있는 형식 중 한 가지를
사용하여 지정하거나 로컬 변수로 지정할 수 있다. 날짜는 지정할 수 없으므로
datetime 값의 날짜 부분은 허용되지 않는다.

TIME : 지정된 시간까지 대기하도록 명령합니다. */


=====================================================================================

문제1) PUBS, titles 테이블 : title_id 가 mc3026, pc9999, tc4203 인 데이터에 대해
title 값을 앞에서 15자로 정의하라.

select title_id,title=
case
when title_id='mc3026' then substring(title,1,15)
when title_id='pc9999' then substring(title,1,15)
when title_id='tc4203' then substring(title,1,15)
end
from
titles

문제2) PUBS, titles, sales : title_id 가 PS2091, TC4203, BU7832 인 데이터에 대해
qty 값이 10 이상이면 price를 2배로 해주고, 작으면 'Low' 라는 메세지를
출력하라.

select t.title_id , s.qty , t.price,'price*2'=
case when s.qty >= 10 and t.title_id IN ('ps2091','tc4203','bu7832')
then convert(char(10),t.price*2)
when s.qty < 10 and t.title_id IN ('ps2091','tc4203','bu7832')
then convert(char(10),'low')
else
convert(char(10),t.price)
end
from
titles as t join sales as s on t.title_id = s.title_id

다운로드
control.jpg (49.6KB)

의견 1 신규등록      목록