我有一张下表:
文件夹ID | 文件夹路径 |
---|---|
1 | “C:\用户\奥巴马” |
2 | “C:\用户名” |
这里,folderId 是一个自增键。 现在,插入表有以下步骤: a)检查表中是否存在给定的folderPath。 b)如果给定的folderPath存在,则返回该路径的folderId。 c)如果folderPath不存在,则将该folderPath插入表中并返回其folderId(最后插入的rowId)
我想在单个 SQlite 查询中添加上述步骤以获得更好的性能。 我是 sqlite 的新手,因此我们将不胜感激。 谢谢
我尝试为上述步骤创建一个 SQLite 查询。 我的期望是通过单个查询来获得更好的性能。
简而言之,您无法在单个查询中完成上述所有操作。 SQLite 一次只能处理一条语句。您始终需要 2 条陈述:-
一个用于插入或不插入,另一个用于查询表以获得id(反之亦然,即先查询然后插入或不插入)。
但是,
SQLiteDatabase
的insert
方法在幕后执行插入操作并获取rowid或其别名(其中folderId列是根据您的问题生成的id)。
此外,
SQLiteDatabase
的insert
方法使用INSERT OR IGNORE ....
。因此,如果存在唯一约束冲突,则不会失败。
出于这些原因,使用
SQliteDatabase
的便利 insert
方法以及在folderPath 列上拥有唯一索引可能是最简单的方法。
就性能而言,如果一次执行多个插入,您应该考虑在单个事务中包装插入。
以下是根据您的问题中提供的信息进行的工作演示:-
DBOpenHelper(特别值得注意的是
insertOrNotFolderReturningFolderId
方法)
class DBOpenHelper extends SQLiteOpenHelper {
/* DATABASE VALUES (constants)*/
public static final String DATABASE_NAME = "the_database.db";
public static final int DATABASE_VERSION = 1;
/* FOLDER TABLKE VALUES (constants) */
public static final String FOLDER_TABLE_NAME = "folder";
public static final String FOLDER_TABLE_COLUMN_FOLDERID = "folderId";
public static final String FOLDER_TABLE_COLUMN_FOLDERPATH = "folderPath";
/*
The Table create SQL noting the UNIQUE index on the folderPath column
*/
private static final String FOLDER_TABLE_CREATE_SQL =
"CREATE TABLE IF NOT EXISTS " + FOLDER_TABLE_NAME + "(" +
FOLDER_TABLE_COLUMN_FOLDERID + " INTEGER PRIMARY KEY " +
"," + FOLDER_TABLE_COLUMN_FOLDERPATH + " TEXT UNIQUE " +
")";
private volatile static DBOpenHelper instance;
public static DBOpenHelper getInstance(Context context) {
if (instance==null) {
instance = new DBOpenHelper(context);
}
return instance;
}
private DBOpenHelper(Context context) {
super(context,DATABASE_NAME,null,DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(FOLDER_TABLE_CREATE_SQL);
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
}
public long insertOrNotFolderReturningFolderId(String folderPath) {
long rv;
ContentValues cv = new ContentValues();
cv.put(FOLDER_TABLE_COLUMN_FOLDERPATH,folderPath);
SQLiteDatabase db = this.getWritableDatabase();
rv = db.insert(FOLDER_TABLE_NAME,null,cv);
if (rv < 0) {
/* use the DatabaseUtils longForQuery to get the id (no need to manage a Cursor)*/
rv = DatabaseUtils.longForQuery(
db,
"SELECT " + FOLDER_TABLE_COLUMN_FOLDERID +
" FROM " + FOLDER_TABLE_NAME +
" WHERE " + FOLDER_TABLE_COLUMN_FOLDERPATH + "=?",
new String[]{folderPath}
);
}
return rv;
}
}
实际演示以下活动代码:-
public class MainActivity extends AppCompatActivity {
DBOpenHelper helper;
/* folders to test (with duplicates on purpose) */
String[] testlist = new String[]{
"C:\\Users\\obama",
"C:\\Users\\biden",
"C:\\Users\\fred",
"C:\\Users\\obama",
"C:\\Users\\biden",
"C:\\Users\\fred",
"C:\\Users\\obama"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
helper = DBOpenHelper.getInstance(this);
SQLiteDatabase db = helper.getWritableDatabase();
db.beginTransaction();
/* insert rows as per the testlist */
for (String folderPath: testlist) {
long folderId = helper.insertOrNotFolderReturningFolderId(folderPath);
Log.d("DBINFO","Folder " + folderPath + " has an ID of " + folderId);
}
db.setTransactionSuccessful();
db.endTransaction();
/* Extract ALL rows and write to the log */
Cursor csr = helper.getWritableDatabase().query(DBOpenHelper.FOLDER_TABLE_NAME,null,null,null,null,null,null);
int folderIdIx = csr.getColumnIndex(DBOpenHelper.FOLDER_TABLE_COLUMN_FOLDERID);
int folderPathIx = csr.getColumnIndex(DBOpenHelper.FOLDER_TABLE_COLUMN_FOLDERPATH);
while (csr.moveToNext()) {
Log.d("DBINFO","FolderID=" + csr.getLong(folderIdIx) + "FolderPath=" + csr.getString(folderPathIx));
}
csr.close();
}
}
结果输出到日志:-
2023-11-01 07:38:22.749 D/DBINFO: Folder C:\Users\obama has an ID of 1
2023-11-01 07:38:22.749 D/DBINFO: Folder C:\Users\biden has an ID of 2
2023-11-01 07:38:22.750 D/DBINFO: Folder C:\Users\fred has an ID of 3
2023-11-01 07:38:22.753 D/DBINFO: Folder C:\Users\obama has an ID of 1
2023-11-01 07:38:22.755 D/DBINFO: Folder C:\Users\biden has an ID of 2
2023-11-01 07:38:22.764 D/DBINFO: Folder C:\Users\fred has an ID of 3
2023-11-01 07:38:22.769 D/DBINFO: Folder C:\Users\obama has an ID of 1
2023-11-01 07:38:22.773 D/DBINFO: FolderID=1FolderPath=C:\Users\obama
2023-11-01 07:38:22.773 D/DBINFO: FolderID=2FolderPath=C:\Users\biden
2023-11-01 07:38:22.773 D/DBINFO: FolderID=3FolderPath=C:\Users\fred
即在测试列表中的 7 次尝试插入中,仅存在 3 行(最后一部分),但已返回相应的文件夹 ID(第一部分)