Comment trouver une contrainte par défaut en utilisant INFORMATION_SCHEMA?


116

J'essaye de tester si une contrainte par défaut donnée existe. Je ne veux pas utiliser la table sysobjects, mais la plus standard INFORMATION_SCHEMA.

J'ai déjà utilisé cela pour vérifier les tables et les contraintes de clé primaire, mais je ne vois aucune contrainte par défaut.

Ne sont-ils pas là? (J'utilise MS SQL Server 2000).

EDIT: Je cherche à obtenir le nom de la contrainte.

Réponses:


121

Si je comprends bien, les contraintes de valeur par défaut ne font pas partie de la norme ISO, elles n'apparaissent donc pas dans INFORMATION_SCHEMA. INFORMATION_SCHEMA semble être le meilleur choix pour ce type de tâche car il s'agit de plusieurs plates-formes, mais si les informations ne sont pas disponibles, il faut utiliser les vues de catalogue d'objets (sys. *) Au lieu des vues de table système, qui sont obsolètes dans SQL Server 2005 et plus tard.

Voici à peu près la même chose que la réponse de @ user186476. Il renvoie le nom de la contrainte de valeur par défaut pour une colonne donnée. (Pour les utilisateurs non-SQL Server, vous avez besoin du nom de la valeur par défaut pour la supprimer, et si vous ne nommez pas la contrainte par défaut vous-même, SQL Server crée un nom fou comme "DF_TableN_Colum_95AFE4B5". Pour faciliter la modification votre schéma dans le futur, nommez toujours explicitement vos contraintes!)

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

1
Remarque: il est possible d'avoir le même nom de table dans différents schémas, vous devez donc vous joindre à la table sys.schemas également.
Daniel James Bryars

1
@DanielJamesBryars sys.schemas maintenant ajouté à la requête.
Stephen Turner

Veuillez voir ma réponse qui est courte et douce, fonctionne dans toutes les versions de SQL Server, ne contient aucune systable et est facile à retenir.
ErikE

2
@ErikE Votre code suppose que le nom de la contrainte par défaut est connu. C'est un problème facile à résoudre, comme le montre votre code. Bonne réponse, mauvaise question.
DarLom

Mon code suppose que, parce que c'est ce que le questionneur a demandé - "Je cherche à obtenir [si 'une contrainte par défaut donnée existe'] par le nom de la contrainte." J'ai édité ma réponse pour rendre sa nature de réponse directe aux questions beaucoup plus claire. J'espère que cela pourra aider.
ErikE

43

Vous pouvez utiliser ce qui suit pour affiner encore plus les résultats en spécifiant le nom de la table et le nom de la colonne avec lesquels la contrainte par défaut correspond:

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'

1
Je recherche cette simple requête depuis quelques heures. Thannnnnkkk youuuu!
Samuel

Il devrait y avoir o.xtype = 'D' pour fonctionner dans une base de données sensible à la casse.
IvanH

37

Il ne semble y avoir aucun nom de contrainte par défaut dans le Information_Schema vues.

utiliser SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name pour rechercher une contrainte par défaut par son nom


juste ce dont j'avais besoin. Merci
drdwilcox

Répond directement aux questions mieux que les alternatives ultérieures (SQL 2000 et requête par nom de contrainte).
Marc L.

Cela ne fonctionne que lorsque vous connaissez le nom de la contrainte, mais si cela est attribué par le système ....
TS

12

Le script ci-dessous répertorie toutes les contraintes par défaut et les valeurs par défaut des tables utilisateur de la base de données dans laquelle il est exécuté:

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

5

Si vous souhaitez obtenir une contrainte par les noms de colonne ou de table, ou si vous souhaitez obtenir toutes les contraintes de la base de données, recherchez d'autres réponses. Cependant, si vous cherchez simplement exactement ce que la question demande, à savoir, "tester si une contrainte par défaut donnée existe ... par le nom de la contrainte" , alors il existe un moyen beaucoup plus simple.

Voici une réponse à l'épreuve du temps qui n'utilise pas du tout les tables sysobjectsou d'autres sys:

IF object_id('DF_CONSTRAINT_NAME', 'D') IS NOT NULL BEGIN
   -- constraint exists, work with it.
END

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

1
Un peu plus d'espaces serait bien, mais cela fait ce que l'affiche originale a demandé en utilisant les vues de catalogue d'objets (sys. *), Qui sont recommandées par Microsoft sur les vues de table système de compatibilité descendante.
Robert Calhoun

2

La colonne COLUMN_DEFAULT de INFORMATION_SCHEMA.COLUMNS est-elle ce que vous recherchez?


Oui et non, cela me dit qu'il y a un défaut et ce que c'est, mais j'ai aussi besoin du nom de la contrainte.
WildJoe

1
Sachez également que si votre connexion SQL d'exécution ne possède pas le schéma dbo, vous pouvez uniquement trouver des valeurs NULL dans la colonne 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 

1

Nécromancie.
Si vous avez seulement besoin de vérifier si une contrainte par défaut existe
(la ou les contraintes par défaut peuvent avoir un nom différent dans les bases de données mal gérées),
utilisez 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 

Si vous souhaitez vérifier uniquement par le nom de la contrainte:

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

Enfin, vous pouvez simplement créer une vue appelée
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'
*/

0

Je ne pense pas que ce soit dans INFORMATION_SCHEMA - vous devrez probablement utiliser des sysobjects ou des tables / vues obsolètes associées.

Vous pourriez penser qu'il y aurait un type pour cela dans INFORMATION_SCHEMA.TABLE_CONSTRAINTS, mais je n'en vois pas.


0

Probablement parce que sur certains des autres SGBD SQL, la "contrainte par défaut" n'est pas vraiment une contrainte, vous ne trouverez pas son nom dans "INFORMATION_SCHEMA.TABLE_CONSTRAINTS", donc votre meilleur pari est "INFORMATION_SCHEMA.COLUMNS" comme d'autres l'ont déjà mentionné.

(SQLServer-ignorant ici)

La seule raison à laquelle je peux penser lorsque vous devez connaître le nom de la "contrainte par défaut" est si SQLServer ne prend pas en charge la "ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT..."commande. Mais alors vous êtes déjà dans une zone non standard et vous devez utiliser les moyens spécifiques au produit pour obtenir ce dont vous avez besoin.


0

Que diriez-vous d'utiliser une combinaison de CHECK_CONSTRAINTS et 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

CONSTRAINT_COLUMN_USAGE ne contient aucune information sur les contraintes par défaut.
Stephen Turner

0

J'utilise le script suivant pour récupérer toutes les valeurs par défaut (sp_binddefaults) et toutes les contraintes par défaut avec les scripts suivants:

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 = ''

0

Vue du catalogue d'objets : sys.default_constraints

Les vues de schéma d'informations INFORMATION_SCHEMAsont conformes à la norme ANSI, mais les contraintes par défaut ne font pas partie de la norme ISO. Microsoft SQL Server fournit des vues de catalogue système pour obtenir des informations sur les métadonnées d'objets SQL Server.

sys.default_constraints vue du catalogue système utilisée pour obtenir les informations sur les contraintes par défaut.

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;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.