为什么SQL存储过程在数据库升级后会失效以及如何批量重新编译?

小磊大大_1549

小磊大大_1549

2026-09-08

388人浏览

原创

数据库升级后存储过程变invalid,根本原因是引擎内部对象定义或行为发生不兼容变更,如系统视图新增列、内置函数移除或权限模型调整,导致加载时校验失败;sql server需用sp_recompile批量标记重编译,oracle则需alter ... compile显式编译。

为什么sql存储过程在数据库升级后会失效以及如何批量重新编译?

数据库升级后存储过程失效,不是代码写错了,而是依赖的元数据(比如系统视图结构、内置函数行为、统计信息格式)变了,导致 SQL Server 或 Oracle 在加载时校验失败,直接标为 INVALID 状态。

为什么升级后存储过程变 INVALID?

根本原因是数据库引擎内部对象定义或行为发生了不兼容变更。例如:

  • SQL Server 升级到 2022(兼容级别 160)后,sys.dm_exec_query_stats 新增列,旧版 SP 若显式 SELECT * FROM 它,就会编译失败
  • Oracle 升级后,DBA_OBJECTSSTATUS 列语义微调,或 UTL_FILE 权限模型变化,也会让依赖它的包体失效
  • 兼容性级别下调(如从 160 改回 150)会清空整个计划缓存,并使部分新语法解析失败,间接触发重编译失败

注意:失效对象仍可调用,但首次执行时会尝试自动重新编译;若编译失败(比如引用了已移除的系统函数),才真正报错“对象名无效”或“PLS-00302”。

SQL Server 批量重新编译失效存储过程

别手动一个个 EXEC sp_recompile —— 升级后往往有几十甚至上百个失效对象,必须脚本化处理。

  • 先查出所有当前库中状态为 INVALID 的存储过程:
    SELECT OBJECT_NAME(object_id) AS name FROM sys.objects WHERE type = 'P' AND is_ms_shipped = 0 AND OBJECTPROPERTY(object_id, 'IsExecuted') = 0
  • 生成批量标记命令(下次执行时才真正编译):
    SELECT 'EXEC sp_recompile ''' + name + ''';' FROM sys.objects WHERE type = 'P' AND is_ms_shipped = 0 AND OBJECTPROPERTY(object_id, 'IsExecuted') = 0
  • 执行结果集里的所有 EXEC sp_recompile 语句;之后首次调用这些过程时,就会用新兼容级别+新统计信息重新生成计划
  • 如果想立刻强制全部重编译(慎用,高并发下可能 CPU 尖刺),可用:
    DBCC FREEPROCCACHE; -- 清全局缓存,触发所有后续执行硬解析
    但更稳妥的做法是配合 UPDATE STATISTICS 后再跑 sp_recompile

Oracle 批量编译失效对象(含存储过程、函数、包)

Oracle 不像 SQL Server 那样有 sp_recompile,它靠 ALTER ... COMPILE 显式重试编译,且必须区分包头和包体。

  • 查所有失效对象:
    SELECT owner, object_name, object_type, status FROM dba_objects WHERE status = 'INVALID' AND object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'TRIGGER', 'VIEW');
  • 生成编译脚本(注意:包体要用 COMPILE BODY):
    SELECT 'ALTER ' || object_type || ' ' || owner || '.' || object_name || 
           CASE WHEN object_type = 'PACKAGE BODY' THEN ' COMPILE BODY;' ELSE ' COMPILE;' END
    FROM dba_objects 
    WHERE status = 'INVALID' 
      AND object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'TRIGGER', 'VIEW');
  • 把结果保存为 recompile_invalid.sql,然后在 SQL*Plus 中运行:
    @recompile_invalid.sql
  • 编译后检查是否还有残留:
    SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';
    若非零,说明某些对象依赖链断裂(比如被删的表还在 SP 里引用),得人工修复源码再重试

容易被忽略的关键点

批量编译只是“让对象能跑起来”,不代表性能恢复。升级后必须同步做三件事:

  • 确认新兼容级别是否已生效:SELECT compatibility_level FROM sys.databases WHERE name = DB_NAME();
  • 更新统计信息:EXEC sp_updatestats;(SQL Server)或 EXEC DBMS_STATS.GATHER_DATABASE_STATS;(Oracle)
  • 检查是否有隐式类型转换:升级后优化器对参数匹配更严格,@id INTBIGINT 值更容易触发 CONVERT_IMPLICIT,导致索引失效
PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

3703

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

791

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

949

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5481

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2463

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5460

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7101

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

970

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

852

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.1万人学习