349

Is the database query faster if I insert multiple rows at once:

like

INSERT....

UNION

INSERT....

UNION

(I need to insert like 2-3000 rows)

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Emma
  • 3,539
  • 3
  • 16
  • 5
  • 8
    UNION is for selects. – Jacob Jul 31 '11 at 11:10
  • 1
    How the rows are coming? Are you directly writing SQL on MySQL Query Browser or using from inside PHP or C# or something else. If you fit in the latter case, then check following links: [The Fastest Way to Insert 100k Records](http://codicesoftware.blogspot.com/2008/04/fastest-way-to-insert-100k-registers.html) [Fast Inserts with Multiple Rows](http://blog.cnizz.com/2010/05/31/optimize-mysql-queries-fast-mutliple-row-inserts/) – RKh Jul 31 '11 at 11:25
  • Fixed second link: [Optimize MySQL Queries — Fast Inserts With Multiple Rows](https://medium.com/@cnizzardini/optimize-mysql-queries-fast-inserts-with-multiple-rows-635d2c5ad5af) – Pavel Shkleinik Mar 20 '18 at 22:32

5 Answers5

1409

INSERT statements that use VALUES syntax can insert multiple rows. To do this, include multiple lists of column values, each enclosed within parentheses and separated by commas.

Example:

INSERT INTO tbl_name
    (a,b,c)
VALUES
    (1,2,3),
    (4,5,6),
    (7,8,9);

Source

leek
  • 11,803
  • 8
  • 45
  • 61
Nicola Cossu
  • 54,599
  • 15
  • 92
  • 98
  • @RPK. I agree with you but I don't know her data source. As I already wrote, if she has a file, I would use load data syntax as cularis suggests. :) – Nicola Cossu Jul 31 '11 at 11:54
  • it's also possible to use `INSERT INTO Table SELECT 1, '14/05/2012', 3 UNION SELECT 2, '05/14/2012', 3`. of course, this will only be better of the inserted values are coming from different tables. – Zohar Peled Jun 01 '15 at 09:18
  • 105
    Helpful reference, because sometimes I just forget simple syntax. – Captain Hypertext Jul 24 '15 at 21:09
  • is a, b and c here temporary variables storing the content of the rows? – Lealo Aug 15 '17 at 16:16
  • 4
    @Lealo no, they are the table column names in which to insert the values in the same order. – BeetleJuice Aug 29 '17 at 13:25
  • Don't forget to that table indexes, specially on large tables, are key to fast updates. It might be more prudent than creating very complex code or insert statements. – sastorsl Jan 16 '19 at 12:39
  • You may also want to see [this answer](https://stackoverflow.com/a/93724/11322237) – Gabriel Arghire Jun 23 '20 at 11:12
  • The issue is how we can automatically take all values in the table and save at one rather than write down these values. Suppose we have a very long table, it will be hard to write these rows one by one. I am stuck this issue too with R language. – Peter Dec 12 '21 at 08:05
64

If you have your data in a text-file, you can use LOAD DATA INFILE.

When loading a table from a text file, use LOAD DATA INFILE. This is usually 20 times faster than using INSERT statements.

Optimizing INSERT Statements

You can find more tips on how to speed up your insert statements on the link above.

Jacob
  • 41,721
  • 6
  • 79
  • 81
34

Just use a SELECT statement to get the values for many lines of the chosen columns and put these values into columns of another table in one go. As an example, columns "size" and "price" of the two tables "test_b" and "test_c" get filled with the columns "size" and "price" of table "test_a".

BEGIN;
INSERT INTO test_b (size, price)
  SELECT size, price
  FROM   test_a;
INSERT INTO test_c (size, price) 
  SELECT size, price
  FROM   test_a;
COMMIT;

The code is embedded in BEGIN and COMMIT to run it only when both statements have worked, else the whole run up to that point gets withdrawn.

questionto42
  • 7,175
  • 4
  • 57
  • 90
sunilsingh
  • 503
  • 1
  • 5
  • 9
-2

Here is a PHP solution ready for use with a n:m (many-to-many relationship) table :

// get data
$table_1 = get_table_1_rows();
$table_2_fk_id = 123;

// prepare first part of the query (before values)
$query = "INSERT INTO `table` (
   `table_1_fk_id`,
   `table_2_fk_id`,
   `insert_date`
) VALUES ";

//loop the table 1 to get all foreign keys and put it in array
foreach($table_1 as $row) {
    $query_values[] = "(".$row["table_1_pk_id"].", $table_2_fk_id, NOW())";
}

// Implode the query values array with a coma and execute the query.
$db->query($query . implode(',',$query_values));

EDIT : After @john's comment I decided to enhance this answer with a more efficient solution :

  • divides the query to multiple smaller queries
  • use rtrim() to delete last coma instead of implod()
// limit of query size (lines inserted per query)
$query_values  = "";
$limit         = 100;
$table_1       = get_table_1_rows();
$table_2_fk_id = 123;

$query = "INSERT INTO `table` (
   `table_1_fk_id`,
   `table_2_fk_id`,
   `insert_date`
) VALUES ";

foreach($table_1 as $row) {
    $query_values .= "(".$row["table_1_pk_id"].", $table_2_fk_id, NOW()),";
    
    // entire table parsed or lines limit reached :
    // -> execute and purge query_values
    if($i === array_key_last($table_1) 
    || fmod(++$i / $limit) == 0) {
        $db->query($query . rtrim($query_values, ','));
        $query_values = "";
    }
}
Meloman
  • 3,558
  • 3
  • 41
  • 51
  • 1
    Using the implode() does circumvent the "last character" problem but it creates a huge memory overhead. She asked for 3000 rows, imagine each row has 1kb of data, that's 3MB of raw data already. The array will take up 30MB of memory she already consumes another 30MB from the $table_1 so the script would use 60MB. Just saying, otherwise it's a good solution – John Sep 17 '17 at 03:10
  • 1
    it is useful for my situation. – Bilal Şimşek Feb 04 '20 at 09:52
-16
// db table name / blog_post / menu /  site_title
// Insert into Table (column names separated with comma)
$sql = "INSERT INTO product_cate (site_title, sub_title) 
  VALUES ('$site_title', '$sub_title')";

// db table name / blog_post / menu /  site_title
// Insert into Table (column names separated with comma)
$sql = "INSERT INTO menu (menu_title, sub_menu)
  VALUES ('$menu_title', '$sub_menu', )";

// db table name / blog_post /  menu /  site_title
// Insert into Table (column names separated with comma)
$sql = "INSERT INTO blog_post (post_title, post_des, post_img)
  VALUES ('$post_title ', '$post_des', '$post_img')";
Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
  • 4
    Aside from the confusingness of this response, you may also be vulnerable to SQL injection, assuming you're using PHP. – ultrafez Jun 26 '18 at 18:35
  • 4
    1. There is bug in your SQL code. 2. The next $sql value will replace the previous $sql value. – Marwan Salim Oct 18 '18 at 10:31
  • 1
    small hint for future readers, this is a really easy mistake to make especially for a novice, NEVER NEVER EVER insert a raw string into a sql query there's a rather nasty attack that users of our website can do to call random queries, more info https://owasp.org/www-community/attacks/SQL_Injection most libraries will have a sanitiser function to edit variables into safe forms that don't break out and escape the quotes – aqm Sep 29 '21 at 07:40