SELECT b.[name], a.[definition] FROM sys.all_sql_modules a, sysobjects b WHERE a.[object_id] = id AND definition LIKE '%表名%'
select col+',' from mytable for xml path('')
排序:html
create table pd(col1 varchar(5),col2 int) insert into pd select 'A',3 union all select 'A',2 union all select 'A',1 union all select 'B',2 union all select 'B',1 select a.col1, stuff((select ','+rtrim(b.col2) from pd b where b.col1=a.col1 order by b.col2 for xml path('')),1,1,'') 'col2' from pd a group by a.col1
select * from sysobjects obj where LOWER(obj.name) LIKE N'%storeroom%' and xtype='U'
DECLARE @t1 TABLE ( c1 NUMERIC (12), c2 VARCHAR (30) ) INSERT INTO @t1 (c1, c2) VALUES (1, 'a'); INSERT INTO @t1 (c1, c2) VALUES (2, 'a'); INSERT INTO @t1 (c1, c2) VALUES (3, 'b'); INSERT INTO @t1 (c1, c2) VALUES (4, 'b'); SELECT CASE WHEN max (c1) > 3 THEN sum (c1) ELSE 0 END AS c FROM @t1 GROUP BY c2; /* 结果: c 0 7 */
http://www.cnblogs.com/wsdj-ITtech/archive/2011/10/06/2199736.html sql
USE [MSSQL] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION [dbo].[My_OneDay_GetWeekFirstAndEndDay](@tmpDate DATETIME) RETURNS @tmpTable TABLE(FirstDay DATETIME , EndDay DATETIME) AS BEGIN INSERT INTO @tmpTable SELECT a.FirstDay,b.EndDay FROM ( SELECT 1 AS ID,DATEADD(wk, DATEDIFF(wk,0,@tmpDate), 0) AS FirstDAy ) a LEFT JOIN ( SELECT 1 AS ID,DATEADD(wk, DATEDIFF(wk,0,@tmpDate), 6) AS EndDay ) b ON a.ID = b.ID RETURN END
SELECT * from My_OneDay_GetWeekFirstAndEndDay('2010-09-01')
http://www.cnblogs.com/wsdj-ITtech/archive/2011/10/06/2199736.html shell
CREATE FUNCTION [dbo].[MY_Range_GetWeekFirstAndEndDays](@tmpDateSTART DATETIME,@tmpDateEND DATETIME) RETURNS @tmpTable TABLE(WeekOrder INT,FirstDay DATETIME , EndDay DATETIME) AS BEGIN DECLARE @tmpDate DATETIME DECLARE @index INT SET @tmpDate=@tmpDateSTART SET @index=1 WHILE @tmpDate <=@tmpDateEND BEGIN INSERT INTO @tmpTable SELECT @index,a.FirstDay,b.EndDay FROM ( SELECT 1 AS ID,DATEADD(wk, DATEDIFF(wk,0,@tmpDate), 0) AS FirstDAy) a LEFT JOIN ( SELECT 1 AS ID,DATEADD(wk, DATEDIFF(wk,0,@tmpDate), 6) AS EndDay) b ON a.ID = b.ID SET @tmpDate=DATEADD(DAY,7,@tmpDate) SET @index=@index+1 END RETURN END
SELECT * from My_Range_GetWeekFirstAndEndDays('2011-09-01','2011-10-06')
不使用临时表:数据库
DECLARE @tmpDateSTART DATETIME DECLARE @tmpDateEND DATETIME SET @tmpDateSTART = '2015-1-1' SET @tmpDateEND = '2015-1-21' DECLARE @tmpDate DATETIME DECLARE @days INT SET @tmpDate = @tmpDateSTART SET @days = 0 WHILE @tmpDate <= @tmpDateEND BEGIN DECLARE @theDate DATETIME; SET @theDate = DATEADD (wk, DATEDIFF (wk, 0, @tmpDate), 6); IF @theDate > @tmpDateSTART AND @theDate < @tmpDateEND SET @days = @days + 1 SET @tmpDate = DATEADD (DAY, 7, @tmpDate) END SELECT @days
SELECT [Spid] = session_Id, ecid, [Database] = DB_NAME (sp.dbid), [User] = nt_username, [Status] = er.status, [Wait] = wait_type, [Individual Query] = SUBSTRING ( qt.text, er.statement_start_offset / 2, ( CASE WHEN er.statement_end_offset = -1 THEN LEN (CONVERT (NVARCHAR (MAX), qt.text)) * 2 ELSE er.statement_end_offset END - er.statement_start_offset) / 2), [Parent Query] = qt.text, Program = program_name, Hostname, nt_domain, start_time, datediff (second, start_time, getdate ()) FROM sys.dm_exec_requests er INNER JOIN sys.sysprocesses sp ON er.session_id = sp.spid CROSS APPLY sys.dm_exec_sql_text (er.sql_handle) AS qt WHERE session_Id > 50 -- Ignore system spids. AND session_Id NOT IN (@@SPID) -- Ignore this current statement. ORDER BY datediff (second, start_time, getdate ()) DESC
C#中用Guid.NewGuid().ToString()缓存
Sql中用NEWID() 安全
以上方法生成的是36位的GUID,若是须要转换成32位,则须要替换掉其中的'-'字符。session
Sql中的方法:replace(newid(), '-', '')dom
--将时间转换为小时 --例如8:22分转换为9 --查询语句以下 SELECT cast ( datepart ( hh, dateadd ( mi, ( datediff (mi, CONVERT (VARCHAR (10), getdate (), 112), getdate ()) / 60 + 1) * 60, CONVERT (VARCHAR (10), getdate (), 112))) AS INT)
http://bbs.csdn.net/topics/190127317 --环境 declare @t table ( 时间 datetime, 金额 int ) insert @t select '2007-1-1 10:00:23', 8 union all select '2007-1-1 10:01:24', 4 union all select '2007-1-1 10:05:00', 2 union all select '2007-1-1 10:06:12', 3 union all select '2007-1-1 10:08:00', 1 union all select '2007-1-1 10:12:11', 5 select dateadd(mi,(datediff(mi,convert(varchar(10),时间,112),时间)/5+1)*5,convert(varchar(10),时间,112)) as 时间段, count(*) as 行数,sum(金额) as 总金额 from @t group by dateadd(mi,(datediff(mi,convert(varchar(10),时间,112),时间)/5+1)*5,convert(varchar(10),时间,112)) --结果 时间段 行数 总金额 ------------------------------------------------------ ----------- ----------- 2007-01-01 10:05:00.000 2 12 2007-01-01 10:10:00.000 3 6 2007-01-01 10:15:00.000 1 5 (所影响的行数为 3 行)
如今的解决办法是,将存储过程当中加个空格,alter一下。ide
exec 存储过程 with recompile函数
http://bbs.csdn.net/topics/340185343
http://my.oschina.net/HenuToater/blog/177175
http://havebb.com/b/post/produce-suddenly-slow.aspx
http://www.cnblogs.com/luckylei66/archive/2012/07/30/2615000.html
SQL优化之存储过程强制编译 ASP.NET调用SQL后台存储过程时,有时忽然就变得很慢,在后台直接执行存储过程没问题,但在前台调用存储过程时就是很慢,并且在前台调用成功后,再次调用仍是同样的慢,但更新一下存储过程再调用就很快了。但这始终不能完全解决问题,过段时间又会出来一样的问题。环境(NET4.0+SQL2008R2) 解决办法: 方法一:在可能比较耗时的语句后面加上option(recompile) 方法二:强制编译存储过程 SQL Server 提供三种从新编译存储过程的方法: (1)、sp_recompile 系统存储过程强制在下次运行存储过程时进行从新编译。 示例:exec sp_recompile 存储过程名 (2)、建立存储过程时在其定义中指定 WITH RECOMPILE 选项,代表 SQL Server 将不对该存储过程计划进行高速缓存;该存储过程将在每次执行时都从新编译。 示例:Create Proc 存储过程名 WITH RECOMPILE AS 参数 (3)、在执行存储过程时指定 WITH RECOMPILE 选项,可强制对存储过程进行从新编译。仅当所提供的参数不典型,或者自建立该存储过程后数据发生显著更改时才应使用此选项。 示例:存储过程名 WITH RECOMPILE
参数探测(Parameter Sniffing)与影响计划重用的SET选项
http://www.cnblogs.com/bigholy/archive/2011/10/18/2216489.html
SQL Server中存储过程比直接运行SQL语句慢的缘由
http://blog.csdn.net/emili/article/details/2192081
在不少的资料中都描述说SQLSERVER的存储过程较普通的SQL语句有如下优势: 1. 存储过程只在创造时进行编译便可,之后每次执行存储过程都不需再从新编译,而咱们一般使用的SQL语句每执行一次就编译一次,因此使用存储过程可提升数据库执行速度。 2. 常常会遇到复杂的业务逻辑和对数据库的操做,这个时候就会用SP来封装数据库操做。当对数据库进行复杂操做时(如对多个表进行 Update,Insert,Query,Delete时),可将此复杂操做用存储过程封装起来与数据库提供的事务处理结合一块儿使用。能够极大的提升数据 库的使用效率,减小程序的执行时间,这一点在较大数据量的数据库的操做中是很是重要的。在代码上看,SQL语句和程序代码语句的分离,能够提升程序代码的 可读性。 3. 存储过程能够设置参数,能够根据传入参数的不一样重复使用同一个存储过程,从而高效的提升代码的优化率和可读性。 4. 安全性高,可设定只有某此用户才具备对指定存储过程的使用权存储过程的种类: A. 系统存储过程:以sp_开头,用来进行系统的各项设定.取得信息.相关管理工做,如 sp_help就是取得指定对象的相关信息。 B. 扩展存储过程 以XP_开头,用来调用操做系统提供的功能 exec master..xp_cmdshell 'ping 10.8.16.1' C. 用户自定义的存储过程,这是咱们所指的存储过程经常使用格式 模版:Create procedure procedue_name [@parameter data_type][output] [with]{recompile|encryption} as sql_statement 解释:output:表示此参数是可传回的 with {recompile|encryption} recompile:表示每次执行此存储过程时都从新编译一次;encryption:所建立的存储过程的内容会被加密。 可是最近咱们项目组中有人写了一个存储过程,其计算时间为1个小时47分钟,而有的时候运行时间都超过了两个小时,同事描述说若是将存储过程当中的语句拿出来直接运行也就10分钟左右就运行完毕,我没当回事,可是今天我本身写的存储过程也遇到了这个问题,在查找资料后缘由终于找到了缘由,原来是Parameter sniffing问题。 下面看我是如何将运行一个小时以上的存储过程优化成在一分钟以内完成的: 原存储过程 CREATE PROCEDURE [dbo].[pro_ImAnalysis_daily] @THEDATE VARCHAR(30) AS BEGIN IF @THEDATE IS NULL BEGIN SET @THEDATE=CONVERT(VARCHAR(30),GETDATE()-1,112); END DELETE FROM RPT_IM_USERINFO_DAILY WHERE THEDATE=@THEDATE; INSERT RPT_IM_USERINFO_DAILY (THEDATE,ALLUSER,NEWUSER) SELECT AA.THEDATE,ALLUSER,NEWUSER FROM ( ( SELECT THEDATE,COUNT(DISTINCT USERID) ALLUSER FROM FACT WHERE THEDATE=@THEDATE GROUP BY THEDATE ) AA LEFT JOIN (SELECT THEDATE,COUNT(DISTINCT USERID) NEWUSER FROM FACT T1 WHERE NOT EXISTS( SELECT 1 FROM FACT T2 WHERE T2.THEDATE<@THEDATE AND T1.USERID=T2.USERID) AND T1.THEDATE=@THEDATE GROUP BY THEDATE ) BB ON AA.THEDATE=BB.THEDATE); GO 每日执行:exec pro_ImAnalysis_daily @thedate=null 耗时:1小时47分~2小时13分 通过查找资料,缘由以下(因为源文是一篇英文,有些地方写的我不是特别清楚,原文见http://groups.google.com/group/microsoft.public.sqlserver.server/msg/ad37d8aec76e2b8f?hl=en&lr=&ie=UTF-8&oe=UTF-8): 在SQL Server中有一个叫作 “Parameter sniffing”的特性。SQL Server在存储过程执行以前都会制定一个执行计划。在上面的例子中,SQL在编译的时候并不知道@thedate的值是多少,因此它在执行执行计划的时候就要进行大量的猜想。假设传递给@thedate的参数大部分都是非空字符串,而FACT表中有40%的thedate字段都是null,那么SQL Server就会选择全表扫描而不是索引扫描来对参数@thedate制定执行计划。全表扫描是在参数为空或为0的时候最好的执行计划。可是全表扫描严重影响了性能。 假设你第一次使用了Exec pro_ImAnalysis_daily @thedate=’20080312’那么SQL Server就会使用20080312这个值做为下次参数@thedate的执行计划的参考值,而不会进行全表扫描了,可是若是使用@thedate=null,则下次执行计划就要根据全表扫描进行了。 有两种方式可以避免出现“Parameter sniffing”问题: (1)经过使用declare声明的变量来代替参数:使用set @variable=@thedate的方式,将出现@thedate的sql语句所有用@variable来代替。 (2) 将受影响的sql语句隐藏起来,好比: a) 将受影响的sql语句放到某个子存储过程当中,好比咱们在@thedate设置成为今天后再调用一个字存储过程将@thedate做为参数传入就能够了。 b) 使用sp_executesql来执行受影响的sql。执行计划不会被执行,除非sp_executesql语句执行完。 c) 使用动态sql(”EXEC(@sql)”来执行受影响的sql。 采用(1)的方法改造例子中的存储过程,以下: ALTER PROCEDURE [dbo].[pro_ImAnalysis_daily] @var_thedate VARCHAR(30) AS BEGIN declare @THEDATE VARCHAR(30) IF @var_thedate IS NULL BEGIN SET @var_thedate=CONVERT(VARCHAR(30),GETDATE()-1,112); END SET @THEDATE=@var_thedate; DELETE FROM RPT_IM_USERINFO_DAILY WHERE THEDATE=@THEDATE; INSERT RPT_IM_USERINFO_DAILY (THEDATE,ALLUSER,NEWUSER) SELECT AA.THEDATE,ALLUSER,NEWUSER FROM ( ( SELECT THEDATE,COUNT(DISTINCT USERID) ALLUSER FROM FACT WHERE THEDATE=@THEDATE GROUP BY THEDATE ) AA LEFT JOIN (SELECT THEDATE,COUNT(DISTINCT USERID) NEWUSER FROM FACT T1 WHERE NOT EXISTS( SELECT 1 FROM FACT T2 WHERE T2.THEDATE<@THEDATE AND T1.USERID=T2.USERID) AND T1.THEDATE=@THEDATE GROUP BY THEDATE ) BB ON AA.THEDATE=BB.THEDATE); GO 测试执行速度为10分钟,我又检查了一下这个SQL,发现这个SQL有问题,这个SQL使用了not exists,在一个大表里面使用not exists是不太明智的,因此,我又对这个sql进行了改进,改为以下: ALTER PROCEDURE [dbo].[pro_ImAnalysis_daily] @var_thedate VARCHAR(30) AS BEGIN declare @THEDATE VARCHAR(30) IF @var_thedate IS NULL BEGIN SET @var_thedate=CONVERT(VARCHAR(30),GETDATE()-1,112); END SET @THEDATE=@var_thedate; DELETE FROM RPT_IM_USERINFO_DAILY WHERE THEDATE=@THEDATE; INSERT RPT_IM_USERINFO_DAILY(THEDATE,ALLUSER,NEWUSER) select @thedate as thedate, count(distinct case when today>0 then userid else null end) as alluser, count(distinct case when dates=0 then userid else null end) as newuser from ( select userid, count(CASE WHEN thedate>=@thedate then null else thedate end) as dates, count(case when thedate=@thedate then thedate else null end) as today from FACT group by userid )as fact GO 测试结果为30ms如下。
http://support.microsoft.com/kb/305977/zh-cn
问题 1:为何在已经有了临时表的状况下还要引入表变量? 解答 1:与临时表相比,表变量具备下列优势: 如 SQL Server 联机丛书“表”(Table) 一文中所述,表变量(如局部变量)具备明肯定义的范围,在该范围结束时会自动清除这些表变量。 与临时表相比,表变量致使存储过程的从新编译更少。 涉及表变量的事务仅维持表变量上更新的持续时间。所以,使用表变量时,须要锁定和记录资源的状况更少。由于表变量具备有限的范围而且不是持久性数据库的一部分,因此事务回滚并不影响它们。 问题 2:若是说使用表变量比使用临时表致使存储过程的从新编译更少,这意味着什么? 解答 2:下面的文章讨论了从新编译存储过程的一些缘由: 243586 存储过程从新编译的疑难解答 “因为某些临时表操做引发的从新编译”一节还列出了为避免一些问题(例如使用临时表致使从新编译)而须要知足的一些要求。这些限制不适用于表变量。 表变量彻底独立于建立这些表变量的批,所以,当执行 CREATE 或 ALTER 语句时,不会发生“从新解析”,而在使用临时表时可能会发生“从新解析”。临时表须要此“从新解析”,以便从嵌套存储过程引用该表。表变量彻底避免了此问题,所以存储过程可使用已编译的计划,从而节省了处理存储过程的资源。 问题 3:表变量有哪些缺陷? 解答 3:与临时表相比,它存在下列缺陷: 在表变量上不能建立非汇集索引(为 PRIMARY 或 UNIQUE 约束建立的系统索引除外)。与具备非汇集索引的临时表相比,这可能会影响查询性能。 表变量不像临时表那样能够维护统计信息。在表变量上,不能经过自动建立或使用 CREATE STATISTICS 语句来建立统计信息。所以,在大表上进行复杂查询时,缺乏统计信息可能会妨碍优化器肯定查询的最佳计划,从而影响该查询的性能。 在初始 DECLARE 语句后不能更改表定义。 表变量不能在 INSERT EXEC 或 SELECT INTO 语句中使用。 表类型声明中的检查约束、默认值以及计算所得的列不能调用用户定义的函数。 若是表变量是在 EXEC 语句或 sp_executesql 存储过程外建立的,则不能使用 EXEC 语句或 sp_executesql 存储过程来运行引用该表变量的动态 SQL Server 查询。因为表变量只能在它们的本地做用域中引用,所以 EXEC 语句和 sp_executesql 存储过程将在表变量的做用域以外。可是,您能够在 EXEC 语句或 sp_executesql 存储过程内建立表变量并执行全部处理,由于这样表变量本地做用域将位于 EXEC 语句或 sp_executesql 存储过程当中。 问题 4:与临时表或永久表相比,表变量的仅存在于内存中的结构保证了更好的性能,是否由于它们是在驻留在物理磁盘上的数据库中维护的? 解答 4:表变量不是仅存在于内存中的结构。因为表变量可能保留的数据较多,内存中容纳不下,所以它必须在磁盘上有一个位置来存储数据。与临时表相似,表变量是在 tempdb 数据库中建立的。若是有足够的内存,则表变量和临时表都在内存(数据缓存)中建立和处理。 问题 5:必须使用表变量来代替临时表吗? 解答 5:答案取决于如下三个因素: 插入到表中的行数。 从中保存查询的从新编译的次数。 查询类型及其对性能的指数和统计信息的依赖性。 在某些状况下,可将一个具备临时表的存储过程拆分为多个较小的存储过程,以便在较小的单元上进行从新编译。 一般状况下,应尽可能使用表变量,除非数据量很是大而且须要重复使用表。在这种状况下,能够在临时表上建立索引以提升查询性能。可是,各类方案可能互不相同。Microsoft 建议您作一个测试,来验证表变量对于特定的查询或存储过程是否比临时表更有效。
x.待续