Bagaimana cara menemukan batasan default menggunakan INFORMATION_SCHEMA?

116

Saya mencoba untuk menguji apakah ada batasan default yang diberikan. Saya tidak ingin menggunakan tabel sysobjects, tetapi INFORMATION_SCHEMA yang lebih standar.

Saya telah menggunakan ini untuk memeriksa tabel dan batasan kunci utama sebelumnya, tetapi saya tidak melihat batasan default di mana pun.

Apakah mereka tidak ada disana? (Saya menggunakan MS SQL Server 2000).

EDIT: Saya ingin mendapatkan nama kendala.

WildJoe
sumber

Jawaban:

121

Seperti yang saya pahami, batasan nilai default bukan bagian dari standar ISO, sehingga tidak muncul di INFORMATION_SCHEMA. INFORMATION_SCHEMA sepertinya pilihan terbaik untuk jenis tugas ini karena lintas platform, tetapi jika informasi tidak tersedia seseorang harus menggunakan tampilan Katalog objek (sys. *) Dan bukan tampilan tabel sistem, yang sudah usang di SQL Server 2005 dan kemudian.

Di bawah ini hampir sama dengan jawaban @ user186476. Ini mengembalikan nama batasan nilai default untuk kolom tertentu. (Untuk pengguna non-SQL Server, Anda memerlukan nama default untuk menghapusnya, dan jika Anda tidak menamai batasan default itu sendiri, SQL Server akan membuat beberapa nama gila seperti "DF_TableN_Colum_95AFE4B5". Untuk mempermudah pengubahan skema Anda di masa mendatang, selalu beri nama batasan Anda secara eksplisit!)

-- 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'
Robert Calhoun
sumber
1
Catatan: dimungkinkan untuk memiliki nama tabel yang sama di skema yang berbeda, jadi Anda juga harus bergabung di tabel sys.schemas.
Daniel James Bryars
1
@DanielJamesBryars sys.schemas sekarang ditambahkan ke kueri.
Stephen Turner
Silakan lihat jawaban saya yang singkat & manis, berfungsi di semua versi SQL Server, tidak ada systabel, dan mudah diingat.
ErikE
2
@ErikE Kode Anda mengasumsikan nama dari batasan default diketahui. Itu masalah yang mudah dipecahkan, seperti yang ditunjukkan oleh kode Anda. Jawaban yang bagus, pertanyaan yang salah.
DarLom
Kode saya mengasumsikan bahwa, karena itulah yang diminta penanya— "Saya ingin mendapatkan [apakah 'batasan default tertentu ada'] dengan nama batasan." Saya telah mengedit jawaban saya untuk memperjelas sifatnya yang langsung memuaskan pertanyaan. Semoga membantu.
ErikE
43

Anda dapat menggunakan yang berikut ini untuk mempersempit hasil lebih lanjut dengan menentukan Nama Tabel dan Nama Kolom yang terkait dengan Batasan Default:

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'
Tim Lentine
sumber
1
Saya mencari kueri sederhana ini sejak beberapa jam. Thannnnnkkk youuuu!
Samuel
Harus ada o.xtype = 'D' untuk bekerja bukan database case sensitive.
IvanH
37

Tampaknya tidak ada nama Batasan Default dalam Information_Schematampilan.

gunakan SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name untuk menemukan batasan default berdasarkan nama

devio
sumber
hanya apa yang saya butuhkan. Terima kasih
drdwilcox
Secara langsung menjawab pertanyaan dengan lebih baik daripada alternatif yang lebih baru (SQL 2000 & kueri dengan nama batasan).
Marc L.
Ini hanya berfungsi jika Anda mengetahui nama kendala tetapi jika sistem ini ditetapkan ....
TS
12

Skrip di bawah ini mencantumkan semua batasan default dan nilai default untuk tabel pengguna dalam database yang sedang dijalankan:

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
Johan Badenhorst
sumber
5

Jika Anda ingin mendapatkan batasan berdasarkan nama kolom atau tabel, atau Anda ingin mendapatkan semua batasan dalam database, lihat jawaban lain. Namun, jika Anda hanya mencari apa yang ditanyakan pertanyaan, yaitu, untuk "menguji jika batasan default tertentu ada ... dengan nama batasan" , maka ada cara yang jauh lebih mudah.

Berikut adalah jawaban bukti masa depan yang tidak menggunakan tabel sysobjectsatau systabel lain sama sekali:

IF object_id('DF_CONSTRAINT_NAME', 'D') IS NOT NULL BEGIN
   -- constraint exists, work with it.
END
ErikE
sumber
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
Florent
sumber
1
Sedikit lebih banyak ruang kosong akan menyenangkan, tetapi ini melakukan apa yang diminta poster asli menggunakan tampilan katalog objek (sys. *), Yang direkomendasikan oleh Microsoft atas tampilan tabel sistem kompatibilitas-mundur.
Robert Calhoun
2

Apakah kolom COLUMN_DEFAULT INFORMATION_SCHEMA.COLUMNS adalah yang Anda cari?

pengguna12861
sumber
Ya dan tidak, itu memberi tahu saya ada default dan apa itu, tapi saya butuh nama kendala juga.
WildJoe
1
Juga, ketahuilah bahwa jika login SQL runtime Anda tidak memiliki skema dbo, Anda hanya dapat menemukan nilai NULL di kolom 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 
pengguna3059720
sumber
1

Necromancing.
Jika Anda hanya perlu memeriksa apakah ada batasan
default ( batasan default mungkin memiliki nama berbeda di DB yang dikelola dengan buruk),
gunakan INFORMATION_SCHEMA.COLUMNS (default_kolom):

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 

Jika Anda ingin memeriksa hanya dengan nama kendala:

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

Dan yang tak kalah pentingnya, Anda bisa membuat tampilan bernama
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'
*/
Stefan Steiger
sumber
0

Saya tidak berpikir itu ada di INFORMATION_SCHEMA - Anda mungkin harus menggunakan sysobjects atau tabel / tampilan terkait yang ditinggalkan.

Anda akan mengira akan ada jenis untuk ini di INFORMATION_SCHEMA.TABLE_CONSTRAINTS, tetapi saya tidak melihatnya.

Cade Roux
sumber
0

Mungkin karena pada beberapa DBMS SQL lain, "batasan default" sebenarnya bukan batasan, Anda tidak akan menemukan namanya di "INFORMATION_SCHEMA.TABLE_CONSTRAINTS", jadi taruhan terbaik Anda adalah "INFORMATION_SCHEMA.COLUMNS" seperti yang telah disebutkan orang lain.

(SQLServer-ignoramus di sini)

Satu-satunya alasan yang dapat saya pikirkan ketika Anda harus mengetahui nama "kendala default" adalah jika SQLServer tidak mendukung "ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT..."perintah. Tapi kemudian Anda sudah berada di zona non-standar dan Anda harus menggunakan cara khusus produk untuk mendapatkan apa yang Anda butuhkan.

Milen A. Radev
sumber
0

Bagaimana jika menggunakan kombinasi CHECK_CONSTRAINTS dan 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

sumber
CONSTRAINT_COLUMN_USAGE tidak menyimpan info apa pun tentang batasan default.
Stephen Turner
0

Saya menggunakan skrip folllowing untuk mengambil semua default (sp_binddefaults) dan semua kendala default dengan skrip berikut:

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
sumber
0

Tampilan Katalog Objek : sys.default_constraints

Tampilan skema informasi INFORMATION_SCHEMAsesuai dengan ANSI, tetapi batasan default bukan bagian dari standar ISO. Microsoft SQL Server menyediakan tampilan katalog sistem untuk mendapatkan informasi tentang metadata objek SQL Server.

sys.default_constraints tampilan katalog sistem yang digunakan untuk mendapatkan informasi tentang batasan default.

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.dll
sumber