Calling a second query if results are empty - php

I'm calling an INNER JOIN Query to display results from a user if they have information in both tables 1 & 2 - this works fine. However, If said user doesn't have information in both tables then my variables come back undefined.
So I'd like to call my INNER JOIN query and if the rows are empty for Table1, it will call a second query to display the results from Table2.
(Table2 definitely has information stored. Table1 is optional depending on the user)
I also want to display results from Tables 1 & 2 if another user has information in both, I can't seem to get it working. Here's what I have so far;
$sql="SELECT * FROM Table1 INNER JOIN Table2 ON Table1.username = Table2.username WHERE Table1.username='" . $_SESSION['username']['1'] . "'";
$result=MySQL_Query($sql);
if (mysql_num_rows($result)==0)
{
$sql2"SELECT * FROM Table2 WHERE username='" . $_SESSION['username']['1'] . "'";
$result2=MySQL_Query($sql2);
}
while ($rows=mysql_fetch_array($result)($result2))
{
$Username = $rows['username'] ." ";
$Email = $rows['email'] . " ";
}
echo $Email; ?>

You can rewrite your query with an outer join as follows:
select
t1.desired_info
t2.desired_info
from
table2 as t2
left outer join
table1 as t1
on (t2.username = t1.username)
where
t2.username = target_username;
The where clause will narrow the result set down to the user of interest and return 0 rows if the target_username does not exist. t2.desired_info will always come back while t1.desired_info will be null if that user is not present in that table.
You can inspect p1.desired_info in your php code first and if that does not appear then use p2.desired.

Echo the suggestion to use OUTER JOIN, which joins all the selected rows in the left table to matching rows in the right, or to an empty row if there are no matching rows on the right.
Also, I've rewritten to use PDO and a prepared statement, to show you how its done. The values in the variables $dbhost, $dbname, $dbuser and dbpassword are supplied by your code.
<?php
$dsn = "mysql:host=$dbhost;dbname=$dbname";
$dbh = new PDO($dsn, $dbuser, $dbpassword);
$sql = "SELECT *
FROM table2 t1
LEFT JOIN table1 t1 ON t1.username = t2.username
WHERE t2.username = :username";
// prepare() parses and compiles the query. Syntax error come out here.
$stmt = $dbh->prepare($sql);
// bindValue() handles quoting, escaping, type-matching and all that crap for you.
$stmt->bindValue(':username', $_SESSION['username']['1']);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_BOTH))
{
$Username = $rows['username'] ." ";
$Email = $rows['email'] . " ";
// and then do something useful with them
}
The use of a prepared statement here gives a significant measure of protection against SQL injection attacks. As usual, I leave error handling as an exercise for the reader.

Related

PHP, PDO, SQLite INNER JOIN Statement And Variable

I need to do a PHP PDO call to my db with an INNER JOIN and WHERE clause.
In navicat GUI this statement is running fine and i can see the results. The problem come out lather in php environment about string concatenation.
I would like to format this request so that it can be digested by php:
SELECT * FROM tsourcetb as T INNER JOIN users as U ON U.username = T.username WHERE U.username = $username AND T.username = $username;
what I tried to do
$sth = $db->prepare("SELECT * FROM tsourcetb as T INNER JOIN users as U ON U.username = T.username WHERE U.username = $username AND T.username = $username");
the return is an error indicating that there is no table with the variable name. Basically it takes the variable as the name of the table the return is an error indicating that there is no table with the variable name. Basically it takes the variable as the table name and not the table name as it should like (SELECT * FROM $username) jumping out the first part of statement).
The intent is to have all the records of table A where the username field is = to the username field of table B with value passed from a variable.
Thank for any suggestion to achieve my goal.
UPDATE
php is magic need to try and retray. At the end tish one help me to goal:
$username = ($_POST['username']);
$password = ($_POST['password']);
$statement = $db->prepare('SELECT p.* FROM `tsourcetb` as p LEFT JOIN `users`as s ON p.username = s.username WHERE s.username = :username;');
$statement->bindParam(':username', $username, PDO::PARAM_STR);
$statement->execute();
/* look here -> $statement->fetchall(PDO::FETCH_ASSOC) */
$array_select = $statement->fetchall(PDO::FETCH_ASSOC);
echo json_encode($array_select, JSON_PRETTY_PRINT);
<?php
$sth = $db->prepare("SELECT * FROM `tsourcetb` as T INNER JOIN users as U ON U.username = T.username WHERE U.username = ? AND T.username = ? ");
$sth->execute([$username,$username]);
$results = $sth->fetchall();
?>
wrapper your table name with backticks and also use placeholders
Try this:
$stmt = $db->prepare("SELECT * FROM tsourcetb as T INNER JOIN users as U ON U.username = T.username WHERE U.username = :username AND T.username = :username");
$stmt->bindValue(':username', $username, PDO::PARAM_STR);
$stmt->execute();
You need to bind a value with prepared statement:
Source: Docs
You have to bind parameters when you are making an dynamic query with PDO.
Change this in your query.
$username -> :username
And before you make the call
$yourQueryObj->bindValue(':username', $username, PDO::PARAM_STR);
That's why prepared statments are safer than regular variables as you assign it's type before it's sent for query.
You can read about it here
http://php.net/manual/en/pdostatement.bindvalue.php
You should be able also execute with array of parameters after preparing like that :
$sth = execute(array(':username'=> $username));

Move Data from one table to another table using PDO php

I know that this may been ask many times, I just can't find the proper keywords to search my problem, although I found several ways doing it on mysqli. Though I was wondering if anyone can help me how to this on PDO.
<?php
$dsn = 'mysql:host=localhost;dbname=dbsample';
$username = 'root';
$password = '';
$options = [];
try {
$connection = new PDO($dsn, $username, $password, $options);
}
catch(PDOException $e) {
$id = $_GET['id'];
$sql = 'INSERT INTO table2 SELECT * FROM table1 WHERE id=:id';
$sql. = 'DELETE FROM table1 WHERE id=:id';
$statement = $connection->prepare($sql);
if ($statement->execute([':id' => $id])) {
header("Location:.");
}
Update: here's the error i get
Parse error: syntax error, unexpected '='
I've tried removing $sql. = but only get another error at the end.
Also tried removing the ., and same error at end Parse error: syntax error, unexpected end of file in
PDO doesn't allow you to execute two queries in a single call. So you need to prepare two different queries, then execute each of them separately.
You should use a transaction to ensure that the database is consistent across the two queries.
$stmt1 = $connection->prepare('INSERT INTO table2 SELECT * FROM table1 WHERE id=:id');
$stmt2 = $connection->prepare('DELETE FROM table1 WHERE id=:id');
$connection->beginTransaction();
if ($stmt1->execute([':id' => $id]) && $stmt2->execute([':id' => $id])) {
$connection->commit();
header("Location:.");
} else {
$connection->rollBack();
}
first end each query with ; PDO allow multiple query but must each one must be properly declared and ternimated ..
$sql = 'INSERT INTO table2 SELECT * FROM table1 WHERE id=:id;';
$sql. = 'DELETE FROM table1 WHERE id=:id';
then if you have error again could be that the schema for the two table don't match (or don't match for insert select ) so try using an explict columns declaration
$sql = 'INSERT INTO table2 (col1, col2, ..,coln)
SELECT (col1, col2, ..,coln)
FROM table1
WHERE id=:id; ';
$sql. = ' DELETE FROM table1 WHERE id=:id';

Prepared statement, loop results to get more results

I have a query where I'm taking several results from a single table. I then need to loop through each result to get information from other tables, however, I can't get it to work.
Here's my code:
<?php
$type = 1;
if ($stmt = $cxn->prepare('SELECT username FROM users WHERE type = ?')) {
$stmt->bind_param('i', $type);
$stmt->execute();
$stmt->bind_result($username);
while ($stmt->fetch()) {
if ($stmt = $cxn->prepare('SELECT count FROM posts WHERE username = ?')) {
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->bind_result($result2);
$stmt->close();
}
}
$stmt->close();
}
?>
I get an error:
Call to a member function fetch() on a non-object
How do I fix this?
I would highly recommend a native SQL JOIN for this because it will avoid unnecessary overhead in sending potentially thousands of queries:
SELECT
u.username,
p.count
FROM
users u
LEFT JOIN // processed as LEFT OUTER JOIN so the syntax is interchangeable just fyi
posts p
ON u.username = p.username
WHERE
p.type = ?
Explaining LEFT JOIN only, we'll keep it simple =)
In the SQL above we start with username from the users table as a whole
users u just grants us the shortcut syntax for u.username so that SQL is readable and doesn't fubar
Next we want to attach the posts p table where u.username = p.username because we need the p.count for each username
Lastly we filter this conglomerate of data based on p.type being equal to something
Please note that are many things at play here depending on the DBMS. Such things include query optimizers, the exact point of filtering, etc... but that is far outside the scope of simply getting the hang of what we are trying to achieve conceptually so I will not go into detail because it will only cause confusion.
You are overwritting your stmt variable. You should use another one, like
$type = 1;
if ($stmt = $cxn->prepare('SELECT username FROM users WHERE type = ?')) {
$stmt->bind_param('i', $type);
$stmt->execute();
$stmt->bind_result($username);
while ($stmt->fetch()) {
if ($stmtCnt = $cxn->prepare('SELECT count FROM posts WHERE username = ?')) {
$stmtCnt->bind_param('s', $username);
$stmtCnt->execute();
$stmtCnt->bind_result($result2);
$stmtCnt->close();
}
}
$stmt->close();
}

Multiple prepared statements (SELECT)

I'm trying to change my SQL queries with prepared statements.
The idea: I'm getting multiple records out of the database with a while loop and then some additional data from the database in the loop.
This is my old SQL code (simplified):
$qry = "SELECT postId,title,userid from post WHERE id='$id'";
$rst01 = mysqli_query($mysqli, $qry01);
// loop trough mutiple results/records
while (list($postId,$title,$userid) = mysqli_fetch_array($rst01)) {
// second query to select additional data
$query05 = "SELECT name FROM users WHERE id='$userid";
$result05 = mysqli_query($mysqli, $query05);
$row05 = mysqli_fetch_array($result05);
$name = $row05[name ];
echo "Name: ".$name;
// do more stuff
// end of while loop
}
Now I want to rewrite this with prepared statements.
My question: is it possible to run a prepared statement in the fetch of another prepared statement ? I still need the name like in the old SQL code I do for the $name.
This is what've written so far.
$stmt0 = $mysqli->stmt_init();
$stmt0->prepare("SELECT postId,title,userid from post WHERE id=?");
$stmt0->bind_param('i', $id);
$stmt0->execute();
$stmt0->bind_result($postId,$title,$userid);
// prepare second statement
$stmt1 = $mysqli->stmt_init();
$stmt1->prepare("SELECT name FROM users WHERE id= ?");
while($stmt0->fetch()) {
$stmt1->bind_param('i', $userid);
$stmt1->execute();
$res1 = $stmt1->get_result();
$row1 = $res1->fetch_assoc();
echo "Name: ".$row1['name'] ;
}
It returns an error for the second statement in the loop:
Warning: mysqli_stmt::bind_param(): invalid object or resource mysqli_stmt in ...
If I use the old method for the loop and just the prepared statement to fetch the $name it works.
You can actually do this with a single JOINed query:
SELECT p.postId, p.title, p.userid, u.name AS username
FROM post p
JOIN users u ON u.id = p.userid
WHERE p.id = ?
In general, if you are running a query in a loop, there is probably a better way of doing it.

Selecting from database where id in given array

I'm trying to select elements from a table in a mysql database where the id of a row is in the given array.
This returns values:
<?php
$ids = '1,2,3,4';
$DBH = ....
$getID = $DBH->prepare("SELECT * FROM t1 WHERE id IN ($ids)");
$getID->execute();
?>
This returns nothing:
<?php
$ids = '1,2,3,4';
$DBH = ....
$getID = $DBH->prepare("SELECT * FROM t1 WHERE id IN (:ids)");
$getID->execute(array(':ids'=>$ids));
?>
I can't understand what is wrong with that code.
In the first one, you're using PHP to do string interpolation before talking to the database; in effect, using PHP variables to generate SQL code. This is where SQL injection comes from - the database doesn't know the difference between data and code, so it can't protect you from "data" leaking into the "code" space. In the second, you are using bound parameters, telling the database "Please deal with :ids as a SINGLE VALUE, whose contents I will tell you later." An easy way to solve the disconnect is something like:
$sql = 'SELECT * from t1 where id in (' . str_repeat('?', count($ids)) . ')';
$stmt = $pdo->prepare($sql);
$stmt->execute($ids);
Check out this tutorial for more on these points.
Assuming you are using PDO, try the following.
<?php
$ids = '1,2,3,4';
$DBH = ....
$getID = $DBH->prepare("SELECT * FROM t1 WHERE id IN (:ids)");
$getID->bindParam(":ids", $ids, PDO::PARAM_INT);
$getID->execute();
?>
When your original query is executed, PDO will escape your input so your query will look like
SELECT * FROM t1 WHERE id IN ("1,2,3,4")
When you tell PDO to bind as a integer, it will execute
SELECT * FROM t1 WHERE id IN (1,2,3,4)

Categories