Android-插入便利方法为WITHOUT ROWID表返回什么值?

时间:2019-01-23 08:47:57

标签: java android sqlite android-sqlite

  

注意:该问题旨在作为share your knowledge, Q&A-style

SQLite默认情况下会创建一个隐藏列 rowid ,该列将被分配一个唯一的64位带符号整数值。

但是,从SQLite版本3.8.2开始,SQLite支持 WITHOUT ROWID 子句,这会导致省略 rowid

假设插入成功,结果将是什么?

即从SQLiteDatabase 插入系列返回的长整数(插入,insertOrThrow和insertWithOnConflict),如下所示:-

  

新插入的行的行ID;如果发生错误,则返回-1。

SQLiteDatabase - insert

1 个答案:

答案 0 :(得分:3)

由于仅从API 21 Lollilop开始提供SQLite 3.8.2或更高版本,因此没有行只能从API 21开始使用。

在API 21编码之前,如果没有ROWID,将导致语法错误,因此将无法获得结果,因为这样的表不存在。

从API 21开始,如果插入可以正常工作,则返回0,否则返回-1。

但是,这只是假设一个简单的情况,即一个表或多个WITHOUT ROWID表(即没有ROWID表)。

将ROWID表添加到混合中(这是最可能的情况),那么结果是以前的时间,因为打开了数据库,所以设置了结果(根据SQLite而不是Android SDK)或-1。

简而言之,该值(如果不是-1)表示已插入行(很有可能),-1通常表示未插入行。

  • caveat 如果您强制将rowid设置为-1(直接或通过别名为rowid列提供-1),即使插入了该行,也可能返回-1的结果。

示例

以下内容演示了如何使用一个WITHOUT ROWID表创建一个数据库,在该表中插入两行并将结果输出到日志。使用SQLiteOpenHelper的子类,因为这似乎是访问SQLite数据库的更常见方法。

DBHelperNoRowid.java(数据库帮助器)

public class DBHelperNoRowid extends SQLiteOpenHelper {

    public final static String DB = "test_norowid";
    public static final int VERSION = 1;
    public static final String TBL_NOROWID = "norowid";
    public static final String COL_ID = BaseColumns._ID;
    public static final String COL_MYDATA = "mydata";

    SQLiteDatabase mDB;

    public DBHelperNoRowid(Context context) {
        super(context, DB, null, VERSION);
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String crt_norowid_table = "CREATE TABLE IF NOT EXISTS " + TBL_NOROWID + "(" +
                COL_ID + " INTEGER PRIMARY KEY, " +
                COL_MYDATA + " TEXT" +
                ") WITHOUT ROWID"; //<<<<<<<<<<
        db.execSQL(crt_norowid_table);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long insertUsingConvenienceInsert(long not_an_id, String text) {
        ContentValues cv = new ContentValues();
        cv.put(COL_ID,not_an_id);
        cv.put(COL_MYDATA,text);
        return mDB.insert(TBL_NOROWID,null,cv);
    }
}

MainActivty.java

public class MainActivity extends AppCompatActivity {

    DBHelperNoRowid mDBhlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDBhlpr = new DBHelperNoRowid(this);
        logInsertResult(2100L,"row 1");
        logInsertResult(-898765432,"row 2");
    }

    private void logInsertResult(long not_an_id, String text) {

        Log.d("INSERTRESULT","Insertion of a row returned " + String.valueOf(
                mDBhlpr.insertUsingConvenienceInsert(not_an_id,text)
        ));
    }
}

结果

2019-01-23 17:36:04.029 24175-24175/so.uru D/INSERTRESULT: Insertion of a row returned 0
2019-01-23 17:36:04.029 24175-24175/so.uru D/INSERTRESULT: Insertion of a row returned 0

第二次运行

运行上述操作将导致UNIQUE约束冲突,该冲突将被 insert 方法捕获,然后返回-1,例如:-

2019-01-23 19:49:51.915 24876-24876/so.uru E/SQLiteDatabase: Error inserting _id=2100 mydata=row 1
    android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: norowid._id (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
        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:1564)
        at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1433)
        at so.uru.DBHelperNoRowid.insertUsingConvenienceInsert(DBHelperNoRowid.java:42)
        at so.uru.MainActivity.logInsertResult(MainActivity.java:23)
        at so.uru.MainActivity.onCreate(MainActivity.java:16)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-01-23 19:49:51.916 24876-24876/so.uru D/INSERTRESULT: Insertion of a row returned -1
2019-01-23 19:49:51.918 24876-24876/so.uru E/SQLiteDatabase: Error inserting _id=-898765432 mydata=row 2
    android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: norowid._id (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
        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:1564)
        at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1433)
        at so.uru.DBHelperNoRowid.insertUsingConvenienceInsert(DBHelperNoRowid.java:42)
        at so.uru.MainActivity.logInsertResult(MainActivity.java:23)
        at so.uru.MainActivity.onCreate(MainActivity.java:17)
        at android.app.Activity.performCreate(Activity.java:7136)
        at android.app.Activity.performCreate(Activity.java:7127)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-01-23 19:49:51.918 24876-24876/so.uru D/INSERTRESULT: Insertion of a row returned -1

用于测试混合rowid和不包含表的代码

  • 请注意,以下只是用于测试的多个排列之一:-

DBHelperBoRowid.java

public class DBHelperNoRowid extends SQLiteOpenHelper {

    public final static String DB = "test_norowid";
    public static final int VERSION = 1;
    public static final String TBL_NOROWID = "norowid";
    public static final String COL_ID = BaseColumns._ID;
    public static final String COL_MYDATA = "mydata";
    public static final String TBL_WITHROWID = "withrowid";

    SQLiteDatabase mDB;

    public DBHelperNoRowid(Context context) {
        super(context, DB, null, VERSION);
        mDB = this.getWritableDatabase();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String crt_norowid_table = "CREATE TABLE IF NOT EXISTS " + TBL_NOROWID + "(" +
                COL_ID + " INTEGER PRIMARY KEY, " +
                COL_MYDATA + " TEXT" +
                ") WITHOUT ROWID";
        db.execSQL(crt_norowid_table);
        String crt_withrowid_table = "CREATE TABLE IF NOT EXISTS " + TBL_WITHROWID + "(" +
                COL_ID + " INTEGER PRIMARY KEY, " +
                COL_MYDATA + " TEXT" +
                ")";
        db.execSQL(crt_withrowid_table);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    public long insertUsingConvenienceInsert(long not_an_id, String text, boolean without_rowid, boolean generate_rowid) {
        ContentValues cv = new ContentValues();
        String table = TBL_WITHROWID;
        if (without_rowid) {
            table = TBL_NOROWID;
            cv.put(COL_ID,not_an_id);
        } else {
            if (generate_rowid) {
                cv.put(COL_ID,not_an_id);
            }
        }
        cv.put(COL_MYDATA,text);
        return mDB.insert(table,null,cv);
    }

    public void logLastInsertId() {
        Cursor csr = mDB.rawQuery("SELECT last_insert_rowid()",null);
        if (csr.moveToFirst()) {
            Log.d("LASTINSERTEDROWID","The Last RowID inserted was " + String.valueOf(csr.getLong(0)));
        } else {
            Log.d("LASTINSERTEDROWID","Ooops there does not appear to have been a row inserted");
        }
    }
}

MainActivity.java(根据最后使用的排列)

public class MainActivity extends AppCompatActivity {

    DBHelperNoRowid mDBhlpr;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDBhlpr = new DBHelperNoRowid(this);
        // Insert some rows into the table that is a rowid table
        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);
        logInsertResult(-1,"row 1",false,true);

        logInsertResult(2100L,"row 1",true,true); //<<<<<<<<<< WITHOUT

        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);

        logInsertResult(-898765432,"row 2",true,true); //<<<<<<<<<< WITHOUT

        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);
        logInsertResult(1,"row 1",false,false);

        logInsertResult(-1L,"3rd row",true,true); //<<<<<<<<<< WITHOUT
    }

    private void logInsertResult(long no_an_id, String text, boolean without_rowid, boolean generate_rowid) {

        if (without_rowid) {
            Log.d("INSERTRESULT",">>>>>>>>>> WITHOUT ROWID ATTEMPT");
        }

        Log.d("INSERTRESULT","Insertion of a row returned " + String.valueOf(
                mDBhlpr.insertUsingConvenienceInsert(no_an_id,text,without_rowid,generate_rowid)
        ));
        mDBhlpr.logLastInsertId(); //
    }
}