一、定义
参数化查询
(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
分享到:
相关推荐
此外,还提供了接受参数化查询的方法版本,增强了安全性。 ```csharp public static bool Exists(string strSql, params SqlParameter[] cmdParms) { object obj = DbHelperSQL.GetSingle(strSql, cmdParms); int...
在PDO中使用参数化查询是一种重要的安全实践,其核心理念是将SQL语句中的参数与数据分离,以防止SQL注入攻击(SQL Injection)。 参数化查询的安全原理在于,当数据库系统处理一条SQL语句时,它会将参数视为一个...
4. 在`GenericTableReader<T>`中,利用抽象工厂创建的数据库连接执行SQL查询或存储过程,获取数据并转换为`T`类型的集合。 5. 将`GenericTableReader<T>`服务化,使用WCF将其配置为一个服务接口,例如`IDataService`...
在实际开发中,为了确保数据安全,应始终使用参数化查询,以防止SQL注入攻击。同时,考虑使用ORM(Object-Relational Mapping)框架,如Entity Framework,它可以简化数据库操作,提供更高级别的抽象。 总之,C#中...
例如,规则可能包括:检测字符串拼接构建SQL语句的方式,检查未经过滤的用户输入直接插入到SQL查询中的情况,以及评估使用参数化查询的频率等。通过识别这些模式,开发人员和安全专家可以更准确地定位到潜在的注入点...
这两种方式都可以实现动态参数查询,即根据传入的参数来构建不同的SQL语句。以下是对这两种方法的详细说明: 1. **HQL(Hibernate Query Language)**: HQL是Hibernate提供的面向对象的查询语言,语法类似于SQL,...
在Java的持久化框架Hibernate中,SQLQuery是用于执行自定义SQL语句的重要工具,它允许开发者绕过ORM(对象关系映射)的抽象层,直接与数据库进行交互。这篇博客"Hibernate SQLQuery 本地查询"可能详细讲解了如何利用...
9. **预编译语句和参数化查询**:防止SQL注入的一种有效方法是使用预编译语句和参数化查询。这允许SQL语句在执行前被解析和编译,从而降低恶意代码注入的风险。 10. **安全性和权限管理**:纯净SQL也考虑了安全性,...
Lambda表达式通常用于LINQ(Language Integrated Query)查询,它允许程序员使用类似SQL的语法在内存中的数据集上进行操作。然而,在某些情况下,我们需要将这些表达式转换为实际的SQL语句,以便在数据库中执行。...
同时,通过将SQL构造过程抽象化,还能提高应用的安全性,防止SQL注入攻击,因为生成器通常会负责正确地转义和格式化输入的参数。 总的来说,SQL查询条件生成器是数据库编程中的强大辅助工具,简化了复杂查询的实现...
DbHelperSQL还可能支持参数化查询,这能防止SQL注入攻击,提高代码安全性。开发者可以通过传递参数数组,将动态的值安全地插入到SQL语句中。 在实际项目中,DbHelperSQL类通常与设计模式结合使用,如工厂模式或者...
它们提供了抽象层,自动处理参数化查询,降低了SQL注入的风险。 3. **输入验证(Input Validation)** 应用程序应该对所有用户输入进行验证,确保其符合预期的数据格式。ASP.NET提供了多种验证控件,如...
书中的存储过程部分将涵盖创建、调用、参数化存储过程,以及存储过程的优化。 7. **触发器**:触发器是一种特殊的存储过程,会在特定的数据更改事件(如INSERT、UPDATE或DELETE)发生时自动执行。书中会讲解触发器...
2. **参数化查询**:为了避免SQL注入等安全问题,使用预编译的参数化SQL(例如:PreparedStatement)是非常重要的。Spring的JdbcTemplate和NamedParameterJdbcTemplate提供了这样的功能。 3. **动态SQL**:在实际...
例如,可以使用参数化查询或命名参数来动态改变查询的条件部分,而无需重构整个查询语句。 虽然SQL也支持动态查询,但实现起来相对复杂,需要拼接字符串或使用存储过程等技术。 #### 4. 性能与优化 SQL在性能优化...
3. **动态条件处理**:允许开发者通过参数化的方式设置查询条件,比如WHERE子句中的条件,SQL生成器会自动根据参数生成对应的SQL片段。 4. **多数据库支持**:优秀的SQL生成器会考虑到不同的数据库系统(如MySQL、...
4. 参数化查询:Sql Helper通过参数化查询来提高安全性。使用参数化查询,开发者可以将用户输入的数据与SQL命令分开,防止恶意用户通过输入特殊字符进行SQL注入攻击。例如,使用 "@" 符号来定义参数,然后在代码中...
易语言可能会提供字符串拼接或者更安全的参数化查询方法来防止SQL注入攻击。 3. 执行SQL:调用数据库API执行SQL语句,并获取返回的结果。 4. 结果处理:处理查询结果,可能包括遍历结果集,将数据转换为程序内部的...
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 ...