若相依 发表于 2015-1-16 22:24:13

MSSQL网站制作之云云高效通用的分页存储历程是带有sql注...

上面我们说了DML的闪回方案。但对于DDL却无能为力,对于大多数的DDL,即使是rowbase格式,二进制日志binlog中仍只记录语句本身。对于删表操作,只记录一个语句droptablet。仅凭这句话,无法还原表的数据。存储历程|分页在google中搜刮“分页存储历程”会出来很多多少了局,是人人经常使用的分页存储历程,明天我却要说它是有毛病的,并且毛病没法经由过程修正存储历程举行弥补,假如你以为我错了,请读下往大概你会改动意见。一般人人城市以为存储历程能够制止sql注进的毛病,这合用于一样平常的存储历程,而关于通用分页存储历程是不合适的,请看上面的代码和剖析!一样平常的通用的分页存储历程代码以下:http://www.ckuyun.com/http://www.ckuyun.com/通用分页存储历程
CREATEPROCEDUREpagination
@tblNamevarchar(255),--表名
@strGetFieldsvarchar(1000)=*,--必要前往的列
@fldNamevarchar(255)=,--排序的字段名
@PageSizeint=10,--页尺寸
@PageIndexint=1,--页码
@doCountbit=0,--前往纪录总数,非0值则前往
@OrderTypebit=0,--设置排序范例,非0值则降序
@strWherevarchar(1500)=--查询前提(注重:不要加where)
AS

declare@strSQLvarchar(5000)--主语句
declare@strTmpvarchar(110)--一时变量
declare@strOrdervarchar(400)--排序范例
if@doCount!=0
begin
if@strWhere!=
set@strSQL=selectcount(*)asTotalfrom[+@tblName+]where+@strWhere
else
set@strSQL=selectcount(*)asTotalfrom[+@tblName+]
end
--以上代码的意义是假如@doCount传送过去的不是0,就实行总数统计。以下的一切代码都是@doCount为0的情形

else
begin
if@OrderType!=0
begin
set@strTmp=<(selectmin
set@strOrder=orderby[+@fldName+]desc
--假如@OrderType不是0,就实行降序,这句很主要!
end

else
begin
set@strTmp=>(selectmax
set@strOrder=orderby[+@fldName+]asc
end
if@PageIndex=1
begin
if@strWhere!=
set@strSQL=selecttop+str(@PageSize)++@strGetFields+from[+@tblName+]where+@strWhere++@strOrder
else
set@strSQL=selecttop+str(@PageSize)++@strGetFields+from[+@tblName+]+@strOrder
--假如是第一页就实行以上代码,如许会加速实行速率
end

else
begin
--以下代码付与了@strSQL以真正实行的SQL代码
set@strSQL=selecttop+str(@PageSize)++@strGetFields+from[
+@tblName+]where[+@fldName+]+@strTmp+([+@fldName+])from(selecttop+str((@PageIndex-1)*@PageSize)+[+@fldName+]from[+@tblName+]+@strOrder+)astblTmp)+@strOrder
if@strWhere!=
set@strSQL=selecttop+str(@PageSize)++@strGetFields+from[
+@tblName+]where[+@fldName+]+@strTmp+([
+@fldName+])from(selecttop+str((@PageIndex-1)*@PageSize)+[
+@fldName+]from[+@tblName+]where+@strWhere+
+@strOrder+)astblTmp)and+@strWhere++@strOrder
end
end
exec(@strSQL)
GO

人人能够看到下面的存储过程当中是经由过程一些步骤终极拼接成一个sql字符串,然后经由过程exec实行这个串失掉分页的了局。我们假定要做一个如许的查询,经由过程用户名UserName含混查询用户,为了叙说便利,便于了解我们只思索取第一页的情形,掏出存储过程当中取第一页的拼串行以下:set@strSQL=SELECTTOP+str(@PageSize)++@strGetFields+from[+@tblName+]where+@strWhere++@strOrder为了便于申明成绩,我们能够假定@pageSize为20,@strGetFields为‘*’,@tblName为UserAccount,@strOrder为’ORDERBYIDDESC’那末下面一行能够写成以下情势:set@strSQL=SELECTTOP20*fromwhere+@strWhere+ORDERBYIDDESC’我们能够假定用户输出的含混用户名是:Jim’sdog我们用SqlParameter传送参数给分页存储历程@strWhere的值是:’UserNameLIKE‘’%Jim’’dog%’’’(注重LIKE后边的字符串中的单引号已全体酿成两个单引号了),我们将这个值代进下面的@strSQL赋值语句中,以下:set@strSQL=SELECTTOP20*fromwhereUserNameLIKE%Jimdog%ORDERBYIDDESC’让我们写上声明变量的部分实行在查询剖析器中测试一下,代码以下:DECLARE@strSQLvarchar(8000)
DECLARE@strWherevarchar(1000)
SET@strWhere=UserNameLIKE%Jimdog%
set@strSQL=SELECTTOP20*fromwhere+@strWhere+ORDERBYIDDESC
print@strSQL
exec(@strSQL)

人人能够把下面几行代码粘贴到查询剖析器中实行一下,就能够看到上面的画面:


在动静的第一行,打印出了要实行的sql语句,很明显此语句的LIKE‘%Jim’前面的部分全体被截断了,也就是说假如用户输出的不是Jim’sdog而是Jim’deletefromUserAccount那末会准确的实行删除操纵,传说中的sql注进就会呈现了。成绩呈现了,我们应当怎样办理成绩?1.很明显我们利用SqlParameter传送参数已将单引号交换成了连个单引号了,但是由于我们在数据库中拼串招致交换其实不能办理成绩。2.依据我的实行证实假如利用存储历程不成能办理这个成绩,我们只要将这个存储历程要实行的拼串操纵放到数据会见层往做,才能够制止这个成绩。假如人人有在存储过程当中办理这个成绩的举措,请不惜见教。
备注:本文说的是MSSQLServer2000的数据库,而非利用SQL2005的新特征分页。对于update操作,只需要把event中的旧行和新行值对调即可。

莫相离 发表于 2015-1-19 10:49:27

其实可以做一下类比,Oracle等数据库产品老早就支持了java编程,而且提供了java池参数作为用户配置接口。但是现在有哪些系统大批使用了java存储过程?!连Oracle自己的应用都不用为什么?!

活着的死人 发表于 2015-1-25 10:24:57

而SQLServer如果能像Oracle一样可以为登陆分配如:5%的cpu,10%的内存。就可以解决这个漏洞。

柔情似水 发表于 2015-2-2 21:42:16

where子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。

简单生活 发表于 2015-2-8 07:08:24

换言之,只有在不断的失败中尝试成功,而关于失败的总结却是很少的

飘灵儿 发表于 2015-2-24 22:50:29

是否碎片会引发效率问题?这都是需要进一步探讨的东西。varbinary(max)代替image也让SQLServer的字段类型更加简洁统一。

金色的骷髅 发表于 2015-3-7 13:52:19

这一点很好的加强了profiler的功能。但是提到profiler提醒大家注意一点。windows2003要安装sp1补丁才能启动profiler。否则点击没有反应。

冷月葬花魂 发表于 2015-3-15 07:36:32

是否碎片会引发效率问题?这都是需要进一步探讨的东西。varbinary(max)代替image也让SQLServer的字段类型更加简洁统一。

山那边是海 发表于 2015-3-21 22:22:19

如果处理少量数据,比如几百条记录的数据,我不知道这两种情况哪个效率更高,如果处理大量数据呢?比如有表中有20万条记录.
页: [1]
查看完整版本: MSSQL网站制作之云云高效通用的分页存储历程是带有sql注...