Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / SQLite Новый топик    Ответить
 Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
Завис в С++ на примитивной вещи. Не могу передать массив double rt[N][5] в таблицу SQLite.
Запрос простой - const char* INS = " insert into foo values(1, 2, 3, 4, 5 );"; Все работает.
Как сформировать строку этого запроса, с элементами массива rt? Или ссылку на инет, где это описано.
Все как-то с Питон или С#, а c С++ c БД не приходилось.(
8 июн 19, 22:28    [21905257]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
White Owl
Member

Откуда:
Сообщений: 12405
Читать здесь: https://www.sqlite.org/c3ref/stmt.html
9 июн 19, 03:17    [21905291]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
Dima T
Member

Откуда:
Сообщений: 14031
Лучше параметризованный запрос как выше посоветовали. Еще можно сформировать свой инсерт, читай про snprintf()
9 июн 19, 14:17    [21905440]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
Не пойму, чего она от меня хочет?
double a = 1.23456;
	const char* QW = "begin; insert into foo(a0) values( ? ); commit;";
	sqlite3_stmt *ppStmt;
	const char      *tail;
	int er;
	er=sqlite3_prepare_v2(db, QW,1000, &ppStmt, &tail);
	printf(" Err1 %d \n", er);
	er=sqlite3_bind_double(ppStmt, 1, a);
	printf(" Err2 %d \n", er);
	er=sqlite3_step(ppStmt);
	printf(" Err3 %d \n", er);
	er=sqlite3_step(ppStmt); //?
	printf(" Err4 %d \n", er);
	er=sqlite3_step(ppStmt); //?
	printf(" Err5 %d \n", er);
	er=sqlite3_reset(ppStmt);
	printf(" Err6 %d \n", er);
	er=sqlite3_finalize(ppStmt);
	printf(" Err7 %d \n", er);

Коды ощибок
Err1 0
 Err2 25
 Err3 101
 Err4 1
 Err5 1
 Err6 1
 Err7 0
Err2 25 - (25) SQLITE_RANGE
Ошибка SQLITE_RANGE указывает на то, что аргумент номера параметра одной из подпрограмм sqlite3_bind или номер столбца в одной из подпрограмм sqlite3_column находится вне допустимого диапазона.
Не понимаю, что она хочет?
9 июн 19, 16:19    [21905461]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
Предыдущий вопрос снят. Изменен запрос, исключен begin;
В пакете ? не работает.
9 июн 19, 17:00    [21905470]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
Вопрос решен.
Полностью рабочий код
const char* QW = "insert into foo(a0,a1,a2,a3,a4) values( ?, ?, ?, ?, ? );";
	double rt[10000][5]; //инициализация массива опущена
        sqlite3_stmt *ppStmt;
	const char      *tail;
	int er;
	i = 0;  j = 0;
	
	er = sqlite3_prepare_v2(db, "begin;", 10, &ppStmt, &tail);
	printf(" ErrBeg %d \n", er);
	er = sqlite3_step(ppStmt);
	printf(" ErrBeg2 %d \n", er);
	for (i = 0;i < 100;i++)
	{
		        er = sqlite3_prepare_v2(db, QW, 1000, &ppStmt, &tail);
			printf(" Err1 %d \n", er);
			er = sqlite3_bind_double(ppStmt, 1, rt[i][j]);
			printf(" Err2.0 %d \n", er);
			er = sqlite3_bind_double(ppStmt, 2, rt[i][j + 1]);
			printf(" Err2.1 %d \n", er);
			er = sqlite3_bind_double(ppStmt, 3, rt[i][j + 2]);
			printf(" Err2.2 %d \n", er);
			er = sqlite3_bind_double(ppStmt, 4, rt[i][j + 3]);
			printf(" Err2.3 %d \n", er);
			er = sqlite3_bind_double(ppStmt, 5, rt[i][j + 4]);
			printf(" Err2.4 %d \n", er);
			er = sqlite3_step(ppStmt);
			printf(" Err3 %d \n", er);
			er = sqlite3_reset(ppStmt);
	}
	
        printf(" Err6 %d \n", er);
	er = sqlite3_prepare_v2(db, "commit;", 10, &ppStmt, &tail);
	printf(" ErrCom %d \n", er);
	er = sqlite3_step(ppStmt);
	er = sqlite3_finalize(ppStmt);
	printf(" Err7 %d \n", er);
	printf(" ErrCom2 %d \n", er);
printf() вставлены для отладки.
9 июн 19, 20:29    [21905515]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7933
Жесть какая. Почему prepare ВНУТРИ цикла?
Весь смысл в Prepared Statements в том, что их заранее подготовливают.

p.s. SQLLite использовал (Java), но C API не пользовался
10 июн 19, 15:53    [21906012]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
Leonid Kudryavtsev, не вижу никакой жести. Не надо драматизировать ситуацию.)
Задача стояла разобраться с С-API SQLite и сделать рабочую конструкцию. Далее, совершенству нет предела.
Следующим этапом в том числе и запланировано вынесение sqlite3_prepare_v2 и sqlite3_reset за пределы цикла.
Пока весь проект делается для оценки быстродействия SQLite через интерфейс C/C++ и возможностей его повышения в разумных пределах. После чего будет рассматриваться вопрос применимости для конкретных целей.
PS Интересно, кстати, что в инете большинство пишут данные в таблицы SQLite через char*. Возможно плохо искал, но экземплы с использованием sqlite3_bind_ не попадались.
10 июн 19, 18:05    [21906116]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7933
IMHO prepare внутри цикла, полное не понимание для чего же этот самый prepare делается
+

https://www.sqlite.org/c3ref/stmt.html

Prepared Statement Object
...
1 Create the prepared statement object using sqlite3_prepare_v2().
2 Bind values to parameters using the sqlite3_bind_*() interfaces.
3 Run the SQL by calling sqlite3_step() one or more times.
4 Reset the prepared statement using sqlite3_reset() then go back to step 2. Do this zero or more times.

6 Destroy the object using sqlite3_finalize().
...


Пока весь проект делается для оценки быстродействия

Тогда жесть вдвойне. Оценивать быстродействие по изначально кривому коду.
Вы бы еще ф-цию sleep в "тест для быстродействия" запихали )))
10 июн 19, 18:43    [21906145]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
Leonid Kudryavtsev, все, что вы пишите, мне уже известно. И ранее уже сделано.
Кстати, вынос prepare за пределы цикла ничего существенного не дал. Что-то в пределах погрешности измерений.
10 июн 19, 19:21    [21906159]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
Фрагмент последней версии кода записи массива в БД с вынесенным за пределы цикла sqlite3_prepare_v2.
double rt[10000][5];
int i, j;
const char* QW = "insert into foo(a0,a1,a2,a3,a4) values( ?, ?, ?, ?, ? );";
sqlite3_stmt *ppStmt;
const char      *tail;
int er;
i = 0;  j = 0;
t0 = clock();
er = sqlite3_prepare_v2(db, "begin;", 10, &ppStmt, &tail);
er = sqlite3_step(ppStmt);
er = sqlite3_prepare_v2(db, QW, 250, &ppStmt, &tail);
for (i = 0;i < 1000;i++)
	{
	 er = sqlite3_bind_double(ppStmt, 1, rt[i][j]);
	 er = sqlite3_bind_double(ppStmt, 2, rt[i][j + 1]);
	 er = sqlite3_bind_double(ppStmt, 3, rt[i][j + 2]);
	 er = sqlite3_bind_double(ppStmt, 4, rt[i][j + 3]);
	 er = sqlite3_bind_double(ppStmt, 5, rt[i][j + 4]);
	 er = sqlite3_step(ppStmt);
	 er = sqlite3_reset(ppStmt);    
	}
er = sqlite3_prepare_v2(db, "commit;", 10, &ppStmt, &tail);
er = sqlite3_step(ppStmt);
er = sqlite3_finalize(ppStmt);
В смысле быстродействия, как писалось ранее это ничего не дает, и не могло дать, т.к. основное время выполнения запроса занимают дисковые операции.
Уже писал в другой теме, что аналогичная БД в :memory: выполняет этот запрос за 3 мс. Код, приведенный в этом фрагменте и фрагменте выше, за 120-130 мс. На долю sqlite3_prepare_v2 приходится небольшая часть из этих 3 мс, что никак не может влиять на быстродействие программы в целом.
10 июн 19, 22:42    [21906241]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
PS Во всех фрагментах кода инициализация массива double rt[10000][5]; опущена.
10 июн 19, 22:45    [21906242]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7933
YUBA, подозреваю, что auto-commit mode Вы тоже забыли отключить.
Если это так, то нет ничего удивительного, что производительность ниже плинтуса

By default, SQLite is in auto-commit mode. It means that for each command, SQLite starts, processes, and commits the transaction automatically.

http://www.sqlitetutorial.net/sqlite-transaction/
11 июн 19, 14:37    [21906764]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
NewBy52
Member

Откуда: Воронеж
Сообщений: 24
Leonid Kudryavtsev
YUBA, подозреваю, что auto-commit mode Вы тоже забыли отключить.
Если это так, то нет ничего удивительного, что производительность ниже плинтуса

Его не надо специально отключать. При посылке команды
begin transaction
он автоматически отключается.
11 июн 19, 15:15    [21906791]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
Leonid Kudryavtsev
Member

Откуда:
Сообщений: 7933
Тогда у автора результаты замеров скорости какие-то странные.
Файловая БД SQLite в памяти.
11 июн 19, 15:43    [21906815]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
YUBA
Member

Откуда:
Сообщений: 751
NewBy52
Его не надо специально отключать. При посылке команды
begin transaction
он автоматически отключается.
Полагаю, вы несколько отстали от жизни, достаточно просто begin;. См. код, кстати.
11 июн 19, 19:11    [21907011]     Ответить | Цитировать Сообщить модератору
 Re: Как вставить много строк из двумерного массива  [new]
NewBy52
Member

Откуда: Воронеж
Сообщений: 24
YUBA
Полагаю, вы несколько отстали от жизни, достаточно просто begin;. См. код, кстати.

Просто "достаточно". Но ведь не "необходимо и достаточно"?
11 июн 19, 21:49    [21907065]     Ответить | Цитировать Сообщить модератору
Все форумы / SQLite Ответить