How run multiple queries in a row - php

I have a table for storing storing page visit counts. The first statement firs makes a query to get the current stored data, and the second increments the first result and updates the table.
here is an example.
$conn = new PDO(...);
//get current value
$stmt = $conn->query("SELECT counter FROM table");
$newValue = $stmt->fetch(PDO::FETCH_ASSOC);
//increment
$stmt = $conn->prepare("update table set counter = ?");
$stmt->execute(array($newValue));
The above is just an example, But I need an approach where it involves making a single prepare() to count and update the counter by 1, on each page visit.

The following will take the column value and increment itself by one (or whatever you'd like) in a single statement
UPDATE table SET counter = counter + 1

You can simply use this query:
update table set counter = (counter+1)

Please try this :
UPDATE table SET counter = ((SELECT counter FROM table)+1)
I hope this help u :)

Related

How to update many rows with uniqid() making them unique in php

I created a new column in mysql, that is going to store a unique value for all of the elements inside the database.
Now I would like to populate all rows with this unique value using uniqid().
But since the function makes use of microtime(), I can't update all rows together.
How could I do it?
$unique_id = uniqid();
$sql = "UPDATE posts SET unique_id = :unique_id";
$stmt = $pdo->prepare($sql);
$stmt->execute(['unique_id' => $unique_id]);
This code updates the same value for all rows.
How can every row be unique?
try with below code
SET #r := 0;
UPDATE posts
SET unique_id = (#r := #r + 1)
ORDER BY RAND();
Try this ,
update posts set unique_id = #i:=#i+1 order by rand();
The numbers will now randomly assigned to rows, but each row has a unique value.
uniqid('', TRUE),
You can use uniqid with the entropy to make it more sensitive in time to narrow down even more the chance of duplicates but keep one thing in mind:
This function does not guarantee uniqueness of return value. Since
most systems adjust system clock by NTP or like, system time is
changed constantly. Therefore, it is possible that this function does
not return unique ID for the process/thread. Use more_entropy to
increase likelihood of uniqueness.
What you can do as well is to put a random prefix like:
uniqid(mt_rand(), TRUE);
That will eliminate every chance to generate a duplicate.
You are going to use a random prefix + entropy sensitivity. The generated value will be unique even if your script runs that fast that the timestamp happens to be the same even in miliseconds.
The problem with your code is that you use uniqid() function one time by assigning it to a variable and from there you get duplicates of course cause you use this variable:
Try this code:
$sql = "UPDATE posts SET unique_id = uuid()";
$stmt = $pdo->prepare($sql);
$stmt->execute();
So after some tries I came across my own solution, using uniqid().
Here's my code, commented:
// Selecting all the posts
$sql = "SELECT id, pro_key FROM posts";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$posts = $stmt->fetchAll();
// Looping through all the results and updating them one by one with a delay of 1 second between the updates
foreach($posts as $post) {
$sql = "UPDATE posts SET unique_id = :unique_id WHERE id = :id";
$stmt = $pdo->prepare($sql);
$stmt->execute(['id' => $post->id, 'unique_id' => uniqid()]);
// delay
sleep(1);
}
Hope this helps.

How can I use mysqli / php to update all records after a query has already been executed?

I have a user form that sets a single record "current". No more than one record can be set to current at a time. So, I present the user a single drop down list, they choose the item they want to set current and hit "UPDATE" at the bottom of the form.
The PHP/Mysqli needs to go in and set all records column "current" to a value of 0 then update the one from the form to a value of "1".
Initially, I just did a simple count the number of rows, and run a bunch of queries to update the column to 0 or 1 if the loop counter = the id of the row. Well... that broke quick as I started doing testing on other portions and the index numbers got higher than the total number of rows. Yes, dumb way to do it initially!
Here's what I tried to do with the PHP / MySQL code:
// $link is the database link defined elsewhere. This does work as I use it all over the place
$setCurrent = X; // This is the number passed from my form
$init_query = "SELECT id, current FROM myTable";
if ($stmt = $link->$prepare($init_query) {
$stmt->execute() or die ($stmt->error);
$stmt ->bind_result($id, $current)
while ($stmt->fetch()){
if ($id == $setCurrent){
$update_sql = "UPDATE myTable SET current ='1' WHERE id='".$setCurrent."'";
$stmt2 = $link->prepare($update_sql);
$stmt2->execute;
}
else {
$update_sql = "UPDATE myTable SET current ='0' WHERE id='".$id."'";
$stmt2 = $link->prepare($update_sql);
$stmt2->execute;
}
$stmt->close();
This fails and gives me a Fatal error: Uncaught Error: Call to a member function execute on boolean in .....
I am racking my brain over this and can't figure out what the heck is going on. Its been a few years since I have worked in PHP/MySql and this is my first forray into OO Mysqli. Please be gentle :)
You're missing two closing curly braces. One for the first if() and the other for while()
why do them one at a time? You can do it in one query
$setCurrent = X;
$query = 'UPDATE myTable
SET `current` = (id = :current)';
$stmt = $link->prepare($query);
$stmt->bindValue(':current', $setCurrent);
$stmt->execute();
(and misusing the fact that if id equals $setCurrent, the part between ( ) resolves to true, which is 1.)
some explaining:
SELECT 10=10; would give a kind of "TRUE". But as Mysql does not give true, it give 1.
the same goes for:
SELECT 10=20; This is FALSE, so gives you 0.
Now back to your query: you want to get a value 0 for all record for which id not equal to some-number. And you want 1 when equal:
So you have to compare the column id's value to $setCurrent. When they match you get 1 and you put that 1 into the column "current"
And when they don't match, all other cases, then you get a 0 and that 0 goes into the column Current.
And yes, this could also be done as:
UPDATE mytable
SET `current` = CASE id
WHEN $setCurrent THEN 1
ELSE 0
END CASE
or using IF,
But they other syntax is way shorter
edit
backtics are needed around column name, as current is a reserved word

Getting Auto Increment multiple times

I'm hoping someone can help me figure out what I thought would be really easy.
I have a form that I dynamically add rows to. When I add the row, I want to display a unique value, and am using the MySql table primary key - called ID. Because there will be multiple users, I want to immediately reserve that ID, so it doesn't get reused. Since a user may decide to add another item to the list, and add another dynamic row, I want to repeat the process (get the new Auto Increment value from that table, and immediately reserve it).
Unfortunately, I continue to get the same ID value, even though I have confirmed the auto increment value has increased.
This is what I am using inside my "add row" function before I use the DOM Element to add the row:
$result = mysql_query("SHOW TABLE STATUS LIKE 'table'");
$row = mysql_fetch_array($result);
$nextId = $row['Auto_increment'];
$query = "INSERT INTO table (id, identifier1, identifier2) VALUES ('".$nextId."','".$identifier1."','".$identifier2."')";
$result = mysql_query($query) or die(mysql_error());
I have tried adding immediately before them the following in the hopes that it will blank everything and pull all new values:
$nextId = 0;
$row = "";
$result = "";
$query = "";
I am hoping someone out there can see something simple or suggest a better way that will work.
Thanks in advance.
Ok as your comment shows you have a slight mistake in your INSERT, try this:
$query = "INSERT INTO table (identifier1, identifier2)
VALUES ('".$identifier1."','".$identifier2."')";
$result = mysql_query($query) or die(mysql_error());
$nextId = mysql_insert_id()+1; //you also need to +1 to get the next number
But there is NO guarentee that the next id will be +1 from the last.

select count doesn't count

I try to build a variable that integrates some other variable.
one of that will be the number of an auto-increment-field where later on an insert-query will happens.
I tried to use:
$get_num = $db/*=>mysqli*/->query("SELECT COUNT (*) auto_increment_column FROM table1");
$num = $query->fetch_assoc($get_num);
$end = $num + 1;
I don't have any update/insert query before that so I can't use
$end = $db->insert_id;
that's why i thought i can just count the numbers of the auto_increment rows and have my last variable that is necessary to build my new variable.
for a reason this wonT count the entries and outputs 0. i dont understand why this happens.
i really would appreciate if there is someone who could tell me what am i doing wrong. thanks a lot.
UPDATE
For everyone who likes to know about what's the goal:
I like to create a specific name or id for a file that later on will be created by the input of the fields from the insert query. I like to have an unique key. this key consists of an user_id and a timestamp. at the end of this generated variable it should be placed the auto_increment nr. of the query that will be placed in the table. so the problem is, that I create an variable before the insert query happens so that this variable will be part of the insert query like:
$get_num = $db->query("SELECT COUNT (*) FROM tableA");
$num = $query->fetch_assoc();
$end = $num + 1;
$file_id = $id .".". time() .".". $end;
$insert = $db->query("INSERT INTO tableA ( file_id, a, b, c) VALUES('".$file_id."','".$a."','".$b."','".c."')");{
hope now, it will be clear what I like to approach.
If you need an auto-incrementing column in MySQL then you should use AUTO_INCREMENT. It implements it all for you and avoids race conditions. The manual way you are trying to implement it has a couple of flaws, namely
If two scripts are trying to insert concurrently they might both get the same COUNT (say 10) and hence both try to insert with ID 11. One will then fail (or else you will have duplicates!)
If you add 10 items but then delete item 1, the COUNT will return 9 but id 10 will already exist.
try
SELECT COUNT(*) FROM table1

Setting status of other rows after INSERT

Hey, I have a field called STATUS and it is either 1 to show or 0 to hide. My code is below. I am using an edit in place editor with jQuery. Everytime you update it creates a new ROW which I want, but I want only the new one to have STATUS = 1 and the others to 0. Any ideas on how I would do that?
<?php
include "../../inc/config.inc.php";
$temp = explode("_", $_REQUEST['element_id'] );
$field = $temp[0];
$id = $temp[1];
$textboxval = stripslashes(mysql_real_escape_string(preg_replace('/[\$]/',"",$_REQUEST["update_value"])));
$query = "INSERT INTO notes ($field,status,date,c_id) VALUES ('$textboxval','1',NOW(),'$id')";
mysql_query($query);
echo($_REQUEST['update_value']);
?>
I am not sure exactly what you mean - do you want to make all the entries except the new one have status = 0? If so, just issue an update before the insert:
UPDATE notes SET status = 0
However, I should also note that you have a potential SQL injection to worry about. By stripping slashes after applying "mysql real escape string", you are potentially allowing someone to put text in your SQL statement that will execute an arbitrary SQL statement.
Something like this, sorry for the post before, I mis read it the first time then went back:
<?php
include "../../inc/config.inc.php";
$temp = explode("_", $_REQUEST['element_id'] );
$field = $temp[0];
$id = $temp[1];
$textboxval = mysql_real_escape_stringstripslashes((preg_replace('/[\$]/',"",$_REQUEST["update_value"])));
// set older entries to 0 - to not show but show in history
$hide_notes = "UPDATE notes SET status = 0";
mysql_query($hide_notes);
// add new entry with status of 1 to show only latest note
$query = "INSERT INTO notes ($field,status,date,c_id) VALUES ('$textboxval','1',NOW(),'$id')";
mysql_query($query);
echo($_REQUEST['update_value']);
?>
i just ran in to a problem I didn't of the set up of my table doesn't allow me to show more than one client a time and i will be having numerous clients, my bad on planning ha
You really want to get the ID of the newly generated row and then trigger an UPDATE where you all rows where the ID is not the new row, e.g.
UPDATE notes SET status = 0 WHERE id != $newly_generated_id
If the ID column in your table is using AUTO_INCREMENT you can get its ID via "SELECT LAST_INSERT_ID()" and then use the return value in that statement in your UPDATE statement.
Pseudo code:
$insert = mysql_query("INSERT INTO ...");
$last_id = mysql_query("SELECT LAST_INSERT_ID()");
$update = mysql_quqery("UPDATE notes SET status = 0 WHERE id != $last_id");
The only caveat to this approach is where you might have a brief moment in time where 2 rows have status=1 (the time between your INSERT and the UPDATE). I would wrap all of this in a transaction to make the whole unit more atomic.

Categories