Mysql pdo different behaviour at 2 servers [duplicate] - php

This question already has answers here:
php pdo prepare repetitive variables
(2 answers)
Closed 6 years ago.
Why at 1st server such code on update set "00-00-00 00:00:00" and at the 2d set current time
$pdo = new PDO;
$sth = $pdo->prepare("INSERT INTO `tbl_process`
SET `good` = :good, `type` = :type, `pid` = :pid, `time` = :time
ON DUPLICATE KEY UPDATE `time` = :time");
$sth->bindParam(':good', $good);
$sth->bindParam(':type', $type);
$sth->bindParam(':pid', $pid);
$sth->bindParam(':time', $time);
$sth->execute();
if i change code to this (add :time2)- i get the right time in both cases
$pdo = new PDO;
$sth = $pdo->prepare("INSERT INTO `tbl_process`
SET `good` = :good, `type` = :type, `pid` = :pid, `time` = :time
ON DUPLICATE KEY UPDATE `time` = :time2");
$sth->bindParam(':good', $good);
$sth->bindParam(':type', $type);
$sth->bindParam(':pid', $pid);
$sth->bindParam(':time', $time);
$sth->bindParam(':time2', $time);
$sth->execute();

Placeholders must be UNIQUE within a query. You're not allowed to re-use them:
SET `good` = :good, `type` = :type, `pid` = :pid, `time` = :time
^^^^^
ON DUPLICATE KEY UPDATE `time` = :time");
^^^^^
The second query works because you've used a different placeholder name.

PDO has three error handling modes.
PDO::ERRMODE_SILENT acts like mysql_* where you must check each result and then look at $db->errorInfo(); to get the error details.
PDO::ERRMODE_WARNING throws PHP Warnings
PDO::ERRMODE_EXCEPTION throws PDOException. In my opinion this is the mode you should use. It acts very much like or die(mysql_error()); when it isn't caught, but unlike or die() the PDOException can be caught and handled gracefully if you choose to do so.
Getting the Last Insert Id
<?php
$result = mysql_query("INSERT INTO table(firstname, lastname) VALUES('John', 'Doe')") or die("Insert Failed ".mysql_error());
$insert_id = mysql_insert_id();
So far we've only shown simple statements that don't take in any variables. These are simple statements and PDO has the shortcut methods query for SELECT statements and exec for INSERT, UPDATE, DELETE statements. For statements that take in variable parameters, you should use bound parameter methods to execute your queries safely. Consider the following mysql_* code.

Related

How to generate a sequential number that restarts yearly in a web application

I need to generate a code which consists of some arbitrary prefix, a year, and an incrementing number. The incrementing number must start at 1 at the first time when the number is generated that year.
This code needs to be added to the sqlite database and be available elsewhere in the PHP script.
What i have done now uses 4 accesses to the database:
$codePrefix = 'TEST';
$stmt = $db->prepare(
'INSERT INTO test (year)
VALUES(strftime("%Y", "now"))'
);
$stmt->execute();
$id = $db->lastInsertId();
$stmt = $db->prepare('SELECT `year` FROM `test` WHERE `id`=:id');
$stmt->bindValue(':id', $id);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$year = $result['year'];
$stmt = $db->prepare('SELECT Ifnull(Max(id), 0) `max_id` FROM `test`
WHERE `year`<:year');
$stmt->bindValue(':year', $year);
$result = $stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
$previousMax = $result['max_id'];
$codeSuffix = $id-$previousMax;
$code = "{$codePrefix}-{$year}-{$codeSuffix}";
$stmt = $db->prepare('UPDATE `test` SET `code`=:code WHERE `id`=:id');
$stmt->bindParam(':code', $code);
$stmt->bindParam(':id', $id);
$stmt->execute();
Here i am abusing the fact that the id is an integer primary key, and autoincrements.
This works. But i feel that it is doing something very easy in a very complicated manner.
Is there a better solution? I need to assume that the midnight of the first of January can happen at any moment of the code, so i cannot do things like get the year information from PHP without hitting the database.
Before somebody asks, the reason i am using prepared statements even when no values are bound is because late on obviously more data will be inserted into the table.
Consider a pure SQL solution using the ROW_NUMBER window function. Below assigns to new field, new_id:
UPDATE test
SET new_id = 'TEST_' || test.[Year] || '_' || sub.rn
FROM (
SELECT id,
[Year],
ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY id) AS rn
FROM test
) AS sub
WHERE test.id = sub.id;

inserting multiple values in mysql table using PDO

I have a form that submits check boxes to a PHP PDO script. I have code that is as follows to store the values into a mysql table
$stmt = $dbPDO->prepare("INSERT INTO group_members(g_id, em_id)
VALUES(:g_id,:em_id)
ON DUPLICATE KEY UPDATE g_id = :g_id, em_id = :em_id");
foreach ($_POST['id'] as $email) {
$stmt->bindParam(':g_id', $gid , PDO::PARAM_INT);
$stmt->bindParam(':em_id', $email , PDO::PARAM_STR);
$stmt->execute();
}
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY093]: Invalid parameter number'
This generates an error. What is the best way to insert multiple values into a mysql table with different values?
Every named placeholder have to be unique!
$stmt = $dbPDO->prepare("INSERT INTO group_members(g_id, em_id) VALUES(:g_id,:em_id) ON DUPLICATE KEY UPDATE g_id = :g_id2, em_id = :em_id2");
$email=null;
//just bind once, that the logic behind 'bind()'
$stmt->bindParam(':g_id', $gid , PDO::PARAM_INT);
$stmt->bindParam(':em_id', $email , PDO::PARAM_STR);
$stmt->bindParam(':g_id2', $gid , PDO::PARAM_INT);
$stmt->bindParam(':em_id2', $email , PDO::PARAM_STR);
foreach ($_POST['id'] as $email) {
$stmt->execute();//write your rows
}
$stmt->close();
You can't reuse placeholder names. You have to create new ones, or use VALUES in your update portion:
$stmt = $dbPDO->prepare("INSERT INTO group_members(g_id, em_id) VALUES(:g_id,:em_id) ON DUPLICATE KEY UPDATE g_id = VALUES(g_id), em_id = VALUES(em_id)");
You can't reuse a placeholder unless you have emulation mode turned on.
Generally speaking, PDO_MYSQL should have emulation on by default. The reason being that MySQL performs poorly with prepared statements. Emulation works significantly faster.
That said, if it is not on for whatever reason, you can set it manually using:
$dbc->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);
In fact, if you are not sure, just set it anyway.

Unable to INSERT dates and times into MYSQL database with PHP

I am trying to build an SQL query that will insert the check-in time for a child at a fictional daycare facility. Here is a condensed version of my query code:
$childFirstName = $_POST['childFirstName'];
$childLastName = $_POST['childLastName'];
$now = new DateTime();
$nowDate = $now->format('m-d-Y');
$nowTime = $now->format('h:i');
$sql_childID = "SELECT id FROM child
WHERE firstName = '$childFirstName'
AND lastName = '$childLastName'";
$result = $pdo->query($sql_childID);
$row = $result->fetch();
$sql = "INSERT INTO checkinout(date, in, child_id) VALUES(?,?,?)";
$statement = $pdo->prepare($sql);
$statement->bindValue(1, $nowDate);
$statement->bindValue(2, $nowTime);
$statement->bindValue(3, $row['id']);
$statement->execute();
The checkinout table uses VARCHAR datatypes for the date and in columns. Originally they were set to use DATETIME, but I received the same errors.
Right now I get the following errors returned...
You can see from the error messages that my values are getting passed in the way I want them to, but I don't understand where my syntax error would be.
Enclose your field names with backticks. Two of them are reserved words (date and in):
$sql = "INSERT INTO checkinout(`date`, `in`, `child_id`) VALUES(?,?,?)";
https://dev.mysql.com/doc/refman/5.5/en/keywords.html

mysqli_multi_query not doing anything

I am doing an ajax call to a PHP which should do 2 SQL queries. The queries look like this:
$sql = "UPDATE customers SET customers_newsletter=1 WHERE customers_id ='".$cid."'";
$sql .= "INSERT INTO coupons (coupon_id,
coupon_type,
coupon_code,
coupon_amount,
coupon_minimum_order,
coupon_start_date,
coupon_expire_date,
uses_per_coupon,
uses_per_user,
coupon_active)
VALUES ('".$cid."',
'NL_".$cid_substr."".$cid."',
'F',
'5.0000',
'100.0000',
'".date("Y-m-d H:i:s")."',
'".$expiredate."',
'1',
'1',
'Y'
)";
mysqli_multi_query($con,$sql);
In another php file the exact same code already worked, i there copied an sql entry to another table and then deleted it from the current one.
If i do only one of the queries it works, but i need to get them to work together.
Any ideas why it is not working?
UPDATE:
I now followed the link for preventing sql injection in the comment and i got the following code now:
<?php
$mysqli = new mysqli("server", "user", "pw", "db");
// TODO - Check that connection was successful.
$unsafe_variable = $_GET['cid'];
$stmt = $mysqli->prepare("INSERT INTO coupons (coupon_id) VALUES (?)");
// TODO check that $stmt creation succeeded
// "s" means the database expects a string
$stmt->bind_param("s", $unsafe_variable);
$stmt->execute();
$stmt->close();
$mysqli->close();
mysqli_close($con);
?>
It is still not working. Where is the fault?
What you're currently running is the same as:
$sql = "UPDATE customers SET customers_newsletter=1 WHERE customers_id ='".$cid."' INSERT INTO coupons (coupon_id,
coupon_type,
coupon_code,
coupon_amount,
coupon_minimum_order,
coupon_start_date,
coupon_expire_date,
uses_per_coupon,
uses_per_user,
coupon_active)
VALUES ('".$cid."',
'NL_".$cid_substr."".$cid."',
'F',
'5.0000',
'100.0000',
'".date("Y-m-d H:i:s")."',
'".$expiredate."',
'1',
'1',
'Y'
)";
mysqli_multi_query($con,$sql);
Which, if you notice right after the first query it starts right into the INSERT. If you ran this in anything that would give you the SQL error (or echo'd the sql error here) you'd likely see that there is a syntax error because the UPDATE query is never closed. Try adding a ; to the end of the update statement, like so:
$sql = "UPDATE customers SET customers_newsletter=1 WHERE customers_id ='".$cid."';";

MySQLi prepared statement silently failing second execution

I am attempting to make a simple system where, once you view forum thread it updates an existing array entry with the current UNIX time in the DB table that holds the user's account information. The column is set to accept MEDIUMTEXT and is set as NOT NULL.
However, while the first prepared statement works as intended and I receive the correct value, and the json_table is correctly re-encoded, the second query does not update the column data. No errors (no matter what error level I set mysqli to). Neither of the parameters I am binding are NULL and are correct.
I am stumped as to why this is happening. MySQLi magic that I haven't learned? Restrictions somewhere?
$DB = GetDatabaseConnection();
$Statement = $DB->prepare("SELECT `forum_newpost_icondata` FROM `user_accounts` WHERE `id` = ?");
print(mysqli_error($DB));
$Statement->bind_param("i", $UserLoggedIn['id']);
$Statement->bind_result($JSONTable);
$Statement->execute();
$PostData = json_decode($JSONTable);
$PostData[$ThreadID] = time();
$PostData = (string)json_encode($PostData);
$Statement->free_result();
$Statement->close();
$Reinsertion = $DB->prepare("UPDATE `user_accounts` SET `forum_newpost_icondata` = ? WHERE `id` = ?");
print(mysqli_error($DB));
$Reinsertion->bind_param("si", $PostData, $UserLoggedIn['id']);
$Reinsertion->execute();
print(mysqli_error($DB)); // Checking after execute is still blank
$DB->close();

Categories