참고로 CRUD란... Create Retrieve Update Delete의 머리 글자에서 따온 용어입니다.
발판 코드의 잇점을 나열하면 이렇습니다.
1. 테이블 별로 INSERT, SELECT, UPDATE, DELETE 작업을 수행하는 SP를 빠르게 작성할 수 있다.
2. 주석, 변수 명명, 에러 핸들링과 같은 코딩 규칙을 통일 할 수 있다.
3. 테이블의 컬럼 정의를 SP의 파라미터 정의에 재활용하여 주석 작성 시간을 줄여준다.
제 경험으로보면, 통상 테이블 수의 3 ~ 4배 가량의 Stored Procedure가 만들어집니다.
(그 이상이라면 SP가 적절히 추상화되지 못했기 때문일 겁니다.)
그 중 50% 이상이 단순 CRUD 작업이라는 점을 생각해보면, 발판 코드의 잇점을 쉽게 이해할 수 있습니다.
이제 Demo DB를 사용하여 실습을 해보도록 하겠습니다.
만들어 볼 SP는 "기사 카테고리 추가"입니다.
ERD를 기억하신다면, 이 작업이 dbo.Categories테이블에 INSERT하는 프로세스임을 쉽게 짐작하실 수 있을 겁니다.
먼저 테이블의 레이아웃을 조회해 봅시다. (테이블이 어떻게 생겼는지 감을 잡기 위해~)
저는 Ctrl + 5 단축키에 sp_helptable을 등록했으므로, Categories라는 테이블 이름을 타이핑하고 선택한 후 단축키를 누릅니다. (또는 EXEC dbo.sp_helptable Categories 를 실행)
실행 결과는 아래와 같습니다.
이제 발판 코드를 생성합니다.
제 단축키 설정으로는 Ctrl + 7이므로, 테이블 레이아웃을 조회할 때와 마찮가지로... Categories라고 타이핑 후 선택하고 단축키를 누릅니다.
단축키 설정을 하지 않았다면 아래와 같은 형태로 직접 작성하고 실행해야 합니다.
- 단축키 설정하시길 강력히 권합니다. (http://purumae.tistory.com/59 하단) 참조
EXEC dbo.sp_mkScaffold @nvcAuthorName=N'doeyull.kim'
, @nvcAuthorEmail=N'purumae@gmail.com'
, @nvcTableName=N'Categories'
실행 결과는 아래와 같습니다.
Messages 탭에 CRUD 발판 코드가 출력되는 것을 볼 수 있습니다.
(제공하는 소스는 Create 1개, Retrieve 4개, Update 1개, Delete 1개.. 총 7개입니다.)
1. 일단 Create 블럭의 소스를 편집창에 복사 - 붙여넣기합니다.
2. Ctrl + Shift + M을 누르고 아래와 같이 SP이름과 설명을 기입합니다.
생성된 SP 코드를 살펴보겠습니다.
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
USE Demo;
GO
IF OBJECT_ID(N'dbo.P_AddCategory', N'P') IS NOT NULL
DROP PROCEDURE dbo.P_AddCategory;
GO
/**
author : doeyull.kim
e-mail : purumae@gmail.com
created date : 2009-03-31
description : 기사카테고리를추가합니다.
return value :
0 = 에러가없습니다.
1 = 트랜잭션을Commit할수없는상태입니다. 트랜잭션을Rollback합니다.
100 = 시스템에러가발생하였습니다. dbo.ErrorLogs 테이블을조회하세요.
**/
CREATE PROCEDURE dbo.P_AddCategory
@intTopCategoryID int --// 최상위기사카테고리일련번호.
, @intParentCategoryID int --// 상위기사카테고리일련번호.
, @nvcCategoryName nvarchar(100) --// 기사카테고리이름.
, @intCategoryLevel int --// 기사카테고리계층깊이.
, @intSortNumber int --// 동일깊이의카테고리에서의정렬순서.
, @intCategoryID int = NULL OUTPUT --// 기사카테고리일련번호.
WITH EXECUTE AS 'SPExecutor'
AS
SET NOCOUNT ON;
SET XACT_ABORT ON;
DECLARE @intReturnValue int;
/**_# Rollback and return if inside an uncommittable transaction.*/
IF XACT_STATE() = -1
BEGIN
SET @intReturnValue = 1;
GOTO ErrorHandler;
END
BEGIN TRY
/**_# [Categories] 테이블에INSERT합니다.*/
INSERT dbo.Categories (topCategoryID, parentCategoryID, categoryName, categoryLevel, sortNumber)
VALUES (@intTopCategoryID, @intParentCategoryID, @nvcCategoryName, @intCategoryLevel, @intSortNumber);
SET @intCategoryID = SCOPE_IDENTITY();
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 547 AND ERROR_MESSAGE() LIKE N'%FK_%'
SET @intReturnValue = ;
ELSE IF ERROR_NUMBER() = 547 AND ERROR_MESSAGE() LIKE N'%FK_%'
SET @intReturnValue = ;
ELSE IF ERROR_NUMBER() = 2627 AND ERROR_MESSAGE() LIKE N'%PK_%'
SET @intReturnValue = ;
ELSE IF ERROR_NUMBER() = 2601 AND ERROR_MESSAGE() LIKE N'%IX_UN_%'
SET @intReturnValue = ;
GOTO ErrorHandler;
END CATCH;
RETURN 0;
ErrorHandler:
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
IF @intReturnValue IS NULL OR @intReturnValue = 0
EXEC @intReturnValue = dbo.P_AddErrorLog;
RETURN @intReturnValue;
GO
게다가 처음 사용할 때는 익숙하지도 않죠.
하지만, 제가 Sequel Safe를 만들고 팀원들에게 공유했을 때 모두 빠른 속도로 적응 할 수 있었습니다.
필요한 것은 관심과 노력입니다.
3. 발판 코드를 수정한 프로덕트 코드는 이렇습니다.
- 파라미터를 가감하고, 로직을 추가하고, CATCH블럭을 완성하면 됩니다.
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
USE Demo;
GO
IF OBJECT_ID(N'dbo.P_AddCategory', N'P') IS NOT NULL
DROP PROCEDURE dbo.P_AddCategory;
GO
/**
author : doeyull.kim
e-mail : purumae@gmail.com
created date : 2009-03-31
description : 기사카테고리를추가합니다.
return value :
0 = 에러가없습니다.
1 = 트랜잭션을Commit할수없는상태입니다. 트랜잭션을Rollback합니다.
100 = 시스템에러가발생하였습니다. dbo.ErrorLogs 테이블을조회하세요.
101 = 상위기사카테고리가존재하지않습니다.
**/
CREATE PROCEDURE dbo.P_AddCategory
@intParentCategoryID int = NULL --// 상위기사카테고리일련번호.
, @nvcCategoryName nvarchar(100) --// 기사카테고리이름.
, @intCategoryID int = NULL OUTPUT --// 기사카테고리일련번호.
WITH EXECUTE AS 'SPExecutor'
AS
SET NOCOUNT ON;
SET XACT_ABORT ON;
DECLARE
@intReturnValue int
, @intTopCategoryID int
, @intCategoryLevel int
, @intSortNumber int;
/**_# Rollback and return if inside an uncommittable transaction.*/
IF XACT_STATE() = -1
BEGIN
SET @intReturnValue = 1;
GOTO ErrorHandler;
END
BEGIN TRY
BEGIN TRANSACTION;
/**_# @intParentCategoryID 인풋값이NULL이면, 최상위카테고리의등록을의미합니다.*/
IF @intParentCategoryID IS NULL
SET @intCategoryLevel = 1;
/**_# @intParentCategoryID 인풋값이있으면, 지금등록하는카테고리의레벨은상위카테고리의레벨+ 1입니다.*/
ELSE
SELECT @intCategoryLevel = (categoryLevel + 1), @intTopCategoryID = topCategoryID
FROM dbo.Categories WITH (UPDLOCK)
WHERE categoryID = @intParentCategoryID;
/**_# [Categories] 테이블에INSERT합니다.*/
INSERT dbo.Categories (topCategoryID, parentCategoryID, categoryName, categoryLevel, sortNumber)
SELECT NULL, @intParentCategoryID, @nvcCategoryName, @intCategoryLevel, ISNULL(MAX(sortNumber), 0) + 1
FROM dbo.Categories WITH (TABLOCKX)
WHERE categoryLevel = @intCategoryLevel;
SET @intCategoryID = SCOPE_IDENTITY();
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 547 AND ERROR_MESSAGE() LIKE N'%FK_Categories_Categories%'
SET @intReturnValue = 101;
GOTO ErrorHandler;
END CATCH;
RETURN 0;
ErrorHandler:
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION;
IF @intReturnValue IS NULL OR @intReturnValue = 0
EXEC @intReturnValue = dbo.P_AddErrorLog;
RETURN @intReturnValue;
GO
EXEC dbo.sp_helpmodule을 실행하면, 지금 추가한 P_AddCategory가 문서화되어 출력됩니다.
CRUD 하나 하나를 상세히 다루는 것은 부득이 생략하도록 하겠습니다.
문의 사항이 있으시다면, 댓글을 달아 주시거나 purumae@gmail.com으로 연락 주십시오.
'SQL Server > SQL Server 형상 관리' 카테고리의 다른 글
[Sequel Safe] SQL 서버 Login 권한 정책 및 물리 모델 변경 제약 (6) | 2009.04.11 |
---|---|
[Sequel Safe] Programmability 버전 관리 (3) | 2009.04.11 |
[Sequel Safe] 에러 핸들링 (下) (3) | 2009.04.11 |
[Sequel Safe] 에러 핸들링 (上) (0) | 2009.04.10 |
[Sequel Safe] SP 작성 규칙 (0) | 2009.04.03 |