Таблица SQLite создана неправильно - PullRequest
0 голосов
/ 24 октября 2018

Я знаю, что есть много вопросов с той же проблемой.Я попытался сделать следующее:

  • Удалите приложение и запустите его снова
  • Очистите данные приложения
  • Проверьте onUpgrade ()и методы onCreate ()

Я думаю, что моя проблема в том, что я не создаю две таблицы одновременно, но не могу понять, почему они не выполняются правильно.

Я пытаюсь заполнить представление списка данными из таблицы 'tomasPendientes', выполнив инструкцию SELECT.

Вот код класса помощника db:

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

Thisэто класс, вызывающий метод, использующий базу данных, функция которого заключается в отображении списка с данными из базы данных:

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 голосов
/ 24 октября 2018

Я считаю, что ваша проблема в том, что вы смотрите не на ту часть 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)

То есть вы использовали registro.put("idPendiente",alarma);, когда такого столбца нет в таблице tomasPendientes .столбец 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.Следовательно, добавлен метод overidden onConfigure , который вызывает инструкцию PRGAMA.
  • Добавлен метод для вставки строк в таблицу 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 (оно игнорируется), ваш конструктор может быть изменен, чтобы просто принять контекст
  • Три строки добавляются в таблицу alarma (примечание три будут добавляться при каждом запуске)
  • Все строки (нет при первом запуске) извлекаются из (пусто при первом запуске)) tomasPendientes таблица в Курсор.
  • Курсор записывается в журнал с использованием метода DatabaseUtils dump .
  • Предпринята попытка добавитьтри строки в таблице tomasPendientes (одна не будет добавлена ​​из-за ограничения внешнего ключа).
  • 2-й курсор записывается в журнал.
  • 2 курсора

Вывод в журнал: -

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 таблица.

0 голосов
/ 24 октября 2018

Вы добавили table2 после того, как table1 уже был создан?

Как, вы ранее компилировали с table1?Если это так, возможно, ваше приложение не запускает onCreate, так как оно запускает его только один раз.После создания базы данных onCreate больше не запускается.

Чтобы исправить это, вам может понадобиться просто удалить приложение в эмуляторе, а затем запустить его снова.

Надеюсь, это поможет:)

Редактировать: я не видел, что вы уже пробовали это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...