我使用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,但是它不起作用。
答案 0 :(得分:1)
您遇到的主要问题是,仅在创建数据库时才调用数据库助手的 onCreate 方法,这是它生命周期中的一次。
这样,如果通过修改 onCreate 方法中使用的创建表SQL对结构(架构)进行了任何更改,则除非删除数据库或删除数据库,否则不会反映这些更改。 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;
}
使用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代替循环中的字符串。请参阅-Why to use StringBuffer in Java instead of the string concatenation operator