MSDE FunClub | 最終更新日 : 2000/08/21 | |
Microsoft Data Engine FunClub |
|
|
SQLServer7.0/MSDE 完全トレーニングテキスト(上巻) | ||
【第8章475p 〜 479p掲載】 |
-- [SQL08_05.SQL] -- SQLServer7.0 Transact-SQL言語 -- 日本技術ソフト開発 堀川 明 -- http://www.horikawa.ne.jp/msde/ -- -- このSQLプログラムは、 -- トランザクションの入れ子構造 -- を理解します -- -- この[社員]テーブルは、AccessのNorthwindデモデータベース -- の[社員]テーブルをSQLServerに転送したものです -- -- カレントデータベースを MySampleTest にする USE MySampleTest GO -- (件処理されました)のメッセージを抑止する SET NOCOUNT ON GO -- ******************************************************************************* -- Transact-SQLスクリプトでは、バッチ間で情報伝達を行う手段が限られている -- ここでは、空白のエラーメッセージを登録し、そのエラーメッセージ番号を使った -- 情報伝達方法を紹介します -- RAISERROR命令を使うと、エラーメッセージ番号が@@ERRORに設定されることを利用する -- ******************************************************************************* --ユーザ定義のエラーメッセージを登録する --先に英語版を登録し、次に日本語版メッセージを登録する --メッセージ番号は sysmessagesテーブルの error列の最大値の次にしてもよい --ここでは、適当な番号としています IF EXISTS( SELECT error FROM master..sysmessages WHERE error = 60001 ) EXEC sp_dropmessage 60001,'all' --既存メッセージの削除 IF EXISTS( SELECT error FROM master..sysmessages WHERE error = 60002 ) EXEC sp_dropmessage 60002,'all' IF EXISTS( SELECT error FROM master..sysmessages WHERE error = 60003 ) EXEC sp_dropmessage 60003,'all' -- メッセージの内容を空白1個にすること EXEC sp_addmessage 60001,1,' ','us_english' EXEC sp_addmessage 60001,1,' ','日本語' EXEC sp_addmessage 60002,1,' ','us_english' EXEC sp_addmessage 60002,1,' ','日本語' EXEC sp_addmessage 60003,1,' ','us_english' EXEC sp_addmessage 60003,1,' ','日本語' GO -- レコード挿入位置にレコードがあれば削除します DELETE FROM 社員 WHERE( 社員コード BETWEEN 10 AND 20 ) GO -- ********************************************************* -- 【トランザクションの3重入れ子構造を理解します】 -- ********************************************************* DECLARE @OutFlag int , @MidFlag int , @InFlag int -- フラグが1のとき、ROLLBACKが行われます SELECT @OutFlag = 0 , @MidFlag = 0 , @InFlag = 0 PRINT '' PRINT ' @OutFlag=' + CAST(@OutFlag as varchar) + ' @midFlag=' + CAST(@MidFlag as varchar) + ' @InFlag =' + CAST(@InFlag as varchar) IF(@InFlag=1) PRINT '一番内側のトランザクション内でROLLBACKします' ELSE IF(@MidFlag=1) PRINT ' 中間 のトランザクション内でROLLBACKします' ELSE IF(@OutFlag=1) PRINT ' 外側 のトランザクション内でROLLBACKします' PRINT '' PRINT 'プログラム開始直後トランザクションネストレベル=' + CAST(@@TRANCOUNT AS varchar) -- 一番外側のトランザクション開始 BEGIN TRANSACTION OutTran PRINT '外側トランザクション開始 ネストレベル=' + CAST(@@TRANCOUNT AS varchar) INSERT INTO 社員(社員コード,フリガナ,氏名) VALUES(10,'ヤマダ イチロウ' , '山田 一郎') -- 中間のトランザクション開始 BEGIN TRANSACTION MidTran PRINT '中間トランザクション開始 ネストレベル=' + CAST(@@TRANCOUNT AS varchar) INSERT INTO 社員(社員コード,フリガナ,氏名) VALUES(11,'ヤマダ ジロウ' , '山田 二郎') -- 内側のトランザクション開始 BEGIN TRANSACTION InTran PRINT '内側トランザクション開始 ネストレベル=' + CAST(@@TRANCOUNT AS varchar) INSERT INTO 社員(社員コード,フリガナ,氏名) VALUES(12,'ヤマダ サブロウ', '山田 三郎') IF( @InFlag = 1 ) BEGIN -- ロールバックを行う -- 名前を付けるときは一番外側のトランザクション名 -- 名前は省略することができる ROLLBACK TRANSACTION OutTran PRINT '内側でROLLBACK 実行直後ネストレベル=' + CAST(@@TRANCOUNT AS varchar) -- エラー番号を@@ERROR外部変数にセットする -- WITH SETERRORオプションを忘れずに! RAISERROR(60001,0,1) WITH SETERROR RETURN END -- 内側のトランザクションをコミットする COMMIT TRANSACTION InTran PRINT '内側トランザクション終了後ネストレベル=' + CAST(@@TRANCOUNT AS varchar) IF( @MidFlag = 1 ) BEGIN -- ロールバックを行う -- 名前を付けるときは一番外側のトランザクション名 ROLLBACK TRANSACTION PRINT '中間でROLLBACK 実行直後ネストレベル=' + CAST(@@TRANCOUNT AS varchar) -- エラー番号を@@ERROR外部変数にセットする -- WITH SETERRORオプションを忘れずに! RAISERROR(60002,0,1) WITH SETERROR RETURN END -- 中間のトランザクションをコミットする COMMIT TRANSACTION MidTran PRINT '中間トランザクション終了後ネストレベル=' + CAST(@@TRANCOUNT AS varchar) IF( @OutFlag = 1 ) BEGIN -- ロールバックを行う -- 名前を付けるときは一番外側のトランザクション名 ROLLBACK TRANSACTION PRINT '外側でROLLBACK 実行直後ネストレベル=' + CAST(@@TRANCOUNT AS varchar) -- エラー番号を@@ERROR外部変数にセットする -- WITH SETERRORオプションを忘れずに! RAISERROR(60003,0,1) WITH SETERROR RETURN END -- 外側のトランザクションをコミットする COMMIT TRANSACTION OutTran PRINT '外側トランザクション終了後ネストレベル=' + CAST(@@TRANCOUNT AS varchar) GO -- ******************************* -- 直前のバッチの実行状態を調べる -- ******************************* DECLARE @Code int SELECT @Code = @@ERROR IF( @Code <> 0 ) BEGIN PRINT '直前のバッチは、エラーメッセージ番号 ' + CAST(@Code as varchar) + ' で終了しました' PRINT CASE @Code WHEN 60001 THEN '内側' WHEN 60002 THEN '中間' WHEN 60003 THEN '外側' END + 'トランザクションで ROLLBACK を実行しました' END GO -- ******************************* -- レコードの登録結果を表示 -- ******************************* DECLARE @社員コード int , @フリガナ varchar(20) , @氏名 varchar(20) DECLARE @Str社員コード varchar(4) , @strout varchar(80) DECLARE hC INSENSITIVE CURSOR FOR SELECT 社員コード,フリガナ,氏名 FROM 社員 WHERE( 社員コード BETWEEN 10 AND 20 ) -- カーソルを開いてレコードを表示する OPEN hC -- レコードはありますか? IF( @@CURSOR_ROWS = 0 ) BEGIN PRINT '*** レコードは存在しません ***' PRINT ' レコード登録に失敗!! ' GOTO L9999 END -- タイトル行の出力 EXEC master..xp_sprintf @strout OUTPUT , '[%.2s][%12s][%12s]' , 'NO' , 'フリガナ' , ' 氏 名 ' PRINT '' PRINT '**** 登録結果 ****' PRINT @strout -- 先頭行の取り出し FETCH NEXT FROM hC INTO @社員コード,@フリガナ,@氏名 -- 0の時は、正常に取得できました WHILE( @@FETCH_STATUS = 0 ) BEGIN -- 取り出し内容の編集とその出力 SELECT @Str社員コード = CONVERT(char(4),@社員コード) EXEC master..xp_sprintf @strout OUTPUT , '[%.2s][%12s][%12s]' , @Str社員コード , @フリガナ , @氏名 PRINT @strout -- 次行の取り出し FETCH NEXT FROM hC INTO @社員コード,@フリガナ,@氏名 END L9999: -- カーソルを閉じて破棄する CLOSE hC DEALLOCATE hC GO