最近在公司项目中使用exec sp_executesql @sql执行一段文本sql的时候老是报错: Could not find database ID 16, name '16'. The database may be offline. Wait a few minutes and try again.执行的sql大概如下,注意其中有个额外的参数@databaseName是nvarchar类型,用来声明数据库的名字:

SET @tableScript=N''+
N'IF (SELECT COUNT(1) FROM ['+@databaseName+N'].dbo.sysobjects WHERE ID = OBJECT_ID(''['+@databaseName+N'].[dbo].[Raw_Tables_Metadata]''))=0
BEGIN
CREATE TABLE ['+@databaseName+N'].[dbo].[Raw_Tables_Metadata](
ID INT IDENTITY(1,1) NOT NULL,
Table_Name NVARCHAR(100) NOT NULL,
Column_Name NVARCHAR(100) NOT NULL,
Column_Type NVARCHAR(100) NOT NULL,
Column_Size NVARCHAR(100) NULL,
Skip_Rows INT NULL,
CONSTRAINT [PK_Raw_Tables_Metadata] 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]
END'
EXEC sp_executesql @tableScript;

后来我查找了master.dbo.sysdatabases这个系统表:

select * from master.dbo.sysdatabases 

发现dbid为16的数据库现在在sql server中不存在。我就纳闷了,明明我在上面sql文本中的参数@databaseName中声明的是数据库'A',执行上面语句后,为啥现在sql server报错说一个不存在的数据库id是offline的。。。后来在网上查了查,发现这有可能是因为sp_executesql这个执行sql文本的系统存储过程会复用缓存的执行计划。我才想起数据库'A'在sql server中前几天被删除重建过,在删除前'A'的dbid是16,而重建后数据库'A'的dbid不是16了,现在dbid为16的数据库在sql server中不存在。。。然而由于sql server中缓存的执行计划没有被更新,所以执行上面语句后,sql server还是会复用老的执行计划,去通过dbid=16来查找数据库'A',最后导致报错。

后来我将上面的语句做了下小小的改动,仅仅是在exec sp_executesql @sql的后面加上了with recompile关键字,如下所示:

SET @tableScript=N''+
N'IF (SELECT COUNT(1) FROM ['+@databaseName+N'].dbo.sysobjects WHERE ID = OBJECT_ID(''['+@databaseName+N'].[dbo].[Raw_Tables_Metadata]''))=0
BEGIN
CREATE TABLE ['+@databaseName+N'].[dbo].[Raw_Tables_Metadata](
ID INT IDENTITY(1,1) NOT NULL,
Table_Name NVARCHAR(100) NOT NULL,
Column_Name NVARCHAR(100) NOT NULL,
Column_Type NVARCHAR(100) NOT NULL,
Column_Size NVARCHAR(100) NULL,
Skip_Rows INT NULL,
CONSTRAINT [PK_Raw_Tables_Metadata] 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]
END'
EXEC sp_executesql @tableScript with recompile;

加上with recompile后,exec sp_executesql @sql就不会重用系统中缓存的执行计划了,每次都是重新生成执行计划。不过这样做性能肯定是要低一些,但是至少保证了在我说的这个场景下不会出错。

所以在使用exec sp_executesql @sql的时候要小心,考虑缓存的执行计划被重用的可能性,另外可以参考下面这篇文章了解sp_executesql的执行计划缓存机制:

sp_executesql的执行计划会被重用

另外也有人建议使用DBCC FREEPROCCACHE清除sql server中所有缓存的执行计划来解决本文所述的问题(下面链接文章),但是DBCC FREEPROCCACHE这个语句对生产环境数据库的性能影响极大,不建议轻易使用!

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=89821

Sql server在使用sp_executesql @sql执行文本sql时,报错: Could not find database ID 16, name '16'. The database may be offline. Wait a few minutes and try again.的更多相关文章

  1. 在sql server中怎样获得正在执行的Sql查询

    方法1:使用DBCC inputbuffer(spid) 使用SP_WHO获得SPID,然后再执行上面的DBCC command,参见下图 执行一段sql语句 打开另一个query窗口并执行SP_WH ...

  2. sql server 2008 R2无法连接127.0.0.1报错 Server error:40(错误:53)

    在公司用sql server 2008 R2很好的,回家连接127.0.0.1就报错.sql server2008R2主机名和.都可以登录,连接127.0.0.1出错,在与 SQL Server 建立 ...

  3. CentOS 7在执行yum操作时 报错

    CentOS 7在执行yum操作时, 报错:Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch ...

  4. 在caffe中执行脚本文件时 报错:-bash: ./train.sh: Permission denied

    报错原因:没有权限 解决方法:chmod 777 train.sh获得权限

  5. 优化SQL Server的内存占用之执行缓存

    在论坛上常见有朋友抱怨,说SQL Server太吃内存了.这里笔者根据经验简单介绍一下内存相关的调优知识   首先说明一下SQL Server内存占用由哪几部分组成.SQL Server占用的内存主要 ...

  6. ms sql server 在cmd中执行sqlcmd的时候报错

    cmd下直接输入sqlcmd会提示 错误: HResult 0x2,级别 16,状态 1命名管道提供程序: 无法打开与 SQL Server 的连接 [2].Sqlcmd: 错误: Microsoft ...

  7. Sql Server 带参数的存储过程执行方法

    Sql Server 带参数的存储过程执行方法 Visual C# 动态操作 SQL Server 数据库实例教程(4):带参数的存储过程执行方法 上一篇文章介绍了带参数的SQL语句执行方法和不带参数 ...

  8. SQL Server游标 C# DataTable.Select() 筛选数据 什么是SQL游标? SQL Server数据类型转换方法 LinQ是什么? SQL Server 分页方法汇总

    SQL Server游标   转载自:http://www.cnblogs.com/knowledgesea/p/3699851.html. 什么是游标 结果集,结果集就是select查询之后返回的所 ...

  9. SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型

    原文:SQL Server 2008空间数据应用系列三:SQL Server 2008空间数据类型 友情提示,您阅读本篇博文的先决条件如下: 1.本文示例基于Microsoft SQL Server ...

随机推荐

  1. 如果非得了解下git系统... - 实践篇

    git的定义是一个内容寻址文件系统.内容.寻址.文件.系统,该来的总会来的… 本文旨在通过实践来介绍.git文件夹中的目录及文件功能,属git基础知识.但在此基础上可解决各git使用过程中可能遇到的问 ...

  2. 215. 数组中的第K个最大元素

    在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2输出: 5示 ...

  3. Java程序读取Properties文件

    一.如果将properties文件保存在src目录下 1.读取文件代码如下: /** * 配置文件为settings.properties * YourClassName对应你类的名字 * / pri ...

  4. SpringMVC之文件上传

    上传是web程序中常见的功能,当使用上传时,需要把form表单中的enctype属性改为multipart/form-data,这样就使用了二进制进行上传,而后台需要解析这些数据.Dispatcher ...

  5. tcp/ip通信中tcp头部结构tcphdrp->check校验计算

    通过raw socket修改通信数据后,可通过函数 set_tcp_checksum1(iph); 重新校验计算iph->check值 在http://www.cnblogs.com/dpf-1 ...

  6. 使用Akka构建集群(二)

    前言 在<使用Akka构建集群(一)>一文中通过简单集群监听器的例子演示了如何使用Akka搭建一个简单的集群,但是这个例子“也许”离我们的实际业务场景太远,你基本不太可能去做这样的工作,除 ...

  7. 读jQuery源码释疑笔记

    本释疑笔记是针对自己在看源码的过程中遇到的一些问题的解答,对大众可能不具有参考性,不过可以看看有没有你也不懂得地方,相互学习,相互进步.  1.each的用法 之前对each的用法一直迷迷糊糊,这次终 ...

  8. 分布式理论(四)—— 一致性协议之 3PC

    前言 我们说为了实现 BASE 理论,需要在可用性和一致性之间找到一个合适的一致性理论,于是,我们在上篇文章中了解了 2PC 理论,也就是两阶段提交,二阶段提交原理简单,实现方便,但是缺点则是同步阻塞 ...

  9. VB.NET的MsgBox

    一.可用按钮(指定消息框显示哪些按钮) MsgBoxStyle.OkOnly = vbOKOnly = 0(确定按钮) MsgBoxStyle.OkCancel = vbOKCancel = 1(确定 ...

  10. 配置Windows 防火墙,允许SQL Server的远程连接

    在运行SQL Server的服务器上,我们要找到哪些是SQL Server正在侦听的端口,并将其添加到Windows防火墙的入站例外. 首先,我们需要添加 SQL Server 服务侦听 Window ...