2009-12-04 33 views
5

Có thể, không có nguồn phân tích cú pháp, để chọn danh sách tất cả các tên sproc chèn, cập nhật hoặc xóa bản ghi? Tôi cần tạo một tập lệnh tiện ích TSQL để thực hiện việc này. Hiệu quả không phải là một vấn đề bởi vì nó sẽ được chạy chỉ một vài lần một năm (Curse'rs tôi có nghĩa là con trỏ là ok). Lý tưởng nhất là tập lệnh này sẽ không bao gồm các bản cập nhật cho các bảng biến tạm thời hoặc cục bộ.Làm cách nào để tìm tất cả các thủ tục được lưu trữ chèn, cập nhật hoặc xóa bản ghi?

Tôi đã thử truy vấn sau đây được tìm thấy trên SO Question.

SELECT 
so.name, 
so2.name, 
sd.is_updated 
from sysobjects so 
inner join sys.sql_dependencies sd on so.id = sd.object_id 
inner join sysobjects so2 on sd.referenced_major_id = so2.id 
where so.xtype = 'p' -- procedure 
and 
is_updated = 1 -- proc updates table, or at least, I think that's what this means 

Nhưng nó tạo ra âm tính giả.

+0

Các liên kết mà bạn cung cấp bao gồm các câu trả lời cho câu hỏi này ... chỉ cần thêm xóa vào nó. –

+0

Im vẫn nhận được khoảng 5% tỷ lệ falure trên thậm chí cập nhật chỉ sprocs. –

Trả lời

6

Gọi sp_refreshsqlmodule trên tất cả các phi schema ràng buộc thủ tục lưu trữ:

DECLARE @template AS varchar(max) 
SET @template = 'PRINT ''{OBJECT_NAME}'' 
EXEC sp_refreshsqlmodule ''{OBJECT_NAME}'' 

' 

DECLARE @sql AS varchar(max) 

SELECT @sql = ISNULL(@sql, '') + REPLACE(@template, '{OBJECT_NAME}', 
              QUOTENAME(ROUTINE_SCHEMA) + '.' 
              + QUOTENAME(ROUTINE_NAME)) 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' 
           + QUOTENAME(ROUTINE_NAME)), 
         N'IsSchemaBound') IS NULL 
     OR OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' 
            + QUOTENAME(ROUTINE_NAME)), 
          N'IsSchemaBound') = 0 

     EXEC (
       @sql 
      ) 
+0

Cảm ơn bạn đã làm điều này khiến tôi gần gũi hơn. Vẫn còn một số âm bản sai nhưng chỉ một vài. Tôi đã có thể sử dụng mã gốc của tôi cùng với mã của bạn để đủ gần. Tôi đăng mã của tôi như là một câu trả lời. –

+0

Bạn có tìm thấy bất kỳ SP nào đã trở thành không hợp lệ do thay đổi cơ bản không? Đó luôn là niềm vui ;-) –

1

Đó là vấn đề với sys.sql_dependencies. SQL không thể theo dõi chính xác các phụ thuộc trong các thủ tục được lưu trữ (có những lý do âm thanh tại sao nó không thể, nhưng bây giờ không cho phép đi). Đó là không cần xem xét các thủ tục SQL hoặc CLR động.

Visual Studio Database Edition có một số khả năng tốt hơn, nhưng nó có thể theo dõi các phụ thuộc trong scipts, không phải trong một cơ sở dữ liệu trực tiếp. Nó có thể mặc dù kỹ sư đảo ngược cơ sở dữ liệu sống vào kịch bản và phân tích các kịch bản kết quả, để một số độ chính xác tốt hơn so với sys.sql_dependencies có thể. Nó không thể xử lý SQL động.

0

Nhờ câu trả lời Cade Roux của tôi đã có thể để có được rất gần với điều này:

DECLARE @RoleName nvarchar(255) 
SET @RoleName = 'READONLYUSER' 

DECLARE @ROUTINE_NAME nvarchar(255) 
DECLARE RoutineList Cursor FOR 
SELECT ROUTINE_NAME 
FROM INFORMATION_SCHEMA.ROUTINES 
WHERE (OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' + QUOTENAME(ROUTINE_NAME)), N'IsSchemaBound') IS NULL OR OBJECTPROPERTY(OBJECT_ID(QUOTENAME(ROUTINE_SCHEMA) + '.' + QUOTENAME(ROUTINE_NAME)), N'IsSchemaBound') = 0) 
    AND NOT ROUTINE_NAME like 'sel%' 
    AND NOT ROUTINE_NAME like 'sp_upd%' 
    AND NOT ROUTINE_NAME like 'sp_sel%' 
    AND NOT ROUTINE_NAME like 'sp_ins%' 
OPEN RoutineList 
FETCH NEXT FROM RoutineList 
INTO @ROUTINE_NAME 
WHILE @@FETCH_STATUS = 0 
BEGIN 

    EXEC ('EXEC sp_refreshsqlmodule ''' + @ROUTINE_NAME + '''') 

    FETCH NEXT FROM RoutineList INTO @ROUTINE_NAME 
END 
CLOSE RoutineList 
DEALLOCATE RoutineList 


DECLARE GrantList Cursor FOR 
SELECT DISTINCT 
    so.name AS ROUTINE_NAME 
FROM sysobjects so 
LEFT JOIN (
    SELECT 
     so.name, 
     so2.name AS [table], 
     sd.is_updated 
     FROM sysobjects so 
     INNER JOIN sys.sql_dependencies sd ON so.id = sd.object_id 
     INNER JOIN sysobjects so2 ON sd.referenced_major_id = so2.id 
     WHERE so.xtype = 'p' 
     and is_updated = 1 
) Updates ON so.name = Updates.name 
WHERE 
    so.xtype = 'p' -- procedure 
    AND Updates.name is null 
    AND so.name NOT LIKE '%[_]%' 
ORDER BY so.name 

OPEN GrantList 
FETCH NEXT FROM GrantList 
INTO @ROUTINE_NAME 
WHILE @@FETCH_STATUS = 0 
BEGIN 

    print 'GRANT EXECUTE ON [dbo].['[email protected]_NAME+'] TO ['[email protected] +'] ' 


    FETCH NEXT FROM GrantList INTO @ROUTINE_NAME 
END 
CLOSE GrantList 
DEALLOCATE GrantList 
Các vấn đề liên quan