我尝试为cdc函数的结果创建索引视图。原始查询庞大而复杂。下面是生成相同错误的查询的简化版本:
SET NUMERIC_ROUNDABORT OFF;
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT,
QUOTED_IDENTIFIER, ANSI_NULLS ON;
GO
--Create view with schemabinding.
IF OBJECT_ID ('dbo.view_Test', 'view') IS NOT NULL
DROP VIEW dbo.view_Test;
GO
CREATE VIEW dbo.view_Test
WITH SCHEMABINDING
AS
SELECT
kz.__$start_lsn,
kz.__$seqval,
kz.__$operation AS operation,
kz.__$update_mask,
kz.GUID,
kz.typezalezh,
kz.category,
kz.zone,
kz.area,
kz.Volume
FROM cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh(sys.fn_cdc_get_min_lsn('dbo_EXT_GeolObject_KategZalezh'), sys.fn_cdc_get_max_lsn(), 'all') AS kz
GO
此查询返回以下错误:
无法架构绑定视图'dbo.view_Test'。 'cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh'不是 架构绑定。
我读了那个
如果要在视图上创建索引,或者要保留视图 在这两种情况下,一旦定义了视图,就会生成基表模式 您必须使用“WITH SCHEMABINDING”子句将视图绑定到 基表的模式
在原始查询中我使用dbo
和cdc
架构,我只使用cdc
架构。但我想在dbo
dchema创建视图。
此外,我正在使用CDC功能,而不是像微软推荐的那样直接使用cdc表。
我在阅读创建索引视图时需要考虑的一些事项:
据我了解,我的查询符合此规则。但我不确定CDC功能是确定性还是不确定性。
是否可以为使用CDC功能的查询创建“索引视图”?
答案 0 :(得分:1)
不,CDC功能不是“架构绑定”,因此依赖于它的视图根本无法编入索引。相反,您可以创建一个表并定期从函数中填充它。
假设您有启用CDC的表“testdb.dbo.Customers_for_cdc_test”。您可以通过代码实现CDC功能:
use testdb
go
select top (0) *
into dbo.SOURCE_NAME_changes
from cdc.fn_cdc_get_all_changes_dbo_Customers_for_CDC_test
(
sys.fn_cdc_get_min_lsn('dbo_Customers_for_cdc_test')
, sys.fn_cdc_get_max_lsn()
, N'all'
) as src
;
create index IX__dbo__SOURCE_NAME_changes
on dbo.SOURCE_NAME_changes
(
__$start_lsn asc
)
;
-- Other needed indices can be here.
go
表填充可以作为作业实现。设置定期启动的作业计划。作业本身可能只包含一个调用填充程序的步骤
use testdb
go
exec dbo.sp_append_new_SOURCE_NAME_changes
“dbo.sp_append_new_SOURCE_NAME_changes”是
use testdb
go
create procedure dbo.sp_append_new_SOURCE_NAME_changes
as
begin
set nocount on
;
declare @max_old_lsn as binary(10)
, @min_old_lsn as binary(10)
, @min_active_lsn as binary(10) = sys.fn_cdc_get_min_lsn('dbo_Customers_for_CDC_test')
, @max_active_lsn as binary(10) = sys.fn_cdc_get_max_lsn()
;
select @max_old_lsn = coalesce(max(__$start_lsn) ,cast(0 as binary(10)))
, @min_old_lsn = coalesce(min(__$start_lsn) ,cast(0 as binary(10)))
from dbo.SOURCE_NAME_changes
;
if (@min_old_lsn < @min_active_lsn
) begin
delete from dbo.SOURCE_NAME_changes
where __$start_lsn < @min_active_lsn
;
end
if (@max_old_lsn < @max_active_lsn
) begin
declare @min_lsn as binary(10) = iif(@min_active_lsn < @max_old_lsn ,@max_old_lsn ,@min_active_lsn) -- Speed up
;
insert into dbo.SOURCE_NAME_changes
--(COLUMN_LIST)
select * --(COLUMN_LIST)
from cdc.fn_cdc_get_all_changes_dbo_Customers_for_CDC_test
(
@min_lsn
, @max_active_lsn
, N'all'
) as src
where src.__$start_lsn > @max_old_lsn -- Because the max old lsn is already in.
;
end
end
go