¿Cómo encuentro una restricción predeterminada usando INFORMATION_SCHEMA?


116

Estoy tratando de probar si existe una restricción predeterminada determinada. No quiero usar la tabla sysobjects, pero el más estándar INFORMATION_SCHEMA.

He usado esto para verificar tablas y restricciones de clave primaria antes, pero no veo restricciones predeterminadas en ninguna parte.

¿No están ahí? (Estoy usando MS SQL Server 2000).

EDITAR: Estoy buscando obtener el nombre de la restricción.

Respuestas:


121

Según tengo entendido, las restricciones de valor predeterminado no forman parte del estándar ISO, por lo que no aparecen en INFORMATION_SCHEMA. INFORMATION_SCHEMA parece ser la mejor opción para este tipo de tarea porque es multiplataforma, pero si la información no está disponible, se deben usar las vistas de catálogo de objetos (sys. *) En lugar de las vistas de tabla del sistema, que están en desuso en SQL Server. 2005 y posteriores.

A continuación, se muestra más o menos lo mismo que la respuesta de @ user186476. Devuelve el nombre de la restricción de valor predeterminado para una columna determinada. (Para los usuarios que no son de SQL Server, necesita el nombre del predeterminado para eliminarlo, y si no nombra la restricción predeterminada usted mismo, SQL Server crea un nombre loco como "DF_TableN_Colum_95AFE4B5". Para facilitar el cambio su esquema en el futuro, ¡siempre nombre explícitamente sus restricciones!)

-- 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
Nota: es posible tener el mismo nombre de tabla en diferentes esquemas, por lo que también debe unirse a la tabla sys.schemas.
Daniel James Bryars

1
@DanielJamesBryars sys.schemas ahora agregado a la consulta.
Stephen Turner

Por favor, vea mi respuesta, que es breve y syssencilla , funciona en todas las versiones de SQL Server, no tiene tablas y es fácil de recordar.
ErikE

2
@ErikE Su código asume que se conoce el nombre de la restricción predeterminada. Ese es un problema fácil de resolver, como lo demuestra su código. Buena respuesta, pregunta incorrecta.
DarLom

Mi código asume eso, porque eso es lo que pidió el interrogador: "Estoy buscando obtener [si 'existe una restricción predeterminada dada'] por el nombre de la restricción". He editado mi respuesta para hacer mucho más clara su naturaleza directa de satisfacción de preguntas. Espero que ayude.
ErikE

43

Puede utilizar lo siguiente para limitar los resultados aún más especificando el nombre de la tabla y el nombre de la columna con los que se correlaciona la restricción predeterminada:

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
Busco esta simple consulta desde hace un par de horas. ¡Thannnnnkkk youuuu!
Samuel

Debe haber o.xtype = 'D' para que funcione en una base de datos que no distinga entre mayúsculas y minúsculas.
IvanH

37

Parece que no hay nombres de restricciones por defecto en las Information_Schemavistas.

usar SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name para encontrar una restricción predeterminada por nombre


justo lo que necesitaba. Gracias
drdwilcox

Responde directamente la pregunta mejor que las alternativas posteriores (SQL 2000 y consulta por nombre de restricción).
Marc L.

Esto solo funciona cuando conoce el nombre de la restricción, pero si está asignado por el sistema ...
TS

12

El siguiente script enumera todas las restricciones predeterminadas y los valores predeterminados para las tablas de usuario en la base de datos en la que se está ejecutando:

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 desea obtener una restricción por los nombres de columna o tabla, o desea obtener todas las restricciones en la base de datos, busque otras respuestas. Sin embargo, si solo está buscando exactamente lo que pide la pregunta, es decir, "probar si existe una restricción predeterminada dada ... por el nombre de la restricción" , entonces hay una manera mucho más fácil.

Aquí hay una respuesta a prueba de futuro que no usa la sysobjectsu otras systablas en absoluto:

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 poco más de espacio en blanco estaría bien, pero esto hace lo que pidió el autor original usando las vistas de catálogo de objetos (sys. *), Que son recomendadas por Microsoft sobre las vistas de tabla del sistema de compatibilidad con versiones anteriores.
Robert Calhoun

2

¿Es la columna COLUMN_DEFAULT de INFORMATION_SCHEMA.COLUMNS lo que está buscando?


Sí y no, me dice que hay un valor predeterminado y cuál es, pero también necesito el nombre de la restricción.
WildJoe

1
Además, tenga en cuenta que si su inicio de sesión de SQL en tiempo de ejecución no posee el esquema dbo, es posible que solo encuentre valores NULL en la columna 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

Nigromante.
Si solo necesita verificar si existe una restricción
predeterminada (las restricciones predeterminadas pueden tener un nombre diferente en las bases de datos mal administradas),
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 

Si desea verificar solo por el nombre de la restricción:

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

Y por último, pero no menos importante, puede crear una vista llamada
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

No creo que esté en INFORMATION_SCHEMA; probablemente tendrá que usar sysobjects o tablas / vistas obsoletas relacionadas.

Pensaría que habría un tipo para esto en INFORMATION_SCHEMA.TABLE_CONSTRAINTS, pero no veo ninguno.


0

Probablemente debido a que en algunos de los otros DBMS SQL la "restricción predeterminada" no es realmente una restricción, no encontrará su nombre en "INFORMATION_SCHEMA.TABLE_CONSTRAINTS", por lo que su mejor opción es "INFORMATION_SCHEMA.COLUMNS" como ya han mencionado otros.

(SQLServer-ignoramus aquí)

La única razón en la que puedo pensar cuando tienes que saber el nombre de la "restricción predeterminada" es si SQLServer no admite el "ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT..."comando. Pero entonces ya se encuentra en una zona no estándar y debe utilizar las formas específicas del producto para obtener lo que necesita.


0

¿Qué tal usar una combinación de CHECK_CONSTRAINTS y ​​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 no contiene información sobre las restricciones predeterminadas.
Stephen Turner

0

Estoy usando el siguiente script para recuperar todos los valores predeterminados (sp_binddefaults) y todas las restricciones predeterminadas con los siguientes 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 = ''

0

Vista del catálogo de objetos : sys.default_constraints

Las vistas del esquema de información INFORMATION_SCHEMA son compatibles con ANSI, pero las restricciones predeterminadas no forman parte del estándar ISO. Microsoft SQL Server proporciona vistas del catálogo del sistema para obtener información sobre los metadatos de los objetos de SQL Server.

sys.default_constraints vista del catálogo del sistema utilizada para obtener información sobre las restricciones predeterminadas.

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;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.