(一)工作总结——当你遇到困难时,心中总会有一个奇怪的念头……

当你遇到困难时,心中总有一个奇怪的念头——我遇到的怎么都是些这么奇怪的问题!

紧张且匆忙的一天终于过去了。说紧张,因为工作效率和同事比起来实在是太低了,匆忙也就不言而喻!

使用一个不熟悉的开发方式下,对一个要求开发效率的公司里面简直是致命的,上一家公司工作几乎快两年了,一直是Jquery(Ajax)+ Oracle2010;C#里面拼接SQL语句,然后参数化该语句。现在完全不一样了,AjaxPro+SQL Server2008+公司框架+存储过程(动态拼接移到SQL语句了)+ 大量JS代码(使用了公司框架)……

下面讲讲今天拼接的一条存储过程及所遇到的困难。由于存储过程需要配合公司所用的一些东西,所以减少了投机取巧的机会,一定程度上只能由自己完成(虽然得到了不少帮助,但是在一个QQ都会卡掉线的情况下简直太不容易了)。在此感谢一下那些给我提供过帮助的朋友。。。

use TestDB
go
if exists (select * from sysobjects where name='pro_GetPdfTransformTasksList' and type='p') 
drop procedure pro_GetPdfTransformTasksList
go
create procedure pro_GetPdfTransformTasksList
	@pageSize int = 10,
	@pageIndex int = 0,
	@RealName nvarchar(100)='',
	@IncidentNo int = -1,
	@STime datetime='1900-01-01 00:00:00',
	@ETime datetime='1900-01-01 00:00:00',
	@MoneyS decimal(18,2)=-1,
	@MoneyE decimal(18,2)=-1,
	@Status int=0,
	@Result int=0,
	@countRecord int output
	--,@countPage int output
AS
	declare @sql nvarchar(1000),@sqlTemp nvarchar(2000)
	
	set @sql=N' select p.PT_Guid,p.PT_FileName,p.PT_FileId,p.PT_ProcessName,p.PT_IncidentNo,p.PT_CreateTime,
p.PT_Money,p.PT_UserId,p.PT_UserLoginName,p.PT_UserRealName,p.PT_Status,p.PT_Result,
p.PT_ResultDesc,p.PT_UrgencyDegree,pf.pdfCount from PdfTransformTasks as p 
left join (select PT_Guid,count(PF_Guid) pdfCount 
from PdfTransformFiles 
group by PT_Guid ) as pf 
on p.PT_Guid=pf.PT_Guid 
where 1=1 '
	
	if((@RealName is not null) and @RealName != '') 
	begin
		set @sql = @sql + ' and p.PT_UserRealName='''+@RealName + ''''
	end
	
	if((@IncidentNo is not null) and @IncidentNo!=-1)
	begin	
		set @sql = @sql + ' and p.PT_IncidentNo=' + convert(nvarchar,@IncidentNo) 
	end 

	if(@STime is not null and @STime!=convert(datetime,'1900-01-01 00:00:00'))
	begin
		set @sql = @sql + ' and p.PT_CreateTime>=''' + convert(nvarchar,@STime)+''''
	end

	if(@ETime is not null and @ETime!=convert(datetime,'1900-01-01 00:00:00'))
	begin 
		set @sql = @sql + ' and p.PT_CreateTime<=''' + convert(nvarchar,@ETime)+''''
	end

	if(@MoneyS is not null and @MoneyS!=-1)
	begin
		set @sql = @sql + ' and p.PT_Money>=' + convert(nvarchar,@MoneyS)
	end
	if(@MoneyE is not null and @MoneyE!=-1)
	begin
		set @sql = @sql + ' and p.PT_Money<=' + convert(nvarchar,@MoneyE)
	end
	if(@Status is not null and @Status!=0)
	begin
		set @sql = @sql + ' and p.PT_Status=' + convert(nvarchar,@Status)
	end
	if(@Result is not null and @Result!=0)
	begin
		set @sql = @sql + ' and p.PT_Result=' + convert(nvarchar,@Result)
	end
	
	set @sqlTemp=N'select top '+cast(@pageSize as nvarchar(10))+' * from ('+@sql+') as tab '+
		' where tab.pt_guid not in (select top '+cast((@pageSize*@pageIndex) as nvarchar(10))+' t.pt_guid from ('+@sql+') as t)'

	declare @counttemp int ,@sqltemp2 nvarchar(2000)
	set @sqltemp2='select @count1=count(1) from ('+@sqlTemp+') as aaa'
	exec sp_executesql @sqltemp2,N'@count1 int out',@counttemp out 

	set @countRecord=@counttemp
	select @countRecord as aaa 
	exec(@sqlTemp)
		
	/*set @countPage=@countRecord/@pageSize 
	if(@countRecord%@pageSize<>0) 
	set @countPage=@countPage+1 */
go 
问题一:select convert(datetime,'1900-00-00 00:00:00') 

说明:看出问题了么?在比较匆忙的情况下你也许会对错误提示比较抓狂。

问题二:拼接SQL语句中,时间类型转换。如:set @sql = @sql + ' and p.PT_CreateTime<=''' + convert(nvarchar,@ETime)+''''

说明:这儿和Oracle的to_date()函数比较像,千万不要写成了 set @sql = @sql + ' and p.PT_CreateTime<='convert(nvarchar,'' + @ETime+')''',不然,变量“@ETime”始终会出现在你的SQL查询结果错误信息中。

问题三:执行报千奇百怪的错误信息,怎么办?1、存储过程里面exec(@sql)的exec换成print,那么执行结果就可以看到错误信息了,然后把打印出来的sql语句复制到查询窗口里面去,看看详细的错误信息。很多时候都是sql拼接错误,对于新手来说,这个方法比较适用。


学到了什么?

一、沉着冷静,不管遇到什么问题,紧张,急于求成,只会带来负面效果。你要做的就是认真分析,查找错误来源,寻找排错对策。

二、除了问题二里面说到的exec换成print,其实还可以在整段存储过程中其他地方添加print,执行后可以看到SQL语句执行到什么地方出错的,然后就是SQL profile监视工具,使用断点调试配合该工具,非常方便。在程序里面想调试的sql语句前后分别断点,当运行到sql前断点时,清除掉所监视的所有数据,然后程序运行到sql后面的断点,让profile暂停下来,这时就可以看到刚才监视到运行的sql语句了。

三、参见贴出的SQL片段,主要注意在幅初始值给不同类型的参数及标点符号、转义等。


疑问:

一、如果使用动态拼接好的sql语句。例如上面SQL片段中的@sql,因为在拼接好@sql语句后,需要通过执行该语句,才能得到数据总条数,例如:现在需要

select count(*) from (@sql),显然,这样写是不行的,上面在同事的帮助下已经给出了答案,但是我想知道有没有跟好的办法,想想上面就因为一个总条数又定义了 一个nvarchar(2000)的变量,感觉不是很好???

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值