I recently cleaned up my web app's code. My web app is a simple social network with Add,Remove,etc procedures. I have a php file which I call when a user want to remove a contact from his friend list.
I came up with a strange bug in my application that I haven't estimate the time I wrote it.
The Bug
Let's say we have two friend emails in our list.
georgeMARK#email.com
MARK#email.com
The contact emails are stored in a MYSQL DB column with name Contacts and every email is separated by a semicolon (;) symbol. So our example's column will look like this (depend on which user has added lastly it can be vice versa):
georgeMARK#email.com;MARK#email.com;
So assume that our user wants to remove MARK from his contacts. He presses the button and ... both email's have gone.!
Have a look in my PHPMyAdmin Panel I found that what has left from the column is this:
george
The problem is in my PDO SQL statement that I use to remove accounts from my column.
$STH = $DHB->prepare("UPDATE `Users` SET `Contacts` = REPLACE(`Contacts`, :email, '') WHERE `UserEmail` = :my_email");
The REPLACE function just replaces all the instances of the :email and thats awful. I use the same approach many times in my application and I understand that this will cause my the same bug to appear elsewhere too.
My question is how can I delete a user's email without affecting the others 'instances'? Do I have to change my point of view and how what do I need to do?
The fast dirty way is to prepend a semicolon to all Contacts field, so that entries as like this:
;georgeMARK#email.com;MARK#email.com;
then you can replace it in this way:
$emailToDelete = ";$emailToDelete;"
... REPLACE(`Contacts`, :email, ';') ...
A better approach can be to store contacts data in a more suitable format (like JSON).
The best solution is to create a relationships table and delete all the entries relative to contact to delete.
Structure
Maybe create a structure like this:
Table Users
id | Name | Email
-----------------
1 | John | john#example.com
2 | Jane | jane#example2.com
Table Friendships
User1_id | User2_id
-------------------
1 | 2
Select users
SELECT * FROM Users WHERE name=:name
Select friends
SELECT
*
FROM
Friendships
LEFT JOIN
Users
ON
Friendships.User1_id = Users.id
WHERE
User1_id=:user_id
Delete friendship
DELETE FROM Friendships WHERE User1_id=:current_user_id AND User2_id=:friend_to_remove_id
Related
I have seen that there are similar questions, but they do not seem to be helping...could just be that I am not understanding correctly and able to translate their examples to my needs. Any help is appreciated.
I am trying to convert an input field on a $_POST form to my users table, specifically on the managers key, from the managers name (in the form), to the managers id (in the DB). Let me show an example.
Our DB has (among other tables) a users table and a managers name. The managers table just has the manager's id, first & last name. The users table has their own id, first_name, last_name, and associated manager id. This is how it looks:
MANAGERS
id first_name last_name
1 John Doe
2 Mary Lewis
USERS
id first_name last_name manager
1 Steve Thompson 1
I have created an edit form for the users table where this information is inputted from the database, but I have joined the two tables in my SELECT statement so that instead of the managers.id showing, it actually shows the managers.first_name and managers.last_name in the form.
So what I am trying to do is allow someone to edit the manager associated with a user, by submitting their name instead of the ID, but in the DB it associates it back to the ID. We have many managers so most people don't know what their ID in the DB is. However, they all know their names. So is it possible to have an SQL UPDATE query to achieve:
As you can see, the User Steve Thompson has manager 1 (John Doe), but the manager of this user needs to be changed to Mary Lewis. How can I enter the name 'Mary Lewis' into the Users Edit Form, and have it update the DB table using the manager's name instead of the manager's id.
I have seen people say you can't update multiple tables in one query, but I feel this is a little different as it is more like a JOIN, but I am unsure how to do it. Does anybody know if this is possible?
EDIT
I have seen this one and feel it might help...but not sure how to implement correctly. Perhaps this can help someone as well?
Update one MySQL table with values from another
After you managed to parse the managers name and split it to first and last name you can just select the managers id in a subselect
update USERS set
first_name = :user_first_name,
last_name = :user_last_name,
manager = (
select id
from MANAGERS
where first_name = :manager_first_name
and last_name = :manager_last_name
)
where id = :user_id
You can also use a (CROSS) JOIN:
update USERS u
cross join MANAGERS m
set
u.first_name = :user_first_name,
u.last_name = :user_last_name,
u.manager = m.id,
where u.id = :user_id
and m.first_name = :manager_first_name
and m.last_name = :manager_last_name
Note that it won't work if the managers name is not unique. It will also not work if no manager with that name exists.
However i would probably use a drop down selection with the managers id as value. You still can display the first and last name:
<select name="manager">
<option value="1">John Doe</option>
<option value="2">Mary Lewis</option>
</select>
This way you will display the name but get the ID on submit.
I'm working on my first project (a project management system) to understand PHP and MySQL better. I currently have 3 tables in my database, one that lists all the projects ('projects' table), one that stores the users username and password ('users' table) and then a third, small 'permissions' table that is meant to filter out what projects a user can see from the projects table.
The third 'permissions' table consists of an unique id, and then a "user_id" and a "project_id" in the other two columns. The "user_id" references the id of the user in the "users" table, and the "project_id" references the id of a project in the projects table.
Note that more than one user can have access to a single project, that's why there isn't just a single column for this in the projects table, and I read that using comma separated lists for the multiple usernames is a bad way to go about it. As such I have set up foreign keys on "user_id" and "project_id" that reference the id of each accordingly.
Now I'm not sure if this is a good way to set things up but it seems okay in my head.
Really what I want to do is retrieve all the projects a certain user has access to. So something kind of like (but obviously works):
SELECT * FROM projects WHERE user_id = 3;
Is there a simpler way to do this? Something to do with the join command but I could never get it right.
Thanks in advance!
EDIT:
Apologies for the ambiguity, gets a bit tricky to explain.
Essentially I just want a way to filter what rows are displayed from the projects table by the user_id in the users table (note again more than one user can access a project so I can just put a "user_id" column in the projects table and leave out the third table altogether).
My tables are pretty much like so:
projects:
|id|project_title|project_notes|project_status|
|1 |A Project |Some Notes |Finished |
|2 |A 2nd Project|Some more... |In Progress |
users:
|id|username|password|
|1 |johndoe |*********|
|2 |benhill |*********|
permissions:
|id|user_id|project_id|
|1 |1 |2 |
|2 |2 |2 |
user_id = id from users table.
project_id = id from projects table.
Then in HTML/PHP I only want to retrieve the projects that a user has access too.
Unfortunately your question isn't very clear but I assume you want to have a single query to find all project that a particular user has access to, you can simply join up the tables with the id as such:
SELECT * from projects INNER JOIN permissions ON
projects.id = permissions.project_id WHERE
permissions.user_id = 3
Assume the user you are looking for has id of 3
Assuming you have
Users (Id, Name)
Projects (Id, Name)
Permissions (UserId, ProjectId)
and you want to "retrieve all the projects a certain user has access to", and you have the user id stored in a variable $userId, you could use a simple query like this:
select * from Projects pr
join Permissions pe on pr.Id = pe.ProjectId
and pe.UserId = $userId
Google around for more info on SQL syntax and joins. Here's a link I just found that looks like a good place to start: http://www.sitepoint.com/understanding-sql-joins-mysql-database/
(Using PHP + mySQL)
I'm hoping someone can give me an idea as to the best way to handle this situation.
I have two tables, users and forms. The users table holds username, password, name, etc. and then the forms table holds various different html forms.
I want to specify which forms a user has access to, on a per user basis. I was thinking about creating a new field in the users table which would be 'forms_allowed' and then storing the form_id of each form the user is allowed to access, separated by commas. Something like 3,6,8,15
Then when I want to check what forms the user is allowed to access and whether they can access the form requested (etc.) i'd grab that field, explode it and check for the form_id.
This seems like a hassle and ineffective way of doing it. Does anyone have a better idea?
Thanks!
Create another table that will hold user_id and form_id pair. This is many-many relationship.
tblUsers:
user_id | name |...
tblForms
form_id | content | ...
tblRelation:
user_id | form_id
So you can simply get info with single query:
SELECT * FROM `tblUsers` AS `t`
JOIN `tblRelation` as `r` ON (t.user_id = r.user_id)
JOIN `tblForms` as `f` ON (f.form_id = r.form_id)
The title pretty much says it all. I have users posting content, and I would like to attach the user ID that is in the users table to the posts. Should I add a userid column in the posts table, should I join via the DB language, or should I use the scripting language to poll each table? If I should join, what kind of join should I do?
Sample content would look like this: "The teddy bears at my store are softer than the teddy goats, but the teddy goats are more lovable." - Posted by James Teddyman at 3:36 PM.
A very often-used concept in situation like this is by having a users table and a post table, linking them together with a unique identifier. This identifier can be anything - a serialized id, a user name, mail address, etc - as long as it's unique. Linking is done using a foreign key constraint. Exactly how this is achieved in MySQL I do not know, but in Postgres it's done like this:
CREATE TABLE users (
id serial PRIMARY KEY,
name text
);
CREATE TABLE posts (
content text,
user_id integer REFERENCES users(id) NOT NULL
);
The tables are then merged using a join. This can be done in several ways, but here is a cross join after insertion of some values to play with:
#> INSERT INTO users (name) VALUES ('James');
#> INSERT INTO users (name) VALUES ('Jones');
#> INSERT INTO posts (content, user_id) VALUES ('Hello from James.', 1);
#> INSERT INTO posts (content, user_id) VALUES ('Greetings from Jones.', 2);
#> SELECT U.id AS user_id, U.name, P.content \
FROM users U, posts P \
WHERE U.id = P.user_id;
user_id | name | content
---------+-------+-----------------------
1 | James | Hello from James.
2 | Jones | Greetings from Jones.
YMMV in MySQL, but I think the constructions above will work straight off.
(edit: Added INSERTs for clarification)
The pretty much way is to add a user id in the post table. Insert user id which each post. Then by extracting the information use the simple join to get the complete information. You select query should looks like
select post.content,post.date,users.firstname,user.lastname from post,users where post.userid=users.id
Database Normalization would suggest that the best method is "two tables with columns", relating user content to user via user_id. This method is known to manage both bears and goats more efficiently in the long-run.
At the moment I have three tables that I am trying to connect and figure out what queries will get the results I need and also follow best practices. MySQL is still pretty new to me, and this is my first stumbling block that I can't figure out.
I am trying to build a simple URL shortener that can "link" multiple long URLs to one short URL. I basically want to have a link www.example.com/google then have google.com, google.co.uk, google.it, etc... and GEO target when the user accesses the link.
My three tables are set up as:
short_id | user_id | short_url //Short URL Table
long_id | user_id | long_url | country_code //Long URL table
user_id | name | password | email | created //User table
I am not sure if foreign keys are the best route. Also, I understand how to add a user, but what queries would I have to run to have a user add a short/long url and have the user_id field in "user" table match the user_id fields in the other tables.
Thanks for the help.
select * from short_url_table
left join long_url_table
using (user_id)
left join user_table
using (user_id) ;