Help me debug my SQL INSERT, please? - php

I am pulling back some data from the twitter query API, and parsing it through PHP like so:
$i =0;
foreach ($tweetArray->results as $tweet) {
$timeStamp = strtotime($tweet->created_at);
$tweetDateTime = date('m-d-Y H:m:s', $timeStamp);
if($i > 0){
$SQL .= ',';
}
$SQL .= "(". $tweet->id .",'" . $tweet->from_user ."','". addslashes($tweet->profile_image_url) . "','". addslashes($tweet->text). "','" . $tweetDateTime ."')";
$i++;
}
$SQL .= " ON DUPLICATE KEY UPDATE 1=1";
This leaves me with a SQL statement looking like this:
INSERT
INTO
tblTwitterSubmit (tweetId, twitterAuthor, authorAvatar, tweetText, tweetDateTime)
VALUES
(111,'name','http://url.com','a string of text','03-04-2011 13:03:09'),
(222,'anothername','http://url.com','another tweet','03-04-2011 12:03:51')
ON DUPLICATE KEY UPDATE 1=1;
I am unfortunately getting the following 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 '1=1' at line 1.
Edit:
The 1=1 is supposed to not do anything. The tweets don't change, and so if I pull the same one back twice for any reason, nothing will happen, but it also won't throw a duplicate key error.
Re-edit:
The problem appears to have something to do with the key field I was using, which was the id of tweet as assigned by twitter.
I re-factored the code anyway, since it seemed pretty evident that what I had read in articles as a "really-good-idea" wasn't. I now included a PDO submit inside the for loop so I just make a bunch of submissions instead of one long sql string.
Hopefully this is better practice.
Leaving this open for a couple minutes hoping for some feedback if this is the way to do it or not.

The ON DUPLICATE KEY UPDATE requires a column name, something like this, assuming tweetId is the key column that's getting duplicates.
ON DUPLICATE KEY UPDATE tweetId=tweetId+1
Your 1=1 doesn't actually do anything.

Are you sure you're using the right syntax for on duplicate key update ?
Judging from it's manual's page, it seems you have to specify a column name, and not 1=1.
From what I understand, if you want to indicate "use the value from the values() clause when there's a duplicate", you should use something like this :
on duplicate key update your_col=values(your_col)
Quoting the relevant part :
You can use the VALUES(col_name)
function in the UPDATE clause to
refer to column values from the
INSERT portion of the INSERT ... ON
DUPLICATE KEY UPDATE statement.
In other words,
VALUES(col_name) in the ON
DUPLICATE KEY UPDATE clause refers to
the value of col_name that would be
inserted, had no duplicate-key
conflict occurred. This
function is especially useful in
multiple-row inserts.
Then, as a sidenote, you must escape your strings using the function that matches your API -- probably mysql_real_escape_string -- and not the generic addslashes, which doesn't know about the specificities of your database engine.

The problem appears to have something to do with the key field I was using, which was the id of tweet as assigned by twitter.
I re-factored the code anyway, since it seemed pretty evident that what I had read in articles as a "really-good-idea" wasn't. I now included a PDO submit inside the for loop so I just

Related

Is it possible and safe to combine MySQL syntax for INSERT INTO SET ánd ON DUPLICATE KEY UPDATE (with the same column set)?

I know how the specific MySQL query syntax for INSERT INTO SET and ON DUPLICATE KEY UPDATE work. But, can you combine them? And... can you use the same $columnSet string (see below) for the INSERT and the UPDATE part, leaving the unique field in there?
Concider this example (I use php with pdo on my server):
// Define the query
$columnSet = "id=:id, date=:date, created=:created, modified=:modified, removed=:removed, synced=1, points=:points, comment=:comment";
$insertQuery = "INSERT INTO point_events SET"
. $columnSet." ON DUPLICATE KEY UPDATE ".$columnSet;
// Define the data
$pointData['id'] = 'someuniqueid not auto incremented';
$pointData['created'] = 1234; // a timestamp
$pointData['modified'] = 1234; // a timestamp
$pointData['removed'] = NULL;
$pointData['points'] = 10;
$pointData['comment'] = "A comment";
$pointData['date'] = time();
// Execute the query. pdoModify is custom function that executes the query.
pdoModify($pdoNew, $insertQuery, $oldData);
All posts I've seen do not combine these two syntaxes and all posts on ON DUPLICATE KEY UPDATE seem to suggest that you should not include the (duplicate) key in the string after UPDATE. So, is this safe, or could this behave differently / have unwanted side effects. Specifically leaving the unique id in the $columnSet for the UPDATE is what concerns me.
I believe that your code should work. Typically, since the duplicate id unique key is initially checked, it is guaranteed than it will left unchanged when the ON DUPLICATE KEY clause is invoked.
However, this behavior is suboptimal (you are updating fields that are unchanged), and alos quite rigid: what if you need to increase the amount with the newly inserted value, or to concatenate the new comment at the end of thte existing one?
As commented by Rogue, MySQL syntax has a nice feature that allows the use of VALUES(<some column>) in the ON DUPLICATE KEY clause to refer to a value that was passed for INSERT. I would suggest to use that, since it is more elegant, and gives you much more control and flexibility.
Example:
$insertQuery =
"INSERT INTO point_events SET"
. $columnSet
." ON DUPLICATE KEY UPDATE"
." modified = VALUES(modified)" # replace this value
.", synced = 1" # assign a fixed value
.", amount = amount + VALUES(amount)" # add the new value
.", comment = CONCAT(comment, ', ', VALUES(comment))" # concatenante the new value

SQL row update +1

I'm trying to add +1 in custom row. Example:
UPDATE `users` SET `MVP` = `MVP` + 1 WHERE `steam_id` = `%s`;
But nothing. What's wrong? Syntax looks good i think.
%s is a value so remove `
You can usually omit that everywhere unless you are using some "unlucky" column names
UPDATE `users` SET `MVP` = `MVP` + 1 WHERE `steam_id` = %s;
Take the ' away from the MVP you are incrementing.
UPDATE `users` SET `MVP` = MVP+1 WHERE `steam_id` = `%s`;
Post the entire code snipped. Can´t really help you like that. What is steam_id? What is %s. When do you replace it with an actual value? You should also just use prepared statements and not DYI that. %s is not how they look like in PDO or MYSQLI, but sure looks like a placeholder for a string.
You also marked this as insert, yet you´re doing an update.
Those `` are kinda unnecessary, never used them for column/table names, but appears to work at least in mysql console.
The sql snipped looks right, assuming MPV is numeric and the id is a string/varchar and equals %s, or you´re replacing it with something.
EDIT: As some have said the %s is the problem use nothing if it´s a int. Use single or double quotes if it´s a string. And you don´t need to use anything anywhere else, but if you wish to do so you can.

ON DUPLICATE KEY UPDATE - Condition WHERE vs CASE WHEN vs IF?

I am refering to this post. I am stuck with a problem I can't resolve. I try to insert multiple rows with a php script into a MySQL database. I don't succeed in updating the whole thing using ON DUPLICATE KEY UPDATE and using a WHERE condition (at the end of the code below) I would like to use to update only an entry has been modified recently:
// for information (used in a foreach loop):
$args[] = '("'.$row['lastname'].'", '.$row['phone'].', "'.$row['lastModification'].'")';
// then:
$stringImplode = implode(',', $args);
// Where I am stuck - WHERE statement:
$sql = $mysqli->query('INSERT INTO table_name '. (lastname, phone, timestamp) .' VALUES '.$stringImplode .'ON DUPLICATE KEY UPDATE lastname=VALUES(lastname), phone=VALUES(phone) WHERE timestamp > VALUES(lastModification);
Everything works fine except I cannot set any WHERE condition at this point that involves multiples entries. Maybe the WHERE statement in this case is not intended to refer to a condition in this statement.
I was told to try with a database procedure using a JOIN statement and a temporary table with first all my entries and then querying some conditions. But I have to admit I don't understand very well how I could leverage such a table to update an other table.
Is there an easy and lovely way to use a "CASE WHEN" or an "IF" statement in this case?
Would something like
INSERT INTO ... ON KEY DUPLICATE UPDATE lastname = VALUES(lastname), phone = VALUES(phone)
CASE WHEN (timestamp > VALUES(lastModification)) THEN do nothing ...
or
...ON KEY DUPLICATE UPDATE... IF (timestamp > VALUES(lastModification)) ...
If anyone could help me, I would be very grateful.
EDIT: Since I will have many variables, could it be used in this way:
INSERT INTO ... ON KEY DUPLICATE UPDATE
IF(timestamp > VALUES(timestamp),
(
name = VALUES(name),
number = VALUES(number),
timestamp = VALUES(timestamp)
....many other variables
),
(
name = name,
number = number,
timestamp = timestamp
....many other variables)
)
You can use simple IF function in value like this:
INSERT INTO ... ON KEY DUPLICATE UPDATE
name = VALUES(name),
number = VALUES(number),
timestamp = IF(timestamp > VALUES(timestamp), VALUES(timestamp), timestamp)
If condition is not met, it will update timestamp with the same timestamp which already exists. It does not matter, because update to same values is optimized before it is even executed, so MySQL will not make real update. You should not afraid of some performance penalty.
EDIT:
IF works likes this:
IF(condition, returned when true, returned when false)
Maybe you need to switch those two arguments to fit your condition like you want.

SQL call IF EXISTS

SOS! I am trying to build a simple search feature that either creates a new row with the search content or increments the amount of times that particular content has been searched if the row already exists. I tried doing a similar SQL call straight inside of phpMyAdmin but it gave me a #1064 error? ($_POST['search'] is the search content)
<?php
$con=mysqli_connect(...);
$result = mysqli_query($con,"IF EXISTS (SELECT * FROM search WHERE text='" . $_POST['search'] . "')
UPDATE search SET searches=searches+1 WHERE text='" . $_POST['search'] . "'
ELSE
INSERT INTO search (text, searches) VALUES ('" . $_POST['search'] . "', '1')");
echo $result;
?>
Make the "text" column of the "search" table a "unique key". Then you can use this query:
INSERT INTO search (text,searches) VALUES ({$searched_text},1)
ON DUPLICATE KEY UPDATE searches=searches+1;
At first you are doing very wrong thing in your sql.
Please for your sake and sake of application, never never let unfiltered input into your sql query. This can lead to SQL Injection and someone can easily highjack your db.
So, lets fix this first:
$search = mysql_real_escape_string($_POST['search']);
Now when we have fixed it, lets try to do something with it.
I dont know if you have set a key for that table, but i suppose you do, so to escape your conditional try to simply do next thing:
insert into search (searches) values($search) on duplicate key update searches=searches+1
Please let me know how its going.
Kind regards
Vlad

php incrementing while loop

$blanknumber = $_POST["blankstartnumber"];
while ($blanknumber <= ($_POST["blankendnumber"] ))
{
echo "$blanknumber";
$blankid = $blanknumber;
$query = "INSERT INTO blank (Blank_ID) VALUES ('$blankid')";
mysql_query($query,$con);
$blanknumber++;
}
So the values are added into the database. Lets say if I have the starting number at 1 and ending at 5. It will all the those values, but it's still trying to add more into the database. I also tried adding an IF statement aswell. if ($blanknumber != $_POST["blankendnumber"])
12345 Error: Duplicate entry '5' for
key 'PRIMARY'
Make sure your $POST value is an integer; by default, I believe it will be cast as a string.
$_POST['varName'] = (int) $_POST['varName'];
edit:
$blanknumber = $_POST["blankstartnumber"];
while ($blanknumber <= ($_POST["blankendnumber"] ))
This should only execute once, since you're setting both comparison variables equal. Definitely 2x check your code.
The database error indicates that Blank_ID is your primary key for that table, and you'd already inserted a 5 into the row. A primary key's values can exist only once in the entire table - duplicates are forbidden (if they were allowed, it wouldn't be a primary key anymore).
If your while loop isn't ending, I'd suggest dumping out both the blankendnumber and blankstartnumber before the loop starts, making sure you've got the right values in there.
It looks like it's actually functioning properly, but you might not have tidy'ed up your db table prior to running. If your output was:
123455 Error: Duplicate entry '5'...
Then, you'd have a programming error, as 5 is getting run twice. Instead, I think you already have data in the blank table that causes a conflict.
Edit: to automatically have MySQL handle the duplicate key error gracefully, you can use the ON DUPLICATE KEY clause to update the row.
INSERT INTO blank (Blank_ID) VALUES (5) ON DUPLICATE KEY UPDATE mod_date = NOW();

Categories