Comment supprimer la contrainte SQL par défaut sans connaître son nom?

196

Dans Microsoft SQL Server, je connais la requête pour vérifier si une contrainte par défaut existe pour une colonne et supprimer une contrainte par défaut est:

IF EXISTS(SELECT * FROM sysconstraints
  WHERE id=OBJECT_ID('SomeTable')
  AND COL_NAME(id,colid)='ColName'
  AND OBJECTPROPERTY(constid, 'IsDefaultCnst')=1)    
ALTER TABLE SomeTable DROP CONSTRAINT DF_SomeTable_ColName

Mais en raison de la faute de frappe dans les versions précédentes de la base de données, le nom de la contrainte pourrait être DF_SomeTable_ColNameou DF_SmoeTable_ColName.

Comment puis-je supprimer la contrainte par défaut sans aucune erreur SQL? Les noms de contraintes par défaut n'apparaissent pas dans la table INFORMATION_SCHEMA, ce qui rend les choses un peu plus compliquées.

Donc, quelque chose comme «supprimer la contrainte par défaut dans cette table / colonne» ou «supprimer DF_SmoeTable_ColName», mais ne donnez aucune erreur s'il ne la trouve pas.

Robo
la source
1
Je ne maîtrise pas SQL Server, pouvez-vous renommer une contrainte après avoir découvert son nom? "Modifier la table pour renommer la contrainte xxx en yyy" dans Oracle.
Juergen Hartelt

Réponses:

262

En développant le code de Mitch Wheat, le script suivant générera la commande pour supprimer la contrainte et l'exécuter dynamiquement.

declare @schema_name nvarchar(256)
declare @table_name nvarchar(256)
declare @col_name nvarchar(256)
declare @Command  nvarchar(1000)

set @schema_name = N'MySchema'
set @table_name = N'Department'
set @col_name = N'ModifiedDate'

select @Command = 'ALTER TABLE ' + @schema_name + '.[' + @table_name + '] DROP CONSTRAINT ' + d.name
 from sys.tables t
  join sys.default_constraints d on d.parent_object_id = t.object_id
  join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id
 where t.name = @table_name
  and t.schema_id = schema_id(@schema_name)
  and c.name = @col_name

--print @Command

execute (@Command)
Philip Kelley
la source
1
Vérifiez stackoverflow.com/a/15786313/2049986 pour voir une version pour supprimer toutes les contraintes pour une table
Jacob van Lingen
J'utilise sys.check_constraints , pas sys.default_constraints
Kiquenet
Non valide si certaines colonnes qui avaient plusieurs contraintes par défaut ou vérifient les contraintes créées, exécutées uniquement pour les dernières contraintes de la requête.
Kiquenet
4
Cette requête ne traite que des contraintes par défaut, dont il ne peut y en avoir qu'une par colonne. Le traitement des contraintes de contrôle est un problème différent.
Philip Kelley
1
J'ai mis à jour cette réponse pour ajouter la prise en charge des noms de schéma non par défaut. J'espère que cela ne vous dérange pas, je peux revenir et poster une réponse séparée si vous le souhaitez.
Jakub Januszkiewicz
234

Le billet de blog de Rob Farley pourrait être utile:

Quelque chose comme:

 declare @table_name nvarchar(256)
 declare @col_name nvarchar(256)
 set @table_name = N'Department'
 set @col_name = N'ModifiedDate'

 select t.name, c.name, d.name, d.definition
 from 
     sys.tables t
     join sys.default_constraints d on d.parent_object_id = t.object_id
     join sys.columns c on c.object_id = t.object_id
                           and c.column_id = d.parent_column_id
 where 
     t.name = @table_name
     and c.name = @col_name
Blé Mitch
la source
104

J'ai trouvé que cela fonctionne et n'utilise aucune jointure:

DECLARE @ObjectName NVARCHAR(100)
SELECT @ObjectName = OBJECT_NAME([default_object_id]) FROM SYS.COLUMNS
WHERE [object_id] = OBJECT_ID('[tableSchema].[tableName]') AND [name] = 'columnName';
EXEC('ALTER TABLE [tableSchema].[tableName] DROP CONSTRAINT ' + @ObjectName)

Assurez-vous simplement que columnName ne comporte pas de crochets, car la requête recherche une correspondance exacte et ne retournera rien s'il s'agit de [columnName].

ScubaSteve
la source
1
Et cette réponse fonctionne avec des schémas autres que la valeur par défaut [dbo], contrairement à toutes les autres réponses.
Contango
Je ne l'ai pas testé, mais vous pouvez essayer d'ajouter un WHILE (@ObjectName IS NOT NULL) autour de lui, mettre TOP 1 avant SELECT (at) ObjectName = OBJECT_Name ([par défaut ... et exécuter uniquement le EXEC ('ALTER TA ... if (at) ObjectName IS NOT NULL.
ScubaSteve
6
Pour rendre ce script idempotent ajouter IF @ObjectName IS NOT NULLavant la commande EXEC
Sept
3
Ne fonctionne pas pour moi en utilisant les contraintes CHECK . [default_object_id])est 0 . Je reçois NULL valeur.
Kiquenet
Doux et simple, mais selon les documents de Microsoft, cette façon de faire ne sera pas là pour toujours. Il y a un avertissement indiquant qu'il disparaîtra dans la prochaine version docs.microsoft.com/en-us/sql/t-sql/statements/…
Hopeless
11

Pour supprimer la contrainte pour plusieurs colonnes:

declare @table_name nvarchar(256)

declare @Command nvarchar(max) = ''

set @table_name = N'ATableName'

select @Command = @Command + 'ALTER TABLE ' + @table_name + ' drop constraint ' + d.name + CHAR(10)+ CHAR(13)
from sys.tables t
join sys.default_constraints d on d.parent_object_id = t.object_id
join sys.columns c on c.object_id = t.object_id
     and c.column_id = d.parent_column_id
where t.name = @table_name and c.name in ('column1','column2','column3')

--print @Command

execute (@Command)
Ken Yao
la source
5

Solution étendue (prend en compte le schéma de table):

-- Drop default contstraint for SchemaName.TableName.ColumnName
DECLARE @schema_name NVARCHAR(256)
DECLARE @table_name NVARCHAR(256)
DECLARE @col_name NVARCHAR(256)
DECLARE @Command  NVARCHAR(1000)

set @schema_name = N'SchemaName'
set @table_name = N'TableName'
set @col_name = N'ColumnName'

SELECT @Command = 'ALTER TABLE [' + @schema_name + '].[' + @table_name + '] DROP CONSTRAINT ' + d.name
 FROM sys.tables t   
  JOIN sys.default_constraints d       
   ON d.parent_object_id = t.object_id  
  JOIN sys.schemas s
        ON s.schema_id = t.schema_id
  JOIN    sys.columns c      
   ON c.object_id = t.object_id      
    AND c.column_id = d.parent_column_id
 WHERE t.name = @table_name
    AND s.name = @schema_name 
  AND c.name = @col_name

EXECUTE (@Command)
Jorge Garcia
la source
3

Supprimez toutes les contraintes par défaut dans une base de données - sans danger pour le seuil nvarchar (max).

/* WARNING: THE SAMPLE BELOW; DROPS ALL THE DEFAULT CONSTRAINTS IN A DATABASE */ 
/* MAY 03, 2013 - BY WISEROOT  */
declare @table_name nvarchar(128)
declare @column_name nvarchar(128)
declare @df_name nvarchar(128)
declare @cmd nvarchar(128) 

declare table_names cursor for 
 SELECT t.name TableName, c.name ColumnName
 FROM sys.columns c INNER JOIN
     sys.tables t ON c.object_id = t.object_id INNER JOIN
     sys.schemas s ON t.schema_id = s.schema_id
     ORDER BY T.name, c.name

     open table_names
fetch next from table_names into @table_name , @column_name
while @@fetch_status = 0
BEGIN

if exists (SELECT top(1) d.name from sys.tables t join sys.default_constraints d on d.parent_object_id = t.object_id join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id where t.name = @table_name and c.name = @column_name)
BEGIN
    SET @df_name = (SELECT top(1) d.name from sys.tables t join sys.default_constraints d on d.parent_object_id = t.object_id join sys.columns c on c.object_id = t.object_id and c.column_id = d.parent_column_id where t.name = @table_name and c.name = @column_name)
    select @cmd = 'ALTER TABLE [' + @table_name +  '] DROP CONSTRAINT [' +  @df_name + ']'
    print @cmd
    EXEC sp_executeSQL @cmd;
END

  fetch next from table_names into @table_name , @column_name
END

close table_names 
deallocate table_names
user2346877
la source
Non valide si certaines colonnes qui avaient plusieurs contraintes par défaut ou vérifient les contraintes créées, exécutées uniquement pour les 1 premières contraintes dans la requête.
Kiquenet
2

Exécutez cette commande pour parcourir toutes les contraintes:

exec sp_helpconstraint 'mytable' --and look under constraint_name. 

Il ressemblera à quelque chose comme ceci: DF__Mytable__Column__[ABC123]. Ensuite, vous pouvez simplement supprimer la contrainte.

Au four
la source
Ne travaille pas pour moi:exec sp_helpconstraint 'Roles2016.UsersCRM'
Kiquenet
@Kiquenet Ne devrait être que le nom de la table: exec sp_helpconstraint 'Roles2016'
Baked Inhalf
Il montre simplement des contraintes de clé étrangère. pas la valeur par défaut constaint
Morez
2

J'espère que cela pourrait être utile pour qui a un problème similaire. Dans la ObjectExplorerfenêtre, sélectionnez votre base de données => Tables, => votre table => Contraintes. Si le client est défini lors de la création de l'heure de la colonne, vous pouvez voir le nom par défaut de la contrainte, y compris le nom de la colonne. puis utilisez:

ALTER TABLE  yourTableName DROP CONSTRAINT DF__YourTa__NewCo__47127295;

(le nom de la contrainte n'est qu'un exemple)

Elnaz
la source
2

La solution suivante supprimera la contrainte par défaut spécifique d'une colonne du tableau

Declare @Const NVARCHAR(256)

SET @Const = (
              SELECT TOP 1 'ALTER TABLE' + YOUR TABLE NAME +' DROP CONSTRAINT '+name
              FROM Sys.default_constraints A
              JOIN sysconstraints B on A.parent_object_id = B.id
              WHERE id = OBJECT_ID('YOUR TABLE NAME')
              AND COL_NAME(id, colid)='COLUMN NAME'
              AND OBJECTPROPERTY(constid,'IsDefaultCnst')=1
            )
 EXEC (@Const)
Abdur Rahman
la source
0

J'ai eu des colonnes qui avaient plusieurs contraintes par défaut créées, donc je crée la procédure stockée suivante:

CREATE PROCEDURE [dbo].[RemoveDefaultConstraints] @table_name nvarchar(256), @column_name nvarchar(256)
AS
BEGIN

    DECLARE @ObjectName NVARCHAR(100)

    START: --Start of loop
    SELECT 
        @ObjectName = OBJECT_NAME([default_object_id]) 
    FROM 
        SYS.COLUMNS
    WHERE 
        [object_id] = OBJECT_ID(@table_name) 
        AND [name] = @column_name;

    -- Don't drop the constraint unless it exists
    IF @ObjectName IS NOT NULL
    BEGIN
        EXEC ('ALTER TABLE '+@table_name+' DROP CONSTRAINT ' + @ObjectName)
        GOTO START; --Used to loop in case of multiple default constraints
    END
END
GO

-- How to run the stored proc.  This removes the default constraint(s) for the enabled column on the User table.
EXEC [dbo].[RemoveDefaultConstraints] N'[dbo].[User]', N'enabled'
GO

-- If you hate the proc, just get rid of it
DROP PROCEDURE [dbo].[RemoveDefaultConstraints]
GO
anztenney
la source
0

Utile pour certaines colonnes qui en avaient créé plusieurs default constraints or check constraints :

Script https://stackoverflow.com/a/16359095/206730 modifié

Remarque: ce script est destiné à sys.check_constraints

declare @table_name nvarchar(128)
declare @column_name nvarchar(128)
declare @constraint_name nvarchar(128)
declare @constraint_definition nvarchar(512)

declare @df_name nvarchar(128)
declare @cmd nvarchar(128) 

PRINT 'DROP CONSTRAINT [Roles2016.UsersCRM].Estado'

declare constraints cursor for 
 select t.name TableName, c.name ColumnName, d.name ConstraintName, d.definition ConstraintDefinition
 from sys.tables t   
 join sys.check_constraints d  on d.parent_object_id = t.object_id  
 join sys.columns c  on c.object_id = t.object_id      
 and c.column_id = d.parent_column_id
 where t.name = N'Roles2016.UsersCRM' and c.name = N'Estado'

open constraints
fetch next from constraints into @table_name , @column_name, @constraint_name, @constraint_definition
while @@fetch_status = 0
BEGIN
    print 'CONSTRAINT: ' + @constraint_name
    select @cmd = 'ALTER TABLE [' + @table_name +  '] DROP CONSTRAINT [' +  @constraint_name + ']'
    print @cmd
    EXEC sp_executeSQL @cmd;

  fetch next from constraints into @table_name , @column_name, @constraint_name, @constraint_definition
END

close constraints 
deallocate constraints
Kiquenet
la source
0

Générez toujours un script et passez en revue avant de lancer. Sous le script

  select 'Alter table dbo.' + t.name + ' drop constraint '+ d.name  
  from sys.tables t
  join sys.default_constraints d on d.parent_object_id = t.object_id
  join sys.columns c on c.object_id = t.object_id
       and c.column_id = d.parent_column_id
  where c.name in ('VersionEffectiveDate','VersionEndDate','VersionReasonDesc')
  order by t.name
user6232480
la source
0
declare @table_name nvarchar(100)
declare @col_name nvarchar(100)
declare @constraint nvarchar(100)
set @table_name = N'TableName'
set @col_name = N'ColumnName'

IF EXISTS (select       c.*
    from        sys.columns c 
    inner join  sys.tables t on t.object_id = c.object_id
    where       t.name = @table_name
    and         c.name = @col_name) 
BEGIN

select @constraint=d.name
from 
sys.tables t
join sys.default_constraints d on d.parent_object_id = t.object_id
join sys.columns c on c.object_id = t.object_id
and c.column_id = d.parent_column_id
where 
t.name = @table_name
and c.name = @col_name

    IF LEN(ISNULL(@constraint, '')) <> 0
    BEGIN
        DECLARE @sqlcmd VARCHAR(MAX)
        SET @sqlcmd = 'ALTER TABLE ' + QUOTENAME(@table_name) + ' DROP CONSTRAINT' + 
        QUOTENAME(@constraint);
        EXEC (@sqlcmd);

    END

END
GO
user2832577
la source
0
declare @ery nvarchar(max)
declare @tab nvarchar(max) = 'myTable'
declare @qu nvarchar(max) = 'alter table '+@tab+' drop constraint '

select @ery = (select bj.name from sys.tables as tb 
inner join sys.objects as bj 
on tb.object_id = bj.parent_object_id
where tb.name = @tab and bj.type = 'PK')

exec(@qu+@ery)

Regarde.

user8310624
la source
2
Même si votre code apporte une solution, il est préférable de l'enrouler autour d'un peu d'explications pour expliquer pourquoi il résout la question.
Fabien