【问题标题】:Pre-execute a query when any Stored Procedure is called调用任何存储过程时预执行查询
【发布时间】:2026-01-21 02:50:02
【问题描述】:

我们企业的数据库已经有 20 多年的历史了,里面充满了垃圾,所以我们打算开始删除表和存储过程。问题是我们并不确切知道哪些是未使用的,因此我们考虑进行研究以发现它们。

我试过this answer's solution,但我认为返回的查询数是系统缓存中的。

我有一个想法,但我不知道它是否可能: - 创建一个包含 3 列的系统表:存储过程名称、执行次数和上次调用日期 - 棘手的部分:每次执行存储过程时,执行查询以插入/更新该表。

为了避免修改我们所有的存储过程(很容易超过 600 个),我想添加一个数据库触发器,但结果只能将它们链接到表,而不是存储过程。

我的问题是,有没有办法在调用任何存储过程时预先执行查询?

编辑:我们的数据库是 SQL Server

【问题讨论】:

  • 我怀疑这是可能的,但你应该用你正在使用的数据库标记问题。
  • 您可以使用 sql profiler 来获取所有调用的跟踪 - 然后对跟踪进行后期处理以解析出您需要的信息。虽然可能会是一个更大的痕迹。
  • 这听起来像是扩展事件的工作。使用直方图目标并捕获rpc_started(或rpc_completed)事件。查询此直方图和/或在您闲暇时制作一张表格。如果您需要有关调用的更多详细信息,请将其设为偶数文件而不是直方图。
  • @Andrew 这是个好主意,但有些存储过程可能每月执行一次,所以我打算计算 1 或 2 个月内的调用次数,然后采取相应的行动。
  • @Jeroen Monstert 我不知道那个东西存在,我一定会试一试。我会让你知道它是否有效。非常感谢:)

标签: sql sql-server stored-procedures


【解决方案1】:

我知道我不久前问过这个问题,但我会发布我发现的内容,以便任何偶然发现它的人都可以使用它。

当这个问题被问到时,我的目标是检索所有存储过程的执行次数,以尝试摆脱未使用的。

虽然这并不完美,因为它没有显示上次执行的日期,但我发现了这个查询,它检索所有数据库上的所有存储过程,并显示它自创建以来执行的次数:

SELECT
    Db_name(st.dbid) [Base de Datos],
    Object_schema_name(st.objectid, dbid) [Schema],
    Object_name(st.objectid, dbid)        [USP],
    Max(cp.usecounts)                     [Total Ejecuciones]
FROM   
    sys.dm_exec_cached_plans cp
    CROSS apply sys.Dm_exec_sql_text(cp.plan_handle) st
WHERE  
    Db_name(st.dbid) IS NOT NULL
    AND cp.objtype = 'proc'
GROUP  BY
    cp.plan_handle,
    Db_name(st.dbid),
    Object_schema_name(objectid, st.dbid),
    Object_name(objectid, st.dbid)
ORDER  BY
        Max(cp.usecounts)

我在this webpage 上找到了这个脚本(它是西班牙语)。它还有 2 个关于类似主题的有用脚本。

【讨论】:

    【解决方案2】:

    我用过这个脚本(后来改进了)

    https://chocosmith.wordpress.com/2012/12/07/tsql-recompile-all-views-and-stored-proceedures-and-check-for-error/#more-571

    遍历所有对象并找到不再有效的对象。

    如果你愿意,我会发布我的增强版,它修复了一些问题。

    然后创建一个新架构(我叫我的recycle)并将那些无效对象移到那里。

    现在再次运行它。

    你最终可能会移出一大堆非功能性对象

    【讨论】:

    • 这会首先找到不能再执行的过程,但它不能识别仍将运行但根本不再使用的过程。您可以通过查找不再使用的 tables、删除它们并然后 运行此脚本来找到它们,但这可能需要多次尝试——而且这样做很危险在生产系统上。
    • 你是对的,它没有回答这样的问题,但这是我在清理另一个客户 dB 时开始的地方。