query - sqlite官方




是否可以在SQLite數據庫中一次插入多行? (16)

從版本3.7.11開始,SQLite確實支持多行插入。 理查德·希普評論道:

我正在使用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

在MySQL中,你可以像這樣插入多行:

INSERT INTO 'tablename' ('column1', 'column2') VALUES
    ('data1', 'data2'),
    ('data1', 'data2'),
    ('data1', 'data2'),
    ('data1', 'data2');

但是,當我嘗試執行此類操作時,出現錯誤。 是否可以在SQLite數據庫中一次插入多行? 這是什麼語法?


更新

正如BrianCampbell在這裡指出的那樣 , SQLite 3.7.11及更高版本現在支持原始文章的更簡單的語法 。 但是,如果您希望在傳統數據庫之間達到最大的兼容性,則所示方法仍然適用

原始答案

如果我有權限,我會碰到andy的回复 :你可以在SQLite中插入多行,你只需要不同的語法 。 為了使它完全清楚,OP的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指出的那樣 ,目前還不清楚在單個事務中是否有更快的包裝單個INSERTs

BEGIN TRANSACTION;
INSERT INTO 'tablename' table VALUES ('data1', 'data2');
INSERT INTO 'tablename' table VALUES ('data3', 'data4');
...
COMMIT;

如果效率是您的目標,那麼您應該先嘗試一下。

一個關於聯盟vs聯盟所有的說明

正如幾個人所評論的,如果你使用UNION ALL (如上所示),所有的行都會被插入,所以在這種情況下,你會得到四行data1, data2 。 如果你省略了ALL ,那麼重複行將被消除(操作可能會稍微慢一點)。 我們使用UNION ALL,因為它更貼近原始帖子的語義。

關閉

PS:請+1 安迪的回复 ,不是我的! 他首先提出了解決方案。


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命令,那麼一定要按照sqlite FAQ中INSERT速度的建議操作:

默認情況下,每個INSERT語句都是它自己的事務。 但是,如果使用BEGIN ... COMMIT包圍多個INSERT語句,則所有插入操作都會分組到一個事務中。 提交事務所需的時間將在所有隨附的插入語句之間進行攤銷,因此每個插入語句的時間會大大減少。

另一個選項是運行PRAGMA synchronous = OFF。 這個命令將導致SQLite不等待數據到達磁盤表面,這將使寫入操作看起來更快。 但是,如果您在交易中斷電,數據庫文件可能會損壞。


fearless_fool對舊版本有很好的答案。 我只想補充一點,你需要確保列出所有列。 所以如果你有3列,你需要確保在3列上選擇行為。

例如:我有3列,但我只想插入2列數據。 假設我不關心第一列,因為它是一個標準的整數ID。 我可以做以下...

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)


你不能,但我不認為你錯過任何東西。

因為你總是在調用sqlite,所以執行1個插入語句或100個插入語句在性能上幾乎沒有關係。 但是提交需要很多時間,因此將這100個插入放入事務中。

當你使用參數化查詢時,Sqlite會快得多(不需要太多解析),所以我不會像這樣連接大的語句:

insert into mytable (col1, col2)
select 'a','b'
union 
select 'c','d'
union ...

他們需要一次又一次地解析,因為每個連接的語句都是不同的。



在mysql lite中,您無法插入多個值,但只需一次打開連接,然後執行所有插入操作並關閉連接,即可節省時間。 它節省了很多時間


在sqlite 3.7.2上:

INSERT INTO table_name (column1, column2) 
                SELECT 'value1', 'value1' 
          UNION SELECT 'value2', 'value2' 
          UNION SELECT 'value3', 'value3' 

等等


從版本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:請給Brian Campbell的回复/回答+1。 不是我的! 他首先提出了解決方案。


我可以使查詢動態。 這是我的桌子:

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查詢的東西動態,但開始給一些語法錯誤。 無論如何,這對我來說運行良好。


我很驚訝沒有人提到準備好的陳述 。 除非你自己使用SQL而不使用任何其他語言,否則我會認為包裝在事務中的準備好的語句將是插入多行的最有效方式。


我有一個像下面這樣的查詢,但是對於ODBC驅動程序,SQLite在“,”中有一個錯誤。 我在HTA(Html應用程序)中運行vbscript。

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())

是的,從SQLite 3.7.11 ,SQLite支持。 從SQLite文檔

(當這個答案最初被寫入時,這不被支持)

為了與舊版本的SQLite兼容,你可以使用使用UNION的andy和fearless_fool建議的技巧,但對於3.7.11和更高版本,這裡描述的更簡單的語法應該是首選。


是的,這是可能的,但不能用通常的逗號分隔插入值。

嘗試這個...

insert into myTable (col1,col2) 
     select aValue as col1,anotherValue as col2 
     union select moreValue,evenMoreValue 
     union...

是的,這有點難看,但很容易從一組值中自動生成聲明。 此外,它似乎只需要在第一個選擇中聲明列名稱。


正如其他海報所說,SQLite不支持這種語法。 我不知道複合INSERT是否是SQL標準的一部分,但以我的經驗來看,它們並未在許多產品中實現。

順便說一句,你應該知道,如果你在一個顯式事務中包裝多個INSERT,SQLite中的INSERT性能會得到很大的提高。


INSERT INTO TABLE_NAME 
            (DATA1, 
             DATA2) 
VALUES      (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2), 
            (VAL1, 
             VAL2); 




syntax