`

抽象SQL参数化查询

    博客分类:
  • db
阅读更多

 

一、定义

  参数化查询 (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(PWMIS数据开发框架)中,对参数的定义统一采用##来处理,具体格式如下:

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

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

  详细内容,请参看“SQL-MAP ” 或者“PDF.NET(PWMIS数据开发框架)之SQL-MAP目标和规范

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

 

UPDATE myTable SET  
c1 = #c1#,  
c2 = #c2:String#,  
c3 = #c3:String,Sring,50#  
WHERE c4 = #c4:Int32#

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

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

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

 

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

  如果想使用动态SQL语句,即SQL语句中有一个“假参数”,在运行时由另外一个字符串来替换的,例如非常复杂的查询条件拼接过程,请参看:

  在SQLMAP中使用动态SQL

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

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

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

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

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

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

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

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

<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文件,我们可以使用代码工具自动生成下面的代码(当然你也可以手写):

01/// <summary>  

02   /// 获取XXXXX列表  

03   /// </summary>  

04   /// <param name="Type"></param>  

05   /// <param name="Name"></param>  

06   /// <param name="isAIP"></param>  

07   /// <returns></returns>  

08   public DataSet GetProductManage_FundSaleAndAIP(String Type  , String Name  , String isAIP   )   

09   {   

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代码。

原文出处:http://www.cnblogs.com/bluedoctor/archive/2011/05/06/2038727.html

分享到:
评论

相关推荐

    NET SQL Server数据访问抽象基础类

    此外,还提供了接受参数化查询的方法版本,增强了安全性。 ```csharp public static bool Exists(string strSql, params SqlParameter[] cmdParms) { object obj = DbHelperSQL.GetSingle(strSql, cmdParms); int...

    pdo中使用参数化查询sql

    在PDO中使用参数化查询是一种重要的安全实践,其核心理念是将SQL语句中的参数与数据分离,以防止SQL注入攻击(SQL Injection)。 参数化查询的安全原理在于,当数据库系统处理一条SQL语句时,它会将参数视为一个...

    抽象工厂 SQL 和Access 利用泛型读取表中数据 WCF发布出去

    4. 在`GenericTableReader&lt;T&gt;`中,利用抽象工厂创建的数据库连接执行SQL查询或存储过程,获取数据并转换为`T`类型的集合。 5. 将`GenericTableReader&lt;T&gt;`服务化,使用WCF将其配置为一个服务接口,例如`IDataService`...

    c#模糊查询之sql语句

    在实际开发中,为了确保数据安全,应始终使用参数化查询,以防止SQL注入攻击。同时,考虑使用ORM(Object-Relational Mapping)框架,如Entity Framework,它可以简化数据库操作,提供更高级别的抽象。 总之,C#中...

    一种基于抽象语法树的C#源代码SQL注入漏洞检测算法.pdf

    例如,规则可能包括:检测字符串拼接构建SQL语句的方式,检查未经过滤的用户输入直接插入到SQL查询中的情况,以及评估使用参数化查询的频率等。通过识别这些模式,开发人员和安全专家可以更准确地定位到潜在的注入点...

    Hibernate 参数查询通用方法

    这两种方式都可以实现动态参数查询,即根据传入的参数来构建不同的SQL语句。以下是对这两种方法的详细说明: 1. **HQL(Hibernate Query Language)**: HQL是Hibernate提供的面向对象的查询语言,语法类似于SQL,...

    Hibernate SQLQuery 本地查询

    在Java的持久化框架Hibernate中,SQLQuery是用于执行自定义SQL语句的重要工具,它允许开发者绕过ORM(对象关系映射)的抽象层,直接与数据库进行交互。这篇博客"Hibernate SQLQuery 本地查询"可能详细讲解了如何利用...

    纯净sql

    9. **预编译语句和参数化查询**:防止SQL注入的一种有效方法是使用预编译语句和参数化查询。这允许SQL语句在执行前被解析和编译,从而降低恶意代码注入的风险。 10. **安全性和权限管理**:纯净SQL也考虑了安全性,...

    C#将Lambda表达式转成Sql语句

    Lambda表达式通常用于LINQ(Language Integrated Query)查询,它允许程序员使用类似SQL的语法在内存中的数据集上进行操作。然而,在某些情况下,我们需要将这些表达式转换为实际的SQL语句,以便在数据库中执行。...

    SQL查询条件生成器源码

    同时,通过将SQL构造过程抽象化,还能提高应用的安全性,防止SQL注入攻击,因为生成器通常会负责正确地转义和格式化输入的参数。 总的来说,SQL查询条件生成器是数据库编程中的强大辅助工具,简化了复杂查询的实现...

    动软生成的DbHelperSQL类、SQLHelper

    DbHelperSQL还可能支持参数化查询,这能防止SQL注入攻击,提高代码安全性。开发者可以通过传递参数数组,将动态的值安全地插入到SQL语句中。 在实际项目中,DbHelperSQL类通常与设计模式结合使用,如工厂模式或者...

    asp.net防sql注入

    它们提供了抽象层,自动处理参数化查询,降低了SQL注入的风险。 3. **输入验证(Input Validation)** 应用程序应该对所有用户输入进行验证,确保其符合预期的数据格式。ASP.NET提供了多种验证控件,如...

    Microsoft SQL Server 2008技术内幕:T-SQL语言基础—源代码

    书中的存储过程部分将涵盖创建、调用、参数化存储过程,以及存储过程的优化。 7. **触发器**:触发器是一种特殊的存储过程,会在特定的数据更改事件(如INSERT、UPDATE或DELETE)发生时自动执行。书中会讲解触发器...

    SQL文的管理和解析源文件

    2. **参数化查询**:为了避免SQL注入等安全问题,使用预编译的参数化SQL(例如:PreparedStatement)是非常重要的。Spring的JdbcTemplate和NamedParameterJdbcTemplate提供了这样的功能。 3. **动态SQL**:在实际...

    HQL与SQL的区别

    例如,可以使用参数化查询或命名参数来动态改变查询的条件部分,而无需重构整个查询语句。 虽然SQL也支持动态查询,但实现起来相对复杂,需要拼接字符串或使用存储过程等技术。 #### 4. 性能与优化 SQL在性能优化...

    Java开发的sql生成器

    3. **动态条件处理**:允许开发者通过参数化的方式设置查询条件,比如WHERE子句中的条件,SQL生成器会自动根据参数生成对应的SQL片段。 4. **多数据库支持**:优秀的SQL生成器会考虑到不同的数据库系统(如MySQL、...

    Sql Helper

    4. 参数化查询:Sql Helper通过参数化查询来提高安全性。使用参数化查询,开发者可以将用户输入的数据与SQL命令分开,防止恶意用户通过输入特殊字符进行SQL注入攻击。例如,使用 "@" 符号来定义参数,然后在代码中...

    SQL对象例程.rar

    易语言可能会提供字符串拼接或者更安全的参数化查询方法来防止SQL注入攻击。 3. 执行SQL:调用数据库API执行SQL语句,并获取返回的结果。 4. 结果处理:处理查询结果,可能包括遍历结果集,将数据转换为程序内部的...

    SQL注入攻击与防御

    8.2.4 PL/SQL中的参数化语句 275 8.3 输入验证 275 8.3.1 白名单 276 8.3.2 黑名单 277 8.3.3 Java中的输入验证 278 8.3.4 .NET中的输入验证 279 8.3.5 PHP中的输入验证 280 8.4 编码输出 280 8.5 规范化 286 8.6 ...

Global site tag (gtag.js) - Google Analytics