T-SQL 에 대해서
변수선언 및 사용
변수(Variable)는 변할수 있는 값을 담는다.
변수는 데이터형식에 기반해 사용되고, 변수의 생존기간은 선언된 범위에 따라 달라진다.
변수 선언은 DECLARE 구문을 통해 이루어진다.
DECLARE @TotalPrice INT; DECLARE @Group nvarchar(50), @Sales money; DECLARE @MyTableVar table( EmpID int NOT NULL, OldVacationHours int, NewVacationHours int, ModifiedDate datetime);
변수의 이름은 “@” 로 시작해야 하며, 별도의 값을 지정하기 전까지는 “NULL” 값을 기본값으로 가진다.
변수의 값 할당은 “SET”문을 통해서 이뤄지며 “SELECT”문을 통해서도 가능하다.
DECLARE @state char(25); set @state = 'Oregon'; select @state = 'Oregon';
유니코드의 경우에는 상수값의 앞에 “N”를 붙여야 유니코드로 변한다.
DECLARE @state char(25); set @state = N'Oregon';
변수의 출력은 두가지 방법이 있는데, SELECT 는 일반적인 행의 집합 형식으로 표시되며, PRINT 는 메세지 출력이다.
주석
- 여러줄을 처리 할경우 “/** ” 로 시작하여 ” **/” 로 마무리
- 한줄을 처리 할경우 “–“
시스템 전역변수
구성함수로 불리는 시스템 전역변수는 “@@” 이라는 표기가 붙여진 일종의 예약변수다. SQL서버가 시작하면서 이 전역변수들의 값이 할당되고 프로그램에서 이용할수 있다.
구성 함수 | 설명 |
---|---|
@@CONNECTIONS | SQL 서버가 시작된 이후 연결을 시도한 개수 |
@@MAX_CONNECTIONS | 사용자가 SQL서버를 사용할때 동시연결 가능한 사용자수 |
@@CPU_BUSY | SQL서버가 시작된 후 동작한 시간 |
@@DATEFIRST | 이번주 시작 요일 |
@@DBTS | 현재 데이터베이스의 마지막 TIMESTAMP값 반환 |
구성 함수 | 설명 |
---|---|
@@CURSOR_ROWS | 커넥션에서 커서가 마지막으로 오픈한 로우의 개수 |
@@ROWCOUNT | 구문 실행이 반영된 로우의 개수 |
@@FETCH_STATUS | 현재 오픈된 커서를 FETCH한 후 상태값 반환 |
@@IDENTITY | 테이블이 IDENTITY 컬럼을 가질때, 이 값이 마지막 INSERT된 후의 IDENTITY 값을 반환 |
@@NESTLEVEL | 저장 프로시저를 실행할때, 프로시저 내에서 호출이 중첩된 수를 반환 |
SELECT @@CONNECTIONS '커넥션 맺은 회수'; SELECT * from Northwind..Customers; SELECT @@ROWCOUNT;
일괄 처리
SQL서버는 여러개의 SQL을 묶어서 한번에 처리할수있다.
이 묶음을 배치(BATCH)라고 한다.
하나의 SQL문의 마지막을 표시하는 것을 세미콜론 “;”으로 할수있다.(반드시 할필요는 없다)
SELECT * FROM Northwind..Customers; SELECT * FROM Northwind..Shippers;
하나의 묶음 작업을 구분하기 위해서는 “GO” 명령을 이용한다.
SELECT * FROM Northwind..Shippers
이 문장은 사실 이런것이다.
SELECT * FROM Northwind..Shippers; go
일괄 처리는 헷갈리기 쉽다.
SQL서버는 여러개의 SQL문을 일괄 처리로 보내면, 이 일괄 처리문을 하나의 실행계획(Execution Plan)으로 변환한다.
그리고 이 실행계획을 수행하게 된다. 예를 들어
“SELECT … GO SELECT … GO” 문장은 두개의 실행계획이 수행되는것이고, “SELECT … SELECT … GO” 는 하나의 실행계획이 수행되는 것이다.
이러한 일괄처리는 구문분석중 문법오류나 개체 오류와 같은것이 발생하면, 실행계획 전체가 취소된다.
select * from Northwind..Categories select * from3 Northwind..Categories go
하지만 go 문장을 첫번째 실행문 다음에 두면 두개의 배치로 나뉘어 지므로 첫번째 문장은 정상적으로 수행된다.
select * from Northwind..Categories go select * from3 Northwind..Categories
GO문의 장점중 하나는, GO 뒤에 숫자를 지정하면 지정된 숫자만큼 일괄배치를 반복할수 있는것이다.
이것은 일종의 더미테이블을 만들때 매우 유용하다. 어느 테이블에 100개의 INSERT 문을 수행하고자 한다면 아주 간단히 만들수 있다.
CREATE TABLE k(id INT IDENTITY(1,1), v CHAR(1)) GO INSERT k VALUES('a') GO 300 SELECT COUNT(*) FROM k GO
T-SQL 제어문
BEGIN … END
수행블록을 지정한다.({}와 비슷한 개념)
IF ELSE
프로그램과 같이 중복해서 쓸수도 있으며, 적용구문이 한줄일경우 BEGIN END 구문을 따로 적지 않아도 된다.
DECLARE @GENDER NCHAR(1) SET @GENDER = N'남' IF @GENDER = '남' BEGIN SELECT '남자' END ELSE BEGIN SELECT '여자' END IF @GENDER = '남' SELECT '남자' ELSE SELECT '여자'
CASE
프로그램의 swich 문으로 보면되며, 문법이 약간 다르므로 주의해야 한다.
DECLARE @AGE INT SET @AGE = 40 SELECT( CASE @AGE WHEN 10 THEN '10대' WHEN 20 THEN '20대' WHEN 30 THEN '30대' WHEN 40 THEN '40대' ELSE '기타' END ) SELECT( CASE WHEN @AGE = 10 THEN '10대' WHEN @AGE = 20 THEN '20대' WHEN @AGE = 30 THEN '30대' WHEN @AGE = 40 THEN '40대' ELSE '기타' END )
WHILE
프로그램의 WHILE 문과 비슷하다.
DECLARE @I INT DECLARE @TOTAL INT SET @I = 1 SET @TOTAL = 0 WHILE(@I <= 100) BEGIN SET @TOTAL = @TOTAL + @I SET @I = @I + 1 IF @I > 10 BREAK END SELECT @TOTAL
RETURN
반환하고 프로그램 제어를 되돌린다. 즉 수행을 종료한다고 볼수있다. 보통 프로시저나 함수등을 만들때 사용된다. RETURN 문 이후에는 수행되지 않는다. 그리고 RETURN문 다음에는 값을 반환할수 있다.
다만 일반 일괄처리에서는 값을 반환할수 없으므로 구문오류가 발생된다.
DECLARE @I INT SET @I = 10 SELECT @I AS FIRST RETURN SET @I = 20 SELECT @I AS LAST
GOTO
이 문장을 만나면 지정된 레이블로 제어를 이동한다. SQL2005이전버전은 TRY CATCH 문이 지원되지 않으므로 이 문구를 쓰는 수밖에 없엇다.
DECLARE @I INT SET @I = 0 WHILE 1=1 BEGIN SET @I = @I + 1 IF @I =99 GOTO MyErr END MyErr: SELECT @I
위 문장에서 WHILE 1=1 를 써서 항상 참인 조건으로 BREAK 구문없이 무한루프를 돌렸지만 @I 값이 99 일경우 수행이 종료 된다.
이것은 조건에서 MyErr 레이블로 분기했기 때문이다.
레이블은 변수명처럼 사용하고 뒤에 콜론 “:”을 붙여 사용한다. 특별히 선언하지 않아도 된다. 호출시에는 콜론을 붙이지 않는다.
WAITFOR
- WAITFOR TIME ‘지정시간’ – 하루의 지정된 시간까지 대기한다.
- WAITFOR DELAY ‘지연시간’ – 지연시간 후에 프로그램을 수행한다.
지정된 시간동안 프로그램을 SLEEP(대기) 상태로 놓아둔다. 지정된 시간이 끝나면 이후 코드블럭을 수행한다.
WHILE 문을 이요하여 일종의 대기상태로 만들수도 있지만, WAITFOR문은 더 정확하게 대기시간을 지정할수 있다.
“시:분:초” 값을 지정하면 된다.
하지만 이러한 대기문은 SQL 서버에서 매우 치명적인 문제를 일으킬수 있다. SQL서버는 동시에 엄청난 수의 트랜잭션들을 처리하는데, 이런 대기상황이 오래되면 SQL서버 성능에 영향을 미치게 된다.
이러한 이유로 커서가 오픈된 상황이나 뷰 등에서는 이 문장을 사용할수없다. 그리고 SQL 서버는 예약작업이라는 에이전트가 있으니 굳이 이구문을 쓰지 않아도 된다.
DECLARE @I INT SET @I = 0 WHILE @I <= 10 BEGIN WAITFOR DELAY '00:00:01' SELECT DATEPART(S,GETDATE()) 수행시각 SET @I = @I + 1 END
위 문장은 1초마다 특정쿼리를 수행시키는 문장이다. 10번만 실행된다.
TRY CATCH
TRY CATCH문은 자바나 닷넷 언어에 주로 자주쓰이는데 구문도 비슷하다.
DECLARE @I INT BEGIN TRY SET @I = 'DDDD' END TRY BEGIN CATCH SET @I = 0 PRINT '나누기 에러' END CATCH
오류 함수 | 설명 |
---|---|
ERROR_NUMBER() | 에러번호 |
ERROR_MESSAGE() | 에러 메세지 |
ERROR_SEVERITY() | 에러 심각도 |
ERROR_STATE() | 에러 상태 |
ERROR_LINE() | 에러 발생 행 번호 |
ERROR_PROCEDURE() | 에러 발생 저장 프로시저 혹은 트리거 |
DECLARE @I INT BEGIN TRY SET @I = 'DDDD' END TRY BEGIN CATCH SET @I = 0 PRINT '에러 번호: ' + CAST(ERROR_NUMBER() as varchar) PRINT '에러 메세지: ' + ERROR_MESSAGE() PRINT '에러 심각도: ' + CAST(ERROR_SEVERITY() as varchar) PRINT '에러 행번호: ' + CAST(ERROR_LINE() as varchar) PRINT '에러 프로시저: ' + ISNULL(ERROR_PROCEDURE(), '없음' ) END CATCH
No Comments