MYSQL delete statement deletes too many rows - php

I have a table for users in my MYSQL db like so:
CREATE TABLE `myDatabase`.`user` (
`id` INT NOT NULL AUTO_INCREMENT ,
`login` VARCHAR(250) NOT NULL ,
`uid` VARCHAR(250) NOT NULL ,
`email` VARCHAR(250) NOT NULL ,
`user_type` VARCHAR(250) NOT NULL ,
PRIMARY KEY (`id`)) ENGINE = InnoDB;
uid is provided by firebase when a user logs in (strings such as 3LmgcBeCUNW1lfMKCQcoI8Xkxai1
or DrFblVatVdacokhcQCuwb8DK13q1.
My project has a delete user option that calls the query:
public function deleteProfile($uid) {
$memberDelete = $this->_db->prepare("DELETE FROM user WHERE uid = :uid");
$memberDelete->bindParam(':uid',$uid,PDO::PARAM_INT);
$resp = $memberDelete->execute();
if(!$resp) {
throw new PDOException('member couldn't be removed');
}
$memberDelete->closeCursor();
return "member successfully removed";
}
When I do this, it deletes way too many users. I tried deleting based on email instead of UID and it deleted all of the users.

Here:
$memberDelete->bindParam(':uid', $uid, PDO::PARAM_INT);
You are binding your param as an integer, while obviously it's a string. This generates a chain of implicit conversions that ends up deleting more rows that you intend.
Instead, you want:
$memberDelete->bindParam(':uid', $uid, PDO::PARAM_STR);

Related

How to allow mutilple page to insert multiple data at the same time (will not clash) in MySQL PHP

I have a online page which will allow user to create an account for them in order to acceess our page.
I worry in some period, there will be a lots of user who create at the same time.
In that case, I worry my database will be clash or conflict.
Can I know is that anyway to prevent that happens?
My table as below:
CREATE TABLE `user` (
`id` int(11) NOT NULL,
`userid` varchar(30) DEFAULT NULL,
`password` varchar(20) DEFAULT NULL,
`name` varchar(40) DEFAULT NULL
)
ALTER TABLE `user`
ADD PRIMARY KEY (`id`);
ADD UNIQUE KEY `userid` (`participant_id`);
ALTER TABLE `user`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
COMMIT;
So my id will be just number and auto increment.
userid wil be unique.
I created the page by using PHP.
And I use following insert command at my page:
do {
$query = "INSERT IGNORE INTO user(userid, password, name) VALUES ('$userid','$password','$name')";
$insert = $conn->query($query);
} while( $insert && ($conn -> affected_rows == 0) );
Are this code can work perfectly to prevent the date conflit?
Another extra question is, how about if I create another extra page which will insert information 'user' table and can I used the same code at the new page?

Why my MySQL function to check if inserted data exists not working?

I'm writing a registry form and wanna check if inserted data exists.
I wrote my own function to do that. This Function should check tables and if rows exist, return FALSE and if not exist then return TRUE and will insert the data to the tables.
I have 2 tables: 'users' and 'passwords'.
USERS(
user_id INT AUTO_INCREMENT,
user_login VARCHAR(30) NOT NULL,
user_email VARCHAR(255) NOT NULL,
join_date TIMESTAMP NOT NULL,
PRIMARY KEY - user_id
)
PASSWORDS(
password_id INT AUTO_INCREMENT,
user_id INT NOT NULL,
hash_password VARCHAR(255) NOT NULL,
PRIMARY KEY - password_id,
FOREIGN KEY - user_id REFERENCES USERS(user_id)
)
My SQL CODE:
CREATE FUNCTION `create_user`(`login` VARCHAR(30), `password` VARCHAR(255), `email` VARCHAR(255)) RETURNS BOOLEAN DETERMINISTIC NO SQL SQL SECURITY DEFINER BEGIN
IF (SELECT EXISTS(SELECT user_login,user_email FROM users WHERE user_login = login OR user_email = email LIMIT 1) OR (SELECT EXISTS(SELECT hash_password FROM passwords WHERE hash_password = password LIMIT 1)))
THEN
RETURN FALSE;
ELSE
INSERT INTO users(user_login,user_email)
VALUES(
login,
email
);
INSERT INTO passwords(user_id, hash_password)
VALUES(
(SELECT MAX(user_id) FROM users),
password
);
RETURN TRUE;
END IF;
END
MY PHP CODE:
public static function createUser($user,$password,$email,$DbDependency)
{
self::setDependency($DbDependency);
$query = "CALL create_user('$user','$password','$email')";
try
{
if(self::getDependency() -> query($query))
{
new UserManager($user,$password,$email);
header("Location: ../../Views/congratulations");
}
else
{
echo "bad";
}
}
catch(PDOException $error)
{
echo $error -> getMessage();
}
}
MySQL function 'create_user' should return FALSE if data exists OR TRUE if not exists,insert data to tables and PHP. IF function works then it should create a new userManager object and go to next page.
Instead of this page, it shows me "bad" and tables are still empty.

PHP SQL query slow?

Here is my function which i am using to un-follow users.It first DELETE the relationship between users and all the notifications that are related to this relationship.Then it INSERT a new notification for user which we are going to un-follow and then UPDATE his followers count (as one follower has left).I am using multi_query and this query seems to be bit slower on large database and i want to know whether it's a good practice or not or is there is any more complex form of query to get the job done.
PHP Function
// 'By' is the array that hold logged user and 'followed' is the user id which we are going to unfollow
function unFollowUser($followed,$by) {
$following = $this->getUserByID($followed);// Return fetch_assoc of user row
if(!empty($following['idu'])) { // if user exists
// return user followers as number of rows
$followers = $this->db->real_escape_string($this->numberFollowers($following['idu'])) - 1;
$followed_esc = $this->db->real_escape_string($following['idu']);
$by_user_esc = $this->db->real_escape_string($by['idu']);
// delete relationship
$query = "DELETE FROM `relationships` WHERE `relationships`.`user2` = '$followed_esc' AND `relationships`.`user1` = '$by_user_esc' ;" ;
// delete notification (user started following you )
$query.= "DELETE FROM `notifications` WHERE `notifications`.`not_from` = '$by_user_esc' AND `notifications`.`not_to` = '$followed_esc' ;" ;
// Insert a new notification( user has unfollowed you)
$query.= "INSERT INTO `notifications`(`id`, `not_from`, `not_to`, `not_content_id`,`not_content`,`not_type`,`not_read`, `not_time`) VALUES (NULL, '$by_user_esc', '$followed_esc', '0','0','5','0', CURRENT_TIMESTAMP) ;" ;
// update user followers (-1)
$query .= "UPDATE `users` SET `followers` = '$followers' WHERE `users`.`idu` = '$followed_esc' ;" ;
if($this->db->multi_query($query) === TRUE) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
Table structures
--
-- Table structure for table `notifications`
--
CREATE TABLE IF NOT EXISTS `notifications` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`not_from` int(11) NOT NULL,
`not_to` int(11) NOT NULL,
`not_content_id` int(11) NOT NULL,
`not_content` int(11) NOT NULL,
`not_type` int(11) NOT NULL,
`not_read` int(11) NOT NULL,
`not_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Table structure for table `relationships`
--
CREATE TABLE IF NOT EXISTS `relationships` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user1` int(11) NOT NULL,
`user2` int(11) NOT NULL,
`status` int(11) NOT NULL,
`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Table structure for table `users`
--
CREATE TABLE IF NOT EXISTS `users` (
`idu` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL,
`password` varchar(256) NOT NULL,
`email` varchar(256) NOT NULL,
`first_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`last_name` varchar(32) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`verified` int(11) NOT NULL,
`posts` text CHARACTER SET utf32 NOT NULL,
`photos` text CHARACTER SET utf32 NOT NULL,
`followers` text CHARACTER SET utf32 NOT NULL,
UNIQUE KEY `id` (`idu`),
UNIQUE KEY `idu` (`idu`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
In my testing, multi_query has been the fastest way to execute multiple different queries. Why do you feel it's running slow? Compared to what?
Anyway, improvements could come from adding indexes to some of the columns you search frequently:
relationships.users2
relationships.users1
notifications.not_from
notifications.not_to
users.idu
Adding indexes makes searching faster, but it has at least two downsides:
Makes the DB a lot more resource hungry, which could affect your server performance
Makes writing operations take longer
I don't see any problem with your current queries. Really consider whether the slow performance you're seeing comes from the DB queries themselves, or from the rest of your PHP process. Try measuring the script time with the queries, then skipping the queries and taking another measurement (you could hardcode query results). It will give you an idea of whether the slowness is attributable to something else.
Either way, benchmark.
Try creating index on user where deletes are running , this may speed up query

Symfony2 MySQL: INSERT SELECT syntax error

I am having problems with writing correct MySql query. I want to insert new collection for every user with id higher than 1000 but less than 10000.
$conn = $this->em->getConnection();
$stmt = $conn->prepare('INSERT INTO collection (name, type)
values(:name, :type)
SELECT * FROM user WHERE id<:endUser AND id>:startUser');
$stmt->bindValue('name', 'Default');
$stmt->bindValue('type', 0);
$stmt->bindValue('startUser', 1000);
$stmt->bindValue('endUser', 10000);
$stmt->execute();
This what I tried to write, but I get syntax error. Please explain me how to correct query
UPD
I should have given detailed structure of tables.
Collection
CREATE TABLE IF NOT EXISTS `collection` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`type` smallint(6) NOT NULL,
PRIMARY KEY (`id`),
KEY `IDX_FC4D6532A76ED395` (`user_id`)
);
User
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
User has one-to-many relationship with Collection.
With a SELECT INTO you have to select the values you want to place in the new row and only those values. And you dont use the VALUES() clause.
As you are using static values for the new rows and not values from the user table you can do it like this.
Oh and I see in your edit you were using the wrong table name It should have been fos_user
Also as fos_user.user_id is a NOT NULL field you need to include that column in the list of fields in the insert.
$conn = $this->em->getConnection();
$stmt = $conn->prepare('INSERT INTO collection (user_id, name, type)
SELECT id, 'default', 0
FROM fos_user
WHERE id > :startUser AND id < :endUser');
$stmt->bindValue('startUser', 1000);
$stmt->bindValue('endUser', 10000);
$stmt->execute();

How to delete user in oo php api (using postman testing tool)

I am working on an basic crud API. So far i have a working get function, but want to delete the current users. MY tables are as follows.
CREATE TABLE IF NOT EXISTS `users`
(
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_fullname` varchar(25) NOT NULL,
`user_email` varchar(50) NOT NULL,
`user_password` varchar(50) NOT NULL,
`user_status` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
This is the delete code, how can i delete a user by specific id?
} elseif ($this->get_request_method() == "DELETE"){
$result = $this->db->query("DELETE * From users");
$result->close();
// Send the response to the response() function (lives in the parent class) the 200 is the HTTP status code that's returned
$this->response(json_encode("Deleted", JSON_PRETTY_PRINT), 200);
} else {
/*
* THE METHOD IS NOT ALLOWED
*/
$this->response(json_encode("Method Not Allowed"), 405);
}
You could send the user_id in the URL string then delete that specific record
http://url.com.script.php?user_id=123
// get the user ID and cast to an integer
$user_id = (int) $_GET['user_id'];
// run the query
$result = $this->db->query("DELETE FROM users WHERE user_id = $user_id");
of course, you'd want to sanitize the $user_id against SQL injection in your query, just in case...

Categories