我相信 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]。
有趣的是:以下方法确实有效:
- 首先插入 ID 为 1 & 2 的记录;
- 然后创建聚集索引;
- 然后插入ID为3的记录;
这当然不能解决我的问题,但很明显,在创建聚集索引后,索引视图有一些 WITH NOCHECK 约束处于活动状态。
欢迎任何想法