SQL Server のインデックス付きビューは、ベース テーブルへの挿入を正しく検証していないと思います。
シミュレートするには、次のことを考慮してください。
テーブルを作成:
CREATE TABLE [dbo].[table_e]
(
[id] [int] NOT NULL,
[module] [varchar](50) NULL,
[event] [varchar](50) NULL,
[params] [nvarchar](max) NULL,
CONSTRAINT [PK_table_e]
PRIMARY KEY CLUSTERED ([id] ASC)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
テーブルに入力
INSERT INTO [dbo].[table_e] ([id], [module], [event], [params])
VALUES (1, 'ModuleB', 'EventT', N'[{"type":"AccountId","value":"AccountX"},{"type":"AccountId","value":"AccountZ"},{"type":"Balance","value":10},{"type":"Balance","value":10}]'),
(2, 'ModuleB', 'EventT', N'[{"type":"AccountId","value":"AccountY"},{"type":"AccountId","value":"AccountX"},{"type":"Balance","value":20}]'),
(3, 'ModuleP', 'EventA', N'[{"type":"AccountId","value":"AccountZ"},{"type":"AccountId","value":"AccountY"},{"type":"Hash","value":"SomeHash"}]')
すべてが順調かどうかを確認する
SELECT *
FROM [dbo].[table_e] -- returning 3 out of 3
スキーマバインド ビューを作成する
CREATE VIEW [dbo].[iv_test]
WITH SCHEMABINDING
AS
SELECT
e.[id],
CAST(JSON_VALUE(e.[params], '$[0].value') AS CHAR(66)) AS [AccountAddress_From],
CAST(JSON_VALUE(e.[params], '$[1].value') AS CHAR(66)) AS [AccountAddress_To],
CAST(JSON_VALUE(e.[params], '$[2].value') AS DECIMAL (36)) AS [Amount_Transferred],
CAST(JSON_VALUE(e.[params], '$[3].value') AS DECIMAL (36)) AS [Amount_Fees]
FROM
[dbo].[table_e] e
WHERE
e.[module] = 'ModuleB' AND e.[event] = 'EventT'
GO
すべてが順調かどうかを確認する
SELECT *
FROM [dbo].[iv_test] -- returning 2 out of 3
テーブルを片付ける
DELETE FROM [table_e] --3 rows affected
クラスター化インデックスを作成してビューを具体化します。
CREATE UNIQUE CLUSTERED INDEX [PK_iv_test]
ON [dbo].[iv_test]([id] 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, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
ここで、以前と同じデータを追加してみてください
INSERT INTO [dbo].[table_e] ([id], [module], [event], [params])
VALUES (1, 'ModuleB', 'EventT', N'[{"type":"AccountId","value":"AccountX"},{"type":"AccountId","value":"AccountZ"},{"type":"Balance","value":10},{"type":"Balance","value":10}]'),
(2, 'ModuleB', 'EventT', N'[{"type":"AccountId","value":"AccountY"},{"type":"AccountId","value":"AccountX"},{"type":"Balance","value":20}]'),
(3, 'ModuleP', 'EventA', N'[{"type":"AccountId","value":"AccountZ"},{"type":"AccountId","value":"AccountY"},{"type":"Hash","value":"SomeHash"}]')
結果:INSERT
機能しません。クラスター化インデックスの作成が次のINSERT
エラーでブロックされています:
メッセージ 8115、レベル 16、状態 6、行 105
nvarchar をデータ型数値に変換中に算術オーバーフロー エラーが発生しました。ステートメントは終了されました。
ここで何が起きてるの?
インデックス付きビュー ege[module_id] = 'Balances' AND e.[event_id] = 'Transfer' に適用された where 句が適用されていないようです。
結果として、ベース テーブルに挿入されたすべてのデータはビュー [iv_test] に対してチェックされますが、私の意見では、ビュー [iv_test] で指定された WHERE 条件を満たす挿入されたデータのみが、ビュー [iv_test] の形式に対してチェックされます [ iv_test]。
面白いことに、次のアプローチは機能します。
- 最初に ID 1 & 2 のレコードを挿入します。
- 次に、クラスター化インデックスを作成します。
- 次に、ID 3 のレコードを挿入します。
もちろん、これで問題は解決しませんが、クラスター化インデックスを作成した後、インデックス付きビューに対してアクティブな WITH NOCHECK 制約があることが明らかになります。
どんな考えでも大歓迎です