2009-07-14 9 views

risposta

42

Se si desidera eseguire questa operazione manualmente, è possibile utilizzare Management Studio per trovarlo (sotto il nodo Vincoli all'interno della tabella).

Per farlo utilizzando SQL:

  • Se i vincoli sono vincoli di default, è possibile utilizzare sys.default_constraints per trovarlo:

    SELECT OBJECT_NAME(parent_object_id) AS TableName, name AS ConstraintName 
    FROM sys.default_constraints ORDER BY TableName, ConstraintName 
    
  • Se siete alla ricerca di altri vincoli, nonché (controllare, unica chiave, straniero, di default, chiave primaria), è possibile utilizzare sysconstraints:

    SELECT OBJECT_NAME(id) AS TableName, OBJECT_NAME(constid) AS ConstraintName 
    FROM sysconstraints ORDER BY TableName, ConstraintName 
    

Non si specifica quale versione di SQL Server si sta utilizzando. Il lavoro di cui sopra sia su SQL 2005 e SQL 2008.

+1

+1 Grazie mille. Funziona anche in SQL 2012. – gotqn

+0

La prima query funzionava perfettamente in SQL 2008 r2 quando ho trovato l'ID oggetto della tabella prima con 'DECLARE @ParentObjectId INT = (selezionare OBJECT_ID da sys.objects dove nome = 'ParentTable' AND type = 'U')' e aggiunto 'WHERE parent_object_id = @ ParentObjectId' alla query. Altrimenti si ottengono tutti i vincoli predefiniti nel database. – Torrents

+0

Questo è bello, ma non mostra lo schema in cui si trovano le tabelle. Sarebbe bello se tu aggiungessi un join a sys.schemas. – AperioOculus

3

È possibile trovare il nome del vincolo da sp_help [nome tabella] e quindi rilasciarlo per nome.

Oppure è possibile farlo tramite Management Studio.

4

Oppure è possibile trovarlo utilizzando la vista del catalogo sys.check_constraints.

57

È possibile utilizzare questo codice per farlo automaticamente:

DECLARE @tableName VARCHAR(MAX) = '<MYTABLENAME>' 
DECLARE @columnName VARCHAR(MAX) = '<MYCOLUMNAME>' 
DECLARE @ConstraintName nvarchar(200) 
SELECT @ConstraintName = Name 
FROM SYS.DEFAULT_CONSTRAINTS 
WHERE PARENT_OBJECT_ID = OBJECT_ID(@tableName) 
AND PARENT_COLUMN_ID = (
    SELECT column_id FROM sys.columns 
    WHERE NAME = @columnName AND object_id = OBJECT_ID(@tableName)) 
IF @ConstraintName IS NOT NULL 
    EXEC('ALTER TABLE '[email protected]+' DROP CONSTRAINT ' + @ConstraintName) 

Basta sostituire <MYTABLENAME> e <MYCOLUMNNAME> a seconda dei casi.

+5

Per le persone pigre (e gli sviluppatori Microsoft SQL Server), in omaggio a questa risposta, sostituire le prime due righe con 'CREATE PROCEDURE dbo.DropColumnDefaultOrConstraint @tableName VARCHAR (MAX), @columnName VARCHAR (MAX) AS', quindi eseguire il wrapping in' BEGIN' e 'END' e usano' EXEC DropColumnDefaultOrConstraint 'tablename', 'columnname'; ' – Chris

+7

Non capisco perché MS SQL non abbandoni automaticamente i vincoli predefiniti. – Tim

+1

questo script automatizzato è essenziale per qualsiasi motore di aggiornamento dello schema del database roll-your-own. Mi chiedo in che modo lo strumento di migrazione EF lo fa? il difetto di fondo, che il server SQL genera nomi per i valori anonimi e richiede che tu conosca/ottenga quel nome per cambiarlo o rilasciarlo di nuovo, è un problema che avrebbe dovuto essere risolto nella stessa sintassi tsql molto tempo fa. ma è ancora in giro in sql2016. @Tim Sì, o almeno una sintassi per forzare il rilascio. – dlatikay

1

Per una singola tabella e colonna in una sola riga utilizzare il seguente

declare @sql nvarchar(max); set @sql = ''; SELECT @sql+='ALTER TABLE [dbo].[YOURTABLENAME] DROP CONSTRAINT ' + ((SELECT OBJECT_NAME(constid) FROM sysconstraints WHERE OBJECT_NAME(id) = 'YOURTABLENAME'AND colid IN (SELECT ORDINAL_POSITION FROM INFORMATION_SCHEMA.COLUMNS Where Table_Name = 'YOURTABLENAME' and COLUMN_NAME = 'YOURCOLUMNNAM'))) + ';'; EXEC sp_executesql @sql; 

Se si dispone di più vincoli sulla colonna sarà necessario discriminare sulla vincolo siete dopo, ma solo se si dispone di un vincolo predefinito questo farà il trucco.

Controllare le altre colonne disponibili in information_schema per consentire di discriminare ulteriormente.

0

qui va la mia versione che scende vincoli tutti i dipendenti - vincolo predefinito (se esiste) e tutti colpiti vincoli di controllo (come standard SQL sembra suggerire e come alcuni altri database sembrano così)

declare @constraints varchar(4000); 
declare @sql varchar(4000); 
with table_id_column_position as (
    select object_id table_id, column_id column_position 
     from sys.columns where object_id is not null and object_id = object_id('TableName') and name = 'ColumnToBeDropped' 
) 
select @constraints = coalesce(@constraints, 'constraint ') + '[' + name + '], ' 
from sysobjects 
where (
    -- is CHECK constraint 
    type = 'C' 
    -- dependeds on the column 
    and id is not null 
    and id in (
     select object_id --, object_name(object_id) 
     from sys.sql_dependencies, table_id_column_position 
     where object_id is not null 
     and referenced_major_id = table_id_column_position.table_id 
     and referenced_minor_id = table_id_column_position.column_position 
    ) 
) OR (
    -- is DEFAULT constraint 
    type = 'D' 
    and id is not null 
    and id in (
    select object_id 
    from sys.default_constraints, table_id_column_position 
    where object_id is not null 
    and parent_object_id = table_id_column_position.table_id 
    and parent_column_id = table_id_column_position.column_position 
) 
); 
set @sql = 'alter table TableName drop ' + coalesce(@constraints, '') + ' column ColumnToBeDropped'; 
exec @sql 

(Attenzione: sia TableName e ColumnToBeDropped apparire due volte nel codice sopra)

Questo funziona con la costruzione di un'unica ALTER TABLE TableName DROP CONSTRAINT c1, ..., COLUMN ColumnToBeDropped ed eseguirlo.

Problemi correlati