Android SQLite查询报no such column错误致应用崩溃
问题根因
崩溃来自SQL语法错误:你手动拼接SQL语句时,字符串类型的用户名、密码值没有包裹单引号,SQLite会直接把传入的rushi、4567识别为列名进行解析,最终抛出「不存在名为rushi的列」异常。
你当前拼接生成的错误SQL语句:
SELECT * FROM register WHERE Username = rushi and password = 4567;
注意:手动拼接SQL不仅容易出现这类语法错误,还存在SQL注入风险,正式开发必须使用参数化查询替代字符串拼接。
修复步骤
1. 重构DBHandler中的查询方法
移除从MainActivity取静态值的逻辑,将用户名、密码作为方法参数传入,使用?作为SQL参数占位符,由SQLite框架自动处理参数转义、引号拼接,修改后代码:
public Cursor CheckUsername(String inputUsername, String inputPassword) { SQLiteDatabase db = this.getReadableDatabase(); String query = "SELECT * FROM register WHERE Username = ? AND password = ?"; // 按占位符顺序传入参数值 return db.rawQuery(query, new String[]{inputUsername, inputPassword}); }
2. 调整登录校验逻辑
直接使用当前页面从输入框获取到的用户名、密码调用查询方法,不再依赖跨类静态取值(该写法容易取到空值、旧值导致逻辑异常),同时补充游标资源释放、登录失败提示逻辑:
private void checkLogin() { EditText emailInput = findViewById(R.id.emaillogin); EditText pwdInput = findViewById(R.id.passwordlogin); String password = pwdInput.getText().toString(); String username = emailInput.getText().toString().trim(); Cursor c = dbHandler.CheckUsername(username, password); if (c.moveToFirst()) { Toast.makeText(MainActivity.this, "Login Success", Toast.LENGTH_LONG).show(); startActivity(new Intent(MainActivity.this, MainActivity2.class)); } else { Toast.makeText(MainActivity.this, "用户名或密码错误", Toast.LENGTH_LONG).show(); } // 用完必须关闭游标,避免内存泄漏 c.close(); }
开发建议
- 所有数据库操作涉及动态传入参数时,统一使用
?占位符的参数化查询,禁止手动拼接SQL语句 - 数据库查询返回的Cursor对象使用完成后必须调用
close()释放资源 - 禁止明文存储用户密码,建议使用加盐哈希算法处理后再存入数据库,降低数据泄露风险
内容的提问来源于stack exchange,提问作者Rishi Ff
相关产品推荐
相关产品推荐

