AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 136099
Accepted
Shaneis
Shaneis
Asked: 2016-04-22 07:22:48 +0800 CST2016-04-22 07:22:48 +0800 CST 2016-04-22 07:22:48 +0800 CST

在 Alter Views 上包含索引脚本

  • 772

在开发人员更改索引视图以添加评论后,在其上创建的聚集索引在没有警告的情况下被删除。

这导致了失败,因为有几个过程有WITH (NOEXPAND)提示。

我目前设置了 SSMS,以便右键单击VIEW并选择SCRIPT VIEW as,CREATE TO包括索引定义。

有没有办法编写索引的VIEWS脚本ALTER to?

sql-server sql-server-2012
  • 1 1 个回答
  • 431 Views

1 个回答

  • Voted
  1. Best Answer
    Marcello Miorelli
    2016-04-23T10:44:29+08:002016-04-23T10:44:29+08:00

    好的,让我们为您创建一个很好的示例,并向您展示如何编写索引视图的索引脚本。

    首先,让我们创建一个名为 T1 的临时表并向其中添加一些有意义的数据

    让我们先创建一个生成随机字符串的过程:

    USE TEMPDB
    GO
    
    CREATE PROCEDURE [dbo].[SpGenerateRandomString]
    @sLength tinyint = 10,
    @randomString varchar(50) OUTPUT
    AS
    BEGIN
    SET NOCOUNT ON
    DECLARE @counter tinyint
    DECLARE @nextChar char(1)
    SET @counter = 1
    SET @randomString = ''
    
    WHILE @counter <= @sLength
    BEGIN
    SELECT @nextChar = CHAR(48 + CONVERT(INT, (122-48+1)*RAND()))
    
    IF ASCII(@nextChar) not in (58,59,60,61,62,63,64,91,92,93,94,95,96)
    BEGIN
    SELECT @randomString = @randomString + @nextChar
    SET @counter = @counter + 1
    END
    END
    END
    

    现在让我们将一些数据添加到 T1 中并测试一些选择:

    use tempdb
    go
    
    create table t1 (i int not null identity(1,1) primary key clustered,
                        the_name varchar (50) NOT NULL)
    
    
    declare @i int 
    declare @randomString varchar(50)
    
    select @i = 1
    
    while @i  < 1008 begin
    
    exec SpGenerateRandomString 50, @randomString output
    
    
    insert into t1(the_name) values ( @randomString)
    
    
    select @i = @i + 1
    
    end 
    

    从 T1 运行一些选择时:

    清除此查询计划的缓存后运行选择,此数据库收集统计信息 io 和时间,以便比较性能。

    DECLARE @intDBID INT;
    SET @intDBID = (SELECT [dbid] 
                    FROM master.dbo.sysdatabases 
                    WHERE name = 'TempDB');
    
    print @intDBID 
    -- Flush the procedure cache for one database only
    DBCC FLUSHPROCINDB (@intDBID);
    
    
    SELECT cp.plan_handle, st.[text]
    FROM sys.dm_exec_cached_plans AS cp 
    CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
    WHERE [text] LIKE N'%order by the_name desc%';
    
    DBCC FREEPROCCACHE (0x060002002065C706F0BE22630400000001000000000000000000000000000000000000000000000000000000);
    
    
    set statistics io on
    set statistics time on
    
    
    select * from t1
      where ([i]% 2) = 0 
    order by the_name desc
    

    这是生成的查询计划:

    在此处输入图像描述

    在此处输入图像描述

    > 现在创建一个索引视图:

    这将在稍后用于运行相同的选择并比较性能

    --DROP VIEW VM_01
    --GO
    
    
    create view vm_01 
    with schemabinding 
    as
    
    select 
       i, the_name 
       from DBO.t1
      where ([i]% 2) = 0 
    
    GO
    CREATE UNIQUE CLUSTERED INDEX PK_VM_01 ON DBO.VM_01 (THE_NAME,I)
    GO
    

    现在测试选择和比较:

    DECLARE @intDBID INT;
    SET @intDBID = (SELECT [dbid] 
                    FROM master.dbo.sysdatabases 
                    WHERE name = 'TempDB');
    
    print @intDBID 
    -- Flush the procedure cache for one database only
    DBCC FLUSHPROCINDB (@intDBID);
    
    
    SELECT cp.plan_handle, st.[text]
    FROM sys.dm_exec_cached_plans AS cp 
    CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
    WHERE [text] LIKE N'%order by the_name desc%';
    
    DBCC FREEPROCCACHE (0x060002002065C706F0BE22630400000001000000000000000000000000000000000000000000000000000000);
    
    
        set statistics io on
        set statistics time on
        select * from vm_01 WITH (NOEXPAND) 
          where ([i]% 2) = 0 
        order by the_name desc
    
    
    set statistics io off
    set statistics time off
    

    在此处输入图像描述

    生成的查询计划:

    因为它被证明使用索引视图的查询执行得更好,所以(因为我们不担心这个例子中的写入)我们想要保留索引。

    在此处输入图像描述

    这里选择向您展示为视图 VM_01 创建的聚簇索引的索引创建脚本:

    SET NOCOUNT ON
    SET DATEFORMAT DMY
    SET DEADLOCK_PRIORITY NORMAL;
    
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    
    declare @TABLEID int
    declare @index_or_table_name varchar(256)
    
    
    select @TABLEID = OBJECT_ID('VM_01')
          , @index_or_table_name = 'vm_01'
    
    BEGIN TRY
    
            SELECT 
    
            i.object_id,
            i.index_id,
            index_name=i.name,
    
            CASE WHEN I.is_primary_key = 1 THEN 
                 ' ALTER TABLE ' + 
                 QUOTENAME(Schema_name(T.Schema_id))+'.'+ QUOTENAME(T.name) + 
                 ' ADD  CONSTRAINT ' + QUOTENAME(i.name) + ' PRIMARY KEY ' + 
                 I.type_desc + 
                 ' ( ' +  KeyColumns + ' )  ' 
    
            ELSE
    
            ' CREATE ' +
                CASE WHEN I.is_unique = 1 THEN ' UNIQUE ' ELSE '' END  + 
                I.type_desc COLLATE DATABASE_DEFAULT +' INDEX ' +  
                I.name  + ' ON '  + 
                QUOTENAME(Schema_name(T.Schema_id)) +'.'+ QUOTENAME(T.name) 
                + ' ( ' + KeyColumns + ' )  ' +
                ISNULL(' INCLUDE ('+IncludedColumns+' ) ','') 
                +  ISNULL(' WHERE  '+I.Filter_definition,'') --sql2005
    
             END -- case primary key or not
    
                + ' WITH ( ' +
                CASE WHEN I.is_padded = 1 THEN ' PAD_INDEX = ON ' ELSE ' PAD_INDEX = OFF ' END + ','  +
                'FILLFACTOR = '+CONVERT(CHAR(5),CASE WHEN I.Fill_factor = 0 THEN 100 ELSE I.Fill_factor END) + ','  +
                -- default value
                'SORT_IN_TEMPDB = OFF '  + ','  +
                CASE WHEN I.ignore_dup_key = 1 THEN ' IGNORE_DUP_KEY = ON ' ELSE ' IGNORE_DUP_KEY = OFF ' END + ','  +
                CASE WHEN ST.no_recompute = 0 THEN ' STATISTICS_NORECOMPUTE = OFF ' ELSE ' STATISTICS_NORECOMPUTE = ON ' END + ','  +
    
                CASE WHEN I.is_primary_key = 1 THEN 
    
                        -- default value 
                        ' ONLINE = OFF '  + ','  
    
                ELSE
    
                        -- default value 
                        ' ONLINE = OFF '  + ','  +
    
                        -- default value 
                        ' DROP_EXISTING = ON '  + ','  
    
                END +
    
               CASE WHEN I.allow_row_locks = 1 THEN ' ALLOW_ROW_LOCKS = ON ' ELSE ' ALLOW_ROW_LOCKS = OFF ' END + ','  +
               CASE WHEN I.allow_page_locks = 1 THEN ' ALLOW_PAGE_LOCKS = ON ' ELSE ' ALLOW_PAGE_LOCKS = OFF ' END  + ' ) ON [' +
               DS.name + ' ] ' 
    
               AS [CreateIndexScript]
    
            FROM sys.indexes I  
    
            INNER JOIN (
                          SELECT  Object_id
                                 ,Schema_id
                                 ,NAME
                                 FROM sys.tables 
    
                          UNION ALL 
    
                          SELECT  Object_id
                                 ,Schema_id
                                 ,NAME
                                 FROM sys.views  
    
                        ) T
    
                       ON T.Object_id = I.Object_id   
             INNER JOIN sys.sysindexes SI ON I.Object_id = SI.id AND I.index_id = SI.indid 
    
             INNER JOIN (SELECT * 
                     FROM ( 
    
                            SELECT IC2.object_id , IC2.index_id , 
                                STUFF((SELECT ' , ' + QUOTENAME(C.name) + CASE WHEN MAX(CONVERT(INT,IC1.is_descending_key)) = 1 THEN ' DESC ' ELSE ' ASC ' END
                            FROM sys.index_columns IC1 
                            JOIN sys.columns C  
                                ON C.object_id = IC1.object_id  
                                AND C.column_id = IC1.column_id  
                                AND IC1.is_included_column = 0 
                            WHERE IC1.object_id = IC2.object_id  
                                AND IC1.index_id = IC2.index_id  
                            GROUP BY IC1.object_id,C.name,index_id 
                            ORDER BY MAX(IC1.key_ordinal) 
                                FOR XML PATH('')), 1, 2, '') KeyColumns  
    
                            FROM sys.index_columns IC2  
                            --WHERE IC2.Object_id = object_id('xtbUApplication') --Comment for all tables 
                            GROUP BY IC2.object_id ,IC2.index_id 
    
                          ) radhe3 
                    ) radhe4  
    
    
              ON I.object_id = radhe4.object_id AND I.Index_id = radhe4.index_id 
             JOIN sys.stats ST ON ST.object_id = I.object_id AND ST.stats_id = I.index_id  
             JOIN sys.data_spaces DS ON I.data_space_id=DS.data_space_id  
             JOIN sys.filegroups FG ON I.data_space_id=FG.data_space_id  
    
             LEFT JOIN (SELECT * FROM (  
                SELECT IC2.object_id , IC2.index_id ,  
                    STUFF((SELECT ' , ' + QUOTENAME(C.name) 
                FROM sys.index_columns IC1  
                JOIN sys.columns C   
                   ON C.object_id = IC1.object_id   
                   AND C.column_id = IC1.column_id   
                   AND IC1.is_included_column = 1  
                WHERE IC1.object_id = IC2.object_id   
                   AND IC1.index_id = IC2.index_id   
                GROUP BY IC1.object_id,C.name,index_id  
                   FOR XML PATH('')), 1, 2, '') IncludedColumns   
               FROM sys.index_columns IC2   
               GROUP BY IC2.object_id ,IC2.index_id) tmp1  
               WHERE IncludedColumns IS NOT NULL ) tmp2   
            ON tmp2.object_id = I.object_id AND tmp2.index_id = I.index_id 
    
            ---------------------------------------------------------------------------------------------------
            -- when @TABLEID = 0 -> all tables
            -- when @TABLEID = -1 -> only the index named = @index_or_table_name
            -- when @TABLEID has the object id of a particular table -> only shows that table
            ---------------------------------------------------------------------------------------------------
    
            WHERE 1 = CASE WHEN @TABLEID = 0 THEN 1 ELSE
                         CASE WHEN @TABLEID = -1 AND UPPER(I.name) = @index_or_table_name THEN 1 ELSE 
                              CASE WHEN @TABLEID = I.object_id THEN 1 ELSE 0 
                              END
                         END
                      END 
    
            ORDER BY i.name
    
    END TRY
    BEGIN CATCH
    
            PRINT '--EXCEPTION WAS CAUGHT--' + CHAR(13) +
                  'THE ERROR NUMBER:' + COALESCE(CAST ( ERROR_NUMBER()  AS VARCHAR), 'NO INFO') + CHAR(13) 
    
            PRINT 'SEVERITY: '        + COALESCE(CAST ( ERROR_SEVERITY()  AS VARCHAR), 'NO INFO') + CHAR(13) +
                  'STATE: '           + COALESCE(CAST ( ERROR_STATE() AS VARCHAR), 'NO INFO')  + CHAR(13) 
    
            PRINT 'PROCEDURE: '       + COALESCE(CAST ( COALESCE(ERROR_PROCEDURE(),'NO INFO')  AS VARCHAR), 'NO INFO') + CHAR(13) +
                  'LINE NUMBER: '     + COALESCE(CAST ( ERROR_LINE() AS VARCHAR), 'NO INFO')  + CHAR(13) 
    
            PRINT 'ERROR MESSAGE: '
            PRINT  CAST ( COALESCE(ERROR_MESSAGE(),'NO INFO')   AS NTEXT)
    
    
    END CATCH;
    

    当你运行上面的脚本时,你会得到:

    在此处输入图像描述

    复制并粘贴向我们展示了脚本:

    CREATE  UNIQUE CLUSTERED INDEX PK_VM_01 
    ON [dbo].[vm_01] (  [the_name] ASC  , [i] ASC  )   
    WITH (  PAD_INDEX = OFF ,
    FILLFACTOR = 100  ,
    SORT_IN_TEMPDB = OFF , 
    IGNORE_DUP_KEY = OFF , 
    STATISTICS_NORECOMPUTE = OFF , 
    ONLINE = OFF , 
    DROP_EXISTING = ON , 
    ALLOW_ROW_LOCKS = ON , 
    ALLOW_PAGE_LOCKS = ON  ) ON [PRIMARY ]
    

    还有一些错误需要修复,比如格式化和 drop_existing=on,但希望这会有所帮助。

    • 2

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve