Tsql 是否可以创建;“索引视图”;查询在哪里使用CDC函数?

Tsql 是否可以创建;“索引视图”;查询在哪里使用CDC函数?,tsql,indexing,view,sql-server-2012,cdc,Tsql,Indexing,View,Sql Server 2012,Cdc,我正在尝试为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 ('db

我正在尝试为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\u Test”。 “cdc.fn_cdc_get_all_changes_dbo_EXT_GeolObject_KategZalezh”不是 模式绑定

我读到了

如果要在视图上创建索引或要保留 在这两种情况下,定义视图后的基表架构 必须使用“WITH schemabind”子句将视图绑定到 基表的模式

在原始查询中,我使用
dbo
cdc
模式,这里我只使用
cdc
模式。但是我没有在
dbo
dchema中创建视图。 我也在使用CDC函数,而不是像微软推荐的那样直接使用CDC表

< >我在创建索引视图时阅读了一些需要考虑的事情:

  • 即使使用架构绑定,也不能在使用外部联接的视图上创建索引
  • 即使使用架构绑定,也不能在使用外部联接的视图上创建索引
  • 当视图绑定到架构时,不能在该视图的select语句中使用“*”
  • 如果视图引用任何不确定函数,则无法在视图上创建聚集索引
  • 使用架构绑定时不能使用聚合函数
  • 不能迁移绑定到架构的视图的基表
据我所知,我的查询符合这个规则。但我不确定CDC函数是确定性的还是非确定性的

可以为使用CDC函数的查询创建“索引视图”吗?

不,CDC函数不是“schemabinding”,因此依赖它的视图根本无法索引。相反,您可以创建一个表并定期从函数中填充它

假设您有一个表“testdb.dbo.Customers\u for\u cdc\u test”,该表启用了cdc。您可以通过代码具体化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\u append\u new\u SOURCE\u NAME\u changes”是

使用testdb
去
创建过程dbo.sp\u append\u new\u SOURCE\u NAME\u changes
作为
开始
不计较
;
将@max_old_lsn声明为二进制(10)
,@min_old_lsn作为二进制(10)
,@min\u active\u lsn作为二进制(10)=sys.fn\u cdc\u get\u min\u lsn('dbo\u Customers\u for\u cdc\u test')
,@max_active_lsn作为二进制(10)=sys.fn_cdc_get_max_lsn()
;
选择@max_old_lsn=coalesce(max(_u$start_lsn),强制转换(0为二进制(10)))
,@min_old_lsn=合并(min(_u$start_lsn),强制转换(0为二进制(10)))
从dbo.SOURCE\u NAME\u更改
;
如果(@min_old_lsn<@min_active_lsn
)开始
从dbo.SOURCE\u NAME\u中删除更改
其中uuu$start\u lsn<@min\u active\u lsn
;
结束
如果(@max_old_lsn<@max_active_lsn
)开始
将@min_lsn声明为二进制(10)=iif(@min_active_lsn<@max_old_lsn,@max_old_lsn,@min_active_lsn)--加速
;
插入dbo.SOURCE\u NAME\u更改
--(列列表)
选择*——(列列表)
从cdc.fn\u cdc\u获取所有更改\u dbo\u客户\u进行cdc\u测试
(
@min_lsn
,@max\u active\u lsn
,不全是
)作为src
其中src.\uuu$start\u lsn>@max\u old\u lsn——因为max old lsn已经在。
;
结束
结束
去

谢谢。我想了想。一个问题。我可以从简单视图创建索引视图吗?可以,当视图满足某些限制时,可以创建索引。这里可以找到限制和一个很好的例子。
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