如何获取存储过程中的表列表?

问题描述 投票:0回答:12

数据库中有很多表和sp。我找到了特定 sp(存储过程)中使用的表名称。

sp_depends

%sp_name%
没有给出想要的结果。我也用过
INFORMATION_SCHEMA.TABLES
INFORMATION_SCHEMA.ROUTINES
桌子。

但是结果并没有完全满足我的要求。

sql-server stored-procedures
12个回答
23
投票

得票最高的两个答案使用了大量应避免使用的已弃用表。
这是一种更干净的方法。

获取存储过程所依赖的所有表:

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+

变更列表:

  • sysdepends
    应替换为
    sys.sql_dependencies
    • 新表使用
      object_id
      代替
      id
    • 新表使用
      referenced_major_id
      代替
      depid
  • 使用
    sysobjects
    应替换为更集中的系统目录视图
  • 此外,实际上不需要使用

    ROW_NUMBER()
    just 的 CTE 来确保我们只返回每个记录集中的一个。这就是
    DISTINCT
    的用途!

    • 事实上,SQL 足够聪明,可以在幕后使用 DISTINCT。
    • 我提交证据:证据A。以下查询具有相同的Execution Plan

      -- 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
      

21
投票

尝试更优雅的方式(但是,它的解决方案仅适用于 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')

16
投票
;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

10
投票

这是这个的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
并不总是返回准确的结果。

参考:

  1. Sql Server Central - 获取存储过程中使用的表列表
  2. SqlAuthority - 查找数据库中与表相关的存储过程 – 在所有存储过程中搜索

7
投票

KyleMit 的答案 使用的表也将很快被弃用。建议使用 sys.sql_experssion_dependency 而不是 sys.sql_dependency,例如,

SELECT DISTINCT p.name AS proc_name, t.name AS table_name
FROM sys.sql_expression_dependencies d
INNER JOIN sys.procedures p ON p.object_id = d.referencing_id
INNER JOIN sys.tables t     ON t.object_id = d.referenced_id
ORDER BY proc_name, table_name

这应该适用于 SQL Server 2008+。

我没有足够高的声誉,无法直接对引用的答案发表评论。


5
投票

OP问题似乎没有完整的答案。上面的大多数答案都没有模式名称,也不包含存储过程中使用的其他对象(例如函数)。

存储过程中使用的表/视图的完整列表,以及架构名称和对象 ID

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')

请注意,有一个可以更改的依赖对象类型过滤器(取决于您想要的输出结果)。类型缩写的完整列表是 这里


3
投票
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
            )

2
投票

但请注意,如果在

动态sql
中使用,sysdepends将不会给出表名。我的建议是反向搜索 即:创建一个循环搜索
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 <=@Idkeyed
    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 '% '+@tblName+' %' 
                        OR ScriptStr LIKE '%.'+@tblName+' %' OR ScriptStr LIKE @tblName+' %' OR ScriptStr LIKE @tblName
                        --OR ScriptStr LIKE '%'+@tblName 
                        OR ScriptStr LIKE '% '+@tblName+'''%' OR ScriptStr LIKE @tblName+'''%'))
        BEGIN
            SET @Objects = CASE WHEN ISNULL(@Objects,'')<>'' THEN @Objects+', '+@tblName 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

1
投票

这是查找过程中使用的表列表的示例

;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

0
投票

此代码递归地查看存储过程中的每个存储过程,并为您提供所有使用的表的完整列表。



    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


0
投票
SELECT Name
FROM sys.procedures
WHERE OBJECT_DEFINITION(OBJECT_ID) LIKE '%Tablename%'

0
投票

KyleMit 的解决方案列出了存储过程引用的所有表,这些表包含在同一数据库中。 如果您需要列出存储过程引用的所有表(包括属于其他数据库的表),该怎么办? 例如,您可能有一个用于报告目的的临时数据库,它访问专有数据库以进行复杂的报告。您需要知道正在引用专有数据库中的哪些表。

注意,如果您想查看所有引用的表,请注释掉Where 子句。

SELECT s.name, p.name, 
  db  = COALESCE(d.referenced_database_name, DB_NAME()),
  obj = COALESCE(d.referenced_schema_name, s.name) + N'.' + 
  d.referenced_entity_name
FROM sys.sql_expression_dependencies AS d
INNER JOIN sys.procedures AS p ON p.[object_id] = d.referencing_id
INNER JOIN sys.schemas AS s ON p.[schema_id] = s.[schema_id]
Where COALESCE(d.referenced_database_name, DB_NAME()) = 'proprietary database'
Group By s.name, p.name, 
d.referenced_database_name, d.referenced_schema_name, s.name, 
d.referenced_entity_name
ORDER BY obj;

这个解决方案是在这里提出的。 Stack Exchange 如何获取所有存储过程中的表列表

© www.soinside.com 2019 - 2024. All rights reserved.