2011-12-28 1 views
5

Sto lavorando in SQL Server 2008 R2 e ho scritto una procedura memorizzata che aggiunge vincoli a più colonne in diverse tabelle nel mio database. Tuttavia, sto trovando che la procedura memorizzata non riesce perché non può impostare una particolare colonna come chiave primaria a causa di un indice sulla colonna. Questo è il caso di molte delle colonne in varie tabelle.Come ALTER COLUMN su NOT NULL quando la colonna è indicizzata

C'è un modo per ALTER COLUMN su NOT NULL e impostarlo come PRIMARY KEY senza rimuovere l'indice? Altrimenti, c'è un buon modo per disabilitare o rilasciare l'indice, quindi abilitarlo o ricrearlo dopo le istruzioni ALTER COLUMN?

+1

Devi eliminare e ricreare l'indice. È possibile creare uno script per entrambe le azioni facendo clic con il tasto destro sull'indice in SSMS e quindi su "Indice script come" – Andomar

+0

@Andomar - Grazie per la risposta. È possibile farlo dinamicamente nella stored procedure? Come ho detto, questo si verifica con molte colonne in molte tabelle. Esiste comunque la possibilità di controllare in modo programmatico un indice sul campo prima di modificarlo, rilasciare l'indice e ricrearlo dopo il post-it? – Brian

+1

Questo post del blog dovrebbe iniziare: http://blog.sqlauthority.com/2009/07/23/sql-server-puzzle-write-script-to-generate-primary-key-and-foreign-key/ – Andomar

risposta

2

Grazie a tutti per i vostri commenti. Dopo alcune ricerche, sono stato in grado di determinare come farlo dinamicamente usando le tabelle esatte menzionate da @mwigdahl. Vedere il codice qui sotto:

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' 

ho usato la funzione Script Index As in SSMS per vedere come l'indice sarebbe stato creato in T-SQL.

Quindi ho interrogato le tabelle sys.indexes e sys.index_columns per determinare quali proprietà erano disponibili.

Il codice mostra una query su tali tabelle salvando tali proprietà su variabili e quindi rilasciando e ricreando l'indice. C'erano alcune opzioni che non erano disponibili in quelle tabelle che ho dovuto hard code. Qualcuno sa se quelle OPZIONI sono disponibili da qualche parte in una tabella di sistema?

Spero che questo aiuti qualcun altro in futuro.