Tạo tập lệnh để tự động đổi tên các ràng buộc mặc định


8

Bối cảnh: Một số ràng buộc cột mặc định của chúng tôi đã được tạo mà không có tên rõ ràng, vì vậy chúng tôi nhận được các tên thú vị khác nhau từ máy chủ này sang máy chủ khác như: DF__User__TimeZoneIn__5C4D869D

Tôi muốn có tất cả chúng có thể quản lý được bằng cách đặt tên nhất quán DF_Users_TimeZoneInfođể chúng tôi có thể đảm bảo rằng các ràng buộc phù hợp tồn tại trên các bảng mục tiêu trong tương lai (như trong so sánh RedGate, hoặc thậm chí chỉ bằng trực quan)

Tôi đã có một kịch bản chủ yếu hoạt động cho những gì tôi muốn:

select 'sp_rename N''[' + s.name + '].[' + d.name + ']'', 
   N''[DF_' + t.name + '_' + c.name + ']'', ''OBJECT'';'
from sys.tables t
    join
    sys.default_constraints d
        on d.parent_object_id = t.object_id
    join
    sys.columns c
        on c.object_id = t.object_id
        and c.column_id = d.parent_column_id
    join sys.schemas s
        on t.schema_id = s.schema_id
WHERE d.NAME like 'DF[_][_]%'

Nhưng điều này chỉ mang lại cho tôi một kết quả, và không phải thứ gì đó tôi thực sự có thể chuyển vào một người thực thi hay bất cứ điều gì.

Làm thế nào tôi có thể thực hiện điều này để tôi có thể thực hiện các sp_renametập lệnh đó mà không cần phải sao chép tất cả các phần tử được trả về và dán chúng vào một cửa sổ truy vấn mới và chạy lại chúng? Cố gắng lưu càng nhiều tổ hợp phím càng tốt để tôi có thể sửa lỗi này trong nhiều môi trường.

nhập mô tả hình ảnh ở đây


<facepalm> Bạn nên hỏi tôi về điều này vào ngày khác - Tôi đã rút câu trả lời của mình từ kịch bản mà tôi có chính xác điều này. :)
Jon Seigel 22/03/13

@JonSeigel ok, làm thế nào về một mức độ chênh lệch xung quanh này để chạy một lần trên mỗi dbs? : D
jcolebrand

Đừng đặt dấu ngoặc vuông xung quanh tên mới - Tôi đã kết thúc với một thế giới bị tổn thương sau khi chạy tập lệnh này :)
samjudson

Câu trả lời:


16

Ok, vài điều.

  1. luôn luôn sử dụng EXECkhi thực hiện các thủ tục lưu trữ; tốc ký mà không EXECchỉ hoạt động khi đó là câu lệnh đầu tiên trong lô (và điều đó sẽ không xảy ra ở đây).
  2. luôn luôn sử dụng các thiết bị đầu cuối bán đại tràng - trong trường hợp này chúng rất hữu ích thay cho việc trả lại xe ngựa và thụt đầu xe đẹp, nhưng chúng luôn khôn ngoan để có.
  3. luôn luôn sử dụng QUOTENAME()thay vì tự áp dụng dấu ngoặc vuông. Trong trường hợp này có lẽ bạn an toàn, nhưng có những trường hợp cách tiếp cận thủ công sẽ bị phá vỡ.
  4. bạn có thể kiểm tra PRINTđầu ra nhưng nó không nhất thiết phải hoàn thành nếu tổng lệnh của bạn> 8k (xem mẹo này để biết một số cách tiếp cận khác ).

    DECLARE @sql NVARCHAR(MAX) = N'';
    
    SELECT @sql += N'EXEC sp_rename N''' 
      + QUOTENAME(s.name) + '.' + QUOTENAME(d.name) 
      + ''', N''DF_' + t.name + '_' + c.name + ''', ''OBJECT'';'
    from sys.tables AS t
      join
      sys.default_constraints d
        on d.parent_object_id = t.object_id
    join
    sys.columns c
        on c.object_id = t.object_id
        and c.column_id = d.parent_column_id
    join sys.schemas s
        on t.schema_id = s.schema_id
    WHERE d.NAME like 'DF[_][_]%';
    
    PRINT @sql;
    -- EXEC sp_executesql @sql;
    

Thật tốt khi biết về EXEC cho mỗi tuyên bố, tôi đã không biết về điều đó.
jcolebrand

3
Vâng, hãy thử thực hiện điều này : sp_help; sp_help;.
Aaron Bertrand

3

Dựa trên câu hỏi của bạn .. mà bạn đã xóa "tự động hóa cùng một tập lệnh trên một số cơ sở dữ liệu"

Dưới đây là mã sẽ giúp bạn

set nocount on
DECLARE @table TABLE 
  ( 
     dbname VARCHAR(30) 
  ) 

INSERT INTO @table 
            (dbname) 
VALUES      ( 'dev_construct1' ), 
            ('dev_construct2'), 
            ('dev_construct3' ); 

DECLARE @sql NVARCHAR(max) = N''; 
DECLARE @dbname VARCHAR(30) 

/*  
Added by Kin : While loop and an extra @dbname variable 
*/ 
SELECT @dbname = Min(dbname) 
FROM   @table 

WHILE @dbname IS NOT NULL 
  BEGIN 
      SELECT @sql = N'USE ' + tt.dbname + Char(10) + N' GO;'
      FROM   @table tt 
      WHERE  @dbname = dbname 

      SELECT @sql += Char(10) + N'EXEC sp_rename N''' 
                     + Quotename(s.name) + '.' + Quotename(d.name) 
                     + ''', N''DF_' + t.name + '_' + c.name 
                     + ''', ''OBJECT'';' 
      FROM   sys.tables AS t 
             JOIN sys.default_constraints d 
               ON d.parent_object_id = t.object_id 
             JOIN sys.columns c 
               ON c.object_id = t.object_id 
                  AND c.column_id = d.parent_column_id 
             JOIN sys.schemas s 
               ON t.schema_id = s.schema_id 
             JOIN @table tt 
               ON tt.dbname = tt.dbname 
      WHERE  d.name LIKE 'DF[_][_]%'; 

      PRINT @sql 

      SELECT @dbname = Min(dbname) 
      FROM   @table 
      WHERE  dbname > @dbname 
  END 
-- EXEC sp_executesql @sql; 

Tôi đã xóa nó vì câu hỏi trước đó thiếu một chút chi tiết chính, vì tên cột thay đổi trong mỗi db, vì vậy tôi cần chạy truy vấn bên trong theo ngữ cảnh của từng db riêng lẻ.
jcolebrand

@jcolebrand cảm ơn đã cập nhật. Trong mọi trường hợp, mã với các thay đổi của tôi sẽ giúp bạn những gì bạn đang tìm kiếm.
Kin Shah
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.