1

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 制約があることが明らかになります。

どんな考えでも大歓迎です

4

1 に答える 1