尝试插入时没有这样的列的SQLite问题

时间:2019-04-23 23:39:57

标签: 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列。数据库具有我要用于插入的nom,但是它不起作用。

1 个答案:

答案 0 :(得分:1)

您遇到的主要问题是,仅在创建数据库时才调用数据库助手的 onCreate 方法,这是它生命周期中的一次。

这样,如果通过修改 onCreate 方法中使用的创建表SQL对结构(架构)进行了任何更改,则除非删除数据库或删除数据库,否则不会反映这些更改。 onCreate 方法是通过其他方式调用的。

通常(至少在开发应用程序时)首先通过执行以下操作之一来应用此类更改:-

  1. 删除应用程序的数据(这会删除数据库,因此会自动调用 onCreate )。
  2. 卸载应用程序(并因此删除应用程序的数据)。
  3. 编写
  4. IF 方法( onUpgrade )以删除已更改的表并重新创建表(通常/通常通过调用 onCreate 方法)

执行上述操作之一后,重新运行该应用程序将导致应用结构更改。

  • 注意:对于已部署的应用程序,上述操作将导致现有数据丢失和不适用

对于您而言,如果使用选项3,则 onUpgrade 方法需要在删除表后包括创建表,因为它只会删除表。

MainActivity中的代码也过于复杂,因为它利用打开数据库而不使用SQLite OpenHelper 来打开数据库,而是使用SQLiteDatabase openOrCreate 来打开数据库方法(不会导致SQLiteOpenHelper(DB_MJG是SQLiteOpenHelper的子类) onCreate 方法被调用)。但是,很奇怪,如果您确实开始使用DB_MJG实例,即 db ,因为该实例是在openOrCreate方法之前创建的,则实际上它会继续调用 onCreat < / strong>方法。

但是,仅使用一种方法打开数据库会更简单。

因此,我建议仅使用 DB_MJG DatabseHelper来实现。

修复

必要的解决方法是引入更改的结构。因此,应采用上述三者之一。

如果使用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方法使Cursor打开。这可能导致打开的数据库或游标过多,因此建议该行:-

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());
    }
}