android - 尝试插入时没有此类列的 SQLite 问题
问题描述
我使用 Sqlite 并且我有以下数据库,我正在为女性开发一个应用程序,它应该包含登录和注册。我在数据库中遇到了“没有这样的列”之类的问题
数据库
public class DB_MJG extends SQLiteOpenHelper {
public static final String name ="dataB.db";
public static final int version =1;
//Les atts de la table FEMME
public static final String table_Femme ="Femme";
public static final String ID_F = "id";
public static final String NOM_F ="nom";
public static final String PRENOM_F="prenom";
public static final String PSEUDO="pseudo";
public static final String MDP="mdp";
public static final String GRP_F="grpSang";
public static final String AGE_F="age";
public static final String POIDS="poids";
public DB_MJG( Context context) {
super(context, name, null, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
String CREATE_TABLE_FEMME = "CREATE TABLE " + table_Femme + "(
"+ID_F+" INTEGER PRIMARY KEY AUTOINCREMENT, "
+NOM_F+" TEXT, "+PRENOM_F+" TEXT " + ")";
db.execSQL(CREATE_TABLE_FEMME);
System.out.println("table femme crée");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS "+table_Femme);
db.execSQL("DROP TABLE IF EXISTS "+table_Enfant);
}
//insérer dans la table FEMME
public void insertFemme(Femme f)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues vals = new ContentValues();
vals.put(NOM_F,f.getNom());
vals.put(PRENOM_F,f.getPrenom());
db.insert(table_Femme,null,vals);
db.close();
}
public ArrayList getFemme()
{
ArrayList<Femme> femmes = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM " +table_Femme, null);
while(c.moveToNext()){
Femme f = new Femme(c.getString(1),c.getString(2));
femmes.add(f);
}
return femmes;
}
}
启动器活动
public class MainActivity extends AppCompatActivity {
DB_MJG db = new DB_MJG(this);
SQLiteDatabase database ;
String s = "";
private Button log,sign;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
database = openOrCreateDatabase(db.name, Context.MODE_PRIVATE, null) ;
db.insertFemme(new Femme("sara","sara"));
ArrayList<Femme> femmes = db.getFemme();
TextView textView= (TextView) findViewById(R.id.textView13);
for(Femme f : femmes){
String ch = "Nom :" +f.getNom() + " Prenom : "
+f.getPrenom()+"\n";
s = s +ch;
}
textView.setText(s);
}
错误
E/SQLiteLog: (1) table Femme has no column named nom
E/SQLiteDatabase: Error inserting nom=sara prenom=sara
android.database.sqlite.SQLiteException: table Femme has no column named
nom (code 1 SQLITE_ERROR): , while compiling: INSERT INTO
Femme(nom,prenom) VALUES (?,?)
at
android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native
Method)
当我编译时,它说没有这样的列。我已经定义了 nom 列。该数据库具有我试图用于插入的名称,但它不起作用。
解决方案
您遇到的主要问题是数据库助手的onCreate方法仅在创建数据库时调用,这是在它的生命周期中调用一次。
因此,如果通过修改创建表 SQL 对结构(模式)进行了任何更改,如 onCreate 方法中使用的那样,除非删除数据库或以其他方式调用onCreate方法,否则它们将不会被反映。
通常,至少在开发应用程序时,通过首先执行以下操作之一来应用此类更改:-
- 删除 App 的数据(这会删除数据库,因此会自动调用onCreate)。
- 卸载应用程序(并因此删除应用程序的数据)。
- 如果编写onUpgrade方法以删除更改的表并重新创建表(通常/通常通过调用onCreate方法)
执行上述任一操作后,重新运行应用程序将导致应用结构更改。
- 请注意,上述内容将导致现有数据丢失,不适用于已部署的应用程序。
在您的情况下,如果使用选项 3,onUpgrade方法需要在删除表后包括创建表,因为它只删除表。
您在 MainActivity 中的代码也过于复杂,因为它利用打开数据库而不使用 SQLite OpenHelper打开数据库,而是使用 SQLiteDatabase openOrCreate方法打开它(这不会导致 SQLiteOpenHelper(DB_MJG 是 SQLiteOpenHelper 的子类) ) onCreate方法被调用)。但是,由于怪癖/运气,当您开始使用 DB_MJG 的实例时,即db,因为该实例是在 openOrCreate 方法之前创建的,它实际上会继续调用onCreat方法。
但是,使用一种方法打开数据库会简单得多。
因此,我建议只使用DB_MJG DatabseHelper 来实现。
使固定
基本的解决方法是引入更改后的结构。因此,应采取上述 3 项中的一项。
如果使用 3. 则需要修改onUpgrade方法以调用onCreate方法,然后增加版本号。那就是 onUpgrade 方法可以是:-
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS "+table_Femme);
db.execSQL("DROP TABLE IF EXISTS "+table_Enfant);
onCreate(db); //<<<<<<<<<< ADDED so that onUpgrade creates the tables after they have been dropped
}
附加/推荐
关闭光标
在 DB_MJG.java 中,getFemme 方法使光标保持打开状态。这可能会导致打开的数据库或游标过多,因此建议该行:-
c.close();
被添加到getFemme方法中,所以它变成:-
public ArrayList getFemme()
{
ArrayList<Femme> femmes = new ArrayList<>();
SQLiteDatabase db = this.getWritableDatabase();
Cursor c = db.rawQuery("SELECT * FROM " +table_Femme, null);
while(c.moveToNext()){
femmes.add(new Femme(c.getString(c.getColumnIndex(NOM_F)),c.getString(c.getColumnIndex(PRENOM_F))));
}
c.close(); //<<<<<<<<<< should always close a cursor when finished with it
return femmes;
}
- 请注意,上面还消除了对中间 Femme 对象f的需要。
使用 DB_MJG 打开数据库
使用 SQliteOpenHelper 的子类时无需打开或创建数据库,因为它会执行此操作。所以MainActivity.java可能是:-
public class MainActivity extends AppCompatActivity {
DB_MJG db; // Only declare the DB_MJG object.
private Button log,sign;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new DB_MJG(this);
db.insertFemme(new Femme("sara","sara"));
ArrayList<Femme> femmes = db.getFemme();
TextView textView= (TextView) findViewById(R.id.textView13);
StringBuilder sb = new StringBuilder(); //<<<<<<<<<< ADDED - Use StringBuilder in a loop
for(Femme f : femmes){
sb.append("Nom: ").append(f.getNom()).append(" Prenom: ").append(f.getPrenom());
}
textView.setText(sb.toString());
}
}
请注意,上述内容应在应用修复的同时或之后进行更改。
而不是在循环中连接字符串,而是使用了 StringBuilder。请参阅 -为什么在 Java 中使用 StringBuffer 而不是字符串连接运算符
推荐阅读
- java - Intellij 插件:无法初始化组件状态异常
- python - 如何返回 Python 类的字符串表示形式?
- javascript - 在构建期间从反应项目导入错误
- php - 如何使用 php 调用程序并在文本字段中获取数据并作为来自 HTML 站点的参数传递?
- java - 如何从 JNI 中正确释放内存?
- php - 使用 Jetstream 在 Laravel 8 中添加新 Livewire 组件时如何解决 RootTagMissingFromViewException 错误
- r - 在 R 中选择某些标签
- visual-c++ - MSVC++ 和 SSE2
- javascript - d3 元素未在反应中显示
- r - 如何在 Rstudio 中组合两个时间序列?