First of all, I am absolute beginner with PHP and SQL.
I have two tables: users(userID, fullname, username, email, pass, userlevel) and games(gameID, userID, club, result, created_time).
In table games I have userID, same as in table users, but it's not foreign key. When I do this query in MySQL it works fine:
DELETE FROM games
WHERE EXISTS
(SELECT * FROM users
WHERE userlevel=2
AND users.userID=games.userID)
It removes anything that users.userID matches with games.userID and if that user is userlevel 2.
I need this in PHP, but only difference would be that userID will match user's ID that is logged,and user will be able to delete only the data that is input with its userID.
Also, how to allow everyone else, with userlevel 1 to be able to delete everything in table games no matter who entered on the same submit?
I have this, but its not working....it keeps givin' me the same error:
Fatal error: Call to a member function bind_param() on a non-object in
C(...)
require ('db_con.php');
session_start();
$userID=$_SESSION["UserID"];
if (isset($_POST['delete'])){
$stmt=$con->prepare("DELETE FROM games WHERE EXISTS (SELECT FROM users AS u WHERE u.userID = ? AND u.userlevel = 2 "));
$stmt->bind_param("s",$_POST['userID']));
$stmt->execute();
}
Even if I put $userlevel=2 and replace in query u.userlevel = '$userlevel', it gives the same error...
Any suggestions would be greatly appreciated.
thanx!
userID is an integer value. Change bind_param line to
$stmt->bind_param('i', $user_id);
One reason prepare() can fail is -
if the sql statement sent to it is not valid in the current DB.
prepare() will then return false.
Eg - if the table name is not correct or one or more field in the query does not exist.
You got a bracket mismatch:
$stmt=$con->prepare("DELETE FROM games WHERE EXISTS (SELECT FROM users AS u WHERE u.userID = ? AND u.userlevel = 2 "));
should really be
$stmt=$con->prepare("DELETE FROM games WHERE EXISTS (SELECT * FROM users AS u WHERE u.userID = ? AND u.userlevel = 2 )");
Anyway, the error you received means that $con->prepare did not return an object. Most likely it returned false. I assume you are using PDO, so according to the docs:
If the database server cannot successfully prepare the statement, PDO::prepare() returns FALSE or emits PDOException (depending on error handling).
So that's the case here. Your MySQL-server was unable to bind the statement. In order to debug this better (e.g. see more helpful error messages) set PDO to throw exceptions on errors.
You could probably do it like this:
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Just add that line right after you connect to the database.
i found the error, here is the wright code:
$stmt=$con->prepare("DELETE FROM games WHERE EXISTS (SELECT * FROM users WHERE users.userID = ? AND users.userlevel = 2 )");
but its not working what i wanted, it deleted all from my games table :D
i guess, SELECT * FROM has to be specific!
Related
Actually im trying to display data from 2 tables on database based on current session, basically, i had read many article and forum on how to solve this problem but i still facing them till now. so those are data and code that already i did:
<?php
include('db.php');
$sql="SELECT*
FROM users
INNER JOIN details ON users.id= details.id LIMIT 1 WHERE users.id ='$loggedin_id' " ;
$result=mysqli_query($db,$sql);
if (!$result) {
printf("Error: %s\n", mysqli_error($db));
exit();
}
?>
so here, i got this error:
"Error: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'WHERE users.id = '16'' at line 3". so if i only use this query:
$sql="SELECT* FROM users INNER JOIN details ON users.id= details.id"
it will display all data in my database, but i only need data from current session.
here is my session.php file:
<?php
include('db.php');
session_start();
$user_check=$_SESSION['sess_username'];
$ses_sql=mysqli_query($db,"select username,id from users where username='$user_check' ");
$row=mysqli_fetch_array($ses_sql,MYSQLI_ASSOC);
$loggedin_session=$row['username'];
$loggedin_id=$row['id'];
$role = $_SESSION['sess_userrole'];
if(!isset($loggedin_session) && $role!="user"){
header('Location: index.php?err=2');
}
?>
this is my tables detail:
table users
table details
hope someone can help me, im new with my sql and php. tq
Change your query like that.
$sql="SELECT*
FROM users
INNER JOIN details ON users.id= details.id WHERE users.id ='$loggedin_id' LIMIT 1" ;
I think your query should be like below:
$sql = "SELECT * FROM users
INNER JOIN details ON users.id= details.id WHERE users.id = $loggedin_id ";
You can neglect the INNER JOIN and Use Procedural Steps as follows:
Step 1: Just Start Session in all your pages- session_start();
Step 2: In your Db create a column for Session e.g sessionCheck
Step 3: On the Sign-up page start session and use MySqli last insert
function like:
$_session["anything"] = mysqli_insert_id(your db connection variable);
then store this session Id to a variable (like - $sessionCheck = $_session["anything"]; Insert the value of this variable to all the column in your Database on the session column as you perform insert. Let the session column by int and unique.
Step 4: On the Display Page use control structure specifically Nested
IF instead of INNER JOIN.
STEP 5: ALL your Insertion insert the value of $_sessionCheck into
sessionCheck in all your tables except the sign-up page (because the
session id is originally picked from sign-up page so you don't need
to insert into sign up again)
Step6: All your Select should be tie to WHERE sessionCheck = $sessionCheck
This works perfectly well for me on my Procedural PHP 7 (MySqli) and MySQL 5
I have the following code in a controller. The query given runs on a MediaWiki database:
// Grab the connection to the replica database (which is separate from the above)
$conn = $this->get('doctrine')->getManager("replicas")->getConnection();
// Prepare the query and execute
$resultQuery = $conn->prepare( "
SELECT 'id' as source, user_id as value FROM $dbName.user WHERE user_name = :username
UNION
SELECT 'arch' as source, COUNT(*) AS value FROM $dbName.archive_userindex WHERE ar_user_text = :username
UNION
SELECT 'rev' as source, COUNT(*) AS value FROM $dbName.revision_userindex WHERE rev_user_text = :username
UNION
SELECT 'groups' as source, ug_group as value FROM $dbName.user_groups JOIN user on user_id = ug_user WHERE user_name = :username
");
$resultQuery->bindParam("username", $username);
$resultQuery->execute();
(I know my SQL isn't efficient, it's legacy code that I'm working on cleaning up)
The fourth query is the focus of this question. When the query is run in PHPMyAdmin or MySQLWorkbench it returns the correct results. However, when run in Symfony sometimes it returns the improper results. How can I ensure that it returns the correct results?
(Full full code: https://github.com/Matthewrbowker/xtools-rebirth/blob/master/src/AppBundle/Controller/SimpleEditCounterController.php#L95)
Figured out my question. One thing that wasn't noted was the fact that I wound up selecting the right database name out of a table. This was stored in the variable $dbName. However, it is possible for $dbName to be different than the database that I connected to from paramaters.yml.
Note:
JOIN user on user_id
This portion of the query was missing $dbName. To fix, just add the variable. Like so:
JOIN $dbName.user on user_id
I have a table of records, table 1.
I want to do 2 things, delete all records in table 1 from a specific user and add those deleted records to table2, as a back up.
I'm using mysqli prepared statements.
I also want to do it with one statement and not multiple statements, if possible.
My research led me to this
$stmt2 = $c1->prepare("DELETE FROM `scroll` OUTPUT.* INTO `deletedscroll` WHERE user= ? ");
But I keep getting syntax errors. This code may not be for mysqli is my guess, but the mysqli documentation doesn't go into this.
Does anyone know the correct syntax? I also see stuff on using:
DELETE FROM [source]
OUTPUT [deleted].<column_list>
INTO [destination] (<column_list>)
But I can not get that to work at all.
I have gotten this to work, which uses 2 calls, but it gets the job done without errors.
$stmt2 = $c1->prepare("INSERT INTO `deletedscroll` (user, text, flag, date ) SELECT user, text, flag, date FROM `scroll` WHERE user= ? ");
$stmt2->bind_param('s', $user);
$stmt2->execute();
$stmt2->close();
//move deleted users records from scrolls to deleted table
$stmt3 = $c1->prepare("DELETE FROM `scroll` WHERE user= ? ");
$stmt3->bind_param('s', $user);
$stmt3->execute();
$stmt3->close();
This question already has answers here:
How to resolve ambiguous column names when retrieving results?
(11 answers)
Closed 2 years ago.
I have fields that have the same name in different tables that I'm joining. Such as ticket.status, user.status and transaction.status. At the moment the query returns just status.
How can I get the table name in such a way that it stops similar field names from overwriting and so I can tell the difference between the fields.
Simply put:
$data = array($eventId);
$statement = $this->db->prepare("SELECT * FROM ticket, user, transaction
WHERE ticket.eventId = ?
AND ticket.userId = user.userId
AND ticket.transactionId = transaction.transactionId");
$statement->execute($data);
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
In my research I've found the constant PDO::ATTR_FETCH_TABLE_NAMES that looks like it could help, but I do not know how to implement ( I assume through $statement->setAttribute(); somehow).
I also have concerns that it will not work, as the PHP documentation mentions it is dependent on the driver.
Thanks
Just add new aliases to your select statements
$statement = $this->db->prepare("
SELECT *, ticket.status AS ticket_status, user.status AS user_status, transaction.status AS transaction_status
FROM ticket, user, transaction
WHERE ticket.eventId = ?
AND ticket.userId = user.userId
AND ticket.transactionId = transaction.transactionId
");
Then you can do
$rows[0]['user_status'];
$rows[0]['ticket_status'];
$rows[0]['transaction_status'];
If you are really concern by performance, the quantity of data returned will be greater so instead of adding new aliases you can select every single columns and while you do so put an alias on the status column.
Why not change your to actually join instead:
SELECT
t.status as ticket_status, u.status as user_status, tr.status as trans_status
FROM
ticket as t
inner join user as u on t.userId = u.userId
inner join transaction as tr on t.transactionId = tr.transactionId
where
t.eventId = ?
You don't even need to cast the tables using as something but I find it's neater.
Note, its the casting of the columns that will actually fix this issue, not the join method.
The most obvious comment is "don't do it, that's why aliases exist". But there's still a good underlying question: does MySQL send information about where a result-set column comes from (table, view or calculated)?
Apparently, it does, since the PDOStatement object has an experimental method called getColumnMeta(). I've been testing and it returns an associative array where the table key
contains the source table if column comes from a table or view
is an empty string if the column is calculated
Of course, I'd stick to aliases anyway. Being able to use associative arrays is a killer feature for me.
I am fairly new to MySQLi and prepared statements. Been following lots of tutorials recently to get to know how they work but still cant get this thing figured out. When new user tries to register I want to check if the username and email already exists in the db. The following code works when I do the check on 1 table but does not when I try to check multiple tables for existing entries. Ive tried join and cross join clauses as well as union and union all. The Dreamweaver shows no syntax errors but there have to be code issues somewhere. I was wondering if I have to set relation between tables in phpmyadmin before I can join the tables but I do not think this causes problem.
// check if the email is taken
$check = $mysqli->prepare("SELECT email FROM parents JOIN leaders WHERE parents.email = ? OR leaders.email = ?");
$check->bind_param("s", $input['email']);
$check->execute();
$check->store_result();
Ok, given that you have 3 tables with the same structure, you want to UNION the tables together in one query, with one condition in the WHERE clause.
// UNION query to combine all three tables.
// The union is wrapped in a subquery to apply the single WHERE clause
// to the whole thing...
$sql = "
SELECT email FROM (
SELECT email FROM parents
UNION SELECT email FROM leaders
UNION SELECT email FROM guides
) combined
WHERE email = ?";
if ($check = mysqli->prepare($sql)) {
// Bind one input param
$check->bind_param("s", $input['email']);
$check->execute();
$check->store_result();
// Then fetch your row however you had planned to do so...
}
Note about the table structure:
Generally it is not recommended to have multiple tables with the same structure. Instead of 3 different tables here, you should have one table which combines all of them and has a column that identifies the type as leader,guide,parent.