Как я могу получить список таблиц в хранимой процедуре
В db есть много таблиц и sp. Я нахожу имя таблиц, которые используются в конкретной sp (хранимая процедура).
sp_depends %sp_name%
не дает результат желания. Я также использовал таблицы INFORMATION_SCHEMA.TABLES
, INFORMATION_SCHEMA.ROUTINES
.
но результат не заполняет мое требование.
Ответы
Ответ 1
;WITH stored_procedures AS (
SELECT
o.name AS proc_name, oo.name AS table_name,
ROW_NUMBER() OVER(partition by o.name,oo.name ORDER BY o.name,oo.name) AS row
FROM sysdepends d
INNER JOIN sysobjects o ON o.id=d.id
INNER JOIN sysobjects oo ON oo.id=d.depid
WHERE o.xtype = 'P')
SELECT proc_name, table_name FROM stored_procedures
WHERE row = 1
ORDER BY proc_name,table_name
Ответ 2
Попробуйте более элегантный способ (но это решение работает только в MS SQL 2008 или выше) -
SELECT DISTINCT
[object_name] = SCHEMA_NAME(o.[schema_id]) + '.' + o.name
, o.type_desc
FROM sys.dm_sql_referenced_entities ('dbo.usp_test1', 'OBJECT') d
JOIN sys.objects o ON d.referenced_id = o.[object_id]
WHERE o.[type] IN ('U', 'V')
Ответ 3
Вот код sql для этого
Чтобы получить список таблиц, используемых в хранимой процедуре
;WITH stored_procedures AS (
SELECT
o.name AS proc_name, oo.name AS table_name,
ROW_NUMBER() OVER(partition by o.name,oo.name ORDER BY o.name,oo.name) AS row
FROM sysdepends d
INNER JOIN sysobjects o ON o.id=d.id
INNER JOIN sysobjects oo ON oo.id=d.depid
WHERE o.xtype = 'P')
SELECT proc_name, table_name FROM stored_procedures
WHERE row = 1
ORDER BY proc_name,table_name
.
Реверс - поиск хранимой процедуры, связанной с таблицей в базе данных - поиск во всей хранимой процедуре
Есть два пути к этому
----Option 1
SELECT DISTINCT so.name
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE sc.TEXT LIKE '%tablename%'
----Option 2
SELECT DISTINCT o.name, o.xtype
FROM syscomments c
INNER JOIN sysobjects o ON c.id=o.id
WHERE c.TEXT LIKE '%tablename%'
PS: sp_help
и sp_depends
не всегда возвращают точные результаты.
Ссылка:
Ответ 4
Два самых высоких голосовых ответа используют множество устаревших таблиц, которых следует избегать.
Здесь гораздо более чистый способ сделать это.
Получить все таблицы, от которых зависит хранимая процедура:
SELECT DISTINCT p.name AS proc_name, t.name AS table_name
FROM sys.sql_dependencies d
INNER JOIN sys.procedures p ON p.object_id = d.object_id
INNER JOIN sys.tables t ON t.object_id = d.referenced_major_id
ORDER BY proc_name, table_name
Работает с MS SQL SERVER 2005 +
Список изменений:
referenced_major_id
Использование sysobjects
должно быть заменено более целенаправленными представлениями системного каталога
Кроме того, нет необходимости в CTE, который использует ROW_NUMBER()
, чтобы убедиться, что у нас есть только один из каждого набора записей вернулся. Это то, что DISTINCT
есть для!
- На самом деле SQL достаточно умен, чтобы использовать DISTINCT за кулисами.
-
Я представляю доказательства: Приложение A - следующие запросы имеют один и тот же план выполнения!
-- Complex
WITH MyPeople AS (
SELECT id, name,
ROW_NUMBER() OVER(PARTITION BY id, name ORDER BY id, name) AS row
FROM People)
SELECT id, name
FROM MyPeople
WHERE row = 1
-- Better
SELECT DISTINCT id, name
FROM People
Ответ 5
SELECT
NAME
FROM SYSOBJECTS
WHERE ID IN ( SELECT SD.DEPID
FROM SYSOBJECTS SO,
SYSDEPENDS SD
WHERE SO.NAME = 'SP_NAME'
AND SD.ID = SO.ID
)
Ответ 6
Вот пример, чтобы найти список таблиц, используемых в процедуре
;WITH procs
AS
(
SELECT o1.name AS proc_name,
o2.name AS table_name,
ROW_NUMBER() OVER(PARTITION BY o1.name,o2.name ORDER BY o1.name,o2.name) AS row
FROM sysdepends d
INNER JOIN sysobjects o1
ON o1.id=d.id
INNER JOIN sysobjects o2
ON o2.id=d.depid
WHERE o1.xtype = 'P'
--AND o2.name = 'tabname1' OR o2.name = 'tblname2'
)
SELECT proc_name, table_name
FROM procs
WHERE row = 1
ORDER BY proc_name, table_name
Кроме того, этот запрос возвращает все имена таблиц всех зависимых таблиц в хранимой процедуре.
SELECT DISTINCT o.id, o.name as 'Procedure_Name' , oo.name as 'Table_Name'
FROM sysdepends d, sysobjects o, sysobjects oo
WHERE o.id=d.id
and oo.id=d.depid and depnumber=1
ORDER BY o.name,oo.name
Ответ 7
Похоже, нет полного ответа на вопрос OP. Большинство ответов выше не имеют ни имени схемы, либо включают другие объекты (например, функции), используемые в хранимых процедурах.
Полный список таблиц/представлений, используемых в хранимых процедурах с именем схемы и идентификатором объекта
SELECT DISTINCT
procObj.[object_id] AS [ProcObjectId],
procSchema.[name] AS [ProcSchema],
procObj.[Name] AS [ProcName],
tableObj.[object_id] AS [TableObjectId],
tableSchema.[name] AS [TableSchema],
tableObj.[Name] AS [TableName]
FROM sys.sql_dependencies AS dep
INNER JOIN sys.objects AS procObj
ON procObj.[object_id] = dep.[object_id]
INNER JOIN sys.schemas AS procSchema
ON procSchema.[schema_id] = procObj.[schema_id]
INNER JOIN sys.objects AS tableObj
ON tableObj.[object_id] = dep.[referenced_major_id]
INNER JOIN sys.schemas AS tableSchema
ON tableSchema.[schema_id] = tableObj.[schema_id]
WHERE procObj.[type] = 'P'
-- using this filter we can control dependent object types
-- e.g. tableObj.[type] IN ('U') - returns tables only
AND tableObj.[type] IN ('V', 'U')
Обратите внимание, что есть фильтр по зависимым типам объектов, которые можно изменить (в зависимости от того, что вы хотите в результатах вывода). Полный список сокращений типа
здесь.
Ответ 8
Но учтите, что sysdepends
не будет указывать имена таблиц, если они используются в динамическом sql. Я предлагаю искать обратно
т.е.: создать цикл поиска таблиц в syscomments
. Следующая хранимая процедура может помочь
CREATE PROCEDURE dbo.sp_getObjects
(
@ObjName VARCHAR(255)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE @Idkeyst INTEGER
DECLARE @Idkeyed INTEGER
DECLARE @tblName VARCHAR(255)
DECLARE @Objects VARCHAR(MAX)
IF NOT EXISTS(SELECT 1 FROM sys.objects where NAME = @ObjName AND type in ('P', 'FN','TR'))
BEGIN
PRINT 'NO Text Available for the Parameter'
RETURN(0)
END
CREATE TABLE #ProcStr
(
Idkey INT IDENTITY(1,1),
ScriptStr VARCHAR(MAX)
)
CREATE TABLE #Depends
(
Idkey INT IDENTITY(1,1),
Depends VARCHAR(255)
)
CREATE TABLE #Objects
(
Idkey INT IDENTITY(1,1),
ObjectName VARCHAR(255)
)
INSERT INTO #ProcStr
(ScriptStr)
EXEC sp_helptext @ObjName
DELETE #ProcStr WHERE LTRIM(ScriptStr) LIKE '--%'
DELETE #ProcStr WHERE LTRIM(REPLACE(ScriptStr,CHAR(9),'')) LIKE '--%'
SET @Idkeyst = 0
SET @Idkeyed = 0
WHILE 1=1
BEGIN
SELECT @Idkeyst = MIN(idKey) FROM #ProcStr WHERE ScriptStr like '%/*%' and Idkey > @Idkeyst
IF @Idkeyst IS NULL
BREAK
SELECT @Idkeyed = MIN(idKey) FROM #ProcStr WHERE ScriptStr like '%*/%' and Idkey >= @Idkeyst
DELETE #ProcStr WHERE Idkey >= @Idkeyst and Idkey <[email protected]
END
DELETE #ProcStr WHERE ISNULL(LTRIM(REPLACE(ScriptStr,CHAR(9),'')),'')=''
INSERT INTO #Depends
(Depends)
SELECT DISTINCT t.name
FROM sys.sql_dependencies d
INNER JOIN sys.procedures p ON p.object_id = d.object_id
INNER JOIN sys.tables t ON t.object_id = d.referenced_major_id
where p.name = @ObjName
INSERT INTO #Objects
SELECT name from sys.objects o WHERE Type = 'U' AND NOT EXISTS
(SELECT 1 FROM #Depends WHERE Depends = o.name)
SET @Objects = ''
SELECT @Objects = CASE WHEN ISNULL(@Objects,'') = '' THEN '' ELSE @Objects+', ' END+ Depends
FROM #Depends
UPDATE #ProcStr
SET ScriptStr = LTRIM(RTRIM(ScriptStr))
UPDATE #ProcStr
SET ScriptStr = REPLACE(ScriptStr,CHAR(9),'')
UPDATE #ProcStr
SET ScriptStr = REPLACE(ScriptStr,CHAR(13),'')
UPDATE #ProcStr
SET ScriptStr = REPLACE(ScriptStr,CHAR(10),'')
SET @tblName = ''
SET @Idkeyst = 0
WHILE 1=1
BEGIN
SELECT @Idkeyst = MIN(idKey) FROM #Objects WHERE Idkey > @Idkeyst
IF @Idkeyst IS NULL
BREAK
SELECT @tblName = ObjectName FROM #Objects WHERE Idkey = @Idkeyst
IF Exists (SELECT 1 FROM #ProcStr WHERE (ScriptStr LIKE '% '[email protected]+' %'
OR ScriptStr LIKE '%.'[email protected]+' %' OR ScriptStr LIKE @tblName+' %' OR ScriptStr LIKE @tblName
--OR ScriptStr LIKE '%'[email protected]
OR ScriptStr LIKE '% '[email protected]+'''%' OR ScriptStr LIKE @tblName+'''%'))
BEGIN
SET @Objects = CASE WHEN ISNULL(@Objects,'')<>'' THEN @Objects+', '[email protected] ELSE @tblName END
END
END
IF ISNULL(@Objects,'') = ''
BEGIN
PRINT 'NO Tables are reffered in the stored procedures'
RETURN(0)
END
PRINT @Objects
SET NOCOUNT OFF
END
Ответ 9
Этот код рекурсивно просматривает каждую хранимую процедуру в хранимой процедуре и предоставляет полный список всех используемых таблиц.
declare @sp_name varchar(100)
declare @curSpName varchar(100)
declare @curObjName varchar(255)
declare @curXType varchar(1)
create table #tmpTables
(
proc_name varchar(255),
table_name varchar(255)
)
set @sp_name = 'STORED_PROCEDURE_NAME'
;WITH stored_procedures AS (
SELECT
o.name AS proc_name, oo.name AS table_name, oo.type AS xType,
ROW_NUMBER() OVER(partition by o.name,oo.name, oo.Type ORDER BY o.name,oo.name, oo.Type) AS row
FROM sysdepends d
INNER JOIN sysobjects o ON o.id=d.id
INNER JOIN sysobjects oo ON oo.id=d.depid
WHERE o.xtype = 'P'
--and oo.type = 'U' --Tables
and o.name = @sp_name)
SELECT proc_name, table_name, xType, 'N' Processed into ##tmpSP
FROM stored_procedures
WHERE row = 1
--ORDER BY proc_name,table_name
While (Select count(*) from ##tmpSP where Processed = 'N') 0
Begin
Select top 1 @curSpName = proc_name, @curObjName = table_name, @curXType = xType
from ##tmpSP
where Processed = 'N'
if @curXType = 'U'
Begin
insert into #tmpTables
values (@curSpName, @curObjName)
End
if @curXType = 'P'
Begin
;WITH stored_procedures AS (
SELECT
o.name AS proc_name, oo.name AS table_name, oo.type AS xType,
ROW_NUMBER() OVER(partition by o.name,oo.name, oo.Type ORDER BY o.name,oo.name, oo.Type) AS row
FROM sysdepends d
INNER JOIN sysobjects o ON o.id=d.id
INNER JOIN sysobjects oo ON oo.id=d.depid
WHERE o.xtype = 'P'
and oo.type = 'U' --Tables
and o.name = @curObjName)
insert into #tmpTables
SELECT @curSpName, table_name
FROM stored_procedures
WHERE row = 1
ORDER BY proc_name,table_name
;WITH stored_procedures AS (
SELECT
o.name AS proc_name, oo.name AS table_name, oo.type AS xType,
ROW_NUMBER() OVER(partition by o.name,oo.name, oo.Type ORDER BY o.name,oo.name, oo.Type) AS row
FROM sysdepends d
INNER JOIN sysobjects o ON o.id=d.id
INNER JOIN sysobjects oo ON oo.id=d.depid
WHERE o.xtype = 'P'
and oo.type = 'P' --SP's
and o.name = @curObjName)
insert into ##tmpSP
SELECT proc_name, table_name, xType, 'N'
FROM stored_procedures
WHERE row = 1
and proc_name not in
(
Select proc_name
from ##tmpSP
)
ORDER BY proc_name,table_name
End
if @curXType = 'v'
Begin
;WITH stored_procedures AS (
SELECT
o.name AS proc_name, oo.name AS table_name, oo.type AS xType,
ROW_NUMBER() OVER(partition by o.name,oo.name, oo.Type ORDER BY o.name,oo.name, oo.Type) AS row
FROM sysdepends d
INNER JOIN sysobjects o ON o.id=d.id
INNER JOIN sysobjects oo ON oo.id=d.depid
WHERE o.xtype = 'v'
and oo.type = 'U' --Tables
and o.name = @curObjName)
insert into #tmpTables
SELECT proc_name, table_name
FROM stored_procedures
WHERE row = 1
ORDER BY proc_name,table_name
End
update ##tmpSP
set Processed = 'Y'
where table_name = @curObjName
End
Select distinct table_name
from #tmpTables
drop table #tmpTables
drop table ##tmpSP