PHP PDO: Insert working without attributes - mysql

This question is about why something is working.
Using unnamed placeholders in PHP PDO:
$STH = $connection->prepare("INSERT INTO Person (firstname, lastname, age) values ("?, ?, ?")");
$STH->execute($the_data);
This sort of insertion works correctly.
However, it still works if written as
$STH = $connection->prepare("INSERT INTO Person () values ("?, ?, ?")");
$STH->execute($the_data);
Huh?
Are attribute names just syntactic sugar or something?

You need to bind values before execute.
This is right way:
$STH = $connection->prepare('INSERT INTO Person (firstname, lastname, age) values (?, ?, ?)');
$STH->bindValue(1, 'MyFirstName', PDO::PARAM_STR);
$STH->bindValue(2, 'MyLastName', PDO::PARAM_STR);
$STH->bindValue(3, 28, PDO::PARAM_INT);
$STH->execute();

Related

You have an error in your SQL syntax in PDO

I am trying to fix my sql problem for 3 hours and I cant find the little thing the destroy my code.
The error :
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'order, image, category_id) VALUES('test', 'test', '<p>test' at line 1
The query: All the variables they are post fields that sended.
try {
$statement = $link->prepare("INSERT INTO `info_pages` (name, title, text, img_credits, meta_title, meta_keywords, order, image, category_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
$statement->execute(array($main_title, $side_title, $content, $img_credits, $meta_title, $meta_keywords, $order, $image, $category_id));
//echo $BNL->msg("הדף <b>{$main_title}</b> נוצר בהצלה, הנך מועבר...", true);
//echo $BNL->MoveTo($url."index.php?page=info_pages",1);
if (!$statement->execute()) {
print_r($statement->errorInfo());
}
} catch(PDOException $e){
echo $BNL->msg("<b>שגיאה</b>, צרו קשר עם המנהל");
}
grave is more commonly referred to as a "backtick", which MySQL uses to escape MySQL reserved words.
Already #Mat said his comment that you used reserve word in your statement that why its thrown error and that is "order",so if you use this type reserve word you have write your query below way.
("INSERT INTO `info_pages`
(`name`,
`title`,
`text`,
`img_credits`,
`meta_title`,
`meta_keywords`,
`order`,
`image`,
`category_id`)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
Though i used for every column but not needed that you can use it for only "order" column

Can't insert url in Mysql properly

I am using this code:
$image = mysqli_real_escape_string($dbc, $res[3][$i]);
Where $res[3][$i] is a url.
Then I store $image in a Mysql DB. But when I retrieve it, it's all messed up with the special characters... (my DB is in utf8).
How can I store a url in mysql and get it back exactly as it was?
Thanks
Actually I am using prepared statement:
$image = mysqli_real_escape_string($dbc, $res[3][$i]);
$md5_of_title = md5($title);
//$query = "INSERT IGNORE INTO scrap (date, journal, section, title, href, teaser, image, md5_of_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
$query = "INSERT INTO scrap (date, journal, section, title, href, teaser, image, md5_of_title) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
$stmt = mysqli_prepare($dbc, $query);
/*i Integers;
d Doubles;
b Blobs;
s Everything Else;*/
mysqli_stmt_bind_param($stmt, "ssssssss", date('Y-m-d H:i:s'), $name, $section, $title, $href, $teaser, $image, $md5_of_title);
mysqli_stmt_execute($stmt);

SQL IF EXIST UPDATE ELSE INSERT prepared statement

I'm breaking my brains over this, i would realy appriciate help!
This is the code i have so far..
$conn = db_connect();
$sql = "INSERT INTO measurements
(`date`, `weight`, `waist`, `id`) VALUES (?,?,?,?)";
$stmt = $conn-> prepare($sql);
$stmt ->bind_param("sddi", $date, $_POST['weight'], $_POST['waist'], $user_id);
$stmt->execute();
$stmt->close();
$conn->close();
Its a prepared statement for an sql insert. Now i want to change it to a IF EXIST THEN UPDATE ELSE insert the way i am doing right now. something like this but then with a prepared statement:
IF EXISTS
(SELECT * FROM measurements WHERE user_id=’4’)
UPDATE measurements SET (`weight`=40, `waist`=45) WHERE user_id=’4’
ELSE
INSERT INTO measurements
VALUES (`date`='week 1', `weight`= 40, `waist`=45, `id`=4)
I found some articles on stackoverflow about the if EXIST then update else insert but i did not find it with a prepared statement in it that worked for me.
Thanks a thousand!
UPDATE:
i've changed it to dublicate key style.
$sql = "
INSERT INTO measurements (uniqueID, date, weight, waist)
VALUES ('$uniqueID', '$date', '$weight', '$waist')
ON DUPLICATE KEY UPDATE weight= '$weight', waist= '$waist'";
$conn->query($sql);
Now the second part of the question, how do i make this a prepared statement?
To implement Mr. Jones' solution as a mysqli prepared statement, you would code it thus:
$sql = "INSERT INTO measurements
(`uniqueID`, `date`, weight, waist)
VALUES
(?, ?, ?, ?)
ON DUPLICATE KEY
UPDATE weight = ?, waist = ?";
$stmt = $conn->prepare($sql);
$stmt ->bind_param("isdddd", $user_id, $date, $_POST['weight'], $_POST['waist'], $_POST['weight'], $_POST['waist']);
$stmt->execute();
A slightly cleaner implementation would be to use PDO:
$sql = "INSERT INTO measurements
(`uniqueID`, `date`, weight, waist)
VALUES
(:uniqueId, :date, :weight, :waist)
ON DUPLICATE KEY
UPDATE weight = :weight, waist = :waist";
/* $conn is a PDO object */
$stmt = $conn->prepare($sql);
$stmt->execute(array(':uniqueId' => $user_id, ':date' => $date, ':weight' => $_POST['weight'], ':waist' => $_POST['waist']));
Note that with named placeholders, you can use the same name in more than one place and only need to assign the value once.
MySQL's approach to this is INSERT ... ON DUPLICATE KEY UPDATE .... It works well; in particular it avoids race conditions if more than one database connection tries to hit the same row.
This requires the table that's the target of your UPSERT to have a meaningful unique index or primary key. It looks like your id is that key.
You can absolutely use parameter binding to present data to this.
You can read about it here. http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

Perl DBI how to prepare single insert multiple rows

I am inserting multiple rows in a table with single insert query using the following format:
INSERT INTO $table (field1,field2) VALUES (value1,value2),(values3,values4);
The number of rows varies. Is there a way to use Perl's prepare statement for this kind of queries ?
For example, if I am inserting only one row I can do like the below:
$query = "INSERT INTO $table (field1,field2) VALUES (?,?)";
$sth = $dbh->prepare($query);
$sth->execute('value1','value2');
However, I want to do something like the below:
$values = '(value1,value2),(values3,values4),(values5,values6)';
$query = "INSERT INTO $table (field1,field2) VALUES ?";
$sth = $dbh->prepare($query);
$sth->execute($values);
Is this possible? or any other ways to achieve this ?
You can build up a query that can do what you want. Assuming that your records are in an array like this.
my #records = ( ['value1', 'value2'], ...) ;
Then you can create a query dynamically and execute it.
my $values = join ", ", ("( ?, ? )") x #records;
my $query = "INSERT INTO $table (field1,field2) VALUES $values";
my $sth = $dbh->prepare($query);
$sth->execute(map { #$_ } #$records);
Also in your example you are using string interpolation on the table name. Be careful with that as it can lead to database injections.
Put each record in its own array, then make an array of those:
my #records = ( [ 'value1', 'value2' ], [ 'value3', 'value4' ], [ 'value5', 'value6' ] );
Then prepare your INSERT statement:
my $query = "INSERT INTO $table (field1,field2) VALUES (?,?)";
my $sth = $dbh->prepare($query);
Then loop over your records and execute your statement handle for each one:
foreach my $rec ( #records ) {
$sth->execute( #$rec );
}

multiple INSERTS and keeping PDO prepared statement security

I have the following piece of code which sends to each member of mya_users a mail (this is what INSERT into inbox does.
$query_write_mass = "SELECT id FROM mya_users ORDER by artist_real_address ASC";
$result_write_mass = $db->prepare($query_write_mass);
$result_write_mass->execute();
while ( list($receiver_id) = $result_write_mass->fetch(PDO::FETCH_BOTH) ) {
$stmt = $db->prepare
("INSERT INTO inbox(folder_id, sender_id, sender_type, receiver_id,
receiver_type, title, message_body, time, date, flag, spam)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$stmt->bindValue(1, 0, PDO::PARAM_INT);
$stmt->bindValue(2, 0, PDO::PARAM_INT);
$stmt->bindValue(3, 'x', PDO::PARAM_STR);
$stmt->bindValue(4, $receiver_id, PDO::PARAM_INT);
$stmt->bindValue(5, $receiver_type, PDO::PARAM_STR);
$stmt->bindValue(6, $_POST['title'], PDO::PARAM_STR);
$stmt->bindValue(7, $_POST['body'], PDO::PARAM_STR);
$stmt->bindValue(8, date("G:i:s"), PDO::PARAM_STR);
$stmt->bindValue(9, date("Y-m-d"), PDO::PARAM_STR);
$stmt->bindValue(10, 'n', PDO::PARAM_STR);
$stmt->bindValue(11, '', PDO::PARAM_STR);
$stmt->execute();
}
what I want is to keep the benefits of security and escaping of PDO prepared statements,
BUT insert say 10 rows at a time, so if I have 40k inserts I would benefit of multiple value insert speed and keep the number of inserts low.
thanks
First, let me assure you that constant value is perfectly secure. So, you can dramatically reduce the number of bound parameters in your code
INSERT INTO inbox(folder_id, sender_id, sender_type, receiver_id,
receiver_type, title, message_body, dt, flag, spam)
VALUES (0, 0, 'x', ?, ?, ?, ?, NOW(), 'n', '')");
I also combined two fields date and time into one dt, as there is no reason to have them separated, yet it can let us use shorter code.
And now you can turn to the next step - using INSERT .. SELECT approach
INSERT INTO inbox(folder_id, sender_id, sender_type, receiver_id,
receiver_type, title, message_body, dt, flag, spam)
SELECT 0, 0, 'x', id, ?, ?, ?, NOW(), 'n', ''
FROM mya_users ORDER by artist_real_address ASC
and bind your data to only three remaining variables!