SQL Server のトランザクションは、try キャッチに記述しなければ、中間ステートメントがエラーを報告してもコミットされます。
データベースにPersonとBookの2つのテーブルがある場合
Personテーブル。
CREATE TABLE [dbo]. [Person](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Code] [nvarchar](50) NULL,
[Name] [nvarchar](50) NULL,
[CreateTime] [datetime] NULL,
[UpdateTime] [datetime] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[ID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo]. [Person] ADD CONSTRAINT [DF_Person_CreateTime] DEFAULT (getdate()) FOR [CreateTime]
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_Person] ON [dbo]. [Person].
(
[Code] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ブックテーブルです。
CREATE TABLE [dbo]. [Book](
[ID] [int] IDENTITY(1,1) NOT NULL,
[BookCode] [nvarchar](50) NULL,
[BookName] [nvarchar](50) NULL,
[PersonCode] [nvarchar](50) NULL,
CONSTRAINT [PK_Book] PRIMARY KEY CLUSTERED
(
[ID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo]. [Book] WITH CHECK ADD CONSTRAINT [FK_Book_Person] FOREIGN KEY([PersonCode])
REFERENCES [dbo]. [Person] ([Code])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo]. [Book] CHECK CONSTRAINT [FK_Book_Person]
GO
PersonテーブルとBookテーブルは1対多の関係で、Personは複数のBookを持つことができるので、BookテーブルのPersonCode列はPersonテーブルのCode列を指す外部キーであり、必須制約であり、BookテーブルのPersonCode列の値はPersonテーブルのCode列の値でなければならないことを示していることがわかるでしょう。そうでない場合、SQL Server は次のようなエラーを報告します。
ここで、2つのテーブルにデータを挿入するために、次のステートメントを実行します。トランザクション トランザクションで Person テーブルと Book テーブルに 2 つの Insert ステートメントを記述しており、1 つの Insert が失敗しても、もう 1 つの Insert は失敗しないという理屈になっています。
BEGIN TRAN
INSERT INTO Person([Code],[Name])
VALUES('P003','Jack')
INSERT INTO [dbo]. [Book]([BookCode],[BookName],[PersonCode])
VALUES
('B001','B001','P003'),
('B002','B002','P003'),
('B003','B003','P003'),
('B004','B004','P003'),
('B005','B005','XXX') - Since the [PersonCode] column value 'XXX' of the Book table does not exist in the [Code] column of the Person table, the entire INSERT INTO [dbo]. [Book] statement will report an error and not execute
COMMIT
Person テーブルの [Name] 列に値 "XXX" が存在しないので、INSERT INTO [dbo].Person テーブルの [Name] 列に値 "XXX" を挿入しました。Book] 文はエラーを報告して実行されませんでしたが、INSERT INTO Person がトランザクション Commit と共にコミットされたことに驚きました。Personテーブルのデータは正常に挿入されました。
(1 row affected)
Message 547, level 16, status 0, line 7
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Book_Person". The conflict occurred in database "TestDB", table "dbo.Person", column 'Code'.
The statement has been terminated.
Personテーブルのデータを問い合わせる。
Bookテーブルのデータを問い合わせる。
これは、INSERT INTO [dbo]. [Book] ステートメントはエラーで実行されませんでしたが、一番下の Commit ステートメントが実行されたため、INSERT INTO [dbo]. [Book]ステートメントは、その後のCommitステートメントの実行を妨げなかったので、INSERT INTO Personステートメントは、トランザクションがデータベースにコミットされたときに有効になった。
ここで、上記のステートメントを以下のように変更し、両方のInsertステートメントをtryキャッチに入れます。
BEGIN TRAN
BEGIN TRY
INSERT INTO Person([Code],[Name])
VALUES('P003','Jack')
INSERT INTO [dbo]. [Book]([BookCode],[BookName],[PersonCode])
VALUES
('B001','B001','P003'),
('B002','B002','P003'),
('B003','B003','P003'),
('B004','B004','P003'),
('B005','B005','XXX') - Since the [PersonCode] column value 'XXX' of the Book table does not exist in the [Code] column of the Person table, the entire INSERT INTO [dbo]. [Book] statement will report an error and not execute
COMMIT
END TRY
BEGIN CATCH
ROLLBACK
END CATCH
実行後、次に Person テーブルにデータを問い合わせます。
Bookテーブルのデータを問い合わせる。
今回は予想通り、INSERT INTO [dbo]の後であることがわかります。Book]ステートメントがエラーを報告した後、その後のCommitステートメントは実行されず、Rollback in catchが実行され、最後には両方のテーブルのデータがデータベースに挿入されません。
関連
-
MySQL Innodb インデックスメカニズム詳細解説
-
MySQLのWhereの使用方法について説明します。
-
SQL集計、グループ化、ソート
-
SpringBootのMySQLへの接続は、バックエンドのインターフェイスの操作方法を書き込むためのデータを取得するために
-
MySQLインストールチュートリアル(Linux版
-
[解決済み】マルチパート識別子をバインドできませんでした。
-
[解決済み】SQLサーバーのテンポラリーテーブルで「すでに名前のついたオブジェクトがあります」エラーが発生する。
-
MySQLにおけるvarchar型とchar型の違い
-
SQLException。オペランドは1列でなければなりません。
-
mysql がエラーを報告します。不明な文字セットです。'utf8mb4'
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ジョイントインデックスのためのmysqlの条件とインデックスが失敗するための条件
-
MySqlの整数インデックスと文字列インデックスの失敗または暗黙の変換問題
-
Mysqlデータベースの手動および定期的なバックアップ手順
-
MySQL インタビューの質問 - ハッシュインデックスを設定する方法
-
MySQLデータベースで数百万件のデータを10秒間で挿入
-
[解決済み】DynamoDB : 提供されたキー要素がスキーマと一致しません。
-
mysql5.7のインストールと、無料・長期利用を目的としたNavicateの導入プロセスについて
-
MySQLの一般的な分割ライブラリおよび分割テーブルスキームの概要
-
Mysqlデータベースへのリンク時にpymysqlがConnection refusedエラーを報告する
-
msql クエリでのエラー 'where 節' の不明な列 'yellow fruit'