24

Androidデータベースの挿入速度を改善しようとしています。私が現在行っているのは、次のような文字列を生成することです。

SELECT ? as title, ? as musician_id, ? as album_id, ? as genre
UNION SELECT ?, ?, ?, ?
UNION SELECT ?, ?, ?, ?
UNION SELECT ?, ?, ?, ?
UNION SELECT ?, ?, ?, ?
UNION SELECT ?, ?, ?, ?

そしてそれを実行します

SQLiteDatabase database = //initialized in some way
String insertQuery; // the string of the query above
String [] parameters; // the parameters to use in the insertion.
database.execSQL(insertQuery.toString(), parameters);

約2000行を挿入しようとすると、次のエラーが発生します。

Caused by: android.database.sqlite.SQLiteException: too many SQL variables (code 1): , while compiling: INSERT INTO songs (title, musician_id, album_id, genre)
SELECT ? as title, ? as musician_id, ? as album_id, ? as genre
UNION SELECT ?, ?, ?, ?
UNION SELECT ?, ?, ?, ?

約200行を挿入しようとすると、すべてが正常に機能します。

当たり前のことだと思います。1つの変数に渡そうとしている変数が多すぎますexecSQL。挿入した行を適切なバッチに分割できるようにするための制限を知っている人はいますか?

4

2 に答える 2

37

制限はsqlite3.cにハードコーディングされており、999に設定されています。残念ながら変更できますが、コンパイル時のみです。関連するスニペットは次のとおりです。

/*
** The maximum value of a ?nnn wildcard that the parser will accept.
*/
#ifndef SQLITE_MAX_VARIABLE_NUMBER
# define SQLITE_MAX_VARIABLE_NUMBER 999
#endif


/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits.  But if SQLITE_MAX_VARIABLE_NUMBER is greater
** than 32767 we have to make it 32-bit.  16-bit is preferred because
** it uses less memory in the Expr object, which is a big memory user
** in systems with lots of prepared statements.  And few applications
** need more than about 10 or 20 variables.  But some extreme users want
** to have prepared statements with over 32767 variables, and for them
** the option is available (at compile-time).
*/
#if SQLITE_MAX_VARIABLE_NUMBER<=32767
typedef i16 ynVar;
#else
typedef int ynVar;
#endif
于 2013-03-09T17:06:13.680 に答える
15

私は私のAndroidデータベースの挿入の速度を改善しようとしています。私が現在行っているのは、次のような文字列を生成することです。

使用を考えましたTRANSACTIONか?私はあなたがあなたのアプローチの代わりにそれを使うことを提案します。UNIONuse句は「勝利」ではなく、それを達成するためのより良い、主に安全な方法があると思います。

db.beginTransaction();
try {
   for (int i = 0 ; i < length ; i++ ) { // or another kind of loop etc.
     // make insert actions
   }
   db.setTransactionSuccessful(); // now commit changes
}
finally {
    db.endTransaction();
}
于 2013-03-09T16:50:08.287 に答える