在MySQL中,你可以像这样插入多行:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2');
然而,当我尝试这样做时,我得到了一个错误。是否可以在SQLite数据库中一次插入多行?这样做的语法是什么?
在MySQL中,你可以像这样插入多行:
INSERT INTO 'tablename' ('column1', 'column2') VALUES
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2'),
('data1', 'data2');
然而,当我尝试这样做时,我得到了一个错误。是否可以在SQLite数据库中一次插入多行?这样做的语法是什么?
当前回答
更新
正如BrianCampbell在这里指出的,SQLite 3.7.11及以上版本现在支持原始帖子更简单的语法。但是,如果您希望在遗留数据库之间实现最大的兼容性,则所示的方法仍然是合适的。
原来的答案
如果我有特权,我会bump river的回复:你可以在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加载大型数据集。然而,正如Jaime Cook指出的那样,在单个事务中封装单个insert并不明显更快:
BEGIN TRANSACTION;
INSERT INTO 'tablename' table VALUES ('data1', 'data2');
INSERT INTO 'tablename' table VALUES ('data3', 'data4');
...
COMMIT;
如果你的目标是提高效率,你应该先试试这个。
关于UNION vs UNION ALL的说明
正如一些人评论的那样,如果使用UNION ALL(如上所示),将插入所有行,因此在本例中,您将得到data1、data2的四行。如果省略ALL,那么重复的行将被消除(并且操作可能会稍微慢一些)。我们使用UNION ALL,因为它更接近原始帖子的语义。
在关闭
附注:请+1条河流的回复,因为它先提出了解决方案。
其他回答
正如其他人所说,SQLite不支持这种语法。我不知道复合insert是否是SQL标准的一部分,但根据我的经验,它们在许多产品中都没有实现。
顺便说一句,您应该意识到,如果在显式事务中包装多个INSERT, SQLite中的INSERT性能将大大提高。
如果你正在使用bash shell,你可以使用这个:
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;
它是如何工作的? 它使用if表选项卡:
id int
------
1
2
然后从TAB a中选择a.id, b.id, 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行
第三次之后,我们插入大约max(1000^ 3,5e5)=500000行,依此类推……
这是我所知道的填充SQLite数据库的最快方法。
根据本页,不支持:
2007-12-03:不支持多行插入,也就是复合插入。
INSERT INTO table (col1, col2) VALUES
('row1col1', 'row1col2'), ('row2col1', 'row2col2'), ...
实际上,根据SQL92标准,VALUES表达式应该能够独立存在。例如,下面应该返回一个三行的单列表:VALUES 'john', 'mary', 'paul';
从3.7.11版本开始,SQLite支持多行插入。Richard Hipp评论道:
新的多值插入词仅仅是该复合词的句法糖(sic) 插入。无论如何,这都没有性能优势。”
INSERT INTO tabela(coluna1,coluna2)
SELECT 'texto','outro'
UNION ALL
SELECT 'mais texto','novo texto';
我能够使查询动态。这是我的桌子:
创造可写的“tblPlanner”文本。
我得到所有的数据通过一个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中保存所有内容。
在此之前,我使工会查询东西动态,但开始给一些语法错误。不管怎样,这对我来说很好。