SQL(参数化)的查询

什么是参数化查询?

一,定义

参数化查询(Parameterized Query 或 Parameterized Statement)是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值,这个方法目前已被视为最有效可预防SQL注入攻击 (SQL Injection) 的攻击手法的防御方式。

有部份的开发人员可能会认为使用参数化查询,会让程序更不好维护,或者在实现部份功能上会非常不便,然而,使用参数化查询造成的额外开发成本,通常都远低于因为SQL注入攻击漏洞被发现而遭受攻击,所造成的重大损失。

原理

在使用参数化查询的情况下,数据库服务器不会将参数的内容视为SQL指令的一部份来处理,而是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有具有损的指令,也不会被数据库所运行。

SQL 指令撰写方法

在撰写 SQL 指令时,利用参数来代表需要填入的数值,例如:

Microsoft SQL Server

Microsoft SQL Server 的参数格式是以 "@" 字符加上参数名称而成,SQL Server 亦支持匿名参数 "?"。

SELECT * FROM myTable WHERE myID = @myID

INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)

Microsoft Access

Microsoft Access 不支持具名参数,只支持匿名参数 "?"。

UPDATE myTable SET c1 = ?, c2 = ?, c3 = ? WHERE c4 = ?

MySQL

MySQL 的参数格式是以 "?" 字符加上参数名称而成。

UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4

Oracle

Oracle 的参数格式是以 ":" 字符加上参数名称而成。

UPDATE myTable SET c1 = :c1, c2 = :c2, c3 = :c3 WHERE c4 = :c4

PostgreSQL

PostgreSQL 的参数格式是以 "$" 字符加上参数顺序号而成。

UPDATE myTable SET c1 = $1, c2 = $2, c3 = $3 WHERE c4 = $4

PostgreSQL也支持Oracle的参数表示形式

--------------------------------------------------------------------------------

总结一下各数据库对于参数符号的定义:

SQLSERVER @

Access,MySQL ?

Oracle :

PostgreSQL $

上面的这些符号是各数据库内部原生支持的方式,但是具体到ADO.NET调用的时候,采用各数据库原生的.NET驱动程序,发现除了Oracle,各种数据库都可以在SQL语句中用@符号表示参数;

采用各数据库的OleDB或者ODBC驱动程序,都要求使用 ?符号表示参数。

还有其它本文未说到的数据库,他们的SQL语句表示参数的符号可能都是不一样的,怎么样在程序里面统一处理呢?本文主题开始了:

二,抽象SQL参数化查询

在PDF.NET数据开发框架中,对参数的定义统一采用##来处理,具体格式如下:

#参数名字[:参数类型],[数据类型],[参数长度],[参数输出输入类型]#

上面定义当中,中括号里面的内容都是可选的。

详细内容,请参看“SQL-MAP规范”

对本文第一部分的示例,可以改写成下面的方式:

 
 
  1. UPDATE myTable SET   
  2. c1 = #c1#,   
  3. c2 = #c2:String#,   
  4. c3 = #c3:String,Sring,50#   
  5. WHERE c4 = #c4:Int32#  

如果不指定参数的类型,默认为String类型,例如c1参数。

程序在运行时,会根据当前具体的数据库访问程序实例,将##内部的参数替换成合适的参数内容。

上面这种参数形式是写在SQL-MAP配置文件里面的,例如下面的一个实际的SQL-MAP查询脚本:

 
 
  1. <Select CommandName="GetStatisticsAnalysis_SalerRoleStatistics" CommandType="Text" Method="" Description="" ResultClass="DataSet"> 
  2.        <![CDATA[  
  3.     SELECT a.角色,a.销售金额/10000 销售金额,a.占比 FROM [GetStatisticsAnalysis_SalerRoleStatistics] (  
  4.    #manageid:Int32#, #min:String#, #max:String#) a]]> 
  5.      </Select> 

通过这种方式,完全屏蔽了不同种类的数据库查询的参数问题,将SQL参数化查询抽象了出来。

看到这里本文似乎该结束了,但本文的标题“参数化”加了一个括号,说明我们抽象的不仅仅是参数,我们还可以抽象整个SQL查询。

三,抽象SQL查询:SQL-MAP技术

在本文第二部分,我们将SQL中的参数“抽象化”了,我们还可以进一步抽象整个SQL,看下面的抽象过程:

  1. 编写任意形式的合法SQL查询语句;
  2. 抽象SQL中的参数;
  3. 将整个SQL语句抽象成一个唯一名字为CommandName;
  4. 将一组CommandName映射到一个DAL类文件;
  5. 将这个CommandName映射到一个DAL类的方法名称;
  6. 将SQL语句中的参数名称映射到该DAL类的当前方法中的参数名称;
  7. 将整个SQL脚本文件映射到一个DAL程序集。

这个思想,就是SQL-MAP,将SQL语句映射为程序的。

下面我们介绍一下PDF.NET数据开发框架对于存储过程的操作思路,当然对于单条SQL也是如此。当然,单条SQL语句的操作我们不必请出SQL-MAP这种“重量级”的方式,还是使用框架中的ORM技术OQL吧,但这不是本文讨论的话题。

首先,在SQL-MAP配置文件里面写下面的脚本:

 
 
  1. <Select CommandName="GetProductManage_FundSaleAndAIP" Method="" CommandType="Text" Description="获取XXX列表" ResultClass="DataSet">    
  2. <![CDATA[    
  3. select * from GetProductManage_FundSaleAndAIP(#Type:String#,#Name:String#,#isAIP:String#)    
  4. ]]>   
  5. </Select>    

注意脚本中的ResultClass属性,它可以将查询映射成为单值,DataSet,实体类,实体类集合。

有了这个SQL-MAP文件,我们可以使用代码工具自动生成下面的代码(当然你也可以手写):

 
 
  1. /// <summary>    
  2.    /// 获取XXXXX列表    
  3.    /// </summary>    
  4.    /// <param name="Type"></param>    
  5.    /// <param name="Name"></param>    
  6.    /// <param name="isAIP"></param>    
  7.    /// <returns></returns>    
  8.    public DataSet GetProductManage_FundSaleAndAIP(String Type  , String Name  , String isAIP   )     
  9.    {     
  10.            //获取命令信息    
  11.            CommandInfo cmdInfo=Mapper.GetCommandInfo("GetProductManage_FundSaleAndAIP");    
  12.            //参数赋值,推荐使用该种方式;    
  13.            cmdInfo.DataParameters[0].Value = Type;    
  14.            cmdInfo.DataParameters[1].Value = Name;    
  15.            cmdInfo.DataParameters[2].Value = isAIP;    
  16.            //参数赋值,使用命名方式;    
  17.            //cmdInfo.SetParameterValue("@Type", Type);    
  18.            //cmdInfo.SetParameterValue("@Name", Name);    
  19.            //cmdInfo.SetParameterValue("@isAIP", isAIP);    
  20.            //执行查询    
  21.            return CurrentDataBase.ExecuteDataSet(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText , cmdInfo.DataParameters);    
  22.        //    
  23.    }//End Function   

从上面的过程可以看出,框架采用SQL-MAP技术,将SQL语句(包括各种查询的单条SQL语句和存储过程等)映射成了DAL层代码,整个过程不需要了解.NET开发技术,所以DAL层的代码完全可以由DBA来写,而业务开发人员只要调用DAL代码即可。

采用这种技术,DBA可以写高效的有数据库特性的SQL,如果要换数据库,只需要换一个配置文件即可,不需要重写程序。

题外话:

SQL-MAP思想并非PDF.NET数据开发框架独有,实际上,该思想也是从著名的iBatis框架借鉴而来的,但与iBatis不同的是,PDF.NET的SQL-MAP参数不需要定义专门的“参数类”,也不需要写额外的XML文件指明查询结果如何与实体类映射,所以整个开发过程大大简化,简化到你只需要会写SQL语句,就可以写DAL代码。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: SQL Server参数化查询是一种使用参数来代替查询语句中的具体数值或字符串的查询方式。通常情况下,我们在编写查询语句时,会使用变量来表示查询条件,然后将参数与查询语句绑定,最后执行查询。 使用参数化查询的好处有以下几个方面: 1. 提高安全性:通过使用参数,可以避免SQL注入攻击。当我们使用变量传递查询条件时,即使用户输入的值恶意改变查询语句,也不能执行除查询以外的其他操作。 2. 提高性能:由于参数化查询使用了预编译的方式,所以可以减少每次查询的编译开销,提高查询性能。 3. 增强可读性:使用参数可以使查询语句更加清晰易读,增加代码的可维护性。 4. 促进代码复用:由于查询条件是通过参数传递的,所以可以实现代码的复用,减少代码冗余。 在SQL Server中,我们可以使用SqlParameter类来创建参数,并将参数添加到SqlCommand对象中。具体步骤如下: 1. 创建SqlCommand对象:使用参数化查询之前,需要创建一个包含查询语句的SqlCommand对象。 2. 创建SqlParameter对象:使用SqlParameter类的构造函数来创建参数对象,需要指定参数名、参数类型、参数值等属性。 3. 添加参数到SqlCommand对象:通过调用SqlCommand对象的Parameters属性的Add方法,将SqlParameter对象添加到SqlCommand对象中。 4. 执行查询:调用SqlCommand对象的ExecuteReader()方法来执行查询,并获取查询结果。 总之,使用SQL Server参数化查询可以提高查询的安全性、性能、可读性和代码复用性。当我们需要对数据库进行操作时,尤其是涉及用户输入的查询条件时,建议使用参数化查询来避免潜在的安全风险。 ### 回答2: SQL Server参数化查询是指在执行SQL语句时,将参数作为独立的变量来处理,而不是将参数直接嵌入到SQL语句中。参数化查询可以提高查询的性能和安全性。 首先,参数化查询可以提高查询的性能。当使用参数化查询时,SQL Server可以缓存已编译的查询计划,然后在后续的查询中重用该计划。这样可以减少查询的编译时间,并且避免每次查询都重新编译查询语句,从而提高查询的执行效率。 其次,参数化查询可以提高查询的安全性。通过将参数作为独立的变量处理,可以避免SQL注入攻击。SQL注入是一种常见的安全漏洞,攻击者可以通过在SQL语句中插入恶意代码来执行未经授权的数据库操作。使用参数化查询可以防止攻击者通过注入恶意代码来破坏数据库或获取敏感数据,从而保护数据库的安全性。 此外,参数化查询还可以提高代码的可读性和维护性。通过将参数与SQL语句分离,可以更清晰地理解查询的逻辑和目的。当修改查询时,只需修改参数值,并不需要修改SQL语句的结构,从而减少错误和代码冗余。 总之,SQL Server参数化查询是一种提高查询性能、安全性和代码可读性的好方法。通过将参数作为独立的变量处理,可以减少查询的编译时间、防止SQL注入攻击,并提高代码的可维护性。 ### 回答3: SQL Server参数化查询是一种使用参数来代替实际值的查询方法。参数化查询可以防止SQL注入攻击,并提高查询的性能和安全性。 在SQL Server中,使用参数化查询可以通过声明和设置参数来实现。首先,我们需要声明参数,并指定参数的名称、数据类型和大小。然后,我们可以将参数绑定到查询语句中的相应位置。 参数化查询的好处之一是可以防止SQL注入攻击。SQL注入是指通过在查询语句中插入恶意代码来攻击数据库。使用参数化查询后,查询语句中的参数值是预编译的,不会被解释为可执行的代码,因此可以有效地防止SQL注入攻击。 此外,参数化查询还可以提高查询的性能。在执行查询之前,数据库服务器会对查询进行优化,并创建查询的执行计划。当使用参数化查询时,数据库服务器可以重用生成的执行计划,避免重新编译查询语句,提高查询的执行效率。 参数化查询还可以提高查询的安全性。通过参数化查询,我们可以限制查询的输入值范围,避免不必要的访问和数据泄漏。例如,我们可以在查询中使用参数来限制返回的结果数量或指定特定的条件,从而提供更加安全的查询结果。 总而言之,SQL Server参数化查询是一种有效的查询方法,可以提高查询的性能和安全性。通过声明和设置参数,我们可以防止SQL注入攻击,并优化查询的执行计划,从而提供更高效和安全的数据库查询服务。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值