Как отказаться от значения по умолчанию или аналогичного ограничения в T-SQL?

Я знаю синтаксис:

ALTER TABLE [TheTable] DROP CONSTRAINT [TheDefaultConstraint]

но как мне отказаться от ограничения по умолчанию, если я не знаю его имени? (То есть он был автоматически создан в CREATE TABLE раз.)


person Frank Krueger    schedule 14.07.2009    source источник


Ответы (6)


Если вы хотите сделать это вручную, вы можете использовать Management Studio, чтобы найти его (в узле «Ограничения» внутри таблицы).

Чтобы сделать это с помощью SQL:

  • Если ограничения являются ограничениями по умолчанию, вы можете использовать sys.default_constraints, чтобы найти их:

    SELECT OBJECT_NAME(parent_object_id) AS TableName, name AS ConstraintName
    FROM sys.default_constraints ORDER BY TableName, ConstraintName
    
  • Если вы ищете и другие ограничения (проверка, уникальный, внешний ключ, значение по умолчанию, первичный ключ), вы можете использовать sysconstraints:

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

Вы не говорите, какую версию SQL Server вы используете. Вышеупомянутое работает как с SQL 2005, так и с SQL 2008.

person adrianbanks    schedule 14.07.2009
comment
Первый запрос отлично работал в SQL 2008 r2, когда я сначала нашел объектный идентификатор таблицы с DECLARE @ParentObjectId INT = (select OBJECT_ID from sys.objects where name = 'ParentTable' AND type = 'U') и добавил WHERE parent_object_id = @ParentObjectId к запросу. В противном случае вы получите все ограничения по умолчанию в базе данных. - person Torrents; 27.01.2015
comment
Это хорошо, но не показывает схему, в которой находятся таблицы. Было бы неплохо, если бы вы добавили соединение к sys.schemas. - person AperioOculus; 01.02.2017
comment
Если вы знаете имя таблицы, добавьте предложение WHERE в SELECT, чтобы вам не приходилось искать в возможно длинном списке имен таблиц. Автоматически сгенерированные имена, кажется, содержат усеченные части имени таблицы и столбца, что позволит вам определить правильное ограничение. Удачи! - person Marcell; 10.04.2018

Вы можете использовать этот код, чтобы сделать это автоматически:

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 '+@tableName+' DROP CONSTRAINT ' + @ConstraintName)

Просто замените <MYTABLENAME> и <MYCOLUMNNAME> соответствующим образом.

person Polemarch    schedule 25.05.2012
comment
Для ленивых (и разработчиков Microsoft SQL Server) в знак уважения к этому ответу замените две верхние строки на CREATE PROCEDURE dbo.DropColumnDefaultOrConstraint @tableName VARCHAR(MAX), @columnName VARCHAR(MAX) AS, затем оберните BEGIN и END и используйте EXEC DropColumnDefaultOrConstraint 'tablename', 'columnname'; - person Chris; 02.05.2015
comment
Я просто не понимаю, почему MS SQL не отменяет автоматически ограничения по умолчанию. - person Tim; 12.07.2016
comment
этот автоматизированный сценарий необходим для любого механизма обновления схемы базы данных с возможностью самостоятельного развертывания. Интересно, как это делает инструмент миграции EF? основной недостаток, заключающийся в том, что SQL-сервер генерирует имена для анонимных значений по умолчанию и требует, чтобы вы знали / получали это имя, чтобы изменить или отбросить его снова, является проблемой, которую давно следовало решить в самом синтаксисе tsql. но он все еще присутствует в sql2016. @Tim да, или хотя бы синтаксис для принудительного сброса. - person Cee McSharpface; 31.08.2016
comment
@dlatikay EF не обрабатывает ограничения по умолчанию. Он не будет создавать их по умолчанию (поскольку нет возможности установить их с помощью атрибутов или свободного API), но если вы добавите их вручную, EF никогда не будет проверять, чтобы удалить их при других изменениях. Я не знаю, правда ли это с автоматическими миграциями. - person Tim; 31.08.2016
comment
@Tim текущая версия EF может это сделать. Я поискал его из любопытства, и их подход очень похож: они извлекают имя из sys.default_constraints; посмотрите в строке 577 и далее - person Cee McSharpface; 31.08.2016
comment
@dlatikay О, спасибо, приятно знать, что они исправлены в EF Core. Я все еще на 6. Стоит ли обновление? - person Tim; 31.08.2016

Или вы можете найти его, используя представление каталога sys.check_constraints.

person Alex_L    schedule 14.07.2009

Вы можете найти имя ограничения с помощью процедуры sp_help [имя таблицы], а затем отбросить его по имени.

Или вы, вероятно, можете сделать это через Management studio.

person Tetraneutron    schedule 14.07.2009

Для одной таблицы и столбца в одной строке используйте следующие

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;

Если у вас есть несколько ограничений для столбца, вам нужно будет различать ограничение, которое вам нужно, но если у вас просто ограничение по умолчанию, это поможет.

Ознакомьтесь с другими столбцами, доступными в information_schema, чтобы вы могли различать дальше.

person sweetfa    schedule 03.12.2013

Вот моя собственная версия, которая отбрасывает все зависимые ограничения - ограничение по умолчанию (если существует) и все затронутые проверочные ограничения (как кажется в стандарте SQL и как кажется в некоторых других базах данных). так)

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

(Осторожно: и TableName, и ColumnToBeDropped появляются дважды в приведенном выше коде)

Это работает путем создания одиночного ALTER TABLE TableName DROP CONSTRAINT c1, ..., COLUMN ColumnToBeDropped и его выполнения.

person Piotr Findeisen    schedule 05.01.2015