Làm cách nào để tìm một ràng buộc mặc định bằng INFORMATION_SCHEMA?


116

Tôi đang cố gắng kiểm tra xem có tồn tại một ràng buộc mặc định nhất định hay không. Tôi không muốn sử dụng bảng sysobjects, nhưng INFORMATION_SCHEMA tiêu chuẩn hơn.

Tôi đã sử dụng điều này để kiểm tra bảng và các ràng buộc khóa chính trước đây, nhưng tôi không thấy các ràng buộc mặc định ở đâu cả.

Họ không có ở đó? (Tôi đang sử dụng MS SQL Server 2000).

CHỈNH SỬA: Tôi đang tìm cách lấy tên của ràng buộc.

Câu trả lời:


121

Theo tôi hiểu, các ràng buộc giá trị mặc định không phải là một phần của tiêu chuẩn ISO, vì vậy chúng không xuất hiện trong INFORMATION_SCHEMA. INFORMATION_SCHEMA có vẻ như là lựa chọn tốt nhất cho loại tác vụ này vì nó đa nền tảng, nhưng nếu thông tin không có sẵn, người ta nên sử dụng các chế độ xem danh mục đối tượng (sys. *) Thay vì các chế độ xem bảng hệ thống, không được dùng trong SQL Server 2005 trở về sau.

Dưới đây khá giống với câu trả lời của @ user186476. Nó trả về tên của ràng buộc giá trị mặc định cho một cột nhất định. (Đối với người dùng không phải SQL Server, bạn cần tên của mặc định để loại bỏ nó và nếu bạn không tự đặt tên cho ràng buộc mặc định, SQL Server sẽ tạo một số tên điên rồ như "DF_TableN_Colum_95AFE4B5". Để thay đổi dễ dàng hơn lược đồ của bạn trong tương lai, hãy luôn đặt tên rõ ràng cho các ràng buộc của bạn!)

-- 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
Lưu ý: có thể có cùng một tên bảng trong các lược đồ khác nhau, vì vậy bạn cũng nên tham gia vào bảng sys.schemas.
Daniel James Bryars

1
@DanielJamesBryars sys.schemas hiện đã được thêm vào truy vấn.
Stephen Turner,

Vui lòng xem câu trả lời của tôi ngắn gọn và hấp dẫn, hoạt động trong tất cả các phiên bản của SQL Server, không có bất kỳ sysbảng nào và rất dễ nhớ.
ErikE

2
@ErikE Mã của bạn giả định rằng tên của ràng buộc mặc định đã được biết. Đó là một vấn đề dễ giải quyết, như mã của bạn thể hiện. Câu trả lời hay, câu hỏi sai.
DarLom

Mã của tôi giả định điều đó, bởi vì đó là những gì người hỏi yêu cầu - "Tôi đang tìm kiếm [liệu 'một ràng buộc mặc định đã cho có tồn tại hay không'] bằng tên của ràng buộc." Tôi đã chỉnh sửa câu trả lời của mình để làm cho bản chất thỏa mãn câu hỏi trực tiếp của nó rõ ràng hơn nhiều. Hy vọng rằng sẽ giúp.
ErikE

43

Bạn có thể sử dụng cách sau để thu hẹp kết quả hơn nữa bằng cách chỉ định Tên Bảng và Tên Cột mà Ràng buộc Mặc định tương quan với:

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
Tôi tìm kiếm truy vấn đơn giản này trong vài giờ. Thannnnnkkk youuuu!
Samuel

Cần có o.xtype = 'D' để làm việc với cơ sở dữ liệu không phân biệt chữ hoa chữ thường.
IvanH

37

Dường như không có tên Ràng buộc Mặc định nào trong các Information_Schemachế độ xem.

sử dụng SELECT * FROM sysobjects WHERE xtype = 'D' AND name = @name để tìm một ràng buộc mặc định theo tên


đúng thứ tôi cần. Cảm ơn
drdwilcox

Trả lời trực tiếp câu hỏi tốt hơn các lựa chọn thay thế sau này (SQL 2000 & truy vấn theo tên ràng buộc).
Marc L.

Điều này chỉ hoạt động khi bạn biết tên ràng buộc nhưng nếu đây là hệ thống được gán ....
TS

12

Tập lệnh dưới đây liệt kê tất cả các ràng buộc mặc định và giá trị mặc định cho các bảng người dùng trong cơ sở dữ liệu mà nó đang được chạy:

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

Nếu bạn muốn nhận một ràng buộc theo tên cột hoặc bảng hoặc bạn muốn nhận tất cả các ràng buộc trong cơ sở dữ liệu, hãy xem các câu trả lời khác. Tuy nhiên, nếu bạn chỉ đang tìm kiếm chính xác những gì câu hỏi yêu cầu, cụ thể là "kiểm tra xem có tồn tại một ràng buộc mặc định đã cho hay không ... bằng tên của ràng buộc" , thì có một cách dễ dàng hơn nhiều.

Đây là một câu trả lời chắc chắn trong tương lai không sử dụng sysobjectshoặc các sysbảng khác :

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
Nhiều khoảng trắng hơn một chút sẽ rất hay, nhưng điều này thực hiện được những gì mà người đăng ban đầu đã yêu cầu bằng cách sử dụng các chế độ xem danh mục đối tượng (sys. *), Được khuyến nghị bởi Microsoft trên các chế độ xem bảng hệ thống tương thích ngược.
Robert Calhoun

2

Cột COLUMN_DEFAULT của INFORMATION_SCHEMA.COLUMNS có phải là cột bạn đang tìm kiếm không?


Có và không, nó cho tôi biết có một mặc định và nó là gì, nhưng tôi cũng cần tên của ràng buộc.
WildJoe

1
Ngoài ra, hãy lưu ý rằng nếu thông tin đăng nhập SQL thời gian chạy của bạn không sở hữu lược đồ dbo, bạn chỉ có thể tìm thấy giá trị NULL trong cột 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

Thăng bằng.
Nếu bạn chỉ cần kiểm tra xem có tồn tại ràng buộc
mặc định hay không ((các) ràng buộc mặc định có thể có tên khác trong các DB được quản lý kém), hãy
sử dụng 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 

Nếu bạn chỉ muốn kiểm tra bằng tên ràng buộc:

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

Và cuối cùng nhưng không kém phần quan trọng, bạn chỉ có thể tạo một chế độ xem có tên
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

Tôi không nghĩ nó nằm trong INFORMATION_SCHEMA - có thể bạn sẽ phải sử dụng sysobjects hoặc các bảng / chế độ xem không dùng nữa có liên quan.

Bạn sẽ nghĩ rằng sẽ có một loại cho điều này trong INFORMATION_SCHEMA.TABLE_CONSTRAINTS, nhưng tôi không thấy.


0

Có thể là vì trên một số SQL DBMS khác, "ràng buộc mặc định" không thực sự là một ràng buộc, bạn sẽ không tìm thấy tên của nó trong "INFORMATION_SCHEMA.TABLE_CONSTRAINTS", vì vậy tốt nhất bạn nên chọn "INFORMATION_SCHEMA.COLUMNS" như những người khác đã đề cập.

(SQLServer-ignoreramus tại đây)

Lý do duy nhất tôi có thể nghĩ ra khi bạn phải biết tên của "ràng buộc mặc định" là nếu SQLServer không hỗ trợ "ALTER TABLE xxx ALTER COLUMN yyy SET DEFAULT..."lệnh. Nhưng khi đó bạn đã ở trong vùng phi tiêu chuẩn và bạn phải sử dụng các cách dành riêng cho sản phẩm để có được thứ bạn cần.


0

Còn việc sử dụng kết hợp CHECK_CONSTRAINTS và CONSTRAINT_COLUMN_USAGE thì sao:

    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 không có bất kỳ thông tin nào về các ràng buộc mặc định.
Stephen Turner

0

Tôi đang sử dụng tập lệnh folllowing để truy xuất tất cả các giá trị mặc định (sp_binddefaults) và tất cả các ràng buộc mặc định với các tập lệnh sau:

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

Chế độ xem danh mục đối tượng : sys.default_constraints

Chế độ xem lược đồ thông tin INFORMATION_SCHEMAtuân thủ ANSI, nhưng các ràng buộc mặc định không phải là một phần của tiêu chuẩn ISO. Microsoft SQL Server cung cấp các dạng xem danh mục hệ thống để lấy thông tin về siêu dữ liệu đối tượng SQL Server.

sys.default_constraints chế độ xem danh mục hệ thống được sử dụng để lấy thông tin về các ràng buộc mặc định.

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.