Wie kann ich die SQL-Standardeinschränkung löschen, ohne den Namen zu kennen?


196

In Microsoft SQL Server ist mir bekannt, dass die Abfrage zum Überprüfen, ob eine Standardeinschränkung für eine Spalte vorhanden ist, und das Löschen einer Standardeinschränkung wie folgt lautet:

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

Aufgrund von Tippfehlern in früheren Versionen der Datenbank kann der Name der Einschränkung jedoch DF_SomeTable_ColNameoder sein DF_SmoeTable_ColName.

Wie kann ich die Standardeinschränkung ohne SQL-Fehler löschen? Standardbeschränkungsnamen werden in der Tabelle INFORMATION_SCHEMA nicht angezeigt, was die Dinge etwas schwieriger macht.

So etwas wie "Löschen Sie die Standardeinschränkung in dieser Tabelle / Spalte" oder "Löschen DF_SmoeTable_ColName", aber geben Sie keine Fehler an, wenn sie nicht gefunden werden kann.


1
Ich beherrsche SQL Server nicht. Können Sie eine Einschränkung umbenennen, nachdem Sie ihren Namen herausgefunden haben? "Ändern Sie die Tabellenumtauschbedingung xxx in yyy" in Oracle.
Jürgen Hartelt

Antworten:


262

Das folgende Skript erweitert den Code von Mitch Wheat und generiert den Befehl, die Einschränkung zu löschen und dynamisch auszuführen.

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)

1
Überprüfen Sie stackoverflow.com/a/15786313/2049986 , um eine Version zu sehen, um alle Einschränkungen für eine Tabelle zu löschen
Jacob van Lingen

Ich benutze sys.check_constraints , nicht sys.default_constraints
Kiquenet

Nicht gültig, wenn für einige Spalten mehrere Standardeinschränkungen erstellt oder Einschränkungen überprüft wurden. Wirdnur für die letzten Einschränkungen in der Abfrage ausgeführt.
Kiquenet

4
Diese Abfrage behandelt nur Standardeinschränkungen, von denen es nur eine pro Spalte geben kann. Der Umgang mit Prüfbeschränkungen ist ein anderes Problem.
Philip Kelley

1
Ich habe diese Antwort aktualisiert, um Unterstützung für nicht standardmäßige Schemanamen hinzuzufügen. Ich hoffe, es macht Ihnen nichts aus, ich kann zurückkehren und eine separate Antwort posten, wenn Sie möchten.
Jakub Januszkiewicz

234

Rob Farleys Blog-Beitrag könnte hilfreich sein:

Etwas wie:

 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

104

Ich habe festgestellt, dass dies funktioniert und keine Verknüpfungen verwendet:

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)

Stellen Sie einfach sicher, dass Spaltenname keine Klammern enthält, da die Abfrage nach einer genauen Übereinstimmung sucht und nichts zurückgibt, wenn es sich um [Spaltenname] handelt.


1
Und diese Antwort funktioniert mit anderen Schemata als dem Standardschema [dbo], im Gegensatz zu allen anderen Antworten.
Contango

Ich habe es nicht getestet, aber Sie können versuchen, ein WHILE (@ObjectName IS NOT NULL) hinzuzufügen, TOP 1 vor SELECT (at) ObjectName = OBJECT_Name ([Standard ...] und nur EXEC ('ALTER) ausführen) TA ... wenn (at) ObjectName NICHT NULL ist.
ScubaSteve

6
Um dieses Skript idempotent zu machen, fügen Sie es IF @ObjectName IS NOT NULLvor dem EXEC-Befehl hinzu
Seven

3
Ich arbeite nicht mit CHECK-Einschränkungen . [default_object_id])ist 0 . Ich bekomme den Wert NULL .
Kiquenet

Süß und einfach, aber laut den Microsoft-Dokumenten wird diese Art, Dinge zu tun, nicht für immer existieren. Es gibt eine Warnung, die darauf hinweist, dass es in der nächsten Version verschwinden wird docs.microsoft.com/en-us/sql/t-sql/statements/…
Hoffnungslos

11

So löschen Sie die Einschränkung für mehrere Spalten:

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)

5

Erweiterte Lösung (berücksichtigt Tabellenschema):

-- 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)

3

Löschen Sie alle Standardbeschränkungen in einer Datenbank - sicher für den Schwellenwert von 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

Nicht gültig, wenn für einige Spalten mehrere Standardeinschränkungen oder Prüfbedingungen erstellt wurden.Wirdnur für die Top-1-Einschränkungen in der Abfrage ausgeführt.
Kiquenet

2

Führen Sie diesen Befehl aus, um alle Einschränkungen zu durchsuchen:

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

Es wird ungefähr so ​​aussehen : DF__Mytable__Column__[ABC123]. Dann können Sie einfach die Einschränkung löschen.


Ich arbeite nicht für mich:exec sp_helpconstraint 'Roles2016.UsersCRM'
Kiquenet

@Kiquenet Sollte nur der Tabellenname sein: exec sp_helpconstraint 'Roles2016'
Baked Inhalf

Es werden nur Fremdschlüsselkonstanten angezeigt. nicht Standardwert constaint
Morez

2

Ich hoffe das könnte hilfreich sein für wen hat ähnliches Problem. ObjectExplorerWählen Sie im Fenster Ihre Datenbank => Tabellen, => Ihre Tabelle => Einschränkungen. Wenn der Kunde beim Erstellen der Spaltenzeit definiert ist, wird der Standardname der Einschränkung einschließlich des Spaltennamens angezeigt. dann benutze:

ALTER TABLE  yourTableName DROP CONSTRAINT DF__YourTa__NewCo__47127295;

(Der Einschränkungsname ist nur ein Beispiel.)


2

Die folgende Lösung löscht eine bestimmte Standardeinschränkung einer Spalte aus der Tabelle

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)

0

Ich hatte einige Spalten mit mehreren Standardeinschränkungen erstellt, daher erstelle ich die folgende gespeicherte Prozedur:

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

0

Nützlich für einige Spalten, für die mehrere default constraints or check constraints erstellt wurden:

Geändertes Skript https://stackoverflow.com/a/16359095/206730

Hinweis: Dieses Skript ist für 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

0

Generieren Sie immer ein Skript und überprüfen Sie es, bevor Sie es ausführen. Unter dem Skript

  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

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

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)

Schau mal.


2
Selbst wenn Ihr Code eine Lösung bringt, ist es am besten, wenn Sie ein paar Erklärungen einschließen, warum er die Frage löst.
Fabien
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.