这是我从重命名数据库中观察到的一些行为。这是什么原因?为了这个问题的目的,这个例子被简化了。
CREATE DATABASE [Database_A]
GO
CREATE DATABASE [Database_B]
GO
CREATE DATABASE [Database_B_Copy]
GO
-- create a table for testing purposes
USE [Database_B]
GO
CREATE TABLE [dbo].[Table_1](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Column1] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT INTO [Database_B].[dbo].[Table_1] (Column1) values ('[Database_B]')
GO
-- create an copy of the table with the same schema
USE [Database_B_Copy]
GO
CREATE TABLE [dbo].[Table_1](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Column1] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT INTO [Database_B_Copy].[dbo].[Table_1] (Column1) values ('[Database_B_Copy]')
GO
-- create a stored procedure to demonstrate the problem
USE [Database_A]
GO
CREATE PROCEDURE [dbo].[TestSP]
AS
BEGIN
SELECT * FROM Database_B.dbo.Table_1
END
GO
[1]. 当我运行存储过程 TestSP 时,预期的结果是 DatabaseB Table_1 的内容。
ID Column1
1 [Database_B]
[2]. 将 Database_B 重命名为 Database_B_Original 将按预期导致此错误:
Msg 208, Level 16, State 1, Procedure TestSP, Line 4
Invalid object name 'Database_B.dbo.Table_1'.
[3]. 使 Database_B_Original 脱机,存储过程中的错误更改为:
Msg 942, Level 14, State 4, Procedure TestSP, Line 4
Database 'Database_B_Original' cannot be opened because it is offline.
[4]. 然后我将 Database_B_Copy 重命名为 Database_B。因为名为 Database_B 的数据库可用,所以我希望存储过程能够工作。但是错误仍然存在。
最后,如果我重新启动 Sql Server,这会神奇地解决问题,并且输出如预期的那样:
ID Column1
1 [Database_B_Copy]
SQL Server 是否错误地缓存了表和数据库名称信息?有没有办法强制Sql Server刷新信息?
我想更好地了解此问题的根本原因是什么,以及它是设计使然还是 sql server 错误。
SQL Server 正在做的是,它正在缓存查询计划
可以使用以下方法找到:
当您在步骤 1、2 或 3 中执行存储过程时,它会缓存在过程缓存中。
因此,在您的第 4 步中,它会抛出一个错误。
如果您执行 a
dbcc freeproccache
,然后重新运行 SPexec [Database_A].[dbo].[TestSP]
,它将起作用。正如@Aaron 指出的那样,它也可以使用
EXEC sys.sp_refreshsqlmodule 'Database_A.dbo.TestSP'
或重新编译 SPsp_recompile TestSP
。参考:http ://technet.microsoft.com/en-us/library/bb326754(v=sql.105).aspx
无需重新启动 SQL Server。
注意: Free ProcCache 会清除所有查询计划,因此最好使用
sys.sp_refreshsqlmodule
orsp_recompile
。