Como encontro uma restrição padrão usando INFORMATION_SCHEMA?

116

Estou tentando testar se existe uma determinada restrição padrão. Não quero usar a tabela sysobjects, mas sim a mais padrão INFORMATION_SCHEMA.

Eu usei isso para verificar as tabelas e restrições de chave primária antes, mas não vejo restrições padrão em lugar nenhum.

Eles não estão lá? (Estou usando o MS SQL Server 2000).

EDIT: Estou tentando obter o nome da restrição.

WildJoe
fonte

Respostas:

121

Pelo que entendi, as restrições de valor padrão não fazem parte do padrão ISO, então não aparecem em INFORMATION_SCHEMA. INFORMATION_SCHEMA parece ser a melhor escolha para este tipo de tarefa porque é multiplataforma, mas se a informação não estiver disponível, deve-se usar as visualizações do catálogo de objetos (sys. *) Em vez das visualizações de tabela do sistema, que são obsoletas no SQL Server 2005 e mais tarde.

Abaixo está praticamente a mesma resposta de @ user186476. Ele retorna o nome da restrição de valor padrão para uma determinada coluna. (Para usuários que não são do SQL Server, você precisa do nome do padrão para eliminá-lo e, se você não nomear a restrição padrão, o SQL Server cria um nome maluco como "DF_TableN_Colum_95AFE4B5". Para facilitar a alteração seu esquema no futuro, sempre nomeie explicitamente suas restrições!)

-- returns name of a column's default value constraint 
SELECT
    default_constraints.name
FROM 
    sys.all_columns

        INNER JOIN
    sys.tables
        ON all_columns.object_id = tables.object_id

        INNER JOIN 
    sys.schemas
        ON tables.schema_id = schemas.schema_id

        INNER JOIN
    sys.default_constraints
        ON all_columns.default_object_id = default_constraints.object_id

WHERE 
        schemas.name = 'dbo'
    AND tables.name = 'tablename'
    AND all_columns.name = 'columnname'
Robert Calhoun
fonte
1
Nota: é possível ter o mesmo nome de tabela em esquemas diferentes, portanto, você também deve unir na tabela sys.schemas.
Daniel James Bryars
1
@DanielJamesBryars sys.schemas agora adicionado à consulta.
Stephen Turner,
Veja minha resposta, que é curta e doce, funciona em todas as versões do SQL Server, não tem systabelas e é fácil de lembrar.
ErikE
2
@ErikE Seu código assume que o nome da restrição padrão é conhecido. Esse é um problema fácil de resolver, como demonstra seu código. Boa resposta, pergunta errada.
DarLom
Meu código presume isso, porque é isso que o questionador pediu - "Estou procurando saber [se 'uma determinada restrição padrão existe'] pelo nome da restrição". Eu editei minha resposta para tornar sua natureza de satisfação direta de perguntas muito mais clara. Espero que ajude.
ErikE
43

Você pode usar o seguinte para restringir os resultados ainda mais especificando o nome da tabela e o nome da coluna aos quais a restrição padrão se correlaciona:

select * from sysobjects o 
inner join syscolumns c
on o.id = c.cdefault
inner join sysobjects t
on c.id = t.id
where o.xtype = 'D'
and c.name = 'Column_Name'
and t.name = 'Table_Name'
Tim Lentine
fonte
1
Eu procuro por esta consulta simples há algumas horas. Thannnnnkkk youuuu!
Samuel
Deve haver o.xtype = 'D' para trabalhar em um banco de dados com distinção entre maiúsculas e minúsculas.
IvanH,
37

Parece não haver nomes de restrição padrão nas Information_Schemavisualizações.

use SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name para encontrar uma restrição padrão por nome

Devio
fonte
apenas o que eu precisava. Obrigado
drdwilcox
Responde diretamente às perguntas melhor do que as alternativas posteriores (SQL 2000 e consulta por nome de restrição).
Marc L.
Isso só funciona quando você sabe o nome da restrição, mas se este for atribuído pelo sistema ...
TS
12

O script a seguir lista todas as restrições padrão e os valores padrão para as tabelas do usuário no banco de dados em que está sendo executado:

SELECT  
        b.name AS TABLE_NAME,
        d.name AS COLUMN_NAME,
        a.name AS CONSTRAINT_NAME,
        c.text AS DEFAULT_VALUE
FROM sys.sysobjects a INNER JOIN
        (SELECT name, id
         FROM sys.sysobjects 
         WHERE xtype = 'U') b on (a.parent_obj = b.id)
                      INNER JOIN sys.syscomments c ON (a.id = c.id)
                      INNER JOIN sys.syscolumns d ON (d.cdefault = a.id)                                          
 WHERE a.xtype = 'D'        
 ORDER BY b.name, a.name
Johan Badenhorst
fonte
5

Se você deseja obter uma restrição pelos nomes de coluna ou tabela, ou deseja obter todas as restrições no banco de dados, procure outras respostas. No entanto, se você está apenas procurando exatamente o que a pergunta pede, a saber, "testar se uma determinada restrição padrão existe ... pelo nome da restrição" , então há uma maneira muito mais fácil.

Aqui está uma resposta preparada para o futuro que não usa a sysobjectsou outras systabelas:

IF object_id('DF_CONSTRAINT_NAME', 'D') IS NOT NULL BEGIN
   -- constraint exists, work with it.
END
ErikE
fonte
3
select c.name, col.name from sys.default_constraints c
    inner join sys.columns col on col.default_object_id = c.object_id
    inner join sys.objects o  on o.object_id = c.parent_object_id
    inner join sys.schemas s on s.schema_id = o.schema_id
where s.name = @SchemaName and o.name = @TableName and col.name = @ColumnName
Florent
fonte
1
Um pouco mais de espaço em branco seria bom, mas isso faz o que o autor original pediu usando as visualizações do catálogo de objetos (sys. *), Que são recomendadas pela Microsoft em vez das visualizações de tabela do sistema de compatibilidade retroativa.
Robert Calhoun,
2

A coluna COLUMN_DEFAULT de INFORMATION_SCHEMA.COLUMNS é o que você está procurando?

user12861
fonte
Sim e não, ele me diz que há um padrão e o que é, mas também preciso do nome da restrição.
WildJoe
1
Além disso, esteja ciente de que se o login do SQL em tempo de execução não possuir o esquema dbo, você só poderá encontrar valores NULL na coluna COLUMN_DEFAULT.
Glen Little
1
WHILE EXISTS( 
    SELECT * FROM  sys.all_columns 
    INNER JOIN sys.tables ST  ON all_columns.object_id = ST.object_id
    INNER JOIN sys.schemas ON ST.schema_id = schemas.schema_id
    INNER JOIN sys.default_constraints ON all_columns.default_object_id = default_constraints.object_id
    WHERE 
    schemas.name = 'dbo'
    AND ST.name = 'MyTable'
)
BEGIN 
DECLARE @SQL NVARCHAR(MAX) = N'';

SET @SQL = (  SELECT TOP 1
     'ALTER TABLE ['+  schemas.name + '].[' + ST.name + '] DROP CONSTRAINT ' + default_constraints.name + ';'
   FROM 
      sys.all_columns

         INNER JOIN
      sys.tables ST
         ON all_columns.object_id = ST.object_id

         INNER JOIN 
      sys.schemas
         ON ST.schema_id = schemas.schema_id

         INNER JOIN
      sys.default_constraints
         ON all_columns.default_object_id = default_constraints.object_id

   WHERE 
         schemas.name = 'dbo'
      AND ST.name = 'MyTable'
      )
   PRINT @SQL
   EXECUTE sp_executesql @SQL 

   --End if Error 
   IF @@ERROR <> 0 
   BREAK
END 
user3059720
fonte
1

Necromante.
Se você só precisa verificar se existe uma restrição
padrão (restrição (ões) padrão podem ter nomes diferentes em bancos de dados mal gerenciados),
use INFORMATION_SCHEMA.COLUMNS (column_default):

IF NOT EXISTS(
    SELECT * FROM INFORMATION_SCHEMA.COLUMNS
    WHERE (1=1) 
    AND TABLE_SCHEMA = 'dbo' 
    AND TABLE_NAME = 'T_VWS_PdfBibliothek' 
    AND COLUMN_NAME = 'PB_Text'
    AND COLUMN_DEFAULT IS NOT NULL  
)
BEGIN 
    EXECUTE('ALTER TABLE dbo.T_VWS_PdfBibliothek 
                ADD CONSTRAINT DF_T_VWS_PdfBibliothek_PB_Text DEFAULT (N''image'') FOR PB_Text; 
    '); 
END 

Se você quiser verificar apenas pelo nome da restrição:

-- Alternative way: 
IF OBJECT_ID('DF_CONSTRAINT_NAME', 'D') IS NOT NULL 
BEGIN
    -- constraint exists, deal with it.
END 

E por último, mas não menos importante, você pode apenas criar uma visualização chamada
INFORMATION_SCHEMA.DEFAULT_CONSTRAINTS:

CREATE VIEW INFORMATION_SCHEMA.DEFAULT_CONSTRAINTS 
AS 
SELECT 
     DB_NAME() AS CONSTRAINT_CATALOG 
    ,csch.name AS CONSTRAINT_SCHEMA
    ,dc.name AS CONSTRAINT_NAME 
    ,DB_NAME() AS TABLE_CATALOG 
    ,sch.name AS TABLE_SCHEMA 
    ,syst.name AS TABLE_NAME 
    ,sysc.name AS COLUMN_NAME 
    ,COLUMNPROPERTY(sysc.object_id, sysc.name, 'ordinal') AS ORDINAL_POSITION 
    ,dc.type_desc AS CONSTRAINT_TYPE 
    ,dc.definition AS COLUMN_DEFAULT 

    -- ,dc.create_date 
    -- ,dc.modify_date 
FROM sys.columns AS sysc -- 46918 / 3892 with inner joins + where 
-- FROM sys.all_columns AS sysc -- 55429 / 3892 with inner joins + where 

INNER JOIN sys.tables AS syst 
    ON syst.object_id = sysc.object_id 

INNER JOIN sys.schemas AS sch
    ON sch.schema_id = syst.schema_id 

INNER JOIN sys.default_constraints AS dc 
    ON sysc.default_object_id = dc.object_id

INNER JOIN sys.schemas AS csch
    ON csch.schema_id = dc.schema_id 

WHERE (1=1) 
AND dc.is_ms_shipped = 0 

/*
WHERE (1=1) 
AND sch.name = 'dbo'
AND syst.name = 'tablename'
AND sysc.name = 'columnname'
*/
Stefan Steiger
fonte
0

Não acho que esteja no INFORMATION_SCHEMA - você provavelmente terá que usar sysobjects ou tabelas / visualizações obsoletas relacionadas.

Você pensaria que haveria um tipo para isso em INFORMATION_SCHEMA.TABLE_CONSTRAINTS, mas não vejo nenhum.

Cade Roux
fonte
0

Provavelmente porque em alguns dos outros SGBDs SQL a "restrição padrão" não é realmente uma restrição, você não encontrará seu nome em "INFORMATION_SCHEMA.TABLE_CONSTRAINTS", então sua melhor aposta é "INFORMATION_SCHEMA.COLUMNS" como outros já mencionaram.

(SQLServer-ignoramus aqui)

A única razão que posso pensar quando você precisa saber o nome da "restrição padrão" é se o SQLServer não oferece suporte ao "ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT..."comando. Mas então você já está em uma zona fora do padrão e deve usar as formas específicas do produto para obter o que precisa.

Milen A. Radev
fonte
0

Que tal usar uma combinação de CHECK_CONSTRAINTS e CONSTRAINT_COLUMN_USAGE:

    select columns.table_name,columns.column_name,columns.column_default,checks.constraint_name
          from information_schema.columns columns
             inner join information_schema.constraint_column_usage usage on 
                  columns.column_name = usage.column_name and columns.table_name = usage.table_name
             inner join information_schema.check_constraints checks on usage.constraint_name = checks.constraint_name
    where columns.column_default is not null

fonte
CONSTRAINT_COLUMN_USAGE não contém nenhuma informação sobre restrições padrão.
Stephen Turner,
0

Estou usando o script a seguir para recuperar todos os padrões (sp_binddefaults) e todas as restrições padrão com os seguintes scripts:

SELECT 
    t.name AS TableName, c.name AS ColumnName, SC.COLUMN_DEFAULT AS DefaultValue, dc.name AS DefaultConstraintName
FROM  
    sys.all_columns c
    JOIN sys.tables t ON c.object_id = t.object_id
    JOIN sys.schemas s ON t.schema_id = s.schema_id
    LEFT JOIN sys.default_constraints dc ON c.default_object_id = dc.object_id
    LEFT JOIN INFORMATION_SCHEMA.COLUMNS SC ON (SC.TABLE_NAME = t.name AND SC.COLUMN_NAME = c.name)
WHERE 
    SC.COLUMN_DEFAULT IS NOT NULL
    --WHERE t.name = '' and c.name = ''
Mirec
fonte
0

Visualização do Catálogo de Objetos : sys.default_constraints

As visualizações do esquema de informações INFORMATION_SCHEMAsão compatíveis com ANSI, mas as restrições padrão não fazem parte do padrão ISO. O Microsoft SQL Server fornece visualizações do catálogo do sistema para obter informações sobre os metadados de objeto do SQL Server.

sys.default_constraints visualização do catálogo do sistema usada para obter informações sobre as restrições padrão.

SELECT so.object_id TableName,
       ss.name AS TableSchema,
       cc.name AS Name,
       cc.object_id AS ObjectID,              
       sc.name AS ColumnName,
       cc.parent_column_id AS ColumnID,
       cc.definition AS Defination,
       CONVERT(BIT,
               CASE cc.is_system_named
                   WHEN 1
                   THEN 1
                   ELSE 0
               END) AS IsSystemNamed,
       cc.create_date AS CreationDate,
       cc.modify_date AS LastModifiednDate
FROM sys.default_constraints cc WITH (NOLOCK)
     INNER JOIN sys.objects so WITH (NOLOCK) ON so.object_id = cc.parent_object_id
     LEFT JOIN sys.schemas ss WITH (NOLOCK) ON ss.schema_id = so.schema_id
     LEFT JOIN sys.columns sc WITH (NOLOCK) ON sc.column_id = cc.parent_column_id
                                               AND sc.object_id = cc.parent_object_id
ORDER BY so.name,
         cc.name;
Eigenharsha
fonte