使用Sybase sp_recompile重新编译存储过程和触发器
Sybase 15.X中提供了内置的存储过程sp_recompile。该存储过程可令表中的存储过程和触发器在下次使用时重新编译。(Causes each stored procedure and trigger that uses the named table to be recompiled the next time it runs.)
存储过程和触发器使用的查询,仅在编译时优化一次。当systabstats统计信息,如行数或聚簇率(cluster ratio)发生显著改变时,已编译的存储过程和触发器效率可能会变低,并可能会受益于sp_recompile的重新编译。通过对表的存储过程和触发器进行重新编译,可优化查询以获得最佳效率。
在Sybase ASE 15.X中,create index和update statistics会自动重新编译存储过程和触发器。在这些情况下使用sp_recompile会导致冗余的重新编译。
该存储过程的唯一输入变量,是数据表的对象名称。
Sybase官方手册给出的语法示例为:
Recompiles each trigger and stored procedure that uses the table titles the next time the trigger or stored procedure is run:
sp_recompile titles
但实际使用中(ASE 15.7),却总是得到如下错误提示:
Msg 17460
Object must be in the current database.
如果在表名前加上用户名,如user_name.title,则会得到如下错误提示:
Msg 102
Incorrect syntax near '.'.
全网查询了一下,用这个存储过程的人很少啊……
百思不得其解,于是使用sybsystemprocs..sp_helptext sp_recompile查看该存储过程的源代码。
create procedure sp_recompile
@objname varchar(767)
as
declare @type smallint
declare @uid int
declare @msg varchar(1024)
declare @dbname varchar(255)
if @objname like '%%.%%.%%' and
substring(@objname, 1, charindex(".", @objname) - 1) != db_name()
begin
/*
** 17390, "Table or view name must be in 'current' database."
*/
raiserror 17390
return (1)
end
if not exists (select * from sysobjects where id = object_id(@objname))
begin
/*
** 17460, "Object must be in the current database."
*/
raiserror 17460
return (1)
end
唯一的输入变量@objname是varchar()类型。如果是使用dbname.username.tabname方法写的,还会检查输入的dbname与当前数据库(db_name())是否一致。然后直接将@objname送入sysobjects表中查询对应的id。
这就很容易理解了:需要为输入加上单引号,如:
sp_recompile 'username.tablename'
或
sp_recompile 'dbname.username.tablename'