В MySQL вы можете вставить несколько строк следующим образом:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2');
Тем не менее, я получаю сообщение об ошибке, когда пытаюсь сделать что-то подобное. Можно ли вставлять сразу несколько строк в базу данных SQLite? Каков синтаксис для этого?
Как BrianCampbell указывает здесь, SQLite 3.7.11 и выше теперь поддерживает более простой синтаксис исходного сообщения. Тем не менее, показанный подход по-прежнему подходит, если требуется максимальная совместимость между устаревшими базами данных.
Если бы у меня были привилегии, я бы bump andy reply: вы можете вставлять несколько строк в SQLite, вам просто нужно другое синтаксис. Чтобы сделать это совершенно ясно, пример OPs MySQL:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2');
Это можно переделать в SQLite как:
INSERT INTO 'tablename'
SELECT 'data1' AS 'column1', 'data2' AS 'column2'
UNION ALL SELECT 'data1', 'data2'
UNION ALL SELECT 'data1', 'data2'
UNION ALL SELECT 'data1', 'data2'
Я изначально использовал этот метод для эффективной загрузки больших наборов данных из Ruby on Rails. Тем не менее, как указывает Хайме Кук, это не ясно, что это какая-то более быстрая упаковка INSERTs
в рамках одной транзакции:
BEGIN TRANSACTION;
INSERT INTO 'tablename' table VALUES ('data1', 'data2');
INSERT INTO 'tablename' table VALUES ('data3', 'data4');
...
COMMIT;
Если эффективность является вашей целью, вы должны попробовать это в первую очередь.
Как прокомментировали несколько человек, если вы используете UNION ALL
(как показано выше), все строки будут вставлены, поэтому в этом случае вы получите четыре строки data1, data2
. Если вы опустите ALL
, то повторяющиеся строки будут удалены (и операция, вероятно, будет немного медленнее). Мы используем UNION ALL, так как он более точно соответствует семантике исходного сообщения.
P.S.: Пожалуйста, +1 andy reply, а не мой! Сначала он представил решение.
Да, это возможно, но не с обычными значениями вставки, разделенными запятыми.
Попробуйте это...
insert into myTable (col1,col2)
select aValue as col1,anotherValue as col2
union select moreValue,evenMoreValue
union...
Да, это немного уродливое, но достаточно легкое, чтобы автоматизировать генерацию инструкции из набора значений. Кроме того, кажется, вам нужно только объявить имена столбцов в первом выборе.
UNION ALL
не UNION
. За исключением случаев, когда вы хотите удалить дубликаты.
Да, с SQLite 3.7.11 это поддерживается в SQLite. Из документации SQLite:
(когда этот ответ был изначально написан, это не поддерживалось)
Для совместимости со старыми версиями SQLite вы можете использовать трюк, предложенный andy и fearless_fool, используя UNION
, но для 3.7.11 и более поздних версий предпочтительным является более простой синтаксис, описанный здесь.
VALUES
есть замкнутый цикл с запятой вне скобок.
Я написал некоторый код ruby для создания единственной вставки из нескольких строк из 500 элементов из ряда операторов вставки, которые были значительно быстрее, чем запуск отдельных вставок. Затем я попробовал просто обернуть несколько вложений в одну транзакцию и обнаружил, что могу получить такую же скорость с гораздо меньшим количеством кода.
BEGIN TRANSACTION;
INSERT INTO table VALUES (1,1,1,1);
INSERT INTO table VALUES (2,2,2,2);
...
COMMIT;
В соответствии с эта страница не поддерживается:
- 2007-12-03: Многострочный INSERT a.k.a. соединение INSERT не поддерживается.
INSERT INTO table (col1, col2) VALUES
('row1col1', 'row1col2'), ('row2col1', 'row2col2'), ...
Собственно, согласно стандарту SQL92, выражение VALUES должно быть в состоянии стоять на себе. Например, следующее должно возвращать таблицу с одним столбцом с тремя строками:
VALUES 'john', 'mary', 'paul';
Начиная с версии 3.7.11 SQLite поддерживает multi-row-insert. Ричард Хипп:
"Новая многозначная вставка представляет собой просто синтаксический шунг (sic) для соединения вставить. Преимущество производительности не существует так или иначе".
Начиная с версии 2012-03-20 (3.7.11), sqlite поддерживает следующий синтаксис INSERT:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
('data1', 'data2'),
('data3', 'data4'),
('data5', 'data6'),
('data7', 'data8');
Прочитайте документацию: http://www.sqlite.org/lang_insert.html
PS: Пожалуйста, +1 к Брайану Кэмпбеллу ответ/ответ. не мой! Сначала он представил решение.
Как и другие плакаты, SQLite не поддерживает этот синтаксис. Я не знаю, являются ли составные INSERT частью стандарта SQL, но по моему опыту они не реализованы во многих продуктах.
В стороне, вы должны знать, что производительность INSERT в SQLite значительно улучшена, если вы переносите несколько INSERT в явную транзакцию.
Да, sql может это сделать, но с другим синтаксисом. Между прочим, документация sqlite. Он также скажет вам, что единственный способ вставить несколько строк - использовать оператор select в качестве источника данных для ввода.
Sqlite3 не может делать это непосредственно в SQL, кроме как через SELECT, и пока SELECT может возвращать "строку" выражений, я не знаю, как заставить его возвращать фальшивый столбец.
Однако CLI может это сделать:
.import FILE TABLE Import data from FILE into TABLE
.separator STRING Change separator used by output mode and .import
$ sqlite3 /tmp/test.db
SQLite version 3.5.9
Enter ".help" for instructions
sqlite> create table abc (a);
sqlite> .import /dev/tty abc
1
2
3
99
^D
sqlite> select * from abc;
1
2
3
99
sqlite>
Если вы наложили цикл на INSERT, а не на команду CLI .import
, то обязательно следуйте советам в часто задаваемом FAQ sqlite для скорости INSERT:
По умолчанию каждый оператор INSERT его собственная сделка. Но если ты объединить несколько инструкций INSERT с BEGIN... COMMIT, тогда все вставки сгруппированы в один сделка. Время, необходимое для фиксации транзакция амортизируется по всем прилагаемые вставки и так далее время для инструкции вставки значительно сокращается.
Другой вариант - запустить PRAGMA синхронное = OFF. Эта команда будет заставить SQLite не ждать данных достигнуть поверхности диска, сделать операции записи кажутся намного быстрее. Но если вы потеряете власть в в середине транзакции, файл базы данных может испортиться.
.import
, это просто цикл, считывающий строку из входного файла (или tty), а затем оператор INSERT для этой строки. К сожалению, не значительно улучшена эффективность.
fearless_fool имеет отличный ответ для более старых версий. Я просто хотел добавить, что вам нужно убедиться, что все столбцы перечислены. Итак, если у вас есть 3 столбца, вам нужно убедиться, что select действует на 3 столбца.
Пример: у меня есть 3 столбца, но я хочу только вставить 2 столбца данных. Предположим, что я не забочусь о первом столбце, потому что это стандартный идентификатор целого числа. Я мог бы сделать следующее...
INSERT INTO 'tablename'
SELECT NULL AS 'column1', 'data1' AS 'column2', 'data2' AS 'column3'
UNION SELECT NULL, 'data3', 'data4'
UNION SELECT NULL, 'data5', 'data6'
UNION SELECT NULL, 'data7', 'data8'
Примечание. Помните, что оператор "select... union" потеряет порядок. (Из AG1)
Алекс прав: оператор "select... union" потеряет порядок, который очень важен для некоторых пользователей. Даже когда вы вставляете в определенном порядке, sqlite меняет настройки, поэтому предпочитайте использовать транзакции, если важно иметь порядок вставки.
create table t_example (qid int not null, primary key (qid));
begin transaction;
insert into "t_example" (qid) values (8);
insert into "t_example" (qid) values (4);
insert into "t_example" (qid) values (9);
end transaction;
select rowid,* from t_example;
1|8
2|4
3|9
INSERT INTO TABLE_NAME
(DATA1,
DATA2)
VALUES (VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2),
(VAL1,
VAL2);
в mysql lite вы не можете вставить несколько значений, но вы можете сэкономить время, открыв соединение только один раз, а затем выполнив все вставки и затем закрыв соединение. Это экономит много времени
Ты не можешь, но я не думаю, что ты что-то пропускаешь.
Поскольку вы вызываете sqlite всегда в процессе, почти не важно, выполняете ли вы 1 инструкцию insert или 100 операторов insert. Однако фиксация занимает много времени, поэтому ставьте эти 100 вставок внутри транзакции.
Sqlite намного быстрее, когда вы используете параметризованные запросы (гораздо меньше требуется синтаксический анализ), поэтому я бы не стал конкатенацией больших операторов вроде этого:
insert into mytable (col1, col2)
select 'a','b'
union
select 'c','d'
union ...
Их нужно разбирать снова и снова, потому что каждое конкатенированное утверждение отличается.
Начиная с версии 3.7.11 SQLite поддерживает многорядную вставку. Ричард Hipp комментарии:
Я использую 3.6.13
Я командую следующим образом:
insert into xtable(f1,f2,f3) select v1 as f1, v2 as f2, v3 as f3
union select nextV1+, nextV2+, nextV3+
С 50 записями за один раз, это занимает всего секунду или меньше.
Это правда, что использование sqlite для вставки нескольких строк за один раз очень возможно. Автор @Andy написал.
спасибо Andy +1
Проблема с использованием транзакции заключается в том, что вы блокируете таблицу и для чтения. Поэтому, если у вас действительно много данных для вставки, и вам нужно получить доступ к вашим данным, например, предварительный просмотр или так, этот способ не работает.
Проблема с другим решением заключается в том, что вы теряете порядок вставки
insert into mytable (col)
select 'c'
union
select 'd'
union
select 'a'
union
select 'b';
В sqlite будут храниться данные a, b, c, d...
INSERT INTO tabela(coluna1,coluna2)
SELECT 'texto','outro'
UNION ALL
SELECT 'mais texto','novo texto';
Я могу сделать запрос динамическим. Это моя таблица:
CREATE TABLE "tblPlanner" ("probid" text,"userid" TEXT,"selectedtime" DATETIME,"plannerid" TEXT,"isLocal" BOOL,"applicationid" TEXT, "comment" TEXT, "subject" TEXT)
и я получаю все данные через JSON
, поэтому после получения всего внутри NSArray
я следил за этим:
NSMutableString *query = [[NSMutableString alloc]init];
for (int i = 0; i < arr.count; i++)
{
NSString *sqlQuery = nil;
sqlQuery = [NSString stringWithFormat:@" ('%@', '%@', '%@', '%@', '%@', '%@', '%@', '%@'),",
[[arr objectAtIndex:i] objectForKey:@"plannerid"],
[[arr objectAtIndex:i] objectForKey:@"probid"],
[[arr objectAtIndex:i] objectForKey:@"userid"],
[[arr objectAtIndex:i] objectForKey:@"selectedtime"],
[[arr objectAtIndex:i] objectForKey:@"isLocal"],
[[arr objectAtIndex:i] objectForKey:@"subject"],
[[arr objectAtIndex:i] objectForKey:@"comment"],
[[NSUserDefaults standardUserDefaults] objectForKey:@"applicationid"]
];
[query appendString:sqlQuery];
}
// REMOVING LAST COMMA NOW
[query deleteCharactersInRange:NSMakeRange([query length]-1, 1)];
query = [NSString stringWithFormat:@"insert into tblPlanner (plannerid, probid, userid, selectedtime, isLocal, applicationid, subject, comment) values%@",query];
И, наконец, выходной запрос таков:
insert into tblPlanner (plannerid, probid, userid, selectedtime, isLocal, applicationid, subject, comment) values
<append 1>
('pl1176428260', '', 'US32552', '2013-06-08 12:00:44 +0000', '0', 'subj', 'Hiss', 'ap19788'),
<append 2>
('pl2050411638', '', 'US32552', '2013-05-20 10:45:55 +0000', '0', 'TERI', 'Yahoooooooooo', 'ap19788'),
<append 3>
('pl1828600651', '', 'US32552', '2013-05-21 11:33:33 +0000', '0', 'test', 'Yest', 'ap19788'),
<append 4>
('pl549085534', '', 'US32552', '2013-05-19 11:45:04 +0000', '0', 'subj', 'Comment', 'ap19788'),
<append 5>
('pl665538927', '', 'US32552', '2013-05-29 11:45:41 +0000', '0', 'subj', '1234567890', 'ap19788'),
<append 6>
('pl1969438050', '', 'US32552', '2013-06-01 12:00:18 +0000', '0', 'subj', 'Cmt', 'ap19788'),
<append 7>
('pl672204050', '', 'US55240280', '2013-05-23 12:15:58 +0000', '0', 'aassdd', 'Cmt', 'ap19788'),
<append 8>
('pl1019026150', '', 'US32552', '2013-06-08 12:15:54 +0000', '0', 'exists', 'Cmt', 'ap19788'),
<append 9>
('pl790670523', '', 'US55240280', '2013-05-26 12:30:21 +0000', '0', 'qwerty', 'Cmt', 'ap19788')
который хорошо работает и с кодом, и я могу успешно сохранить все в SQLite.
До этого я произвел UNION
материал запроса динамический, но это начало давать некоторую синтаксическую ошибку. В любом случае, это работает хорошо для меня.
В sqlite 3.7.2:
INSERT INTO table_name (column1, column2)
SELECT 'value1', 'value1'
UNION SELECT 'value2', 'value2'
UNION SELECT 'value3', 'value3'
и т.д.
У меня есть запрос, как показано ниже, но с драйвером ODBC SQLite имеет ошибку с "," говорится в нем. Я запускаю vbscript в HTA (приложение Html).
INSERT INTO evrak_ilac_iliskileri (evrak_id, ilac_id, baglayan_kullanici_id, tarih) VALUES (4150,762,1,datetime()),(4150,9770,1,datetime()),(4150,6609,1,datetime()),(4150,3628,1,datetime()),(4150,9422,1,datetime())
Если вы используете плагин firefox Sqlite manager, он поддерживает массовые вставки из операторов INSERT
SQL.
Infact это не поддерживает, но Sqlite Browser работает (работает в Windows, OS X, Linux)
Я удивлен, что никто не упомянул о подготовленных заявлениях. Если вы не используете SQL самостоятельно, а не на каком-либо другом языке, я бы подумал, что подготовленные операторы, заключенные в транзакцию, будут наиболее эффективным способом вставки нескольких строк.
вы можете использовать InsertHelper, это легко и быстро
Документация: http://developer.android.com/reference/android/database/DatabaseUtils.InsertHelper.html
Изменить: InsertHelper устарел с уровня API уровня 17
Если вы используете оболочку bash, вы можете использовать это:
time bash -c $'
FILE=/dev/shm/test.db
sqlite3 $FILE "create table if not exists tab(id int);"
sqlite3 $FILE "insert into tab values (1),(2)"
for i in 1 2 3 4; do sqlite3 $FILE "INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5"; done;
sqlite3 $FILE "select count(*) from tab;"'
Или, если вы находитесь в sqlite CLI, вам нужно сделать это:
create table if not exists tab(id int);"
insert into tab values (1),(2);
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
INSERT INTO tab (id) select (a.id+b.id+c.id)*abs(random()%1e7) from tab a, tab b, tab c limit 5e5;
select count(*) from tab;
Как это работает?
Он использует это, если таблица tab
:
id int
------
1
2
затем select a.id, b.id from tab a, tab b
возвращает
a.id int | b.id int
------------------
1 | 1
2 | 1
1 | 2
2 | 2
и т.д. После первого выполнения мы вставляем 2 строки, затем 2 ^ 3 = 8. (три, потому что у нас tab a, tab b, tab c
)
После второго выполнения мы вставляем дополнительные строки (2+8)^3=1000
Aftern thrid вставляем строки max(1000^3, 5e5)=500000
и так далее...
Это самый быстрый для меня способ заполнения базы данных SQLite.