Android下的SQLite:在空数据库上插入/替换时约束失败

Android下的SQLite:在空数据库上插入/替换时约束失败,android,sqlite,Android,Sqlite,我遇到了一个问题,在一个完全空的数据库/表上,我的键约束似乎失败了,我不知道为什么。我已经用adb导出了数据库,并用sqliteman打开了它;它还是空的 这是我的代码: public class DatabaseAdapterSystem extends SQLiteOpenHelper { private Context context; private static final int DATABASE_VERSION = 20; private stati

我遇到了一个问题,在一个完全空的数据库/表上,我的键约束似乎失败了,我不知道为什么。我已经用adb导出了数据库,并用sqliteman打开了它;它还是空的

这是我的代码:

public class DatabaseAdapterSystem extends SQLiteOpenHelper {

    private Context context;
    private static final int    DATABASE_VERSION = 20;
    private static final String DATABASE_NAME    = "databaseSystem";

    public DatabaseAdapterSystem(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context;
    }

    @Override
    public void onOpen(SQLiteDatabase db) {
        Log.d(getClass().getSimpleName(), "isReadOnly: " + db.isReadOnly());
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        try {
            db.beginTransaction();
            db.execSQL(
                "CREATE TABLE \"accounts\" (" +
                    "\"userId\" INTEGER PRIMARY KEY NOT NULL, " +
                    "\"nickname\" TEXT NOT NULL, " +
                    "\"password\" TEXT NOT NULL, " +
                    "\"profileImageFileName\" TEXT NOT NULL " +
                ")"
            );
            db.setTransactionSuccessful();
        }
        finally {
            db.endTransaction();
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Until yet no need
    }

    // -------------------------------------------------------------------------

    public synchronized BackendAccountList getAccounts() {
        Log.d(getClass().getSimpleName(), "DatabaseAdapterSystem::getAccounts has been called");

        BackendAccountList result = new BackendAccountList();
        SQLiteDatabase db = null;
        Cursor resultSet = null;

        try {
            db = this.getReadableDatabase();

            resultSet = db.query(
                    "accounts", 
                    new String[] {"userId", "nickname", "password", "profileImageFileName"}, // Columns
                    null,                                                           // Selection
                    null,                                                           // SelectionArgs
                    null,                                                           // GroupBy
                    null,                                                           // Having
                    "userId asc"
                    );

            if (resultSet != null) {
                int colUserId = resultSet.getColumnIndex("userId");
                int colNickname = resultSet.getColumnIndex("nickname");
                int colPassword = resultSet.getColumnIndex("password");
                int colProfileImageFileName = resultSet.getColumnIndex("profileImageFileName");

                if (resultSet.moveToFirst()) {
                    do {
                        result.add(new BackendAccount(
                                    resultSet.getInt(colUserId),
                                    resultSet.getString(colNickname),
                                    resultSet.getString(colPassword),
                                    resultSet.getString(colProfileImageFileName)
                                ));
                    } while (resultSet.moveToNext());
                }
            }
        }
        finally {
            if (resultSet != null) {
                resultSet.close();
            }
            if (db != null) {
                db.close();
            }
        }
        return result;
    }

    public synchronized BackendAccountList putAccount(BackendAccount account) {
        Log.d(getClass().getSimpleName(), "DatabaseAdapterSystem::putAccount has been called");

        BackendAccountList result = new BackendAccountList();
        SQLiteDatabase db = null;

        try {
            db = this.getWritableDatabase();
            ContentValues cv = new ContentValues();
            cv.put("userId", account.getUserId());
            cv.put("nickname", account.getUsername());
            cv.put("password", account.getPassword());
            cv.put("profileImageFileName", account.getProfileImage());
            db.insertOrThrow("accounts", null, cv);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (db != null) {
                db.close();
            }
        }
        return result;
    }
}
加载应用程序后,将调用getAccounts并返回后端帐户列表。 通信成功后,可能会调用putAccount在数据库中存储新帐户

我已经尝试过使用replaceOrThrow,但即使在约束条件下也失败了(错误19)

//编辑:Stacktrace

04-16 10:47:05.910: W/System.err(13130): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
04-16 10:47:05.910: W/System.err(13130):    at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
04-16 10:47:05.910: W/System.err(13130):    at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:66)
04-16 10:47:05.910: W/System.err(13130):    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1426)
04-16 10:47:05.910: W/System.err(13130):    at android.database.sqlite.SQLiteDatabase.insertOrThrow(SQLiteDatabase.java:1308)
04-16 10:47:05.910: W/System.err(13130):    at com.jappy.service.DatabaseAdapterSystem.putAccount(DatabaseAdapterSystem.java:183)
04-16 10:47:05.910: W/System.err(13130):    at com.jappy.service.JappyService$1.handleMessage(JappyService.java:60)
04-16 10:47:05.910: W/System.err(13130):    at android.os.Handler.dispatchMessage(Handler.java:99)
04-16 10:47:05.910: W/System.err(13130):    at android.os.Looper.loop(Looper.java:123)
04-16 10:47:05.920: W/System.err(13130):    at android.app.ActivityThread.main(ActivityThread.java:4363)
04-16 10:47:05.920: W/System.err(13130):    at java.lang.reflect.Method.invokeNative(Native Method)
04-16 10:47:05.920: W/System.err(13130):    at java.lang.reflect.Method.invoke(Method.java:521)
04-16 10:47:05.920: W/System.err(13130):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
04-16 10:47:05.920: W/System.err(13130):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
04-16 10:47:05.920: W/System.err(13130):    at dalvik.system.NativeStart.main(Native Method)
//编辑 其中一列包含NULL(profileImageFilename)。这就是sqlite抛出此消息的原因。
问题已解决。

如果违反其中一个约束,将引发
SQLiteConstraintException
。在您的情况下,所有四个字段都被约束为非空。因此,该错误是由于尝试将
null
值插入其中一个字段而导致的。添加一些日志记录以确定是哪一个。

错误是什么?张贴stacktrace。那么,四个字段中的一个是
null
。添加一些日志记录以了解它是哪一个。我不知道sqlite在这种情况下会抛出那个错误。谢谢。我现在只是回答,而不是评论。不客气。:)