Як знайти обмеження за замовчуванням за допомогою INFORMATION_SCHEMA?


116

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

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

Їх там немає? (Я використовую MS SQL Server 2000).

EDIT: Я хочу отримати назву обмеження.

Відповіді:


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!
— Самуїл

Для роботи не залежно від регістру БД має бути o.xtype = 'D'.
— IvanH

37

Здається, у переглядах немає імен обмежень за замовчуванням Information_Schema.

використовувати, SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name щоб знайти обмеження за замовчуванням за назвою


саме те, що мені було потрібно. Спасибі
— drdwilcox

Безпосередньо відповідає на питання краще, ніж пізніші альтернативи (SQL 2000 & запит за назвою обмеження).
— Марк Л.

Це працює лише тоді, коли ви знаєте ім'я обмеження, але якщо це призначено системою ....
— 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

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?


Так і ні, це говорить мені, що за замовчуванням є і що це таке, але мені також потрібна назва обмеження.
— 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 

1

Некромантування.
Якщо вам потрібно лише перевірити, чи існує обмеження за замовчуванням (обмеження
(за замовчуванням) обмеження можуть мати іншу назву в керованих БД),
використовуйте INFORMATION_SCHEMA.COLUMNS (стовпець_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 = ''

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;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.