Каков предел переменных SQL, которые можно указать в одном запросе execSQL
Я пытаюсь улучшить скорость вставки моей базы данных 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 строк, все работает нормально.
Я предполагаю, что это очевидно - я пытаюсь передать слишком много переменных в одном execSQL
. Кто-нибудь знает, каков предел, чтобы я мог разбить строки, которые я вставляю в соответствующие партии?
Ответы
Ответ 1
Предел жестко закодирован в 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
Ответ 2
Я пытаюсь улучшить скорость вставки моей базы данных Android.. Какие В настоящее время я создаю строку вроде:
Думали ли вы об использовании TRANSACTION
? Я предлагаю вам использовать его вместо вашего подхода. Я думаю, что использование предложения UNION
не является "победой" вообще, и есть лучший и в основном более безопасный способ его достижения.
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();
}