¿Cómo encuentro una restricción predeterminada usando INFORMATION_SCHEMA?
-
02-07-2019 - |
Pregunta
Estoy tratando de probar si existe una restricción predeterminada dada. No quiero usar la tabla sysobjects, sino el INFORMATION_SCHEMA más estándar.
He usado esto para verificar las tablas y las restricciones de clave principal antes, pero no veo restricciones predeterminadas en ninguna parte.
¿No están allí? (Estoy usando MS SQL Server 2000).
EDITAR: Estoy buscando el nombre de la restricción.
Solución
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 es prácticamente lo mismo que la respuesta de @ user186476. Devuelve el nombre de la restricción de valor por defecto para una columna dada. (Para los usuarios que no son de SQL Server, necesita el nombre del valor predeterminado para eliminarlo, y si no nombra la restricción predeterminada, SQL Server crea un nombre loco como " DF_TableN_Colum_95AFE4B5 " ;. Para que sea más fácil cambie 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'
Otros consejos
Puede usar lo siguiente para restringir aún más los resultados al especificar el Nombre de la tabla y el Nombre de la columna con los que se relaciona 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'
Parece que no hay nombres de Restricción predeterminados en las vistas Information_Schema
.
use SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name
para encontrar una restricción predeterminada por nombre
El script a continuación enumera todas las restricciones predeterminadas y los valores predeterminados para las tablas de usuario en la base de datos en la que se ejecuta:
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
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
Si desea obtener una restricción por los nombres de columna o tabla, o si desea obtener todas las restricciones en la base de datos, busque otras respuestas. Sin embargo, si solo está buscando exactamente lo que pregunta la pregunta, es decir, para " probar si existe una restricción predeterminada dada ... por el nombre de la restricción " , entonces hay mucho más fácil manera.
Aquí hay una respuesta preparada para el futuro que no usa las tablas sysobjects
u otras sys
:
IF object_id('DF_CONSTRAINT_NAME', 'D') IS NOT NULL BEGIN
-- constraint exists, work with it.
END
¿Es la columna COLUMN_DEFAULT de INFORMATION_SCHEMA.COLUMNS lo que está buscando?
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
No creo que esté en INFORMATION_SCHEMA, probablemente tendrás que usar sysobjects o tablas / vistas en desuso relacionadas.
Usted pensaría que habría un tipo para esto en INFORMATION_SCHEMA.TABLE_CONSTRAINTS, pero no veo uno.
Probablemente porque en algunos de los otros DBMS de 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 apuesta es " INFORMATION_SCHEMA.COLUMNS " como otros ya han mencionado.
(SQLServer-ignoramus aquí)
El único motivo por el que puedo pensar cuando tienes que saber el nombre de la restricción predeterminada es si SQLServer no admite " ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT ... "
comando. Pero entonces ya está en una zona no estándar y tiene que usar las formas específicas del producto para obtener lo que necesita.
¿Qué hay de 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
Estoy usando la siguiente secuencia de comandos para recuperar todos los valores predeterminados (sp_bindefault) y todas las restricciones predeterminadas con las siguientes secuencias de comandos:
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 = ''
Vista del catálogo de objetos : sys.default_constraints
Las vistas de esquema de información INFORMATION_SCHEMA
son compatibles con ANSI, pero las restricciones predeterminadas no son parte del estándar ISO. Microsoft SQL Server proporciona vistas de catálogo del sistema para obtener información sobre los metadatos de objetos de SQL Server.
sys.default_constraints
vista de catálogo del sistema utilizada para obtener la 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;