为了防止程序SQL语句错误以及SQL注入,单引号必须经过处理。有2种办法:

1、使用参数,比如SELECT * FROM yourTable WHERE name = @name;

在C#中使用SqlParameter parameter = new SqlParameter("@name", objValue);来添加参数,懒得写SqlDbType这东西了,因为不写也完全可以,只需要参数名和值。

在JAVA中就是用预处理PreparedStatement来添加参数。

2、如果不用参数,而用字符串拼接的话,单引号必须经过判断并替换,在数据库中,用2个单引号代表1个实际的单引号。所以,如果是拼接方式,需要用String.Replace("'", "''")来替换一下,将1个单引号替换为2个就没有问题了。

SQL语句中,字符串是用两个单引号包起来标示的,所以要在字符串里保留单引号,必须要转义,而转义很简单,就是两个连续的单引号就表示一个单引号字符。

再说一下C#中的模糊查询,为了避免单引号,我们使用参数的方式,下面的语句是不对的:

SELECT * FROM yourTable WHERE name LIKE ‘%@name%’;在这个句子中,’%@name%’被整体当作一个字符串来处理,你无论如何查询不到结果。修改一下,SELECT * FROM yourTable WHERE name LIKE @name;然后添加参数的时候这么添加:

new SqlParameter("@name", "%" + categoryName + "%"); 这下就没问题了,正常查询,你输单引号照样查。

一. SQL Injection及其防范的基本知识 
可能大家都知道,SQL注入主要是利用字符型参数输入的检查漏洞。 
比如说,程序中有这样的查询: 
string sql = "SELECT * FROM SiteUsers WHERE UserName=" + userName + ""; 
其中的userName参数是从用户界面上输入的。 
如果是正常的输入,比如"Peter",SQL语句会串接成: 
"SELECT * FROM SiteUsers WHERE UserName=Peter"; 
如果攻击者输入的是下面的字符串: 
"xxx; DROP TABLE SiteUsers WHERE 1=1 or UserName=xxx" 
此时SQL语句会变成下面这个样子: 
"SELECT * FROM SiteUsers WHERE UserName=xxx; DROP TABLE SiteUsers WHERE 1=1 or UserName=xxx";
其结果,得到执行的是两个SQL语句,第二个语句的后果就比较严重了。 
防止注入的方法其实很简单,只要把用户输入的单引号变成双份就行了: 
string sql = "SELECT * FROM SiteUsers WHERE UserName=" + userName.Replace("","") + "";
这样,如果输入的是上面那种恶意参数,整个SQL语句会变成: 
"SELECT * FROM SiteUsers WHERE UserName=xxx; DROP TABLE SiteUsers WHERE 1=1 or UserName=xxx";
被执行的还是一个SQL语句,整个粗体部分都成为参数值。 
一般的做法,是在程序中统一调用下面这样的共通函数,对参数进行处理: 
private string SafeSqlLiteral(string inputSQL) 

return inputSQL.Replace("'", "''"); 

由于很多人会疏忽这种单引号替换,所以真正安全的做法是使用参数化查询。 
二. 参数化查询 
在ADO.NET中,提供了一种参数化查询方法,可以替代上面这种拼接SQL语句的做法。 
参数化查询的具体实现是: 
(1)组织一个夹带参数名的SQL语句,作为SqlCommand的CommandText。 
(2)使用Parameters.Add方法设置参数值。 
(3)执行SqlCommand。(这个步骤跟上面那种拼接SQL的办法是一样的。) 
下面是一个例子: 
string sql = "SELECT T2.dep_code, T2.dep_name FROM DEP "; 
sql += " WHERE T2.dep_name like (%+ @Param + %) "; 
SqlCommand sqlCommand = new SqlCommand(sql,cn); 
sqlCommand.Parameters.Add(new SqlParameter("Param", s)); 
其中的@Param就是参数名,s则是用户输入的查询条件字串。 
(顺便注:Oracle查询语句参数用问号表示,不是"@参数名"的形式。) 
使用这种参数化查询的办法,防止SQL注入的任务就交给ADO.NET了。 
如果在项目中统一规定必须使用参数化查询,就不用担心因个别程序员的疏忽导致的SQL注入漏洞了。 
但是,问题还没有完,SQL注入的漏洞是堵住了,但是查询结果的正确性,参数化查询并不能帮上什么忙。 
三. 通配符问题 
如果使用LIKE语句进行模糊查询,会有一些特殊的通配符问题。 
SQL Server的通配符包括下划线(_)和百分号(%),分别表示单个字符和任意多字符。 
如果用户输入参数中包括这些通配符,就会出现结果不正确的问题。 
比如说: 
WHERE T2.name like (%+ @Param + %) 
如果用户输入下划线,他期待的结果应该是name字段值含有下划线的记录,但是结果是所有记录都会被查询出来。输入百分号也是如此。 
为此,在将用户输入的内容作为参数值传入之前,必须进行通配符的转义处理(英文叫做Escape),也就是说,如果用户输入的查询条件中含有通配符,必须将这些字符作为数据而不是通配符来对待。
在SQL Server的查询语句中,将通配符转义为普通数据的方法是用方括号括起来。 
比如说,如果想要查询带有下划线的字段,正确的写法是: 
WHERE T2.name like (%+ [_] + %) 
同样,如果想要查询带有百分号的字段,正确的写法是: 
WHERE T2.name like (%+ [%] + %) 
所以,即使使用参数化查询,也必须在将用户输入的内容当作参数值传入SqlCommand.Parameters之前,先进行下面的处理: 
s = s.Replace("%", "[%]"); 
s = s.Replace("_", "[_]"); 
四. 方括号问题 
如果你足够细心,可能发现了还有一个方括号问题。 
既然方括号是用来界定数据内容的,那么如果用户输入的查询参数本身就包括方括号时,会出现什么结果呢? 
根据用户的期望,如果输入一个方括号,查询结果中应该只包括那些字段值中含有方括号的记录。 
但是实验结果表明,如果是没有配成对的单个左方括号,查询时这个左方括号会被忽略。 
也就是说,下面这个语句: 
WHERE T2.name like (%+ [ + %) 
等价于下面这个语句: 
WHERE T2.name like (%+ + %) 
这将导致查询结果中包含表中的全部记录,就像没有任何过滤条件一样。 
为此,如果用户输入的查询条件中含有左方括号的话,还必须对左方括号进行转义: 
s = s.Replace("[", "[[]"); 
注:右方括号没有这个问题。 
五. 其他注意事项 
按照微软的建议,凡是有可能导致问题的输入,可以在UI部分就进行检查并拒掉。 
这些可疑输入包括: 
分号(;):多个查询语句之间的分隔符,注入攻击时的恶意查询语句往往就是第二个查询语句。 
单引号():字符串数据分隔符,这是最危险的,前面已经讨论了。 
注释符(–或者/*,*/):有些数据库可以利用注释设置一些查询引擎的行为,比如如何利用索引等。 
xp_:扩展存储过程的前缀,SQL注入攻击得手之后,攻击者往往会通过执行xp_cmdshell之类的扩展存储过程,获取系统信息,甚至控制、破坏系统。 
六、结论 
为了防止SQL注入,同时避免用户输入特殊字符时查询结果不准确的问题,应该做两件事: 
(1)使用参数化查询。 
(2)在使用用户输入的字符串数据设置查询参数值之前,首先调用下面的共通处理函数: 
private static string ConvertSql(string sql) 

//sql = sql.Replace("", ""); // ADO.NET已经做了,不要自己做 
sql = sql.Replace("[", "[[]"); // 这句话一定要在下面两个语句之前,否则作为转义符的方括号会被当作数据被再次处理 
sql = sql.Replace("_", "[_]"); 
sql = sql.Replace("%", "[%]"); 
return sql; 
}

SQL语句中的单引号处理以及模糊查询的更多相关文章

  1. SQL语句中有关单引号、双引号和加号的问题

    字符串数据是用单引号包在外面的,而+号只是用来连接这些字符串的. 数据库里的字段是整型的时候不要加单引号,是字符串的时候要加,其它类型根据实际情况来,双引号就是用来拼接字符串的,单引号是sql文的固有 ...

  2. SQL语句中&、单引号等特殊符号的处理

    今天遇到一个insert语句,在SQL Tools(链接Oracle数据库)插入的某列值为“Computer Hardware & Software>>CPU",这样执行 ...

  3. sql 语句哪里添加单引号问题

    1.sql 语句哪里添加单引号问题,哪些地方必须加双引号,否则sql语句会报错? :涉及varchar的值的时候,必须有单引号包括varchar值.int等其他字段类型,则不需要加单引号包括. 如: ...

  4. sql语句中3表删除和3表查询

    好久没来咱们博客园了,主要近期在忙一些七七八八的杂事,包括打羽毛球比赛的准备和自己在学jqgrid的迷茫.先不扯这些没用的了,希望大家能记得小弟,小弟在此谢过大家了. 回归正题:(以下的sql是本人在 ...

  5. PL/SQL Block中对单引号进行转义

    可以使用如下的方式: STR := q'[ CREATE TABLE TNAME AS SELECT ... FROM INPUT_TABLE IP WHERE ((IP.DATE_FIELD = T ...

  6. MyBatis Sql语句中的转义字符

    1.在xml的sql语句中,不能直接用大于号.小于号要用转义字符 如果用小于号会报错误如下: org.apache.ibatis.builder.BuilderException: Error cre ...

  7. 在sql语句中添加php变量

    在sql语句中使用{}将php变量扩起来,php就会解析{}中的内容. //案件统计 function getCount($dsql,$tableName,$year){ //诉讼案件总数,总金额 $ ...

  8. java中的单引号和双引号

    1.单引号引的数据 是char类型的,双引号引的数据 是String类型的:单引号只能引一个字符,而双引号可以引0个及其以上.char只是一个基本类型,而String 可以是一个类,可以直接引用.比如 ...

  9. (转载)总结一下SQL语句中引号(')、quotedstr()、('')、format()在SQL语句中的用法

    总结一下SQL语句中引号(').quotedstr().('').format()在SQL语句中的用法 总结一下SQL语句中引号(').quotedstr().('').format()在SQL语句中 ...

随机推荐

  1. bootstrap列表添加滚动条

    有时候列表中数据过多,导致超出页面,影响视觉感受.这时我们需要添加一个滚动条. 初始状态如图: 代码如下: <ul class="list-group"> <li ...

  2. PAT L1-048 矩阵A乘以B

    https://pintia.cn/problem-sets/994805046380707840/problems/994805082313310208 给定两个矩阵A和B,要求你计算它们的乘积矩阵 ...

  3. extract函数行结果

    $arr2=array('a'=>'aaaa','b'=>'bbbb','c'=>'cccc','d'=>'dddd','e'=>'eeeee','b'=>'fff ...

  4. C# 7.0 新特性

    先列一下相关的语法: 1.out-variables(Out变量) 2.Tuples(元组) 3.Pattern Matching(匹配模式) 4.ref locals and returns (局部 ...

  5. Oracle查询字段中有空格的数据

    一.问题说明 最近在给某个用户下的表批量添加注释时,在程序中将注释名用trim()过滤一遍就可以了,但是在程序执行成功后怎么检测添加的注释名是否有空格存在呢? 二.解决方法 1.SELECT * FR ...

  6. docker使用记录

    1.安装(开始前要注意系统内核版本是否合适,建议用7以上的系统吧,少点坑) //安装docker yum -y install docker-io //启动 service docker start ...

  7. bzoj1968 约数研究

    题意 令\(f(i)\)表示\(i\)的约数个数,求\(\Sigma^n_{i=1}f(i)\). 做法 我们直接算每个数的贡献,问题可以转化成每个数在\(1\)到\(n\)中有多少个倍数,累加答案. ...

  8. CF986B Petr and Permutations

    题意翻译 Petr要打乱排列.他首先有一个从 111 到 nnn 的顺序排列,然后进行 3n3n3n 次操作,每次选两个数并交换它们. Alex也要打乱排列.他与Petr唯一的不同是他进行 7n+17 ...

  9. 编写高效Lua代码的方法

    编写高效Lua代码的方法 翻译自<Lua Programming Gems>Chapter 2:Lua Performance Tips:Basic fact By Roberto Ier ...

  10. bzoj 2588 Count on a tree 解题报告

    Count on a tree 题目描述 给定一棵\(N\)个节点的树,每个点有一个权值,对于\(M\)个询问\((u,v,k)\),你需要回答\(u\) \(xor\) \(lastans\)和\( ...