база данных sqlite иногда вставляет данные в неправильном порядке - PullRequest
0 голосов
/ 09 ноября 2019

Я работаю с Android Studio, и мне нужно вставить некоторые данные в базу данных. Иногда это работает, но иногда я получаю эту ошибку. Я действительно не могу понять разницу между временем, когда оно работает, и временем, которое это не делает.

2019-11-09 11:38:34.912 4369-4369/com.example.android.fresh 
D/DatabaseHelper: addData: Adding John Smith to people_table
2019-11-09 11:38:34.913 4369-4369/com.example.android.fresh E/SQLiteLog: 
(20) statement aborts at 5: [INSERT INTO 
people_table(name,amount,contact_no) VALUES (?,?,?)] datatype mismatch
2019-11-09 11:38:34.916 4369-4369/com.example.android.fresh 
E/SQLiteDatabase: Error inserting name=John Smith amount=255.0 contact_no= 1234567890 from {P:4369;U:10178}
android.database.sqlite.SQLiteDatatypeMismatchException: datatype mismatch (code 20 SQLITE_MISMATCH)
    at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
    at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:796)
    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:1613)
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1482)
    at com.example.android.fresh.DatabaseHelper.addData(DatabaseHelper.java:51)
    at com.example.android.fresh.createPerson.AddData(createPerson.java:94)
    at com.example.android.fresh.createPerson$1.onClick(createPerson.java:58)
    at android.view.View.performClick(View.java:6669)
    at android.view.View.performClickInternal(View.java:6638)
    at android.view.View.access$3100(View.java:789)
    at android.view.View$PerformClick.run(View.java:26145)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6898)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Соответствующий код в моем классе помощника по базе данных выглядит следующим образом:

private static final String COL1 = "contact_no";
private static final String COL2 = "name";
private static final String COL3 = "amount";

@Override
public void onCreate(SQLiteDatabase db) {
String createTable = "CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT,"
            + COL1 + " TEXT NOT NULL," +
            COL2 + " TEXT NOT NULL,"
            + COL3 + " REAL)" ;
    db.execSQL(createTable);

public boolean addData(String contactNo, String contactName, double amount) {
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues contentValues = new ContentValues();
    contentValues.put(COL1, contactNo);
    contentValues.put(COL2, contactName);
    contentValues.put(COL3, amount);

    Log.d(TAG, "addData: Adding " + contactName + " to " + TABLE_NAME);

    long result = db.insert(TABLE_NAME, null, contentValues);

    if (result == -1) {
        return false;
    } else {
        return true;
    }
}

Это код в классе createPerson:

public void AddData(String contactNo, String contactName, double amount) {
    boolean insertData = mDatabaseHelper.addData(contactNo, contactName, amount);

    if (insertData) {
        check =1;
        toastMessage("Contact Inserted");
    } else {
        toastMessage("Something went wrong");
    }
}

И это оператор вызова метода:

 AddData(contactNumber, contactName, amount);

Каждый из них находится в порядке contactNumber, contactName иколичество, но ошибка sqlite, которую я получаю, вставляет его в порядке contactName, сумму и contactNumber. Я действительно не могу понять, как это происходит.

Ответы [ 2 ]

0 голосов
/ 10 ноября 2019

@ MikeT уже правильно ответил на это подробно, но тем не менее мне интересно: почему бы не следовать шаблонам проектирования архитектуры и реализовать Android Room? Используя Room, вам не придется беспокоиться о такой «низкоуровневой» ошибке. Он скажет вам, что не так, и именно для этого он предназначен. Совет: пусть Room сделает вставку за вас и будет рад постоянным данным

0 голосов
/ 09 ноября 2019

Существует только 1 ситуация, когда происходит несоответствие типов данных из-за возможности SQLite хранить данные любого типа в любом типе столбца (с 1 исключением и, следовательно, причиной / проблемой).

  • вы хотите прочитать типы данных в SQLite версии 3 , поскольку это объясняет тип и его гибкость по сравнению с типичными базами данных. Это также объясняет псевдонимы rowid и AUTOINCREMENT.

Исключение составляет столбец, который является псевдонимом столбца rowid. Псевдоним столбца rowid определяется с помощью INTEGER PRIMARY KEY (в частности, INTEGER, а не INT или каких-либо других значений, которые приведут к производному типу INTEGER).

  • Обратите внимание, что можно добавить AUTOINCREMENT(и только для) определения, хотя это неэффективно и редко требуется.

rowid и, следовательно, его псевдоним ДОЛЖНЫ содержать целочисленное значение (до 64 бит со знаком).

Таким образом, вы как-то пытаетесь вставить нецелочисленное значение в псевдоним rowid, это не может быть в случае, если SQL, как показано, используется для создания таблицы.

Таким образом, SQL не был успешно запущен и создал таблицу, но, скорее всего, причина в том, что существует предыдущая таблица, созданная с использованием другого SQL.

Простоизменение SQL для создания не приведет к изменению таблицы . Это потому, что база данных сохраняется (остается там) между запусками. Таким образом, метод onCreate будет автоматически запускаться только один раз за время существования базы данных.

Если вы измените схему (создание SQL), то вам нужно будет найти какой-то способ запускаSQL (который будет включать в себя удаление таблицы). Самый простой способ при разработке приложения - либо

  1. удалить данные приложения,
  2. , чтобы удалить приложение, либо
  3. увеличить номер версии
    1. эта последняя опция будет работать только в том случае, если onUpgrade удаляет таблицы, чтобы их можно было воссоздать, и вызывает измененный SQL (обычно путем вызова onCreate)).

После выполнения одного из перечисленных выше действий приложение должно быть перезапущено.

  • Обратите внимание, что все приведенные выше параметры приведут к потере текущих данных. Если необходимо сохранить текущие данные, тогда процесс будет более сложным и, вероятно, будет включать операторы ALTER для переименования таблиц и операторы для копирования (INSERT) данных из исходной таблицы (таблиц) в новую таблицу (таблицы).
...