This question already has answers here:
PHP MySQLi Multiple Inserts
(3 answers)
Closed 3 years ago.
Hoping someone can give me some insight here.
When having to insert multiple rows into a table at once, I've used sql that looks something like this:
INSERT INTO some_names (firstName, lastName) VALUES ('Joe', 'Smith'),('Fred','Sampson'),('Lisa','Pearce')
As you can see I'm inserting three rows with one statement. The reason I do this is that I believe it is more efficient than executing three distinct statements to insert the rows.
So my question is this: how do I do this if I want to be able to bind my values to a statement? Unfortunately I've been looking all over the web and I can only find example of single statements in the form of:
$stmt = $mysqli->prepare("INSERT INTO some_names (firstName, lastName) VALUES (?, ?)");
$stmt->bind_param('ss', $firstName, $lastName);
$firstName = "Joe";
$lastName = "Smith";
$stmt->execute();
$firstName = "Fred";
$lastName = "Sampson";
$stmt->execute();
It seems that this would be the equivalent of doing separate INSERT statements and seems to be less efficient.
So my question is: Is there any way to bind in a multi-insert statement? Please educate me here! Thanks
Simple:
$stmt = $mysqli->prepare("INSERT INTO some_names (firstName, lastName) VALUES (?, ?),(?,?),(?,?)")
$stmt->bind_param('ssssss', 'Joe', 'Smith','Fred','Sampson','Lisa','Pearce');
It seems that this would be the equivalent of doing separate INSERT statements and seems to be less efficient.
No, it’s not less efficient – because a statement is prepared only once (to figure out what it is supposed to do), and after that is done only the data is send to the database afterwards.
You are looking at this the wrong way.
You would pretty much never do what you have shown above, it would almost always be done in a loop. And even if you dynamically constructed (?, ?), (?, ?), (?, ?) you would still have to loop to build the query string and bind the data (which would get even more complicated because of MySQLi's ridiculous insistance on by-ref bindings) so it wouldn't gain you anything in terms of work that needs to be done by PHP - you just moved the loop - and it would lose you a lot in terms of readability.
It does have a gain in round trips to the database (assuming you are always inserting more than one row) - but this would only make a meaningful difference when inserting hundreds or thousands or rows, in which case you are most likely performing some kind of import operation, in which case the extra couple of seconds probably don't matter (it won't be e.g. slowing a page load).
Related
I have read a lot of PHP sql examples that use MySQL. I often see queries like this that have placeholders for values:
$query = “INSERT INTO users
(username, firstname, lastname, salutation, countrycode)
VALUES(:1, :2, :3, :4, :5)”;
Notice the values are :1, :2 etc.
I use the standard PHP module for postgres in PHP. My queries inject variables names like this:
$query = “INSERT INTO users(username)
VALUES($hello)”;
How do I use the same placebolder technique with postgres in PHP? Is it possible?
Prepared queries cause two database communication roundtrips instead of one: one for prepare, one for execute. If you want to reuse the same query many times, yet only parse it once, they will be faster, but if you want to use the query once, they will be slower. Basically, prepared queries are the wrong answer to your problem ; the correct answer is parameterized queries.
$result = pg_query_params($dbconn,
'SELECT * FROM users WHERE first_name = $1 AND last_name=$2',
array($firstname,$lastname));
This pg-specific function makes a parameterized query where placeholders of the form $number are replaced by the parameters with the corresponding one-based index in the array. Parameters are properly handled, and there is no risk of SQL injection.
I am trying to insert a data from a form which has about 1990 characters into mysql. How ever the insert is not working. when i var_damp the content of the variable is shows the correct content. When i set it to an empty string the insert works. I have done my research and still can't get ti to work. I am not trying to upload a file. This characters are from a textarea in my form.
Below is the insert code:
if (isset($_POST['val'])) {
$score = $_POST['val'];
$course = $_POST['course'];
$mysqli->query("INSERT INTO `evaluate` (`id`, `course`, `score`) VALUES (Null, '$course', '$score')");
Note: is score column has type TEXT in the database.
This is a common problem because most introductions to mysqli don't cover it right away even when it should be the first thing you learn. Inserting into any database, especially SQL, requires carefully escaping the values you're supplying. The way these are escaped varies depending on the platform, but the good news is that mysqli can handle it for you.
The key is using prepared statements:
$stmt = $mysqli->prepare("INSERT INTO evaluate (course, score) VALUES (?,?)");
$stmt->bind_param('ss', $_POST['course'], $_POST['val']);
$stmt->execute();
Now it's best to enable exceptions so that any errors are not ignored. Once in a while we all make little mistakes that can be a giant pain to track down if there isn't any warning about them. Exceptions make a lot of noise.
If you're just getting started with PHP and databases, you might want to evaluate using PDO which is significantly better than mysqli for a number of reasons, or a higher level database layer like Doctrine or
Propel which make using the database a lot more pleasant.
I have a single quote (') in the text and not escaping it meant that the SQL statement was been interpreted wrongly
The correct way to go, and you must always do this, is:
$score = $mysqli->real_escape_string($_POST['val']);
$course = $mysqli->real_escape_string($_POST['course']);
$mysqli->query("INSERT INTOevaluate(id,course,score)VALUES (Null, '$course', '$score')");
I have an array $authors with some numbers I want to insert into a table.
I can have a prepared statement to execute multiple times for each element from the array:
$stmt = $pdo->prepare('INSERT INTO authors (article_id, user_id) VALUES(?, ?)');
$stmt->bindParam(1, $article_id);
$stmt->bindParam($author);
foreach($authors as $author) {
$stmt->execute();
}
However, I can do a trick using implode() and execute the statement only once:
// here probably $authors = array_map('intval', $authors);
$stmt = $pdo->prepare(
'INSERT INTO authors (article_id, user_id)
VALUES ('.implode(', :article_id), (', $authors).', :article_id)');
$stmt->execute([':article_id' => $article_id]);
The first solution is more conventional and looks more securely.
The second (I think) is faster because there is only one query to the database. (and is shorter - there are no loops except in implode)
I don't see any security issues here but it looks safer (to me) when there are no string concatenations in queries.
Which is the proper way in this situation?
Edit: echo of the second query gives this:
INSERT INTO authors (article_id, student_id)
VALUES (121, :article_id), (50, :article_id)
And executes with no errors.
According to the PDO's doc "You cannot use a named parameter marker of the same name more than once in a prepared statement, unless emulation mode is on.". So that alone makes your "implode" solution bad.
That being said, I'll answer on the theory. The point of prepared statements is to compile the query only once, so repeated executions are faster. So prepared statements are meant to be used as in your first example : one simple "template" query, repeated many times.
In your second example, you make a custom query, that will hardly ever be repeated (since it's based on the content of your $authors array). Therefore, prepared statement in this case is completely useless, you have the overhead of the PREPARE without the benefits of repeated executions. It's not the way it's supposed to be used.
Extended insert is a perfectly valid solution, and a good one with that, but use it with normal query (i.e. exec()), and be sure to use quote() to protect against SQL-injection!
This question already has answers here:
Insert multiple rows with PDO prepared statements
(4 answers)
Closed 8 years ago.
Ok so i need to insert multiple rows into a database using MySql from one form, each row is a result. The was i started doing it is the following:
INSERT INTO results (1,2,3,4,5,6,7) VALUES (1,2,3,4,5,6,7), (8,9,10,11,12,13,14)
And so on, my question is:
I don't know how many rows of results a user will want to insert ( a maximum of 15 will apply). Is their a more practical way of achieving the same result? Or am I better off sticking to the way i originally planned?
1°) Use prepared statement (like in Java):
(For safe code, always use prepared statement and avoid generate SQL)
$stmt = $db->stmt_init();
$stmt->prepare("INSERT INTO foo_table (id, firstname, lastname) VALUES(?, ?, ?)");
foreach($myarray as $row)
{
$stmt->bind_param('iss', $row['id'], $row['firstname'], $row['lastname']);
$stmt->execute();
}
$stmt->close();
To understant "iss" param in bind_param: http://uk3.php.net/manual/fr/mysqli-stmt.bind-param.php
2°) Generate batch insert:
Batch inserts with PHP
This question already has answers here:
PHP MySQLi Multiple Inserts
(3 answers)
Closed 9 years ago.
I'm trying to figure out how to properly achieve multiple row inserts along the format of
insert to tbl values (?,?,?), (?,?,?), (?,?,?);
The mysqli_bind_param doc is pretty clear on how to accomplish this for a single row.
From the docs their example looks like:
$stmt = $mysqli->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
However I have an multi-dimensional array where each inner element represents a value set, or row, to be inserted.
Well, you have 2 choices
Use the very prepared statement approach to do multiple inserts using once prepared query. Wrapped in a transaction they have to be blazingly fast
Create a dynamical call to bind_param which is going to be a pain, an unexpected pain. For some reason mysqli makes dynamical binding overcomplicated.
You will need to merge your array into single one, then create a second array for the references and then call call_user_func_array() for this latter approach. Dunno if it worth the mess.