SQL 프로그래밍이란 SQL을 사용하여 데이터베이스와 상호작용하는 프로그램을 작성하는 것을 의미한다.
SQL 프로그래밍은 단순한 SQL 쿼리 작성뿐만 아니라, 절차형 프로그래밍 요소(IF, LOOP, CURSOR 등)를 포함하여 복잡한 데이터 처리 로직을 구현하는 것을 의미한다. 이때 PL/SQL(Oracle), T-SQL(MSSQL) 같은 확장형 SQL을 사용하여 데이터베이스 내에서 프로시저, 함수, 트리거, 커서 등을 구현할 수 있다.
1. IF….ELSE ….
IF…ELSE.. 문은 조건에 따라 분기 처리를 한다. 한 문장 이상이 처리되어야 할 때는 BEGIN…END 와 함께 묶어줘야만 하며, 실행할 문장의 한 문장이라도 BEGIN..END로 묶어주는 것이 좋다.
IF <조건식> BEGIN 쿼리문1 END ELSE BEGIN 쿼리문2 END
조건식이 참(True)라면 쿼리문1을 수항하며, 거짓(False) 라면 쿼리문2를 수행한다.
거짓일 경우 아무것도 할 것이 없다면 ELSE 이하는 생략해도 된다.
DECLARE @var1 INT SET @var1 = 100 IF @var1 = 100 BEGIN PRINT '@var1이 100이다' END ELSE BEGIN PRINT '@var1이 100이 아니다' END

이번에는 AdventureWorks2022 데이터베이스의 HumanResources.Employee 테이블을 사용해보자. 직원번호 111번에 해당하는 직원의 입사일이 5년이 넘었는지를 확인해보자.
USE AdventureWorks2022 DECLARE @hireDate SMALLDATETIME -- 입사일 DECLARE @curDate SMALLDATETIME -- 오늘 DECLARE @years DECIMAL(5,2) -- 근무한 년수 DECLARE @days INT -- 근무한 일수 SELECT @hireDate = HireDate -- HireDate 열의 결과를 @hiredate에 대입 FROM HumanResources.Employee WHERE BusinessEntityID = 111 SET @curDate = GETDATE() -- 현재 날짜 SET @years = DATEDIFF(year,@hireDate,@curDate) -- 날짜의 차이, 년 단위 SET @days = DATEDIFF(day,@hireDate,@curDate) -- 날짜의 차이, 일 단위 IF(@years >=5) BEGIN PRINT N'입사한지'+CAST(@days AS NCHAR(5)) + N'일이 지났습니다.' PRINT N'축하합니다.' END ELSE BEGIN PRINT N'입사한지' + CAST(@days AS NCHAR(5)) + N'일 밖에 안되었네요.' PRINT N'열심히 일하세요.' END

다중 분기를 사용하기 위해선 ELSE IF 를 사용할 수 있다.
DECLARE @point INT = 77 , @credit NCHAR(1) IF @point >= 90 SET @credit = 'A' ELSE IF @point >=80 SET @credit = 'B' ELSE IF @point > 70 SET @credit = 'C' ELSE IF @point >=60 SET @credit = 'E' ELSE SET @credit = 'F' PRINT N'취득점수 = ' + CAST(@point AS NCHAR(3)) PRINT N'학점 = ' + @credit

ELSE IF 를 사용하면 여러 조건에 대하여 분기를 처리할 수 있다.
2. ELSE IF문, CASE
CASE문은 ELSE IF와 비슷하게 다중 분기를 처리한다. CASE문은 ELSE IF 보다 직관적이며, 값의 반환이 필요할 때 실행한다.
DECLARE @point INT = 77 , @credit NCHAR(1) SET @credit = CASE WHEN (@point >= 90) THEN 'A' WHEN (@point >= 80) THEN 'B' WHEN (@point >= 70) THEN 'C' WHEN (@point >= 60) THEN 'D' ELSE 'F' END PRINT N'취득학점 = ' + CAST(@point AS NCHAR(3)) PRINT N'학점 = ' + @credit

CASE 구문의 결과는 하나의 값만을 돌려주고, 그 값을 @credit 변수에 대입하였다. IF문을 사용하는 것보다 훨씬 코드가 간결해졌다. CASE문은 혹시 조건에 맞는 WHEN이 여러 개 라도 먼저 조건이 만족하는 WHEN이 처리된다. 그리고 CASE를 종료한다.
3. WHILE / BREAK / CONTINUE / RETURN
WHILE문은 다른 프로그래밍 언어의 WHILE과 같은 개념이다. 조건식이 참인 동안에는 계쏙 반복되는 반복문이다.
WHILE <조건식> BEGIN 쿼리문 END
1에서 100까지의 값을 모두 더하는 기능을 구현해보자.
DECLARE @i INT = 1 -- 1에서 100까지 증가할 변수 DECLARE @hap BIGINT = 0 -- 더한 값을 누적할 변수 WHILE(@i <= 100) BEGIN SET @hap += @i -- @hap의 원래의 값에 @i 를 더해서 다시 @hap에 넣음 SET @I += 1 -- @i의 원래 값에 1을 더해서 다시 @i에 넣음 END PRINT '결과값 : ' + CAST(@hap AS VARCHAR)

만약 1에서 100까지 중에서 7의 배수는 더하는 것에서 제외시키려면 어떻게 할까?
그럴 경우 CONTINUE 문과 BREAK 문을 사용할 수 있다.
DECLARE @i INT = 1 DECLARE @hap BIGINT = 0 WHILE (@i <= 100) BEGIN IF (@i % 7 = 0) BEGIN PRINT N'7의 배수 :' + CAST(@i AS NCHAR(3)) SET @i += 1 CONTINUE END SET @hap += @i IF(@hap > 1000) BREAK SET @i += 1 END PRINT N'합계 = ' + CAST(@hap AS NCHAR(10))

CONTINUE 문을 만나면 바로 WHILE문으로 이동해서 비교(@i ≤ 100) 를 다시 하고, BREAK를 만나면 WHILE문을 빠져 나온다.
그런데 만약 BREAK 자리에 RETURN을 쓰게 되면 현재 처리되는 것을 무조건 종료하고 호출자에게 값을 반환한다. 즉 마지막의 ‘합계=1029’를 출력하지 않고 마치게 된다.
4. TRY/CATCH
TRY/CATCH는 오류를 처리하는데 아주 편리하다.
BEGIN TRY 쿼리문 END TRY BEGIN CATCH 쿼리문에서 오류가 발생하면 처리 로직 END CATCH
원래 사용하고자 하던 SQL문을 BEGIN TRY/ END TRY 구문으로 묶으면 된다. 프로그램은 원래대로 실행되며, 만약 오류가 발생하게 되면 BEGIN CATCH/ END CATCH 로 묶은 부분이 실행된다.
USE sqlDB BEGIN TRY INSERT INTO userTb1 VALUES('LSG','이상구',1988,'서울',NULL,NULL,170,GETDATE()) PRINT N'정상적으로 입력되었다.' END TRY BEGIN CATCH PRINT N'오류 발생' END CATCH

userTb1 은 이미 아이디 ‘LSG’가 존재하기 때문에 오류가 발생한다. 오류가 발생하면 BEGIN CATCH/ END CATCH 내부가 실행된다.
BEGIN CATCH/ END CATCH 내부에 오류를 확인할 수 있는 함수를 사용하면 오류의 원인을 쉽게 분석할 수 있다.
- ERROR_NUMBER() : 오류 번호
- ERROR_MESSAGE() : 오류 메세지
- ERROR_SEVERITY() : 오류 심각도
- ERROR_STATE() : 오류 상태 번호
- ERROR_LINE() : 오류를 발생시킨 행 번호
- ERROR_PROCEDURE() : 오류가 발생한 저장 프로시저나 트리거의 이름
위의 함수를 사용해 오류의 원인을 파악해보자.
USE sqlDB BEGIN TRY INSERT INTO userTb1 VALUES('LSG','이상구',1988,'서울',NULL,NULL,170,GETDATE()) PRINT N'정상적으로 입력되었다.' END TRY BEGIN CATCH PRINT N'***오류가 발생했다***' PRINT N'오류 번호 :' PRINT ERROR_NUMBER() PRINT N'오류 메세지 :' PRINT ERROR_MESSAGE() PRINT N'오류 상태 코드 :' PRINT ERROR_STATE() PRINT N'오류 심각도 :' PRINT ERROR_SEVERITY() PRINT N'오류 발생 행번호 :' PRINT ERROR_LINE() PRINT N'오류 발생 프로시저/트리거' PRINT N'ERROR_PROCEDURE' END CATCH

함수를 사용해 오류를 파악할 수 있다.
5. EXEC (동적 SQL)
EXEC (또는 EXECUTE) 는 SQL문장을 실행시키는 역할을 한다.
USE sqlDB DECLARE @sql VARCHAR(100) SET @sql = 'SELECT * FROM userTb1 WHERE userid = ''EJW'' ' EXEC (@sql)

해당 쿼리는 'SELECT * FROM userTb1 WHERE userid = ''EJW'' ' 문장을 바로 실행하지 않고, 변수 @sql에 입력시켜놓고 EXEC() 함수로 실행한다.
이렇게 EXEC를 이용해서 쿼리문을 실행하는 것을 동적 SQL이라고 한다.
만약 테이블을 생성해야 하는데, 테이블의 이름이 ‘myTbl현재년월일’으로 항상 만들어져야 하는 경우를 가정해 보자. 즉, 오늘이 2024년 12월 9일이라면 테이블 이름은 ‘myTbl12024_12_9’ 의 형태로 만들어져야 한다. 동적 SQL을 활용해 만들어보자.
DECLARE @curDate DATE DECLARE @curYear VARCHAR(4) DECLARE @curMonth VARCHAR(2) DECLARE @curDay VARCHAR(2) DECLARE @sql VARCHAR(100) SET @curDate = GETDATE() SET @curYear = YEAR(@curDate) SET @curMonth = MONTH(@curDate) SET @curDay = DAY(@curDate) SET @sql = 'CREATE TABLE myTbl' + @curYear + '_' + @curMonth + '_' + @curDay SET @sql += '(id INT , name NCHAR(10))' EXEC(@sql)

동적 SQL로 현재 날짜를 이름에 사용한 테이블을 만들 수 있다.
Share article