You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中User.update函数报SQLite3::SQLException: no such column: COLIN错误排查

问题原因与修复方案

错误根源

你遇到的SQLite3::SQLException: no such column: COLIN错误,本质是字符串值没被正确转义,SQL把它当成了列名。

看你的update方法代码:

def self.update(user_id, attribute, value)
  DBConnection.execute(<<-SQL, user_id, attribute, value)
      UPDATE
          users
      SET
          #{attribute} = #{value}
      WHERE
          id = #{user_id}
  SQL
end 

当调用User.update(1, :firstname, 'COLIN')时,插值后的SQL语句会变成:

UPDATE users SET firstname = COLIN WHERE id = 1

这里的COLIN没有被单引号包裹,数据库会误以为这是一个列名,但你的users表中不存在名为COLIN的列,因此抛出错误。

另外这段代码还有两个严重问题:

  • 明明在execute方法里传了参数,却没用到占位符?绑定,完全浪费了参数绑定的安全特性,全程用字符串插值。
  • 字符串插值会带来SQL注入风险,如果传入恶意内容,能直接篡改数据库数据。

修复代码

修改update方法,正确使用占位符绑定值,同时先校验列名的合法性:

def self.update(user_id, attribute, value)
  # 先验证列名是否合法,防止恶意注入
  valid_columns = ['firstname', 'lastname', 'age', 'password', 'email']
  unless valid_columns.include?(attribute.to_s)
    raise ArgumentError, "非法列名: #{attribute}"
  end

  DBConnection.execute(<<-SQL, value, user_id)
      UPDATE
          users
      SET
          #{attribute} = ?
      WHERE
          id = ?
  SQL
end 

修复后,调用User.update(1, :firstname, 'COLIN')生成的SQL会是:

UPDATE users SET firstname = 'COLIN' WHERE id = 1

数据库会把COLIN当成字符串值处理,不会再报错。

顺带提一句,你的create方法也存在同样的SQL注入问题,建议改成参数绑定的写法:

def self.create(user_info)
  DBConnection.execute(<<-SQL, 
    user_info[:firstname], user_info[:lastname],
    user_info[:age], user_info[:password], user_info[:email]
  )
    INSERT INTO
      users (firstname, lastname, age, password, email)
    VALUES
      (?, ?, ?, ?, ?)
  SQL
  DBConnection.last_insert_row_id
end

内容的提问来源于stack exchange,提问作者Colin Jackson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 03:45:38