Reputation: 2777
DETAILS
I am doing a single insert for the expiry of a new or renewed licence. The time period for the expiry is 2 years from the insertion date. If a duplicate is detected, the entry will be updated such that the expiry equals the remaining expiry plus 2 years.
Regarding duplicates, in the example below there should only be one row containing user_id =55 and licence=commercial.
TABLE: licence_expiry
--------------------------------------------------------
| user_id | licence | expiry |
--------------------------------------------------------
| 55 | commercial | 2013-07-04 05:13:48 |
---------------------------------------------------------
user_id (int11), licence (varchan50), expiry (DATETIME)
I think in mysql you would write it something like this (Please note that I haven't checked whether the code works in mysql. )
INSERT INTO `licence_expiry`
(`user_id`, `licence`, `expiry`)
VALUES
(55, commercial, NOW()+ INTERVAL 2 YEAR)
ON DUPLICATE KEY UPDATE
`expiry` = `expiry` + INTERVAL 2 YEAR
QUESTION: How can I do this with PDO? I've written a rough outline of what I think I will use, but I'm not sure what to write for the expiry value for the ON DUPLICATE KEY UPDATE.
$sql = "INSERT INTO $table (user_id, licence, expiry)
VALUES (
:user_id,
:licence,
:expiry)
ON DUPLICATE KEY UPDATE expiry = Something";
try {
$dbh = new PDO('login info here');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':user_id', $userID, PDO::PARAM_INT);
$stmt->bindParam(':licence',$licence, PDO::PARAM_STR);
$stmt->bindParam(':expiry',$expiry, PDO::PARAM_STR);
$stmt->execute();
//$stmt->closeCursor(); //use this instead of $dbh = null if you will continue with another DB function
$dbh = null;
}
catch(PDOException $e)
{
$error=$e->getMessage();
}
Any help is much appreciated.
Upvotes: 3
Views: 10998
Reputation: 349
I know you have answer below, but i had same problem and my solution looks quite different but it works for me so if you want to use different statement of using insert in mysql with explicit binding values to columns you can try this code
$sql = "
INSERT INTO
$table
SET
user_id = :user_id,
licence = :licence,
expiry = :expiry
ON DUPLICATE KEY UPDATE
expiry = :expiry
";
$dbh = new PDO('login info here');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare($sql);
$stmt->bindValue('user_id', $userID , PDO::PARAM_INT);
$stmt->bindValue('licence', $licence, PDO::PARAM_STR);
$stmt->bindValue('expiry' , $expiry , PDO::PARAM_STR);
Upvotes: -1
Reputation: 125865
You can use MySQL's VALUES()
function:
In an
INSERT ... ON DUPLICATE KEY UPDATE
statement, you can use theVALUES(col_name)
function in theUPDATE
clause to refer to column values from theINSERT
portion of the statement. In other words,VALUES(col_name)
in theUPDATE
clause refers to the value ofcol_name
that would be inserted, had no duplicate-key conflict occurred.
Therefore, in your case:
ON DUPLICATE KEY UPDATE expiry = VALUES(expiry)
Alternatively, you can create a fourth parameter to which you bind $expiry
again:
$sql = "INSERT INTO $table (user_id, licence, expiry)
VALUES (
:user_id,
:licence,
:expiry)
ON DUPLICATE KEY UPDATE expiry = :another";
try {
$dbh = new PDO('login info here');
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':user_id', $userID , PDO::PARAM_INT);
$stmt->bindParam(':licence', $licence, PDO::PARAM_STR);
$stmt->bindParam(':expiry' , $expiry , PDO::PARAM_STR);
$stmt->bindParam(':another', $expiry , PDO::PARAM_STR);
$stmt->execute();
// etc.
Upvotes: 10