Sql-Server

獲取包含 INSERT 的儲存過程的“列表”而不命名所涉及的列

  • July 23, 2019

作為某些增強功能的一部分,已在 750 多個表中添加了一個新列。現在我的問題是在近 3000 多個儲存過程中,一些舊的 INSERT 沒有命名列。

有沒有什麼辦法可以得到一個沒有列名插入的所有儲存過程的“列表”?

我試過了:

SELECT OBJECT_NAME(object_id)
FROM sys.sql_modules
WHERE definition LIKE '%insert into%' 
AND definition NOT LIKE '%) value%'
AND definition NOT LIKE '%)%' + CHAR(10) + '%value%'
AND definition NOT LIKE '%)%' + CHAR(13) + '%value%'
AND definition LIKE '%value%' 

但它仍然錯過了很多。

PS - 上面的查詢也返回 Insert Into (ColumnNames) SELECT 場景,這是我不想要的。

有一個名為sys.dm_sql_referenced_entities的 DMV 。它返回一個is_insert_all記錄的列

1 = 對像在沒有列列表的 INSERT 語句中使用(僅限對象級)。

這似乎是您正在尋找的。

這是實踐中的一個例子。首先,我們將創建一個簡單的單列表

drop table if exists dbo.T1;
go
create table dbo.T1(c int);

現在有兩個儲存過程,一個顯式引用列,另一個沒有。

create or alter procedure dbo.p_named
as
begin
   insert dbo.T1(c)  -- columns are listed
   select 1;
end
go

create or alter procedure dbo.p_not_named
as
begin
   insert dbo.T1   -- no column list
   select 2;
end
go

DMV 是一個表值函式。因此,可以使用CROSS APPLY語法呼叫它。傳遞給此函式的過程名稱可以從目錄視圖sys.procedures中獲得。此 DMV 的文件說明

當引用類為 OBJECT 時,s​​chema_name 是必需的。

我們可以使用名為SCHEMA_NAME()的內置元數據函式輕鬆獲取模式名稱。把它們放在一起,我們得到

select
   p.name, is_insert_all -- other columns exist
from sys.procedures as p
cross apply sys.dm_sql_referenced_entities(CONCAT(SCHEMA_NAME(p.schema_id), '.', p.name), 'OBJECT');

哪個返回這個

name          is_insert_all
------------- -------------
p_named       0
p_named       0
p_not_named   1

引用自:https://dba.stackexchange.com/questions/243271