Using sql JOIN - php

I'm a sql noob trying to get this query to use 2 tables.
tables & columns are:
person:
department_id,
name,
etc...
department:
department_id,
dept_name,
etc...
I have a 'select' html form that the user will choose a dept_name from, and I need my php script to return every person with a matching department_id. Here is my code & query so far, I'd appeciate any help.
$search_dept = $_POST['search_dept'];
$conn = odbc_connect($odbc_name, $user_name, $pass_wd);
if ($conn) {
$query = "SELECT person.*
FROM department
JOIN person
ON department.department_id=person.department_id
WHERE department.name=$search_dept";
if($result = odbc_exec($conn, $query)) {
echo '..stuff';
while ($row = odbc_fetch_array($result)) {
...echo stuff
}
echo '...stuff';
}
else {
echo 'Query was unsuccessful';
}
}
else {
echo 'Unable to connect to database';
}

First of all, you are going about this the wrong way. You don't want to execute a WHERE clause against a text-type column if you can avoid it. Since your person table already has the department_id as a foreign key, you will want to use that value to do your selection. This means you will have to modify your select element to contain the department IDs as the options' values.
<!-- Example -->
<select name="dept_id">
<option value="1">Sales</option>
<option value="2">Support</option>
<option value="3">Fulfillment</option>
</select>
So now, not only will just the raw selection occur faster since you'll be executing against an indexed column (you did make it a proper FK so it's indexed, right?), but you will also be removing the join altogether! (which is another boost to the query's speed)
// Here is injection-safe code for the ODBC driver
$stmt = odbc_prepare( "SELECT * FROM person WHERE department_id = ?" );
$success = odbc_execute( $stmt, array( $_POST['dept_id'] ) );
// Here is the old, non-secure version, but is db-driver agnostic
$deptId = $_POST['dept_id']; // escape this please!
$query = "SELECT * FROM person WHERE department_id = $deptId";

Try this query, also make sure to escape any user input. What if the user would provide:
$_POST['search_dept']= "'; DROP TABLE person;";
Never ever ever thrust userinput!
$search_dept = mysql_escape_string($_POST['search_dept']); //make sure to escape this! you can use other functions for this as well. I'm not sure if PDO has some.
$query = "SELECT *
FROM person
JOIN department
ON department.department_id=person.department_id
WHERE department.name='$search_dept'";

Related

nested while loop stops after first iteration PHP

I'm fairly new to this so I am probably missing something very basic, but I am trying to write some PHP script. I want to normalize my main table of data, which is info on used cars, make, model, price, etc. So I have another table with all of the unique car manufacturers in, this stores the makeName with a unique id makeId In my script, I connect to the database, read in all of the data from the main table, run it as an SQL query, then store it as a variable. I do the same with the make table.
Then I try to run through a nested while loop to replace all of the strings in the main table in the Manufacturer column with the makeId from the make table so that I can link these two tables. It works for one iteration then stops, I've tried adding !==FALSE after the fetch_assoc in either and both while loops, but that gives me infinite loops I think. Here is my code...
<?php
include("conn.php");
$sqlAll= "SELECT * FROM carData";
$carDataResult = $conn->query($sqlAll);
if(!$carDataResult){
echo $conn->error;
die();
}
$sqlMake = "SELECT * FROM 000make";
$makeResult = $conn->query($sqlMake);
if(!$makeResult){
echo $conn->error;
die();
}
while ( $make =$makeResult-> fetch_assoc()){
$makeID = $make['makeId'];
$makeName = $make['makeName'];
while ($row = $carDataResult->fetch_assoc()){
$sqlUpdate="UPDATE carData SET Manufacturer = '$makeID'
WHERE Manufacturer='$makeName' AND Manufacturer IS NOT NULL";
$res = $conn->query($sqlUpdate);
if(!$res){
echo $conn->error;
die();
}
}
}
?>
About 10 mins after I posted the question, after staring at this all day, I realised that I didn't need a nested loop at all and wrote the code below, which is clunky but it solved the problem, but I like your solution better #TangentiallyPerpendicular...thanks for your help guys...
while ($make =$makeResult-> fetch_assoc()){
$makeID = $make['makeId'];
$makeName = $make['makeName'];
$sqlUpdate="UPDATE carData SET Manufacturer = '$makeID'
WHERE Manufacturer='$makeName' AND Manufacturer IS NOT NULL";
$res = $conn->query($sqlUpdate);
if(!$res){
echo $conn->error;
die();
}
}
As a general rule, reading a result set and looping through it to run successive queries is the wrong way to deal with this sort of problem. You can do it all in a single query:
update carData set `Manufacturer` = (select `makeId` from `000make` where 000make.makeName=carData.Manufacturer)
Your entire program becomes:
<?php
include("conn.php");
$sqlAll= "update carData set `Manufacturer` = (select `makeId` from `000make` where 000make.makeName=models.Manufacturer) ";
$carDataResult = $conn->query($sqlAll);
if(!$carDataResult){
echo $conn->error;
die();
} else {
echo "Update Successful"
}
As an aside, I'd create a new column (called, perhaps, makeId) in your carData table and insert the data there rather than overwriting the Manufacturer column. That way you retain the Manufacturer column if something goes wrong. You can drop that column later.

Reading data from two tables on a same database, using "if - else"

ok guys I need a bit of help with this, remaking this to format ir properly.
I have this code:
(this is accessing a table called "students" in database.)
<?php
require_once('connection.php');
$id = $_SESSION['SESS_MEMBER_ID'];
$result3 = mysql_query("SET NAMES UTF8;");
$result3 = mysql_query("SELECT * FROM students where mem_id='$id'");
while($row3 = mysql_fetch_array($result3))
{
$fname = $row3['fname'];
$country = $row3['country'];
$class = $row3['class'];
$headteacher = $row3['headteacher'];
$attendance = $row3['attendance'];
$homework = $row3['homework'];
$messagestudent = $row3['messagestudent'];
}
?>
<?php
if($class=='K1')
echo "teacher 1";
else if($class=='K2')
echo "teacher 2";
else if($class=='K3')
echo "teacher 3";
?>
In another table, i have the teacher names and what i need to do and i cannot find the right way to do it, is to call the teacher's name from the table "teachers" after the query confirms the K1, K2 or K3 data on the "students" table column "class".
Basically what i need is to change the contents of the echo part, switching it from static data needed to be within the code, to a data contained on another table, for example. both tables have a column called "class", so if class column for a student says "K1" i want this to then go check the "teacher" table's column "class" and pick the one that matches "K1" and display it in the result echo, I'm sure it is possible, but not with my current skill level.
The table structure for students is:
mem_id, username, password, fname, country, class, attendance, homework, messagestudent
The table structure for teacher is:
mem_id, class, name, comment
Hope you guys shed some light on me!
Thanks in advance.
PS. I know the query is using the deprecated mysql_, but when I tried to change it to mysqli_ following a guide, it never worked.
If I understood, you can get the desired data through this query (without JOIN or if statement):
SELECT students.*,teachers.name FROM students,teachers WHERE students.id='$id' AND students.class = teachers.class
It returns the teacher name according the student class, at the same row.
You can use left join for this. Try using following query:
SELECT * FROM students as st
LEFT JOIN teachers AS ts
on st.class=ts.class
WHERE st.mem_id = '$id'
You don't need to use if-else statement for this. And it will also work with mysqli.
According to your script, it should work like:
<?php
require_once('connection.php');
$id = $_SESSION['SESS_MEMBER_ID'];
$result3 = mysql_query("SET NAMES UTF8;");
$result3 = mysql_query("SELECT st.*, ts.name AS teacher_name FROM students as st LEFT JOIN teachers AS ts on st.class=ts.class WHERE st.mem_id = ".$id);
while($row3 = mysql_fetch_array($result3))
{
$fname = $row3['fname'];
$country = $row3['country'];
$class = $row3['class'];
$headteacher = $row3['headteacher'];
$attendance = $row3['attendance'];
$homework = $row3['homework'];
$messagestudent = $row3['messagestudent'];
$teachername = $row3['teacher_name'];
}
echo $class. ' - '. $teachername;
?>

Need to update only one tuple, but this is updating the whole column in table

I check if the the url is present first and see if he is up voting first time, if so then i will add the users repute to the upvoted column, but i want to add only to that url not to all urls, this code is adding to all all tuples in "upvotes" column, i want it to add only to a particular tuple.
<!Doctype html>
<html>
<?php
$c=$_GET['a'];// users name
$d=$_GET['b'];// usesrs id
$e=$_GET['c'];// users repute
$ur=$_POST['url'];
// Create connection
$con=mysqli_connect("localhost","root","","repute system");
if(mysqli_connect_errno()){
echo "ERROR ".mysqli_connect_error();
}
$sql = mysqli_query($con,"SELECT * FROM sites");
if (mysqli_num_rows($sql) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($sql))
{
if($ur == $row['URL'] && $d != $row['id'])
{
$ne = $row['upvotes'] + $e;
$sol = mysqli_query($con, "UPDATE sites SET upvotes = $ne ");
$bew = mysqli_query($con,"INSERT INTO v_sites(teacher_id,URL,vote) VALUES ('$d','$ur','$e')");
echo "Upvoted the site ";
echo $ur;
}
}
} else {
echo "Sorry before upvoting you have to block it first or you are trying to upvote your own report, in which you cant";
}
?>
</html>
You need a WHERE clause that matches the URL:
$stmt = mysqli_prepare($con, "UPDATE sites
SET upvotes = upvotes + 1
WHERE url = ? AND id = ?";
mysqli_stmt_bind_param($stmt, "ss", $ur, $d);
mysqli_stmt_execute($stmt);
You don't need the SELECT or while loop, since MySQL can find the matching rows and update them all by itself.
You also shouldn't have the INSERT query inside the loop, since it's inserting the same row each time.
And you should switch to prepared statements, as shown above, instead of inserting strings into your queries, since your code is subject to SQL injection.
All your rows are being updated because you are not using a where clause.
UPDATE sites SET upvotes = $ne
should be changed to:
UPDATE sites SET upvotes = $ne WHERE id='$d'
However, if $ne is also a string, $ne should also be quoted:
UPDATE sites SET upvotes = '$ne' WHERE id='$d'
Read up on UPDATE:
https://dev.mysql.com/doc/refman/5.0/en/update.html
"My table's name in sites it has 5 columns, which are URL,status,upvotes,downvotes, id and all are varchar with 30 length"
This tells me that id is VARCHAR also; not a good idea but that's up to you. It's best to use int for queries like this should all your id's be numerically-based.
Which is why using quotes WHERE id='$d' around the $d variable will be required.
Your present code is open to SQL injection. Use prepared statements, or PDO with prepared statements, they're much safer.

Using data from multiple tables

Here's my issue: I have 3 tables, with overlapping information (specifically, the username) in each. Except the username row isn't named the same thing in every table. Because the username is specific to the user, it makes sense to get all the other information about the user based on the username. Here's what I have. (The first function returns the query, the second function returns the information in an array (or is supposed to, anyway).
function get_user_by_id($id) {
global $connection;
$query = "SELECT * FROM ownerOrganization, owner, queue_acl";
$query .=" WHERE owner.ownerId=ownerOrganization.ownerId";
$query .=" AND owner.ownerId=queue_acl.user_id";
$query .= " AND owner.ownerId ='{$id}'";
$result_set = mysql_query($query);
confirm_query($result_set);
if ($user = mysql_fetch_array($result_set)) {
return $user;
} else {
return NULL;
}
}
function get_user_id() {
if (isset($_GET['ownerId'])) {
return get_user_by_id($_GET['ownerId']);
}
}
But when I do something like, $sel_user = get_user_id(); on another page, it doesn't actually pull up any of the selected users information... I assume that this is happening because my syntax regarding working with multiple tables is incorrect. Anyway, any input would be much appreciated.
To use JOINS, take this snipcode in example :
$query = "SELECT * FROM (ownerOrganization INNER JOIN owner ON owner.ownerId=ownerOrganization.ownerId) INNER JOIN queue_acl ON owner.ownerId=queue_acl.user_id";
$query .=" WHERE owner.ownerId ='{$id}'";
Regards
I was typing what more or less what #MTranchant wrote. I would suggest renaming your columns for easier query authoring and to avoid confusion. For instance your ownerOrganization.ownerid could be named oo_ownerid, and the other columns in the table could follow that naming convention.
Also, have you run the query against the database with a hard-coded $id that you know exists?
Lastly in the query string being sent to the next page, does a ownerId parameter appear that looks like "&ownerId="?

mySQL fetch column based on another column in PHP

I'm trying to write my first PHP script with mySQL and I desperately need some help. I'm sure this is relatively simple, but if I have one field in my table (username, for example), and I want to fetch another field (name, for example), that is in the same row as the given username, how do I do that?
Again, I'm sure this is easy, but I'm lost, so I'd really appreciate any help. Thanks!
$sql = "SELECT username, name FROM table";
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)) {
echo "This {$row['username']} has the name {$row['name']}\n";
}
halfdan's answer sort of works, but it fetches all rows and displays them. What you want is a WHERE clause, which lets you filter the contents of the table so the query only returns the row(s) you want:
SELECT username, name
FROM sometable
WHERE (username = 'johndoe');
This will return only the rows where the username field is equal to 'johndoe'. Conceptually, it's equivalent to:
$results = mysql_query("SELECT username, name FROM table");
while($row = mysql_fetch_assoc($results)) {
if ($row['username'] == 'johndoe') {
// do something, this is a row you want
} else {
// not a row you want. ignore it, or deal with it some other way
}
}
the main difference is that for large data sets in the database, doing client-side filtering like this is expensive, as the entire contents of the table has to be transferred over. Using a WHERE clause to limit things to just what you want is far more efficient in the long run.

Categories