无意中看到的文章,简单而又可怕的拼接SQL造成的意想不到的后果,转来记录下

虽然公司有要求sql语句要调用ORM的方法处理,就算自己写也要参数化,但还是有些地方会没用注意到,看到下面的文章,惊出冷汗!

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

 执行数据操作时,由于拼接SQL存在种种弊端,早就应该抛弃了,但在现实开发时,又由于种种原因,公司一直采用这种方式(UI层和逻辑层都有严格的过滤,倒也没出现过什么问题),但昨天开发时却出现了意想不到的问题,一个简单的语句会造成严重后果。简单的语句示例如下:

复制代码
     ///   <summary>
    
///  更新主键为2的记录的总钱数
    
///   </summary>
    
///   <param name="totalMoney"> 修改后的总钱数 </param>
     public   void  UpdateTotalMoney( int  totalMoney)
    {
        
int  id  =   2 // 数据库表主键
         int  oldTotalMoney  =   5000 ;        // 主键为2的记录原来的总钱数
         int  newTotalMoney  =  totalMoney;  // 主键为2的记录更改后的钱数
         int  totalMoneyChange  =  oldTotalMoney  -  newTotalMoney;  // 总钱数的变化量
         string  sql  =   string .Format( " update Test1220 set totalMoney = {0},remainMoney = remainMoney-{1} where id = {2} " , newTotalMoney, totalMoneyChange, id);    // 总钱数变化,剩余可支配钱数也跟着编号
        SqlConnection con  =   new  SqlConnection(sqlConnectString);
        con.Open();
        SqlCommand cmd 
=   new  SqlCommand(sql, con);
        cmd.ExecuteNonQuery();
        con.Close();
    }
复制代码

 

复制代码
     CREATE   TABLE  Test1220(
        id 
int   IDENTITY ( 1 , 1 NOT   NULL   PRIMARY   KEY ,
        totalMoney 
int   NULL ,
        remainMoney 
int   NULL
    )

    
insert   into  Test1220(totalMoney,remainMoney)  values ( 3000 , 2000 )
    
insert   into  Test1220(totalMoney,remainMoney)  values ( 5000 , 5000 )
    
insert   into  Test1220(totalMoney,remainMoney)  values ( 1000 , 1000 )
    
insert   into  Test1220(totalMoney,remainMoney)  values ( 3000 , 3000 )
    
insert   into  Test1220(totalMoney,remainMoney)  values ( 3000 , 3000 )
    
insert   into  Test1220(totalMoney,remainMoney)  values ( 3000 , 3000 )
复制代码

 
      接下来调用方法UpdateTotalMoney()更新主键为2的记录的总钱数和剩余钱数,UpdateTotalMoney(4000)和UpdateTotalMoney(8000)更新id=2的记录,会发生什么情况呢?执行UpdateTotalMoney(4000)时正常,表中只有id=2的记录跟着更新;但执行完UpdateTotalMoney(8000)之后,却出现了意想不到的问题,所有记录的totalMoney都变成8000了,而remainMoney却一个也没有修改。是什么原因造成的呢?明明已经加了where条件id=2,怎么会更新到所有记录?

      这可把我这个菜鸟级的给难住了,简单的语句,传递不同的参数会有时正常有时异常,反复跟踪调试,才发现问题出现在SQL语句上,当参数为8000时,得到的SQL语句为“update Test1220 set totalMoney = 8000,remainMoney = remainMoney--3000 where id = 2”,原来是减运算符和负号连在一起成了SQL的注释符号,把更新时的where条件给注释掉了,真是一个危险的操作!这个错误很隐蔽,查找错误花了很长时间,如果执行数据库操作时参数化,就不会有这种情况了。

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

太可怕了!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java,根据方法执行结果来判定要拼接SQL语句通常是在进行数据库操作时使用的一种常见的技巧。具体来说,这种技巧通常用于动态拼接SQL语句,以便根据不同的条件或者查询结果来生成不同的SQL语句。 例如,在进行查询操作时,我们通常需要根据不同的条件来生成不同的SELECT语句。如果查询条件为空,则可以生成一个简单的SELECT语句,如果查询条件不为空,则需要在SELECT语句加入WHERE子句来限制查询结果的范围。在这种情况下,我们可以使用如下的代码来实现: ``` public String buildSelectSql(String tableName, Map<String, Object> queryParams) { StringBuilder sb = new StringBuilder(); sb.append("SELECT * FROM ").append(tableName); if (queryParams != null && !queryParams.isEmpty()) { sb.append(" WHERE "); int index = 0; for (String key : queryParams.keySet()) { if (index > 0) { sb.append(" AND "); } sb.append(key).append("=").append(queryParams.get(key)); index++; } } return sb.toString(); } ``` 在这个方法,我们首先使用StringBuilder来创建一个初始的SELECT语句,然后根据传入的查询条件来判断是否需要拼接WHERE子句。如果查询条件不为空,则使用循环遍历查询条件,将其拼接到WHERE子句。 在实际使用,我们可以根据方法执行的结果来判断是否需要使用这个方法生成SQL语句。例如,我们可以使用如下的代码来查询一个用户的基本信息: ``` public User getUserById(int userId) { String sql = "SELECT * FROM user WHERE id=" + userId; //执行查询操作 //... //根据查询结果构造User对象并返回 } ``` 在这个方法,我们直接拼接了一个静态的SELECT语句,并将查询条件作为参数传入。然后根据查询结果来构造User对象并返回。 需要注意的是,直接拼接SQL语句可能存在SQL注入的风险,因此在实际使用应该尽量避免直接拼接SQL语句,而是使用预编译的SQL语句或者ORM框架来执行数据库操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值