存储过程中执行sql语句时如何转义双引号?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了存储过程中执行sql语句时如何转义双引号?相关的知识,希望对你有一定的参考价值。
我的sqlserver版本2008 我想实现的效果是 将查出来的数据每个表的每个列中的数据前后都去掉双引号,
因为我的列数据都是这个样子。如下示例
=====================================================
id | name |
“f325sd” “asdfsdga”
“f3234d” “asd45dga”
=====================================================
而在最后这个sql中的双引号一直有问题,无法转义。。请大家提供一个好的解决方案
如果对于去掉数据中前后双引号有更好的办法还请不吝赐教
如:select replace('"dfdf''df"','"','')
用全角的演示一下 select replace( ‘“abc ’’ de ”’,‘“”’,‘’)追问
你这种写法是没问题的,但是我这是在存储过程中执行的,就会报错,对于第二个参数中不能填写双引号,否则颜色你看也不对。
追答那是因为你单引号没转义,应该是
@columnname+',''"'','''')'
最外层单引号表示括起来的是串,而串里若有单引号,需要在前面再加一个单引号进行转义
譬如我前面那个select,变成动态的就是
exec('select replace(''"dfdfdf"'',''"'','''')')
exec('update '+@tableName+' set '+@columnName+' = replace('+@columnName+',''"'','''')')嵌套拼接字符中的单引号处理很麻烦的
仅代表个人观点,不喜勿喷,谢谢。 参考技术B exec('update '+@tableName+' set '+@columnName+' = replace('+@columnName+',''"'','''')')
嵌套拼接字符中的单引号处理很麻烦的
exec('update '+@tableName+' set '+@columnName+' = replace('+@columnName+',''"'','''')')追问
提示为字符串 ‘)’ 后的引号不完整 不行 编译正常 无法执行
追答可能是你没复制完整的原因,如果只复制了下面这部分,就会报出你遇到的问题
exec('update '+@tableName+' set '+@columnName+' = replace('+@columnName+',''"'','''')
mybatis中#{}与${}的差别(如何防止sql注入)
默认情况下,使用#{}语法,MyBatis会产生PreparedStatement语句中,并且安全的设置PreparedStatement参数,这个过程中MyBatis会进行必要的安全检查和转义。
#相当于对数据 加上 双引号,$相当于直接显示数据
示例1:
执行SQL:select * from emp where name = #{employeeName}
参数:employeeName=>Smith
解析后执行的SQL:select * from emp where name = ?
示例2:
执行SQL:select * from emp where name = ${employeeName}
参数:employeeName传入值为:Smith
解析后执行的SQL:Select * from emp where name =Smith
综上所述、${}方式会引发SQL注入的问题、同时也会影响SQL语句的预编译,所以从安全性和性能的角度出发,能使用#{}的情况下就不要使用${}
Q:但是${}在什么情况下使用呢?
A:有时候可能需要直接插入一个不做任何修改的字符串到SQL语句中。这时候应该使用${}语法。
比如,动态SQL中的字段名,如:ORDER BY ${columnName}
重要:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。
MyBatis框架作为一款半自动化的持久层框架,其SQL语句都要我们自己手动编写,这个时候当然需要防止SQL注入。其实,MyBatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构,如下:
<select id="getBlogById" resultType="Blog" parameterType=”int”> SELECT id,title,author,content FROM blog WHERE id=#{id} </select>
这里,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。回应上文,如果我们想防止SQL注入,理所当然地要在输入参数上下功夫。上面代码中黄色高亮即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:
SELECT id,title,author,content FROM blog WHERE id = ?
不管输入什么参数,打印出的SQL都是这样的。这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。
【底层实现原理】MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。
在MyBatis中,${xxx}这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用${xxx}这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。
【结论】
在编写MyBatis的映射语句时,尽量采用#{xxx}这样的格式。若不得不使用${xxx}这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。
#{}:相当于JDBC中的PreparedStatement
${}:是输出变量的值
简单说,#{}是经过预编译的,是安全的;${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。
如果我们order by语句后用了${},那么不做任何处理的时候是存在SQL注入危险的。你说怎么防止,那我只能悲惨的告诉你,你得手动处理过滤一下输入的内容。如判断一下输入的参数的长度是否正常(注入语句一般很长)
参考:
http://blog.csdn.net/szwangdf/article/details/26714603
http://www.myexception.cn/sql/1938757.html
以上是关于存储过程中执行sql语句时如何转义双引号?的主要内容,如果未能解决你的问题,请参考以下文章