Как найти ограничение по умолчанию с помощью INFORMATION_SCHEMA?

116

Я пытаюсь проверить, существует ли заданное ограничение по умолчанию. Я не хочу использовать таблицу sysobjects, но более стандартную INFORMATION_SCHEMA.

Я раньше использовал это для проверки таблиц и ограничений первичного ключа, но нигде не вижу ограничений по умолчанию.

Их там нет? (Я использую MS SQL Server 2000).

РЕДАКТИРОВАТЬ: Я ищу название ограничения.

WildJoe
источник

Ответы:

121

Насколько я понимаю, ограничения значений по умолчанию не являются частью стандарта ISO, поэтому они не отображаются в INFORMATION_SCHEMA. INFORMATION_SCHEMA кажется лучшим выбором для такого рода задач, потому что он кроссплатформенный, но если информация недоступна, следует использовать представления каталога объектов (sys. *) Вместо представлений системных таблиц, которые устарели в SQL Server. 2005 г. и позже.

Ниже почти то же самое, что и ответ @ user186476. Он возвращает имя ограничения значения по умолчанию для данного столбца. (Для пользователей, не использующих SQL Server, вам нужно имя по умолчанию, чтобы его отбросить, и если вы сами не назовете ограничение по умолчанию, SQL Server создаст какое-то сумасшедшее имя, например "DF_TableN_Colum_95AFE4B5". Чтобы упростить изменение свою схему в будущем, всегда явно указывайте свои ограничения!)

-- 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
Примечание: одно и то же имя таблицы может быть в разных схемах, поэтому вам также следует присоединиться к таблице sys.schemas.
Дэниел Джеймс Брайарс,
1
@DanielJamesBryars sys.schemas теперь добавлен в запрос.
Стивен Тернер
Пожалуйста, посмотрите мой ответ, который краток и приятен, работает во всех версиях SQL Server, не содержит sysтаблиц и легко запоминается.
ErikE
2
@ErikE Ваш код предполагает, что имя ограничения по умолчанию известно. Как показывает ваш код, эту проблему легко решить. Хороший ответ, неправильный вопрос.
DarLom
Мой код действительно предполагает это, потому что именно об этом просил вопрошающий: «Я хочу узнать [существует ли« заданное ограничение по умолчанию »] по имени ограничения». Я отредактировал свой ответ, чтобы сделать его прямой вопрос, отвечающий за вопрос, гораздо более ясным. Надеюсь, это поможет.
ErikE
43

Вы можете использовать следующее, чтобы еще больше сузить результаты, указав имя таблицы и имя столбца, с которыми коррелирует ограничение по умолчанию:

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
Я ищу этот простой запрос пару часов. Thannnnnkkk youuuu!
Samuel
Для работы с базой данных, чувствительной к регистру, должно быть o.xtype = 'D'.
IvanH
37

Кажется, что в представлениях нет имен ограничений по умолчанию Information_Schema.

используйте, SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name чтобы найти ограничение по умолчанию по имени

devio
источник
именно то, что мне было нужно. Спасибо
drdwilcox
Прямые ответы на вопрос лучше, чем более поздние альтернативы (SQL 2000 и запрос по имени ограничения).
Marc L.
Это работает, только если вы знаете имя ограничения, но если оно назначено системой ....
TS
12

В приведенном ниже сценарии перечислены все ограничения по умолчанию и значения по умолчанию для пользовательских таблиц в базе данных, в которой он выполняется:

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

Если вы хотите получить ограничение по именам столбцов или таблиц или хотите получить все ограничения в базе данных, посмотрите другие ответы. Однако, если вы просто ищете именно то, что задает вопрос, а именно: «проверить, существует ли данное ограничение по умолчанию ... по имени ограничения» , то есть гораздо более простой способ.

Вот надежный ответ, который вообще не использует те sysobjectsили иные sysтаблицы:

IF object_id('DF_CONSTRAINT_NAME', 'D') IS NOT NULL BEGIN
   -- constraint exists, work with it.
END
ErikE
источник
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
Немного больше пробелов было бы неплохо, но это делает то, что просил исходный плакат, используя представления каталога объектов (sys. *), Которые рекомендуются Microsoft вместо представлений системных таблиц с обратной совместимостью.
Роберт Калхун
2

Столбец COLUMN_DEFAULT в INFORMATION_SCHEMA.COLUMNS то, что вы ищете?

user12861
источник
Да и нет, он сообщает мне, что есть значение по умолчанию и что это такое, но мне также нужно имя ограничения.
WildJoe,
1
Кроме того, имейте в виду, что если ваша учетная запись SQL среды выполнения не владеет схемой dbo, вы можете найти только значения NULL в столбце COLUMN_DEFAULT.
Глен Литтл,
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
источник
1

Necromancing.
Если вам нужно только проверить, существует ли ограничение по
умолчанию ( ограничения по умолчанию могут иметь другое имя в плохо управляемых БД),
используйте 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 

Если вы хотите проверить только по имени ограничения:

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

И последнее, но не менее важное: вы можете просто создать представление
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

Я не думаю, что это в INFORMATION_SCHEMA - вам, вероятно, придется использовать sysobjects или связанные устаревшие таблицы / представления.

Можно подумать, что в INFORMATION_SCHEMA.TABLE_CONSTRAINTS есть тип для этого, но я его не вижу.

Кейд Ру
источник
0

Вероятно, потому что в некоторых других СУБД SQL «ограничение по умолчанию» на самом деле не является ограничением, вы не найдете его имени в «INFORMATION_SCHEMA.TABLE_CONSTRAINTS», поэтому лучше всего будет «INFORMATION_SCHEMA.COLUMNS», как уже упоминалось другими.

(SQLServer-ignoramus здесь)

Единственная причина, по которой я могу думать, когда вам нужно знать имя «ограничения по умолчанию», - это то, что SQLServer не поддерживает "ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT..."команду. Но тогда вы уже находитесь в нестандартной зоне, и вам нужно использовать специфические для продукта способы, чтобы получить то, что вам нужно.

Милен А. Радев
источник
0

Как насчет использования комбинации CHECK_CONSTRAINTS и 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 не содержит информации об ограничениях по умолчанию.
Стивен Тернер
0

Я использую следующий сценарий, чтобы получить все значения по умолчанию (sp_binddefaults) и все ограничения по умолчанию со следующими сценариями:

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
источник
0

Просмотр каталога объектов : sys.default_constraints

Представления информационной схемы INFORMATION_SCHEMAсовместимы с ANSI, но ограничения по умолчанию не являются частью стандарта ISO. Microsoft SQL Server предоставляет представления системного каталога для получения информации о метаданных объекта SQL Server.

sys.default_constraints представление системного каталога, используемое для получения информации об ограничениях по умолчанию.

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
источник