Como verificar se existe uma restrição no servidor Sql?

271

Eu tenho este sql:

ALTER TABLE dbo.ChannelPlayerSkins
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels

mas, aparentemente, em alguns outros bancos de dados que usamos, a restrição tem um nome diferente. Como verifico se há uma restrição com o nome FK_ChannelPlayerSkins_Channels.

Lieven Cardoen
fonte
Muitas das respostas aqui falham quando o mesmo nome de restrição é usado em vários objetos ou em outro esquema.
Mark Schultheiss

Respostas:

353

tente isto:

SELECT
    * 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS 
    WHERE CONSTRAINT_NAME ='FK_ChannelPlayerSkins_Channels'

- EDITAR -

Quando eu originalmente respondi a essa pergunta, estava pensando em "Chave estrangeira" porque a pergunta original perguntou sobre como encontrar "FK_ChannelPlayerSkins_Channels". Desde então, muitas pessoas comentaram sobre a descoberta de outras "restrições", aqui estão outras perguntas para isso:

--Returns one row for each CHECK, UNIQUE, PRIMARY KEY, and/or FOREIGN KEY
SELECT * 
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
    WHERE CONSTRAINT_NAME='XYZ'  


--Returns one row for each FOREIGN KEY constrain
SELECT * 
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS 
    WHERE CONSTRAINT_NAME='XYZ'


--Returns one row for each CHECK constraint 
SELECT * 
    FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS
    WHERE CONSTRAINT_NAME='XYZ'

aqui está um método alternativo

--Returns 1 row for each CHECK, UNIQUE, PRIMARY KEY, FOREIGN KEY, and/or DEFAULT
SELECT 
    OBJECT_NAME(OBJECT_ID) AS NameofConstraint
        ,SCHEMA_NAME(schema_id) AS SchemaName
        ,OBJECT_NAME(parent_object_id) AS TableName
        ,type_desc AS ConstraintType
    FROM sys.objects
    WHERE type_desc LIKE '%CONSTRAINT'
        AND OBJECT_NAME(OBJECT_ID)='XYZ'

Se você precisar de ainda mais informações sobre restrições, consulte o procedimento armazenado no sistema master.sys.sp_helpconstraintpara ver como obter determinadas informações. Para visualizar o código-fonte usando o SQL Server Management Studio, entre no "Object Explorer". A partir daí, expanda o banco de dados "Mestre", expanda "Programabilidade", "Procedimentos armazenados" e "Procedimentos armazenados do sistema". Você pode encontrar "sys.sp_helpconstraint" e clicar com o botão direito do mouse e selecionar "modificar". Apenas tome cuidado para não salvar nenhuma alteração. Além disso, você pode usar este procedimento armazenado do sistema em qualquer tabela usando-o como EXEC sp_helpconstraint YourTableNameHere.

KM.
fonte
3
Uma coisa a observar, no meu SQL para adicionar a restrição, usei colchetes ao redor do nome como [fk_Client_ProjectID_Project]. Você DEVE remover os colchetes na cláusula WHERE.
ScubaSteve
2
Não há nada errado entre parênteses. Esta é uma pergunta do SQL Server, não do MySQL.
Álvaro González
1
Se for uma restrição exclusiva que você precisa de uma versão ligeiramente diferente: SE NÃO EXISTE (SELECT 1 FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS onde CONSTRAINT_NAME = 'UNIQUE_Order_ExternalReferenceId') BEGIN ALTER TABLE Order ADD CONSTRAINT UNIQUE_Order_ExternalReferenceId UNIQUE END (ExternalReferenceId)
A Coder
2
O exemplo acima não funcionou para uma restrição de coluna exclusiva (SQL2008). Eu tive que usar o seguinte: SELECT * FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE CONSTRAINT_NAME = 'UC_constraintName'
Alan B. Dee
Para restrições padrão, apenas o método alternativo listado retorna uma linha.
ChargingPun
249

A maneira mais fácil de verificar a existência de uma restrição (e fazer algo como eliminá-la, se existir) é usar a função OBJECT_ID () ...

IF OBJECT_ID('dbo.[CK_ConstraintName]', 'C') IS NOT NULL 
    ALTER TABLE dbo.[tablename] DROP CONSTRAINT CK_ConstraintName

OBJECT_ID pode ser usado sem o segundo parâmetro ('C' apenas para restrições de verificação) e isso também pode funcionar, mas se o nome da restrição corresponder ao nome de outros objetos no banco de dados, você poderá obter resultados inesperados.

IF OBJECT_ID('dbo.[CK_ConstraintName]') IS NOT NULL 
    ALTER TABLE dbo.[tablename] DROP CONSTRAINT CK_ConstraintName

OBJECT_ID também pode ser usado com outras "restrições", como restrições de chave estrangeira ou chave primária, etc. Para obter melhores resultados, sempre inclua o tipo de objeto apropriado como o segundo parâmetro para a função OBJECT_ID:

Tipos de objetos de restrição:

  • C = restrição de CHECK
  • D = PADRÃO (restrição ou autônomo)
  • F = restrição de CHAVE ESTRANGEIRA
  • Restrição PK = PRIMARY KEY
  • R = Regra (estilo antigo, autônomo)
  • UQ = restrição ÚNICA

Observe também que o esquema geralmente é necessário. O esquema de restrições geralmente leva o esquema da tabela pai.

A falha em colocar suas restrições (ou o que você estiver verificando) entre colchetes ao usar esse método também pode causar um falso negativo - se o seu objeto usar caracteres incomuns (como a.), Os colchetes serão necessários.

EricI
fonte
16
O importante é adicionar o nome do esquema no parâmetro ao OBJECT_ID da seguinte forma: SE OBJECT_ID ('dbo.CK_ConstraintName', 'C') NÃO É NULL. Sem especificar o esquema, ele retorna NULL.
precisa saber é o seguinte
Olá, obrigado pela sua resposta, é realmente útil. Apenas querendo saber se isso se aplica ao Oracle?
Allen Xia
Não funciona no sql2000. Basta OBJECTPROPERTY(OBJECT_ID('constraint_name'), 'IsConstraint') = 1ser compatível com a versão atual até o sql2000. No dboesquema necessário também.
Wqw 12/07/19
47

Se você estiver procurando por outro tipo de restrição, por exemplo, padrões, deverá usar uma consulta diferente (em Como encontrar uma restrição padrão usando o INFORMAÇÕES_SCHEMA? Respondida por devio ). Usar:

SELECT * FROM sys.objects WHERE type = 'D' AND name = @name

para encontrar uma restrição padrão por nome.

Reuni diferentes verificações 'SE NÃO EXISTE' na minha postagem ' DDL' SE NÃO EXISTE 'condições para tornar os scripts SQL novamente executáveis ​​"

Michael Freidgeim
fonte
28
IF (OBJECT_ID('FK_ChannelPlayerSkins_Channels') IS NOT NULL)
DevDave
fonte
Acontece que eu tinha para adicionar o nome do esquema, consulte stackoverflow.com/questions/29680286/...
Johan Maes
19

Você está olhando algo parecido com isto, abaixo é testado no SQL Server 2005

SELECT * FROM sys.check_constraints WHERE 
object_id = OBJECT_ID(N'[dbo].[CK_accounts]') AND 
parent_object_id = OBJECT_ID(N'[dbo]. [accounts]')
asyncwait
fonte
10

Apenas algo a observar ......

No SSMS do SQL Server 2008 R2, o comando "Restrição de script como -> DROP AND CREATE To" produz T-SQL como abaixo

USE [MyDatabase]
GO

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[DEF_Detail_IsDeleted]') AND type = 'D')
BEGIN
ALTER TABLE [Patient].[Detail] DROP CONSTRAINT [DEF_Detail_IsDeleted]
END

GO

USE [MyDatabase]
GO

ALTER TABLE [Patient].[Detail] ADD  CONSTRAINT [DEF_Detail_IsDeleted]  DEFAULT ((0)) FOR [IsDeleted]
GO

Fora da caixa, esse script NÃO elimina a restrição porque o SELECT retorna 0 linhas. (consulte a publicação Microsoft Connect ).

O nome da restrição padrão está errado, mas entendo que também tem algo a ver com a função OBJECT_ID, pois alterar o nome não resolve o problema.

Para corrigir isso, removi o uso de OBJECT_ID e usei o nome da restrição padrão.

(SELECT * FROM dbo.sysobjects WHERE [name] = (N'DEF_Detail_IsDeleted') AND type = 'D')
Mike1234
fonte
1
Parece que o script não qualifica o nome do esquema. Seria mais seguro usar se OBJECT_ID(N'[YourSchema].[DEF_Detail_IsDeleted]')você tiver 2 restrições com o mesmo nome em esquemas diferentes.
Martin Smith
7

Eu uso a consulta a seguir para verificar uma restrição existente antes de criá-la.

IF (NOT EXISTS(SELECT 1 FROM sysconstraints WHERE OBJECT_NAME(constid) = 'UX_CONSTRAINT_NAME' AND OBJECT_NAME(id) = 'TABLE_NAME')) BEGIN
...
END

Isso consulta a restrição por nome, segmentando um determinado nome de tabela. Espero que isto ajude.

Christo
fonte
3
IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.TableName'))
 BEGIN 
ALTER TABLE TableName DROP CONSTRAINT CONSTRAINTNAME 
END 
StackOrder
fonte
3
IF EXISTS(SELECT TOP 1 1 FROM sys.default_constraints WHERE parent_object_id = OBJECT_ID(N'[dbo].[ChannelPlayerSkins]') AND name = 'FK_ChannelPlayerSkins_Channels')
BEGIN
    DROP CONSTRAINT FK_ChannelPlayerSkins_Channels
END
GO
Tim Masters
fonte
2

INFORMATION_SCHEMAé seu amigo. Tem todos os tipos de visualizações que mostram todos os tipos de informações de esquema. Verifique as visualizações do seu sistema. Você encontrará três visões que lidam com restrições, uma delas CHECK_CONSTRAINTS.

TomTom
fonte
1

Eu uso isso para verificar se há restrições remotas em uma coluna. Deve ter tudo o que você precisa.

DECLARE
  @ps_TableName VARCHAR(300)
  , @ps_ColumnName VARCHAR(300)

SET @ps_TableName = 'mytable'
SET @ps_ColumnName = 'mycolumn'

DECLARE c_ConsList CURSOR LOCAL STATIC FORWARD_ONLY FOR
    SELECT
    'ALTER TABLE ' + RTRIM(tb.name) + ' drop constraint ' + sco.name AS csql
    FROM
        sys.Objects tb
        INNER JOIN sys.Columns tc on (tb.Object_id = tc.object_id)
        INNER JOIN sys.sysconstraints sc ON (tc.Object_ID = sc.id and tc.column_id = sc.colid)
        INNER JOIN sys.objects sco ON (sc.Constid = sco.object_id)
    where
        tb.name=@ps_TableName
        AND tc.name=@ps_ColumnName
OPEN c_ConsList
FETCH c_ConsList INTO @ls_SQL
WHILE (@@FETCH_STATUS = 0) BEGIN

    IF RTRIM(ISNULL(@ls_SQL, '')) <> '' BEGIN
        EXECUTE(@ls_SQL)
    END
    FETCH c_ConsList INTO @ls_SQL
END
CLOSE c_ConsList
DEALLOCATE c_ConsList
user2196815
fonte
0
SELECT tabla.name as Tabla,

        restriccion.name as Restriccion, 
        restriccion.type as Tipo, 
        restriccion.type_desc as Tipo_Desc
FROM {DATABASE_NAME}.sys.objects tabla 

INNER JOIN {DATABASE_NAME}.sys.objects restriccion

ON tabla.object_id = restriccion.parent_object_id

WHERE tabla.type = 'U' - Solo tablas creadas por el usuario.

AND restriccion.type = 'UQ' --Tipo de Restriccion UNIQUE

ORDER BY tabla.name, restriccion.type_desc                
Christhian
fonte
1
Essa resposta seria mais útil se houvesse alguma explicação junto, em vez de apenas despejar código.
Sam Hanley
1
Para segunda @ sphanley: Você responde a uma pergunta antiga que já possui várias respostas bem recebidas. Explique o que é melhor ou pelo menos específico sobre sua resposta para que valha a pena postar.
Honk
0

Você pode usar o acima com uma ressalva:

IF EXISTS(
    SELECT 1 FROM sys.foreign_keys 
    WHERE parent_object_id = OBJECT_ID(N'dbo.TableName') 
        AND name = 'CONSTRAINTNAME'
)
BEGIN 
    ALTER TABLE TableName DROP CONSTRAINT CONSTRAINTNAME 
END 

É necessário usar o, name = [Constraint name]pois uma tabela pode ter várias chaves estrangeiras e ainda não ter a chave estrangeira sendo verificada.

alaniane
fonte