最近在公司项目中使用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. mysql 删除单表内多个字段重复的数据

    mysql 删除单表内多个字段重复的数据 DELETE from lot_log_payflow WHERE (pay_no,sub_flow_type) in () s1) AND id ) s2) ...

  2. Centos7 开启端口

    CentOS7默认没有使用iptables,所以通过编辑iptables的配置文件来开启80端口是不可以的. CentOS 7 采用了 firewalld 防火墙. 如要查询是否开启80端口: [ro ...

  3. Linux-(ping,traceroute,ss)

    ping命令 1.命令格式: ping [参数] [主机名或IP地址] 2.命令功能: ping命令用于:确定网络和各外部主机的状态:跟踪和隔离硬件和软件问题:测试.评估和管理网络.如果主机正在运行并 ...

  4. UVa 1572 Self-Assembly (拓扑排序)

    题目链接: https://cn.vjudge.net/problem/UVA-1572 Automatic Chemical Manufacturing is experimenting with ...

  5. zoj 1109 Language of FatMouse(map映照容器的典型应用)

    题目连接: acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1109 题目描述: We all know that FatMouse doe ...

  6. .17-浅析webpack源码之compile流程-入口函数run

    本节流程如图: 现在正式进入打包流程,起步方法为run: Compiler.prototype.run = (callback) => { const startTime = Date.now( ...

  7. 用MVC5+EF6+WebApi 做一个小功能(二) 项目需求整理

    在一个项目开始前,需求整理大概要占到整个项目周期15%甚至30%的比重,可以说需求理得越清楚,后续开发中返工几率越小.在一个项目中,开发新功能的花费的精力要远远小于修改功能的精力,这基本是一个共识.老 ...

  8. sqlserver 删除表中数据 id 从1开始

    TRUNCATE  TABLE  TbName   --TbName是表名 但如果TbName中某些字段与其它表有主外键关系,会报错: 无法截断表 'Plants',因为该表正由 FOREIGN KE ...

  9. mysql匿名登录 导致创建不了数据库

    常见问题 Access denied for user ''@'localhost' to database 'web02' //web02是我自己创建的数据库 原因分析:mysql数据库的user表 ...

  10. 【Java深入研究】3、HashMap源码解析(jdk 1.7)

    1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1 ...