IT Log
[SQL Server] 흐름제어(Control-of-Flow) 본문
728x90
반응형
- BEGIN...END
- BREAK
- CONTINUE
- GOTO
- IF...ELSE
- RETURN
- THROW
- TRY...CATCH
- WAITFOR
- WHILE
BEGIN...END
- 중첩 가능
BEGIN
{ sql_statement | statement_block }
END
예시
USE AdventureWorks2012
GO
BEGIN TRANSACTION
GO
IF @@TRANCOUNT = 0
BEGIN
SELECT FirstName, MiddleName
FROM Person.Person WHERE LastName = 'Adams';
ROLLBACK TRANSACTION;
PRINT N'Rolling back the transaction two times would cause an error.';
END;
ROLLBACK TRANSACTION;
PRINT N'Rolled back the transaction.';
GO
/*
Rolled back the transaction.
*/
BREAK
- 현재 WHILE 루프를 종료
- 루프가 중첩되어 있는 경우, 현재 루프만을 종료
- 일반적으로 IF문 내에 존재
예시
WHILE (1=1)
BEGIN
IF EXISTS (SELECT * FROM ##MyTempTable WHERE EventCode = 'Done')
BEGIN
BREAK; -- 'Done' row has finally been inserted and detected, so end this loop.
END
PRINT N'The other process is not yet done.'; -- Re-confirm the non-done status to the console.
WAITFOR DELAY '00:01:30'; -- Sleep for 90 seconds.
END
CONTINUE
- WHILE 루프를 다시 시작
- CONTINUE 다음에 나오는 것은 무시됨
GOTO
- 지정된 label에서 처리를 이어감
- 중첩 가능
예시
DECLARE @Counter int;
SET @Counter = 1;
WHILE @Counter < 10
BEGIN
SELECT @Counter
SET @Counter = @Counter + 1
IF @Counter = 4 GOTO Branch_One --Jumps to the first branch.
IF @Counter = 5 GOTO Branch_Two --This will never execute.
END
Branch_One:
SELECT 'Jumping To Branch One.'
GOTO Branch_Three; --This will prevent Branch_Two from executing.
Branch_Two:
SELECT 'Jumping To Branch Two.'
Branch_Three:
SELECT 'Jumping To Branch Three.';
IF...ELSE
IF Boolean_expression
{ sql_statement | statement_block }
[ ELSE
{ sql_statement | statement_block } ]
예시
-- 간단한 예시
IF DATENAME(weekday, GETDATE()) IN (N'Saturday', N'Sunday')
SELECT 'Weekend';
ELSE
SELECT 'Weekday';
-- 분석 예시
DECLARE @maxWeight FLOAT, @productKey INTEGER
SET @maxWeight = 100.00
SET @productKey = 424
IF @maxWeight <= (SELECT Weight from DimProduct WHERE ProductKey = @productKey)
SELECT @productKey AS ProductKey, EnglishDescription, Weight, 'This product is too heavy to ship and is only available for pickup.'
AS ShippingStatus
FROM DimProduct WHERE ProductKey = @productKey
ELSE
SELECT @productKey AS ProductKey, EnglishDescription, Weight, 'This product is available for shipping or pickup.'
AS ShippingStatus
FROM DimProduct WHERE ProductKey = @productKey
RETURN
- 쿼리나 프로시저를 무조건 종료
- RETURN 다음에 있는 쿼리는 실행되지 않음
RETURN [ integer_expression ]
예시
-- 간단한 예시
CREATE PROCEDURE findjobs @nm sysname = NULL
AS
IF @nm IS NULL
BEGIN
PRINT 'You must give a user name'
RETURN
END
ELSE
BEGIN
SELECT o.name, o.id, o.uid
FROM sysobjects o INNER JOIN master..syslogins l
ON o.uid = l.sid
WHERE l.name = @nm
END;
-- 값에 따른 상태코드 반환 예시
-- 프로시저 생성 (StateProvince가 'WA'면 1을 아니면 2를 반환)
USE AdventureWorks2012;
GO
CREATE PROCEDURE checkstate @param VARCHAR(11)
AS
IF (SELECT StateProvince FROM Person.vAdditionalContactInfo WHERE ContactID = @param) = 'WA'
RETURN 1
ELSE
RETURN 2;
GO
-- 결과는 1
DECLARE @return_status INT;
EXEC @return_status = checkstate '2';
SELECT 'Return Status' = @return_status;
GO
-- 결과는 2
DECLARE @return_status INT;
EXEC @return_status = checkstate '6';
SELECT 'Return Status' = @return_status;
GO
THROW
- TRY...CATCH 구문의 CATCH 블록으로 실행을 이전
THROW [ { error_number | @local_variable },
{ message | @local_variable },
{ state | @local_variable } ]
[ ; ]
예시
USE tempdb;
GO
CREATE TABLE dbo.TestRethrow
( ID INT PRIMARY KEY
);
BEGIN TRY
INSERT dbo.TestRethrow(ID) VALUES(1);
-- Force error 2627, Violation of PRIMARY KEY constraint to be raised.
INSERT dbo.TestRethrow(ID) VALUES(1);
END TRY
BEGIN CATCH
PRINT 'In catch block.';
THROW;
END CATCH;
-- 결과
In catch block.
Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK__TestReth__3214EC272E3BD7D3'. Cannot insert duplicate key in object 'dbo.TestRethrow'.
The statement has been terminated.
TRY...CATCH
- TRY 블록 내에서 오류가 발생하는 경우 CATCH 블록으로 제어가 전달
BEGIN TRY
{ sql_statement | statement_block }
END TRY
BEGIN CATCH
[ { sql_statement | statement_block } ]
END CATCH
[ ; ]
예시
BEGIN TRY
-- Generate a divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO
WAITFOR
- 지정된 시간 또는 시간 간격이 경과하거나 지정된 명령문이 하나 이상의 행을 수정 또는 반화할 때까지 일괄처리, 저장 프로시저 또는 트랜잭션의 실행을 차단
WAITFOR
{
DELAY 'time_to_pass'
| TIME 'time_to_execute'
| [ ( receive_statement ) | ( get_conversation_group_statement ) ]
[ , TIMEOUT timeout ]
}
예시
-- TIME 사용
EXECUTE sp_add_job @job_name = 'TestJob';
BEGIN
WAITFOR TIME '22:20';
EXECUTE sp_update_job @job_name = 'TestJob',
@new_name = 'UpdatedJob';
END;
GO
-- DELAY 사용
BEGIN
WAITFOR DELAY '02:00';
EXECUTE sp_helpdb;
END;
GO
-- 지역변수와 함께 DELAY 사용
IF OBJECT_ID('dbo.TimeDelay_hh_mm_ss','P') IS NOT NULL
DROP PROCEDURE dbo.TimeDelay_hh_mm_ss;
GO
CREATE PROCEDURE dbo.TimeDelay_hh_mm_ss
(
@DelayLength char(8)= '00:00:00'
)
AS
DECLARE @ReturnInfo VARCHAR(255)
IF ISDATE('2000-01-01 ' + @DelayLength + '.000') = 0
BEGIN
SELECT @ReturnInfo = 'Invalid time ' + @DelayLength
+ ',hh:mm:ss, submitted.';
-- This PRINT statement is for testing, not use in production.
PRINT @ReturnInfo
RETURN(1)
END
BEGIN
WAITFOR DELAY @DelayLength
SELECT @ReturnInfo = 'A total time of ' + @DelayLength + ',
hh:mm:ss, has elapsed! Your time is up.'
-- This PRINT statement is for testing, not use in production.
PRINT @ReturnInfo;
END;
GO
/* This statement executes the dbo.TimeDelay_hh_mm_ss procedure. */
EXEC TimeDelay_hh_mm_ss '00:00:10';
GO
WHILE
- 지정된 조건이 TRUE면, 반복적으로 실행
- BREAK와 CONTINUE 키워드를 사용하여 제어 가능
WHILE Boolean_expression
{ sql_statement | statement_block | BREAK | CONTINUE }
예시
-- 중첩된 IF...ELSE
USE AdventureWorks2012;
GO
WHILE (SELECT AVG(ListPrice) FROM Production.Product) < $300
BEGIN
UPDATE Production.Product
SET ListPrice = ListPrice * 2
SELECT MAX(ListPrice) FROM Production.Product
IF (SELECT MAX(ListPrice) FROM Production.Product) > $500
BREAK
ELSE
CONTINUE
END
PRINT 'Too much for the market to bear';
-- 커서에서 예시
DECLARE @EmployeeID as NVARCHAR(256)
DECLARE @Title as NVARCHAR(50)
DECLARE Employee_Cursor CURSOR FOR
SELECT LoginID, JobTitle
FROM AdventureWorks2012.HumanResources.Employee
WHERE JobTitle = 'Marketing Specialist';
OPEN Employee_Cursor;
FETCH NEXT FROM Employee_Cursor INTO @EmployeeID, @Title;
WHILE @@FETCH_STATUS = 0
BEGIN
Print ' ' + @EmployeeID + ' '+ @Title
FETCH NEXT FROM Employee_Cursor INTO @EmployeeID, @Title;
END;
CLOSE Employee_Cursor;
DEALLOCATE Employee_Cursor;
GO
참조 URL : https://docs.microsoft.com/ko-kr/sql/t-sql/language-elements/control-of-flow?view=sql-server-ver15
728x90
반응형
'SQL > SQL Server' 카테고리의 다른 글
[SQL Server] PROCEDURE 성능 개선 (0) | 2022.02.14 |
---|---|
[SQL Server] CREATE PROCEDURE (0) | 2022.02.14 |
[SQL Server] Functions - 논리 함수 (0) | 2022.02.08 |
[SQL Server] Functions - Cursor 함수 (0) | 2022.01.25 |
[SQL Server] CURSOR (0) | 2022.01.25 |
Comments