質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

1回答

4259閲覧

SQL Server トリガーの複数行更新(挿入)

Chandler_Bing

総合スコア673

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2021/10/19 14:32

編集2022/01/12 10:55

SQL

1ALTER TRIGGER [dbo].[trTest] ON [dbo].[table_1] 2AFTER INSERT, UPDATE 3 4AS 5BEGIN 6 7--パラメータを指定 table_1 8DECLARE @VarA varchar(50) 9DECLARE @IntB int 10 11--トリガ内で処理された行数を示すメッセージが結果セットの一部として返されないようにします。 12SET NOCOUNT ON; 13 14SELECT 15@VarA = A 16, @IntB = B 17FROM inserted 18 19PRINT @VarA --OK 20 21--存在している場合 22If Exists 23 (SELECT * FROM dbo.table_2 WHERE A = @VarA) 24 If Exists 25 (SELECT * FROM dbo.table_2 WHERE A = @VarA) 26 AND 27 (@IntB = 1 OR 28 @IntB = 2) 29 BEGIN 30 UPDATE dbo.table_2 31 SET B = @IntB 32 WHERE (A = @VarA) 33 END 34--存在していない場合 35ELSE 36 BEGIN 37 --table_2へインサート 38 INSERT INTO 39 dbo.table_2 (A, B) 40 SELECT A,B 41 FROM dbo.table_1 42 WHERE (A = @VarA) 43 END 44END

上記のような処理があります。

概要
table_1とtable_2の同期処理(table_1にトリガ-)

処理①
table_1.Aとtable_2.Aが同じレコードがあれば、
table_1.Bの値が1か2の時、table_2.B = table_1.Bとする

処理②
table_1.Aとtable_2.Aが同じレコードがなければ、
table_1のレコードをtable_2のインサートする

現在以の問題があります。

★問題1★
トリガーが仕込んである、table_1に一気に2件レコードを追加しても1回しかトリガーが実行されていない
(PRINTが1回しかコンソールに表示されませんでした。。。。)

どうかご教授のほどよろしくお願いします。

SQL

1--回答を参考にソースを修正 2CREATE TRIGGER trTest ON table_1 3AFTER INSERT, UPDATE 4 5AS 6BEGIN 7 8--トリガ内で処理された行数を示すメッセージが結果セットの一部として返されないようにします。 9SET NOCOUNT ON; 10 11UPDATE table_2 12SET B = (SELECT B 13 FROM inserted 14 WHERE table_2.A 15 = inserted.A) 16WHERE table_2.A IN 17 (SELECT A FROM inserted); 18 19END 20 21 22delete from [dbo].[table_1]; --全削除 23 24insert into [dbo].[table_1] 25select * from [dbo].[wk_table_1]; --トリガー発火のためレコードを挿入
--テーブル定義(table_1、tqble_2、wk_table_1) USE [XXXXXX] GO /****** Object: Table [dbo].[table_1] Script Date: 2021/10/19 16:12:37 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE TABLE [dbo].[table_1]( [A] [varchar](50) NOT NULL, [B] [int] NULL, CONSTRAINT [PK_table_1] PRIMARY KEY CLUSTERED ( [A] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO ALTER TABLE [dbo].[table_1] ADD CONSTRAINT [DF_table_1_B] DEFAULT (0) FOR [B] GO --テストデータ insert into dbo.wk_table_1 values ('00001', 1); --A(主キー), B values ('00002', 2); --A(主キー), B

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2021/10/20 00:45

実際にそれが再現する情報を提供して下さい。 具体的には、テーブルの定義と、データ投入用のスクリプト。 実際のテーブルでは無くてテスト用に作成するのが良いでしょう。 また、それをすることにより、原因対象のスコープの判別にもなります。
Chandler_Bing

2021/10/20 01:38

動作確認用に使用したデータになります。 ご教授のほどよろしくお願いします。
sazi

2021/10/20 02:01 編集

テーブルの定義も追記して下さい。それから確認用のデータは2件ではないのですか? 尚、その情報を使用して手元で再現するのを確認したものにして下さい。
Chandler_Bing

2021/10/20 02:10

UPDATEしか記載していないので、INSET INTO が実行できるとは思えないのですが
guest

回答1

0

トリガーが仕込んである、table_1に一気に2件レコードを追加しても1回しかトリガーが実行されていない

トリガーの動きとしては正しそうです。
トリガーとしては1回呼ばれ、その際に inserted テーブルに複数行入っている為と思います。

<参考>
■ 複数行のデータを処理するための DML トリガーの作成
https://docs.microsoft.com/ja-jp/sql/relational-databases/triggers/create-dml-triggers-to-handle-multiple-rows-of-data

<追記>
参考までにトリガーのコードを書いてみました。以下のような感じでどうでしょうか?(ちゃんと検証していないので間違いがあるかもしれません。)

SQL

1ALTER TRIGGER [dbo].[trTest] ON [dbo].[table_1] 2AFTER INSERT, UPDATE 3 4AS 5BEGIN 6 7 SET NOCOUNT ON; 8 9 --存在している場合 10 If EXISTS (SELECT * FROM dbo.table_2 WHERE A IN (SELECT A FROM inserted) AND (B = 1 OR B = 2)) 11 BEGIN 12 --table_2を更新 13 UPDATE dbo.table_2 14 SET B = inserted.B 15 FROM 16 inserted 17 WHERE 18 table_2.A = inserted.A 19 AND (inserted.B = 1 OR inserted.B = 2) 20 END 21 22 --存在していない場合 23 If NOT EXISTS (SELECT * FROM dbo.table_2 WHERE A IN (SELECT A FROM inserted)) 24 BEGIN 25 --table_2へインサート 26 INSERT INTO 27 dbo.table_2 (A, B) 28 SELECT A,B 29 FROM dbo.table_1 30 WHERE A NOT IN (SELECT A FROM dbo.table_2) 31 END 32 33END

投稿2021/10/19 14:49

編集2021/10/20 03:09
cx20

総合スコア4632

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chandler_Bing

2021/10/19 14:57

PurchaseOrderHeaderというテーブルを作成していますが、 よけいなテーブルを作成せずに、table_1だけで管理したいのですが、それは無理な感じなのでしょうか?
cx20

2021/10/19 17:26

参考サイトの例だと PurchaseOrderDetail が table_1 相当、 PurchaseOrderHeader が table_2 相当 という感じかと思います。 トリガの中では table_1 の変更分のレコードが inserted テーブルとして入ってくるので、 それを使って table_2 に対して UPDATE / INSERT したら良いかと思います。
Chandler_Bing

2021/10/19 23:43

なるほど、一度ためしてみます。
Chandler_Bing

2021/10/20 00:26

お世話になります。 試してみたのですが、インサートされません。 ソースをはりましたので、確認いただけますでしょうか??
Chandler_Bing

2021/10/20 00:37 編集

table_2にレコードをあらかじめセットした状態だとうまく変更されてくれます。。。。 インサートには対応できないのでしょうか?
cx20

2021/10/20 03:09

サンプルを回答に追記しました。
Chandler_Bing

2021/10/23 11:34

いつもお世話になっております。 ためしてみます! 回答してから時間が経過しているので、もしかするとまた新たに質問させて頂くかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問