TSQL для создания текста создания индекса, а затем оценить его - PullRequest
0 голосов
/ 19 октября 2011

У меня есть скрипт, который создает и заполняет кучу таблиц из данных, которые мы получаем в виде текстовых файлов.После загрузки данных в SQL Server 2008, я хочу добавить индексы.Используемый мной сценарий вырезания и вставки показан ниже.

Есть ли способ в TSQL создать функцию, которая будет генерировать, а затем оценивать команды DDL?Функция будет принимать параметры имени таблицы, имен столбцов и кластеризованных / нет.Если бы понадобилась отдельная функция для индексов 1 столбец / 2 столбца, я все равно был бы заинтересован.

Я предполагаю что-то вроде:

hypotheticalFunction('clustered', 'precCdaEarn', 'account', 'seq')
hypothericalFunction('nonClustered', 'flats', 'vendorAcct')

, и это проверило быесли в таблице precCdaEarn существует действие с именем «idx_acct_seq», и, если это так, отбросить его, то создайте его как кластерный индекс.(Отбрасывание на всякий случай, если я изменю определение).И создайте / воссоздайте некластеризованный индекс на dbo.flats с именем "idx_vendorAcct"

========= это то, что теперь использует cut & paste, извинения за ошибочный интервал ==============

IF EXISTS (Select 'X' 
  FROM sysindexes
    WHERE id = (SELECT OBJECT_ID('precCdaEarn'))
      and name = 'idx_account_seq')
     DROP index precCdaEarn.idx_account_seq 
   Create nonclustered index idx_account_seq
      ON precCdaEarn(account, seq)

;

IF EXISTS (Select 'X' 
FROM sysindexes
      WHERE id = (SELECT OBJECT_ID('acct'))
             and name = 'idx_c_precAcct_precMod')
 DROP index acct.idx_c_precAcct_precMod
CREATE CLUSTERED INDEX index idx_c_precAcct_precMod
    ON acct(precAcct, precMod)

1 Ответ

1 голос
/ 19 октября 2011

AFAIK, вы не можете создать функцию для этого, но с сохраненной процедурой это не проблема.

Что-то вроде:

IF(OBJECT_ID('PRC_CREATE_INDEX', N'P') IS NOT NULL)
    DROP PROCEDURE PRC_CREATE_INDEX
GO

CREATE PROCEDURE dbo.PRC_CREATE_INDEX 
(
    -- Table name to add index to
    @pTablename AS VARCHAR(120)

    -- Index name to add/change
,   @pIndexname AS VARCHAR(120)         

    -- UNIQUE, CLUSTERED or other definition
,   @pNewIndexDef AS VARCHAR(255) = ''

    -- Columns in index     
,   @pNewIndexCols AS VARCHAR(255)

    -- Recreate even if same 
,   @pForceRecreate AS SMALLINT = 0

    -- Additional columns for INCLUDE
,   @pColumnsInclude AS VARCHAR(255) = ''
)
AS

------------------------------------
--  Variabels
------------------------------------
    DECLARE @SQL_DROP AS NVARCHAR(1000)
    ,   @SQL_CREATE AS NVARCHAR(1000)
    ,   @retval AS INTEGER
    ,   @rowcount AS INTEGER

    DECLARE @oldDescription AS VARCHAR(255)
    ,   @newUnique AS SMALLINT
    ,   @newClustered AS SMALLINT
    ,   @newIndexDef AS VARCHAR(255)
    ,   @newDescription AS VARCHAR(255)
    ,   @drop_index AS BIT
    ,   @temp AS VARCHAR(MAX)


------------------------------------
--  Initiate
------------------------------------
    SET XACT_ABORT ON
    SET NOCOUNT ON


-- Table exists?

    IF(OBJECT_ID(@pTablename) IS NULL)
    BEGIN
        PRINT   'Error: Table does not exist: ' + @pTablename + 
            ' ('  + 'creation of index ''' + @pTablename +  '.' + @pIndexname + ''')'
        RETURN (1)
    END


-----------------------------------------------------------------------------------------------------
-- New index
-----------------------------------------------------------------------------------------------------


-- Initiate (Remove blanks, get unique/clustered info)

    SELECT  @newIndexDef = @pNewIndexDef
    -- Remove NONCLUSTERED
    ,   @newIndexDef = REPLACE(@newIndexDef, 'nonclustered', '')
    -- CLUSTERED?
    ,   @newClustered = CASE WHEN PATINDEX('%clustered%', LOWER(@newIndexDef)) > 0 THEN 1 ELSE 0 END
    ,   @newIndexDef = REPLACE(@newIndexDef, 'clustered', '')
    -- UNIQUE?
    ,   @newUnique = CASE WHEN PATINDEX('%unique%', LOWER(@pNewIndexDef)) > 0 THEN 1 ELSE 0 END
    ,   @newIndexDef = REPLACE(@newIndexDef, 'unique', '')
    -- Remove blanks etc.
    ,   @pNewIndexCols = REPLACE(@pNewIndexCols, ' DESC', '#DESC')
    ,   @newIndexDef = REPLACE(@newIndexDef, ' ', '')
    ,   @newIndexDef = REPLACE(@newIndexDef, ',', '')
    ,   @pNewIndexCols = REPLACE(@pNewIndexCols, ' ', '')
    ,   @pColumnsInclude = REPLACE(@pColumnsInclude, ' ', '')


-- Correct defintion?

    IF LEN(@newIndexDef) > 0
    BEGIN
        RAISERROR ('Index defintion ''%s'' is incorrect for index ''%s.%s''!', 11, 11, @pNewIndexDef, @pTablename, @pIndexname)
        RETURN (1)
    END     

    IF @newClustered = 1 AND LEN(@pColumnsInclude) > 0
    BEGIN
        RAISERROR ('Cannot specify included columns for a clustered index (''%s.%s'')!', 11, 11, @pIndexname, @pTablename)
        RETURN (1)
    END

    IF @pNewIndexCols LIKE '%#DESC%'
    BEGIN
        RAISERROR ('Descending sort direction not supported (''%s.%s'')!', 11, 11, @pTablename, @pIndexname)
        RETURN (1)
    END

    IF  @newClustered = 1 AND EXISTS
    ( 
        SELECT  1
        FROM    sys.indexes (NOLOCK)
        WHERE   object_id = OBJECT_ID(@pTablename, N'U')
        AND name <> @pIndexname
        AND type = 1            -- CLUSTERED
        AND is_hypothetical = 0
    )   
    BEGIN
        SELECT  @temp = name
        FROM    sys.indexes (NOLOCK)
        WHERE   object_id = OBJECT_ID(@pTablename, N'U')
        AND name <> @pIndexname
        AND type = 1            -- CLUSTERED
        AND is_hypothetical = 0

        RAISERROR ('Cannot add CLUSTERED index (''%s.%s'') - table already has a clustered index (''%s'')!', 11, 11, @pTablename, @pIndexname, @temp)
        RETURN (1)
    END


-- Prepare SQL

    -- CREATE
    SELECT  @SQL_CREATE = ''
    +   'CREATE '
    +   CASE WHEN @newUnique = 1 THEN 'UNIQUE ' ELSE '' END
    +   CASE WHEN @newClustered = 1 THEN 'CLUSTERED ' ELSE 'NONCLUSTERED ' END
    +   'INDEX ' + @pIndexname + ' '
    +   'ON ' + @pTablename + ' ' 
    +   '(' + @pNewIndexCols + ')'
    +   CASE WHEN LEN(@pColumnsInclude) > 0 THEN ' INCLUDE (' + @pColumnsInclude + ')' ELSE '' END

    -- Description
    SELECT  @newDescription = ''
    +   CASE WHEN @newUnique = 1 THEN 'UNIQUE ' ELSE '' END
    +   CASE WHEN @newClustered = 1 THEN 'CLUSTERED ' ELSE 'NONCLUSTERED ' END
    +   '(' + @pNewIndexCols + ')'
    +   CASE WHEN LEN(@pColumnsInclude) > 0 THEN ' INCLUDE (' + @pColumnsInclude + ')' ELSE '' END

    -- DROP
    SET @SQL_DROP = ''
    +   'DROP INDEX ' + @pTablename
    +   '.' + @pIndexname



-----------------------------------------------------------------------------------------------------
-- Current index
-----------------------------------------------------------------------------------------------------

-- Initiate 

    SELECT  @drop_index = 0

-- Get definition/description and check if recreation is needed

    IF EXISTS
    (   
        SELECT  1
        FROM    sys.indexes (NOLOCK)
        WHERE   object_id = OBJECT_ID(@pTablename, N'U')
        AND name = @pIndexname
    )
    BEGIN   

    -- Description

        SELECT  @oldDescription = ''
        +   CASE WHEN i.is_unique = 1 THEN 'UNIQUE ' ELSE '' END
        +   CASE 
                WHEN    i.type = 1 THEN 'CLUSTERED ' 
                WHEN    i.type = 2 THEN 'NONCLUSTERED ' 
                ELSE    '? '
            END
        +   '(' + STUFF(
                (
                    SELECT  ',' + COL_NAME(ic.object_id, ic.column_id)
                    FROM    sys.index_columns ic (NOLOCK)
                    WHERE   ic.object_id = i.object_id
                    AND ic.index_id = i.index_id
                    AND ic.is_included_column = 0
                    ORDER   BY ic.key_ordinal
                    FOR XML PATH('')
                )
            , 1, 1, '') + ')'
        +   ISNULL(' INCLUDE (' + STUFF(
                (
                    SELECT  ',' + COL_NAME(ic.object_id, ic.column_id)
                    FROM    sys.index_columns ic (NOLOCK)
                    WHERE   ic.object_id = i.object_id
                    AND ic.index_id = i.index_id
                    AND ic.is_included_column = 1
                    ORDER   BY ic.index_column_id    -- Or column_id???
                    FOR XML PATH('')
                )
            , 1, 1, '') + ')', '')
        FROM    sys.indexes i (NOLOCK)
        WHERE   i.object_id = OBJECT_ID(@pTablename, N'U')
        AND i.name = @pIndexname

    -- Exit?

        -- If not changed and no force of recreation
        IF  @oldDescription = @newDescription
            AND
            @pForceRecreate = 0
        BEGIN       
            RETURN 0
        END


    -- We should drop current index..

        SET @drop_index = 1
    END



-----------------------------------------------------------------------------------------------------
-- Execute SQL
-----------------------------------------------------------------------------------------------------

-- Exec

    IF @drop_index = 1
        EXEC    sp_executesql @SQL_DROP

    IF LEN(@pNewIndexCols) > 0
        EXEC    sp_executesql @SQL_CREATE


-- Message

    IF LEN(@pNewIndexCols) > 0 AND @drop_index = 0
        PRINT   'Created index ' + @pTablename + '.' + @pIndexname + ' (' + @newDescription + ')'
    ELSE IF LEN(@pNewIndexCols) > 0 AND @drop_index = 1
        PRINT   'Recreated index ' + @pTablename + '.' + @pIndexname + CHAR(10) +
            '   From: ' + @oldDescription + CHAR(10) +
            '   To:   ' + @newDescription
    -- Well, this will perhaps occur when and if this proc is changed...
    ELSE IF @drop_index = 1
        PRINT 'Removed index ' + @pTablename + '.' + @pIndexname + ' (' + @oldDescription + ')'


-----------------------------------------------------------------------------------------------------
-- Exit
-----------------------------------------------------------------------------------------------------
    RETURN (0)
GO

Используйте это как:

EXEC    dbo.PRC_CREATE_INDEX
    @pTablename = 'someTable'
,   @pIndexname = 'idx_someTable'
,   @pNewIndexDef = 'CLUSTERED' 
,   @pNewIndexCols = 'some, columns, listed'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...