Как я могу изменить COLUMN на NOT NULL, когда столбец проиндексирован - PullRequest
6 голосов
/ 29 декабря 2011

Я работаю в SQL Server 2008 R2 и написал хранимую процедуру, которая добавляет ограничения к нескольким столбцам в нескольких таблицах в моей базе данных.Тем не менее, я обнаружил, что хранимая процедура не удается, потому что она не может установить конкретный столбец в качестве первичного ключа из-за индекса на столбце.Это относится ко многим столбцам в разных таблицах.

Есть ли способ изменить значение ALTER COLUMN на NOT NULL и установить его в качестве ПЕРВИЧНОГО КЛЮЧА без удаления индекса?Иначе, есть ли хороший способ отключить или удалить индекс, а затем включить или воссоздать его после операторов ALTER COLUMN?

1 Ответ

2 голосов
/ 30 декабря 2011

Спасибо всем за ваши комментарии. После некоторых исследований я смог определить, как сделать это динамически, используя точные таблицы, упомянутые @mwigdahl. Смотрите код ниже:

DECLARE @indexName nvarchar(254),
    @tableName nvarchar(254),
    @indexType nvarchar(254),
    @columnName nvarchar(254),
    @isPadded integer,
    @ignore_dup_key integer,
    @allow_row_locks integer,
    @allow_page_locks integer,
    @fillFactor integer

SELECT
    @indexName = i.name, 
    @tableName = o.name,
    @indexType = i.type_desc,
    @columnName = co.[name],
    @isPadded = i.is_padded,
    @ignore_dup_key = i.[ignore_dup_key],
    @allow_row_locks = i.[allow_row_locks],
    @allow_page_locks = i.[allow_page_locks],
    @fillFactor = i.fill_factor
FROM sys.indexes AS i
    INNER JOIN sys.objects AS o ON i.object_id = o.object_id
    INNER JOIN sys.index_columns ic on ic.object_id = i.object_id AND ic.index_id = i.index_id
    INNER JOIN sys.columns co on co.object_id = i.object_id AND co.column_id = ic.column_id
WHERE
    i.[type] = 2 AND
    o.[type] = 'U'

DECLARE @sql varchar(max)

SET @sql = 'DROP INDEX [' + @indexName + '] ON [' + @tableName + ']'

EXEC (@sql)

PRINT 'Dropped Index'

-- Do work here

DECLARE @pad_index nvarchar(3),
    @ignore_dup nvarchar(3),
    @row_locks nvarchar(3),
    @page_locks nvarchar(3)

IF @isPadded = 0 SET @pad_index = 'OFF'
ELSE SET @pad_index = 'ON'

IF @ignore_dup_key = 0 SET @ignore_dup = 'OFF'
ELSE SET @ignore_dup = 'ON'

IF @allow_row_locks = 0 SET @row_locks = 'OFF'
ELSE SET @row_locks = 'ON'

IF @allow_page_locks = 0 SET @page_locks = 'OFF'
ELSE SET @page_locks = 'ON'

SET @sql = 'CREATE ' + @indexType + ' INDEX [' + @indexName + '] ON [' + @tableName + ']' + 
    '(' + 
    '[' + @columnName + '] ASC' + 
    ') WITH (' + 
    'PAD_INDEX = ' + @pad_index + ',' + 
    'STATISTICS_NORECOMPUTE = OFF,' + 
    'SORT_IN_TEMPDB = OFF,' + 
    'IGNORE_DUP_KEY = ' + @ignore_dup + ',' + 
    'DROP_EXISTING = OFF,' + 
    'ONLINE = OFF,' + 
    'ALLOW_ROW_LOCKS = ' + @row_locks + ',' + 
    'ALLOW_PAGE_LOCKS = ' + @page_locks + ',' + 
    'FILLFACTOR = ' + CONVERT(nvarchar(100),@fillFactor) + ')' + 
    'ON [PRIMARY]'

PRINT @sql

EXEC (@sql)

PRINT 'Created Index'

Я использовал функцию Script Index As в SSMS, чтобы посмотреть, как будет создаваться индекс в T-SQL.

Затем я запросил таблицы sys.indexes и sys.index_columns, чтобы определить, какие свойства были доступны.

Код показывает запрос к этим таблицам, сохраняя эти свойства в переменных, а затем отбрасывая и воссоздавая индекс. Было несколько вариантов, которые не были доступны в тех таблицах, которые мне пришлось жестко кодировать. Кто-нибудь знает, доступны ли эти ОПЦИИ где-нибудь в системной таблице?

Надеюсь, это поможет кому-то еще в будущем.

...