SQL/PHP Conditional SELECT and UPDATE - php

I'm trying to return 5 unused values from the codes column of the table below and then set used in the related row to 1.
|--- codes ---| | used |
| FIomQVu71l | | 0 |
| 4TW0lwLWNK | | 0 |
| SjzLB2Shzr | | 0 |
| uTWJrtCgh4 | | 0 |
| tLwOwYGz5R | | 0 |
| byEhzYMWJG | | 0 |
| XFBmGzDGIR | | 0 |
I've managed to get the code working to output 5 random values from codes where used = 0
<?php
$sql = "SELECT codes FROM code_table WHERE used =0 ORDER BY rand() LIMIT 5";
$records = mysql_query($sql, $connection);
while($rows = mysql_fetch_array($records)){
echo "Code: " . $rows['codes'] . "<br />";
?>
But now I'm lost as to how to update the used value for each output codes. All of my attempts have updated every single instance of used to 1 rather than just the instances associated with the 5 codes

You could store the rows in a temporary table. Note that this is not entirely concurrency safe. If another query comes between the insert and the update, it might grab the same rows.
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_codes (codes varchar(50));
-- Get five new rows
INSERT INTO tmp_codes
(codes)
SELECT codes
FROM code_table
WHERE used = 0
ORDER BY
rand()
LIMIT 5;
-- Update the five rows
UPDATE code_table
SET used = 1
WHERE codes in
(
SELECT codes
FROM tmp_codes
);
-- Return to application
SELECT codes
FROM tmp_codes;
DROP TABLE tmp_codes;
Example at SQL Fiddle.

You should execute an update query:
$sql = "SELECT codes FROM code_table WHERE used =0 ORDER BY rand() LIMIT 5";
$records = mysql_query($sql, $connection);
$codes = array();
while($rows = mysql_fetch_array($records)){
echo "Code: " . $rows['codes'] . "<br />";
$codes[] = "'" . $rows['codes'] . "'";
}
$updateSql = "UPDATE code_table SET used = 1 WHERE codes in(" . implode (',' , $codes ) . ")";
$res = mysql_query($updateSql, $connection);

Related

a field from table A IN a field on table B + mysql + php

I have two tables with the following structure:
tblA:
+----------+---------------+
| id (int) | name (string) |
+----------+---------------+
| 1 | a |
| 2 | b |
| 3 | c |
+----------+---------------+
tblB:
+----------+---------------+-------------+
| id (int) | name (string) | aid(string) |
+----------+---------------+-------------+
| 1 | x | '1,2' |
| 2 | y | '2,' |
| 3 | z | '1,3' |
+----------+---------------+-------------+
$a = $this::$db->prepare('SELECT * FROM tblB WHERE id= :id LIMIT 1');
$a->bindValue(':id', $ID, PDO::PARAM_INT);
$a->execute();
$r = $a->fetch(pdo::FETCH_ASSOC);
if ($a->rowCount() > 0){
$bInf = $r['id'] . '|*|' .
$r['name'] . '|*|' .
$r['aid'] . '|**|';
$b = $this::$db->prepare('SELECT id,name FROM tblA WHERE FIND_IN_SET(id,:ids)');
$b->bindValue(':ids', $r['aid']);
$b->execute();
$rs = $b->fetchAll(pdo::FETCH_ASSOC);
if ($b->rowCount() > 0)
{
foreach ($rs as $srow => $srval)
$aInf .= $srval['id'] . '[|]' .
$srval['name'] . '[#]' ;
} else
$aInf = ' ';
$aInf.= '|***|' . $bInf;
}
}
i need to query from tblA and tblB as above sample, but second query dont return any records.
i also tried 'IN' operator but dont worked too...
pls help me...
You can use a different approach by extracting each of the ids from aid column separately
$a = $this::$db->prepare('SELECT * FROM tblB WHERE id= :id LIMIT 1');
$a->bindValue(':id', $ID, PDO::PARAM_INT);
$a->execute();
$r = $a->fetch(pdo::FETCH_ASSOC);
if ($a->rowCount() > 0)
{
$bInf = $r['id'] . '|*|' .
$r['name'] . '|*|' .
$r['aid'] . '|**|';
//extract each of the ids in the variable 'aid'
$tbla_ids = explode(',',$r['aid']);
foreach($tbla_ids as $tbla_id){
//case for the record where aid = '2,'
if(strlen($tbla_id)==0){
continue;
}
$b = $this::$db->prepare('SELECT id,name FROM tblA WHERE id= :ids');
$b->bindValue(':ids', $tbla_id);
$b->execute();
//do what you need to do here. The query returns the single record
//from tbla that matches the id $tbla_id
}
}
Try something like this:
SELECT * FROM tblb,tbla
WHERE tblb.id= 1 AND FIND_IN_SET(tbla.id, tblb.aid)
for details, refer to:
FIND_IN_SET() vs IN()
I had a funny mistake, by removing ' Character from "aid" field, the problem was solved and FIND_IN_SET works right now.

PHP SQL query in while loop JOIN

I'm making a basic notification system for a practice project. I have several tables, two of which look something like the following:
> Table 1: "Users"
>
userid | username | Firstname | Lastname
1 | Daffy | Daffy | Duck
2 | Flinstone | Fred | Flinstone
3 | dduck | Donald | Duck
>
> Table 2: "Notifications"
>
Notification_id | from_user_id | to_user_id | SeenOrUnseen | type
1 | 1 | 2 | 1 | fRequest
> 2 | 1 | 2 | 0 | comment
> 3 | 1 | 2 | 1 | comment
> 4 | 3 | 1 | 1 | fRequest
> 5 | 2 | 3 | 1 | fRequest
> 6 | 2 | 3 | 0 | comment
> 7 | 3 | 2 | 0 | comment
I then need data from both these tables, and would normally JOIN the tables on the user_id and from_user_id before sending of an sql query. However, a join seems to return multiple values because in the second table there are multiple instances of from_user_id. Instead, i'm querying the database, returning the data in a while loop, and within that while loop sending out another query to the database for a different tables' information:
include('../../db_login.php');
$con = mysqli_connect("$host", "$username", "$password", "$db_name");
$tbl_name = "Profile";
$tplname = "profile_template.php";
$tplname2 = "public_profile_template.php";
$myid = $_SESSION['identification'];
//CHECK CONNECTION
if(mysqli_connect_errno($con)) {
echo "failed to connect" . mysql_connect_error();
}else {
$result = mysqli_query($con, "SELECT * FROM Notifications WHERE to_user_id='$myid'");
$count = mysqli_num_rows($result);
if($count == 0){
$style = "display:none;";
} else {
echo "<ul class='notifications'>";
while($row = mysqli_fetch_array($result)){
$from_user_id = $row['from_user_id'];
$to_user_id = $row['to_user_id'];
$seen = $row['seen'];
$nature = $row['nature'];
$result2 = mysqli_query($con, "SELECT * FROM users WHERE id='$from_user_id'");
$count2 = mysqli_num_rows($result2);
if($count2 != 0){
while($row2 = mysqli_fetch_array($result2)){
$fromFirstname = $row2['Firstname'];
$fromLastname = $row2['Lastname'];
}
if($nature == 'fRequest'){
echo "<li> You have received a friend request from" . $fromFirstname . " " . $fromLastname . "</li>";
}
}
}
echo "</ul>";
}
mysqli_close($con);
}
echo "<div id='NoNotification'></div>";
echo "<div id='Notification' style='" . $style . "'></div>";
?>
Is there a better way of doing this?
Thanks for any help!
You can do something like this:
SELECT n.*, u.*
FROM Notifications n
JOIN users u ON n.from_user_id=u.id
WHERE n.to_user_id=$myid
ORDER BY n.id, u.id
You will get all the data you need. The notification data and the user data. It is better to define which fields you want to retrieve in stead of * so you got a better view of what your using and your not sending data which you don't use.
Als you are using an integer (id) as a string, you can just put the $myid there. Also beaware this is not a safe query for MySQL injection. For more info.

Basic select and delete in MySQL (PDO)

I have the following basic query that selects a PIN from a table, binds it to a variable, and then deletes it from the table.
$sth = $this->db->query("SELECT available_pins FROM pin_list ORDER BY RAND() LIMIT 0,1 ;");
$pinarray = $sth->fetch();
$this->user_pin = $pinarray->available_pins;
$sth = $this->db->prepare("DELETE FROM pin_list WHERE available_pins = ? LIMIT 0,1");
$sth->execute(array($this->user_pin));
My problem: The PIN is selected and echoes fine, but it does not delete from the table. What am I doing wrong?
Also, how would I best add an if statement to catch an error in each of these two cases?
You have a syntax error in your DELETE syntax. LIMIT does not have an offset argument for DELETE.
When selecting the tuple, expand it to include the PK. After you have tied your attribute to a variable, you may delete the tuple by qualifying the where-clause with the PK.
Here is an example. Alas, the example is written in procedural PHP, I haven't coded OO-php for some time now. Sorry about that. Nonetheless, I think the main idea is conveyed. Please let me know otherwise.
Given that the database looks like this:
CREATE TABLE `pin_list` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT ,
`available_pins` CHAR( 8 ) NOT NULL ,
`aux` VARCHAR( 14 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = MYISAM ;
mysql> select * from pin_list;
+----+----------------+-----+
| id | available_pins | aux |
+----+----------------+-----+
| 1 | 43236543 | f |
| 2 | 43236523 | f |
| 3 | 43266523 | f |
| 4 | 48266523 | f |
| 5 | 48264823 | f |
+----+----------------+-----+
5 rows in set (0.00 sec)
The PHP-script may be written like this:
mysql_connect('mysql_server','user-id','pwd');
mysql_select_db('database-name');
//Select the available pin and its PK.
$query = "SELECT id, available_pins FROM pin_list ORDER BY RAND() LIMIT 0,1";
$rs = mysql_query( $query );
//Select id and available_ping into an array
$pinarray = mysql_fetch_array( $rs );
echo "The pin: " . $pinarray[1]; //Do something with it
//Save the primary key (PK, here: the id-attribute) for use in delete statement
$pk = $pinarray[0];
//Now: delete the pin that you have fetched from the database
echo "DELETE FROM pin_list WHERE id = " . $pk; //echo to debug sql-statements in php.
//Uncomment to delete
//$del_qry = "DELETE FROM pin_list WHERE id = " . $pk;
//mysql_query( $del_qry )

Sort SQL output by the order of added WHERE conditions

How can I sort values from SQL output by an external condition or e.g. the order of added WHERE conditions?
First I generate multiple ID's with a "json_decode foreach loop"
$itemid = '';
$arr = json_decode($string,true);
foreach($arr['feed']['entry'] as $val)
{
$itemid .= " OR `item_id` = ".$val['id']['att']['ix:id'];
}
The output is e.g. (simplified)
`item_id` = 2
OR `item_id` = 3
OR `item_id` = 1
Here the order of the output is important for me. 2 is the ID of the first position, 3 of the second position and so on.
In the next step I use all IDs in a MySQL statement to pull information for each IDs
$sql = "
SELECT *
FROM `itemtable`
WHERE $itemid
";
Which is more readable:
$sql = "
SELECT *
FROM `itemtable`
WHERE `item_id` = 2
OR `item_id` = 3
OR `item_id` = 1
";
The SQL output is now in the order of the IDs ASC
+-------+-----------+
| ID | INFO |
+-------+-----------+
| 1 | something |
+-------+-----------+
| 2 | something |
+-------+-----------+
| 3 | something |
+-------+-----------+
But I need the Info in the order how the IDs where generated by the json_decode:
+-------+-----------+
| ID | INFO |
+-------+-----------+
| 2 | something |
+-------+-----------+
| 3 | something |
+-------+-----------+
| 1 | something |
+-------+-----------+
I am outputing the received data with another foreach loop in the same php script:
$output = '';
foreach ($xpdo->query($sql) as $row) {
$output .= $row['ID']
.$row['INFO']
."</br>";
}
return $output;
How can I get the output into the order of the json_decode? Actually I dont mind weather the sorting happens in the SQL statement or in PHP.
EDIT : SOLUTION from Fluffeh
Modified the json_decode to + adding an IF condition for the first entry to remove the "union all" here.
$itemid = '';
$arr = json_decode($string,true);
foreach($arr['feed']['entry'] as $val)
{
$itemid .= "union all
SELECT * FROM `itemtable`
WHERE `item_id` = ".$val['id']['att']['ix:id'];
}
You technically can't, but if the query isn't TOO bad, you could write some code to do this:
$sql = "
SELECT *
FROM `itemtable`
WHERE $itemid1
union all
SELECT *
FROM `itemtable`
WHERE $itemid2
";
If you put some PHP to join the queries together it will work quite easily.
When you run union queries, the data will be returned in the order of the queries themselves.

Handling singular records of a column

I have a database like this:
----------------------------------------------
| ID | Time | Typeop | Operator |
----------------------------------------------
| 1 | 10:01 | withdrawal | John |
| 2 | 10:01 | deposit | Mike |
| 3 | 10:01 | deposit | Andrew |
| 4 | 10:02 | check | John |
| 5 | 10:02 | withdrawal | Simon |
| 6 | 10:03 | withdrawal | Dorothy |
by the following query i select the last three rows:
SELECT * from mytable ORDER BY ID DESC LIMIT 0,3
THE ISSUE: I need to "echo" in a php script the last three operators in different places of my script and in different orders, so i'd assign each name to a different variable. In this example:
$name0 = Dorothy
$name1 = Simon
$name3 = John
So I will be able to put them (for example) in a text like this... "Dorothy has been the last to make an operation after Simon. John today stopped before the three..."
Thk in advance
// Collects data from table
$data = mysql_query("SELECT * from mytable ORDER BY ID DESC LIMIT 0,3") or die(mysql_error());
// puts the "mytable" info into the $info array
$info = mysql_fetch_array( $data );
// print the info
while($info = mysql_fetch_array( $data ))
{
echo "<b>Operator:</b> ".$info['Operator'] . " ";
}
Put the result into an array and use the keys 0, 1, and 2 to target them:
$operators = array();
$result = $mysqli->query("SELECT Operator from mytable ORDER BY ID DESC LIMIT 0,3");
if($result)
{
while($row = $result->fetch_assoc())
{
$operators[] = $row['Operator'];
}
}
if(count($operators) >= 3)
{
echo htmlentities($operators[0]) . " has been the last to make an operation after " . htmlentities($operators[1]) . ". " . htmlentities($operators[2]) . " today stopped before them";
}
This example uses MySQLi and assumes there will always be 3 records.
Edit: It's the same principle when any MySQL library, for example with the native mysql_* library:
$operators = array();
$result = mysql_query("SELECT Operator from mytable ORDER BY ID DESC LIMIT 0,3");
if($result)
{
while($row = mysql_fetch_assoc($result))
{
$operators[] = $row['Operator'];
}
}
if(count($operators) >= 3)
{
echo htmlentities($operators[0]) . " has been the last to make an operation after " . htmlentities($operators[1]) . ". " . htmlentities($operators[2]) . " today stopped before them";
}
You need to store the result in an independent php array
$ops = array();
$result = mysql_query("SELECT Operator from mytable ORDER BY ID DESC LIMIT 0,3");
$i = 0;
if($result)
{
while($row = mysql_fetch_assoc($result))
$ops[$i++] = $row[0];
}
Here $row changes each time, it will keep only latest value but $ops is storing all
Now you can use this array for your desired output anywhere (until you change the array $ops) e.g.
$st = $ops[0]." has been the last to make an operation after ".$ops[1].". ".$ops[2]." today stopped before the three...";
echo $st;

Categories