SQLite表未正确创建

时间:2018-10-23 22:53:48

标签: android sqlite

我知道有很多问题都存在相同的问题。接下来我将尝试做的事情:

  • 卸载该应用,然后再次运行
  • 清除应用数据
  • 检查onUpgrade()和onCreate()方法

我认为我的问题是我没有同时创建两个表,但是我看不到为什么它没有正确执行。

我正在尝试通过执行SELECT语句,使用“ tomasPendientes”表中的数据填充列表视图。

这是db helper类的代码:

public class AdminSQLiteOpenHelper extends SQLiteOpenHelper {
private ContentValues registro;
private static final String nombre ="dbAlarma";
private static final int versionDB = 1;
private static String table1 = "create table alarma( idal integer primary key autoincrement, nombreMed text, hora time, pastillasTotales integer, pastillasRestantes integer)";
private static String table2 = "create table tomasPendientes( idPend integer, FOREIGN KEY (idPend) REFERENCES alarma (idal))";

public AdminSQLiteOpenHelper(Context context, String nombre, SQLiteDatabase.CursorFactory factory, int version) {
    super(context, nombre, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
    Log.d("DATABASE_CREATION", "Base de datos creandose...");
    db.execSQL(table1);
    db.execSQL(table2);
}

@Override
public void onUpgrade(SQLiteDatabase db, int versionAnte, int versionNue) {
    Log.d("DATABASE_UPDATE", "Base de datos actualizandose...");
    db.execSQL("drop table if exists alarma" );
    db.execSQL("drop table if exists tomasPendientes");
    db.execSQL(table1);
    db.execSQL(table2);
}

public Cursor getTomasPendientes(){
    SQLiteDatabase db = this.getWritableDatabase();
    String query = "SELECT * FROM tomasPendientes NATURAL JOIN alarma";
    Cursor data = db.rawQuery(query, null);
    return data;
}

public void insertarPendiente(String alarma){
    SQLiteDatabase bd = this.getWritableDatabase();
    registro = new ContentValues();
    registro.put("idPendiente",alarma);
    bd.insert("tomasPendientes", null, registro);//nombre de la tabla
    bd.close();
}
}

这是正在调用使用数据库的方法的类,该函数用于显示带有db数据的列表视图:

public class VerTomasPendientes extends AppCompatActivity {
private ListView lv;
AdminSQLiteOpenHelper mDataBaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_ver_tomas_pendientes);
    lv = findViewById(R.id.lvAlarmas);
    mDataBaseHelper = new AdminSQLiteOpenHelper(this, vars.bd, null, vars.version);
    populateLV();
}

private void populateLV() {
    Cursor data = mDataBaseHelper.getTomasPendientes();
    ArrayList<String> listData = new ArrayList<>();
    while(data.moveToNext()){
        listData.add("Id alarma: " + data.getString(0) + "\n");
    }
    ListAdapter adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, listData);
    lv.setAdapter(adapter);
}

}

logcat中的错误是下一个:

   Caused by: android.database.sqlite.SQLiteException: no such table: tomasPendientes (code 1): , while compiling: SELECT * FROM tomasPendientes NATURAL JOIN alarma
    at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
    at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:893)
    at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:504)
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:726)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
    at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
    at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
    at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1426)
    at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1365)
    at farmacia.farmacia.AdminSQLiteOpenHelper.getTomasPendientes(AdminSQLiteOpenHelper.java:48)
    at farmacia.farmacia.VerTomasPendientes.populateLV(VerTomasPendientes.java:25)
    at farmacia.farmacia.VerTomasPendientes.onCreate(VerTomasPendientes.java:21)

我不明白为什么它创建不正确。

2 个答案:

答案 0 :(得分:1)

我相信您的问题是您正在查看logcat的错误部分。那是您在查看先前的故障,而不是当前的故障。

运行确切的代码,不会导致表格未找到错误,但会按照以下说明发出列未找到错误:-

10-23 23:29:36.039 2189-2189/? E/SQLiteLog: (1) table tomasPendientes has no column named idPendiente
10-23 23:29:36.043 2189-2189/? E/SQLiteDatabase: Error inserting idPendiente=bert
    android.database.sqlite.SQLiteException: table tomasPendientes has no column named idPendiente (code 1): , while compiling: INSERT INTO tomasPendientes(idPendiente) VALUES (?)
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:882)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:493)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
        at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
        at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1467)
        at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1339)
        at axtest.axtest.AdminSQLiteOpenHelper.insertarPendiente(AdminSQLiteOpenHelper.java:48)
        at axtest.axtest.MainActivity.onCreate(MainActivity.java:18)
        at android.app.Activity.performCreate(Activity.java:5008)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
        at android.app.ActivityThread.access$600(ActivityThread.java:130)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)

如果 tomasPendientes 表中没有这样的列,则您已使用registro.put("idPendiente",alarma);。列为 idPend

但是,更改为列 idPend 会导致外键约束冲突(但是这些键未打开),因为似乎没有任何行插入到该表中 tomasPendientes 表所依赖。

工作示例

以下代码是AdminSQLiteOpenhelper.java的修改版和一个调用活动。

AdminSQLiteOpenHelper.java

public class AdminSQLiteOpenHelper extends SQLiteOpenHelper {
    private ContentValues registro;
    private static final String nombre ="dbAlarma";
    private static final int versionDB = 1;


    //<<<<<<<<<< HIGHLY RECOMMEND A SINGLE DEFINITION OF TABLE and COLUMN NAMES
    public static final String TABLE_ALARMA = "alarma";
    public static final String TABLE_TOMASPENDIENTES = "tomasPendientes";
    public static final String ALARMA_COL_IDA1 = "ida1";
    public static final String ALARMA_COL_NOMBREMED = "nombreMed";
    public static final String ALARMA_COl_HORA = "hora";
    public static final String ALARMA_COL_PASTILLASTOTALES = "pastillasTotales";
    public static final String ALARMA_COL_PASTILLASRENTANTES = "pastillasRestantes";
    public static final String TOMASPENDIENTES_COL_IDPEND = "idPend";


    private static String table1 = "create table alarma( idal integer primary key autoincrement, nombreMed text, hora time, pastillasTotales integer, pastillasRestantes integer)";

    private static String crtt1 = "CREATE TABLE IF NOT EXISTS " + TABLE_ALARMA + "(" +
            ALARMA_COL_IDA1 + " INTEGER PRIMARY KEY, " + //<<<<<<<<<< AUTOINCREMENT VERY LIKELY NOT REQUIRED SO OMITTED
            ALARMA_COL_NOMBREMED + " TEXT, " +
            ALARMA_COl_HORA + " TEXT," + //<<<<<<<<<< no column type called time as text (bit of a moot point as it probablu will not matter)
            ALARMA_COL_PASTILLASTOTALES + " INTEGER, " +
            ALARMA_COL_PASTILLASRENTANTES + " INTEGER " +
            ")";
    private static String table2 = "create table tomasPendientes( idPend integer, FOREIGN KEY (idPend) REFERENCES alarma (idal))";

    //<<<<<<<<<< THIS TABLES IS USELESSS AS IT IS >>>>>>>>>>
    private static String crtt2 = "CREATE TABLE IF NOT EXISTS " + TABLE_TOMASPENDIENTES + "(" +
            TOMASPENDIENTES_COL_IDPEND + " INTEGER REFERENCES " +  TABLE_ALARMA +  "(" + ALARMA_COL_IDA1 + ") " +
            ")";

    public AdminSQLiteOpenHelper(Context context, String nombre, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, nombre, factory, version);
    }

    @Override
    public void onConfigure(SQLiteDatabase db) {
        super.onConfigure(db);
        db.execSQL("PRAGMA foreign_keys = ON;");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d("DATABASE_CREATION", "Base de datos creandose...");
        db.execSQL(crtt1);
        db.execSQL(crtt2);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int versionAnte, int versionNue) {
        Log.d("DATABASE_UPDATE", "Base de datos actualizandose...");
        db.execSQL("drop table if exists alarma" );
        db.execSQL("drop table if exists tomasPendientes");
        onCreate(db); //<<<<<<<<<< just call onCreate
    }

    public Cursor getTomasPendientes(){
        SQLiteDatabase db = this.getWritableDatabase();
        String query = "SELECT * FROM tomasPendientes NATURAL JOIN alarma";
        Cursor data = db.rawQuery(query, null);
        return data;
    }


    //<<<<<<<<<< NEW
    public long insertAlarma(String nombreMed, String hora, int pastillastotales, int pastillarentantes) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(ALARMA_COL_NOMBREMED,nombreMed);
        cv.put(ALARMA_COl_HORA,hora);
        cv.put(ALARMA_COL_PASTILLASTOTALES,pastillastotales);
        cv.put(ALARMA_COL_PASTILLASRENTANTES,pastillarentantes);
        return db.insert(TABLE_ALARMA,null,cv);
    }

    //<<<<<<<<<< REPLACEMENT
    public long insertTomaPendientes(long idpend) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(TOMASPENDIENTES_COL_IDPEND,idpend);
        return db.insert(TABLE_TOMASPENDIENTES,null,cv);
    }


    /*<<<<<<<<<< OLD
    public void insertarPendiente(String alarma){
        SQLiteDatabase bd = this.getWritableDatabase();
        registro = new ContentValues();
        registro.put("idPendiente",alarma);
        bd.insert("tomasPendientes", null, registro);//nombre de la tabla
        bd.close();
    }
    */
}
  • 请参阅注释。
  • 请注意要使用外键,必须为Android打开外键支持。因此,添加了用于调用PRGAMA语句的覆盖的 onConfigure 方法。
  • 已添加一种在 alarma 表中插入行的方法。
  • 将行插入 tomasPendientes 的方法已被替换。

该活动中使用的代码为:-

public class MainActivity extends AppCompatActivity {


    AdminSQLiteOpenHelper mASQLiteHlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mASQLiteHlpr = new AdminSQLiteOpenHelper(this,"fred",null,1);

        mASQLiteHlpr.insertAlarma("Alarm1","2018-01-11 23:59:59",1234,156);
        mASQLiteHlpr.insertAlarma("Alarm2","2018-01-11 23:59:59",2234,256);
        mASQLiteHlpr.insertAlarma("Alarm3","2018-01-11 23:59:59",3234,356);
        Cursor c1 = mASQLiteHlpr.getTomasPendientes();
        DatabaseUtils.dumpCursor(c1);

        mASQLiteHlpr.insertTomaPendientes(1); // 1 will be OK as there a row in alama table will have 1 in column ida1
        mASQLiteHlpr.insertTomaPendientes(100); // ooops nor row in alarma with 100 in column ida1
        mASQLiteHlpr.insertTomaPendientes(2); // will work
        Cursor c2 = mASQLiteHlpr.getTomasPendientes();
        DatabaseUtils.dumpCursor(c2);
        c1.close();
        c2.close();
    }
}
  • mASQLiteHlpr(一个AdminSQLiteOpenhelper对象)最初被声明为类变量,然后实例化。
    • 请注意,数据库名称是如何作为 fred 传递的(忽略),您的构造函数可以更改为仅接受上下文
  • 将三行添加到 alarm 表中(注意,每次运行将添加三行)
  • 所有行(第一次运行时都没有)从(第一次运行时为空) tomasPendientes 表中提取到游标中。
  • 使用DatabaseUtils dump 方法将游标写入日志。
  • 尝试在 tomasPendientes 表中添加三行(由于外键约束,将不会添加一行)。
  • 第二个游标被写入日志。
  • 两个光标已关闭。

输出到日志:-

10-24 00:38:30.423 2694-2694/axtest.axtest D/DATABASE_CREATION: Base de datos creandose...
10-24 00:38:30.431 2694-2694/axtest.axtest I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@53450f08
10-24 00:38:30.431 2694-2694/axtest.axtest I/System.out: <<<<<
10-24 00:38:30.435 2694-2694/axtest.axtest E/SQLiteDatabase: Error inserting idPend=100
    android.database.sqlite.SQLiteConstraintException: foreign key constraint failed (code 19)
        at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:775)
        at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
        at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
        at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
        at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1339)
        at axtest.axtest.AdminSQLiteOpenHelper.insertTomaPendientes(AdminSQLiteOpenHelper.java:92)
        at axtest.axtest.MainActivity.onCreate(MainActivity.java:27)
        at android.app.Activity.performCreate(Activity.java:5008)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
        at android.app.ActivityThread.access$600(ActivityThread.java:130)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4745)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
        at dalvik.system.NativeStart.main(Native Method)
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@5346544c
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: 0 {
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    idPend=1
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    ida1=1
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    nombreMed=Alarm1
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    hora=2018-01-11 23:59:59
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    pastillasTotales=1234
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    pastillasRestantes=156
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: }
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: 1 {
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    idPend=1
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    ida1=2
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    nombreMed=Alarm2
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    hora=2018-01-11 23:59:59
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    pastillasTotales=2234
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    pastillasRestantes=256
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: }
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: 2 {
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    idPend=1
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    ida1=3
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    nombreMed=Alarm3
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    hora=2018-01-11 23:59:59
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    pastillasTotales=3234
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    pastillasRestantes=356
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: }
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out: 3 {
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    idPend=2
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    ida1=1
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    nombreMed=Alarm1
10-24 00:38:30.439 2694-2694/axtest.axtest I/System.out:    hora=2018-01-11 23:59:59
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    pastillasTotales=1234
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    pastillasRestantes=156
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out: }
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out: 4 {
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    idPend=2
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    ida1=2
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    nombreMed=Alarm2
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    hora=2018-01-11 23:59:59
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    pastillasTotales=2234
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    pastillasRestantes=256
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out: }
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out: 5 {
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    idPend=2
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    ida1=3
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    nombreMed=Alarm3
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    hora=2018-01-11 23:59:59
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    pastillasTotales=3234
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out:    pastillasRestantes=356
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out: }
10-24 00:38:30.443 2694-2694/axtest.axtest I/System.out: <<<<<
  • 注意。由于外键约束而导致的错误不会导致应用崩溃。
  • 注意(如果使用以上代码,则应在运行代码之前执行以下操作之一):-

    • 删除应用程序的数据。
    • 卸载应用。
    • 增加数据库版本。
  • tomasPendientes 表本身没有任何用处,因为它只有1列必须与 ida1 列中的值重复> alarma 表。

答案 1 :(得分:0)

您已经在创建table1之后添加了table2吗?

与之类似,您以前是否使用table1进行编译?如果是这样,可能只是您的应用程序未运行onCreate,因为它仅运行一次。创建数据库后,onCreate将不再运行。

要解决此问题,您可能只需要在模拟器中卸载该应用,然后再次运行即可。

希望有帮助:)

编辑:我没有看到您已经尝试过此操作。