inserting form data into mysql - php

Please advise how to do this php mysql form and data insert.Already searched on this site and couldn't find any question regarding this.
I have a form that collects student information - student_info(fields: id, name, sex, dob). I can insert this to a table. Now I would like to create two other tables like this
male_students (id, student_info_id, male_names)
female_students (id, student_info_id, female_names).
My idea for these two separate tables is because I can show the list of male and female easily by a SELECT query.
To do this, I thought I can do this but I am not sure how and if this is even a right approach.
for example I have a script called form_submit.php - this has the form
filling and submitting the form would insert data into student_info tables.
when doing the step 2, I would like to check if ($sex == male) or (if $sec==female), do a insert into male_students and female_students respectively.
but I am stuck
should i just write three individual queries inside the
form_submit.php ?
how to get the student_info_id for these two
tables. I thought of LAST_INSERT_ID but I am confused what will
happen if two users fill out the form at same time. So how to
approach this?
If this is not even a right way to approach, how to populate the data for those two tables?
Please advise.
regards

There is absolutely no reason to split "males" and "females" into their own tables in this scenario. (And I'm at a loss to imagine any scenario where it would make sense.)
The entity you're storing is, for lack of a better term, a Person. (User, Individual, etc. could be used in this context as well. Stick with whatever language is appropriate for the domain.) So a Person is a record in a table. Gender is an attribute of a Person, so it's a data element on that table. A highly simplified structure to convey this might be:
Person
----------
ID (integer)
GivenName (string)
FamilyName (string)
Gender (enumeration)
The Gender value would simply be a selected value from whichever possible options are available. Such options might include:
Male
Female
Unknown
Undisclosed
There are medical cases where there may be even more options, and psychological cases may indeed further add to the set. But for most domains that might be covered by "Unknown" or "Undisclosed" (or perhaps "Other" as an option, though that might look strange on the form to the vast majority of users).
To select this information, you'd simply add a WHERE clause to your query. Something like this:
SELECT * FROM Person WHERE Gender=1
If 1 maps to, for example, Male then this would select all Persons who have a Gender attribute of Male.

Related

Insert Array into MYSQL field

For a forum, i want to enable the users to send messages to each other to.
In order to do this, I made a table called Contacts, within this table I have 5 collumns: The user_id, a collumn for storing Friends, one for storing Family, one for storing Business and one for other contacts. These last four should all contain an array, which holds the user_id's of that type of contact. The reason I chose for this design is because I don't want to type an awful lot or limit the users on the amount of friends, like friend1, friend2 etc.
My question is: Is this correct how I do it? If not, what should be improved?And what type of MYSQL field should Friends, Family, Business and Other be?
What you should do instead of that is have a map table between your Contacts table and any related tables (User, Friends, Family, Business). The purpose would purely be to create a link between your Contact and your User(s) etc, without having to do what you're talking about and use arrays compacted into a varchar etc field.
Structured data approach gives you a much more flexible application.
E.g. UserContacts table purely contains its own primary key (id), a foreign key for Users and a foreign key for Contacts. You do this for each type, allowing you to easily insert, or modify maps between any number of users and contacts whenever you like without potentially damaging other data - and without complicated logic to break up something like this: 1,2,3,4,5 or 1|2|3|4|5:
id, user_id, contact_id
So then when you come to use this structure, you'll do something like this:
SELECT
Contacts.*
-- , Users.* -- if you want the user information
FROM UserContacts
LEFT JOIN Contacts ON (UserContacts.contact_id = Contacts.id)
LEFT JOIN Users ON (Users.id = UserContacts.user_id)
Use the serialize() and unserialize() functions.
See this question on how to store an array in MySQL:
Save PHP array to MySQL?
However, it's not recommended that you do this. I would make a separate table that stores all the 'connections' between two users. For example, if say John adds Ali, there would be a record dedicated to Ali and John. To find the friends of a user, simply query the records that have Ali or John in them. But that's my personal way of doing things.
I recommend that you query the users friends using PHP/MySQL all the time you need them. This could save considerable amount of space and would not take up so much speed.
serialize the array before storing and unserialize after retrieving.
$friends_for_db = serialize($friends_array);
// store $friends_for_db into db
And for retrieving:
// read $friends_for_db from db
$friends_array = unserialize($friends_for_db);
However, it should be wiser to follow other answers about setting up an appropriate many-to-many design.
Nevertheless, I needed this kind of design for a minor situation which a complete solution would not be necessary (e.g. easy storing/retrieving some multi-select list value which I'll never query nor use, other than displaying to user)

mysql distinct query using joins

I have a complex database relationship (to me its complex). In theory, I think it a good design, but my roadblock now is getting data out of it in as few queries as possible. Here is the database structure I have:
student table:
some fields like name, phone, email, etc.
students_requirements table (mapping table):
student_id,
requirement_id,
date
requirements table (belongs to a requirement type):
id,
requirement_type_id,
name
requirement_type table (has many requirements):
id,
type,
name,
Ok, so here is an example of how it is used. I can build requirement types. An example would be something like an assignment. Each assignment has multiple requirements. A student can pass off requirements for a specific assignment, but doesn't necessarily have requirements passed off for all assignments. So I would want to query all assignments by student. So say there are 50 assignments entered in the system, and jon smith has entered requirements for 4 of those assignments. I would like to query by jon smith id to find all assignments that he has entered any requirements for.
I hope that makes sense. My only guess is to use a join, but to be honest, I really don't understand them very well.
Any help would be awesome!
Try this:
SELECT * FROM student_table, students_requirements_table,
requirements_table, requirement_type_table
WHERE student_table.name = "Jon Smith"
AND students_requirements_table.id = student_table.id
AND requirements_table.id = students_requirements_table.requirement_id
AND requirement_type_table.id = requirements_table.requirement_type_id;
Check that the table names are accurate, as I've had to assume a couple of things (such as there being underscores in some of your table names), and note that all of the above should actually be one long line (but that makes it unreadable on this page, so I've split it across multiple lines).
I don't have a LAMP rig setup at the moment, so I can't mock this up to test it, and it's been a while since I had to write MySQL joins, but I think this is on the right track.
If you need to use LEFT JOIN then take a look at this page: Left joins to link three or more tables.

Is it considered bad form to encode object-oriented data directly into single rows in a relational database?

I'm relatively new to databases so I apologize if there's an obvious way to approach this or if there is some fundamental process I'm missing. I'm using PHP and MySQL in a web application involving patient medical records. One requirement is that users be able to view and edit the medical records from a web page.
As I envisage it, a single Patient object has basic attributes like id, name, and address, and then each Patient also has an array of Medication objects (med_name, dose, reason), Condition objects (cond_name, date, notes), and other such objects (allergies, family history, etc.). My first thought was to have a database schema with tables as follows:
patients (id, name, address, ...)
medications ( patient_id, med_name, dose, reason)
conditions ( patient_id, cond_name, date, notes)
...
However, this seems wrong to me. Adding new medications or conditions is easy enough, but deleting or editing existing medications or conditions seems ridiculously inefficient - I'd have to, say, search through the medications table for a row matching patient_id with the old med_name, dose, and reason fields, and then delete/edit it with the new data. I could add some primary key to the medications and conditions tables to make it more efficient to find the row to edit, but that would seem like an arbitrary piece of data.
So what if I just had a single table with the following schema?
patients (id, name, address, meds, conds, ...)
Where meds and conds are simply representations (say, binary) of arrays of Medication and Condition objects? PHP can interpret this data and fetch and update it in the database as needed.
Any thoughts on best practices here would be welcome. I'm also considering switching to Ruby on Rails, so if that affects any decisions I should make I'm interested to hear that as well. Thanks a lot folks.
The 'badness' or 'goodness' of encoding your data like that depends on your needs. If you NEVER need to refer to individual smaller chunks of data in those 'meds' and 'conds' tables, then there's no problem.
However, then you're essentially reducing your database to a slightly-smarter-than-dumb storage system, and lose the benefits of the 'relational' part of SQL databases.
e.g. if you ever need to run a a query for "find all patients who are taking viagra and have heart conditions", then the DBMS won't be able directly run that query, as it has no idea how you've "hidden" the viagra/heart condition data inside those two fields, whereas with a properly normalized database you'd have:
SELECT ...
FROM patients
LEFT JOIN conditions ON patients.id = conditions.patient_id
LEFT JOIN meds ON patients.id = meds.patient_id
WHERE (meds.name = 'Viagra') AND (condition.name = 'Heart Disease')
and the DBMS hands everything automatically. If you're encoding everything into a single field, then you're stuck with substring operations (assuming the data's in some readable ascii format), or at worse, having to suck the entire database across to your client app, decode each field, check its contents, then throw away everything that doesn't contain viagra or heart disease - highly inefficient.
This breaks first normal form. You can never query on object attributes that way.
I'd recommend either an ORM solution, if you have objects, or an object database.
I'd have to, say, search through the medications table for a row
matching patient_id with the old med_name, dose, and reason fields,
and then delete/edit it with the new data.
Assuming the key was {patient_id, med_name, start_date}, you'd just do a single update. No searching.
update medications
set reason = 'Your newly edited reason, for example.'
where patient_id = ?
and med_name = ?
and start_date = ?
Your app will already know the patient id, med name, and start date, because the user will have to somehow "select" the row those are in before any change will make sense.
If you're going to change the dosage, you need two changes, an update and an insert, in order to make sense.
update medications
set stop_date = '2012-01-12'
where patient_id = ?
and med_name = ?
and start_date = ?
-- I'm using fake data in this one.
insert into medications (patient_id, med_name, start_date, stop_date, dosage)
values (1, 'that same med', '2012-01-12', '2012-01-22', '40mg bid')

When to use comma-separated values in a DB Column?

OK, I know the technical answer is NEVER.
BUT, there are times when it seems to make things SO much easier with less code and seemingly few downsides, so please here me out.
I need to build a Table called Restrictions to keep track of what type of users people want to be contacted by and that will contain the following 3 columns (for the sake of simplicity):
minAge
lookingFor
drugs
lookingFor and drugs can contain multiple values.
Database theory tells me I should use a join table to keep track of the multiple values a user might have selected for either of those columns.
But it seems that using comma-separated values makes things so much easier to implement and execute. Here's an example:
Let's say User 1 has the following Restrictions:
minAge => 18
lookingFor => 'Hang Out','Friendship'
drugs => 'Marijuana','Acid'
Now let's say User 2 wants to contact User 1. Well, first we need to see if he fits User 1's Restrictions, but that's easy enough EVEN WITH the comma-separated columns, as such:
First I'd get the Target's (User 1) Restrictions:
SELECT * FROM Restrictions WHERE UserID = 1
Now I just put those into respective variables as-is into PHP:
$targetMinAge = $row['minAge'];
$targetLookingFor = $row['lookingFor'];
$targetDrugs = $row['drugs'];
Now we just check if the SENDER (User 2) fits that simple Criteria:
COUNT (*)
FROM Users
WHERE
Users.UserID = 2 AND
Users.minAge >= $targetMinAge AND
Users.lookingFor IN ($targetLookingFor) AND
Users.drugs IN ($targetDrugs)
Finally, if COUNT == 1, User 2 can contact User 1, else they cannot.
How simple was THAT? It just seems really easy and straightforward, so what is the REAL problem with doing it this way as long as I sanitize all inputs to the DB every time a user updates their contact restrictions? Being able to use MySQL's IN function and already storing the multiple values in a format it will understand (e.g. comma-separated values) seems to make things so much easier than having to create join tables for every multiple-choice column. And I gave a simplified example, but what if there are 10 multiple choice columns? Then things start getting messy with so many join tables, whereas the CSV method stays simple.
So, in this case, is it really THAT bad if I use comma-separated values?
****ducks****
You already know the answer.
First off, your PHP code isn't even close to working because it only works if user 2 has only a single value in LookingFor or Drugs. If either of these columns contains multiple comma-separated values then IN won't work even if those values are in the exact same order as User 1's values. What do expect IN to do if the right-hand side has one or more commas?
Therefore, it's not "easy" to do what you want in PHP. It's actually quite a pain and would involve splitting user 2's fields into single values, writing dynamic SQL with many ORs to do the comparison, and then doing an extremely inefficient query to get the results.
Furthermore, the fact that you even need to write PHP code to answer such a relatively simple question about the intersection of two sets means that your design is badly flawed. This is exactly the kind of problem (relational algebra) that SQL exists to solve. A correct design allows you to solve the problem in the database and then simply implement a presentation layer on top in PHP or some other technology.
Do it correctly and you'll have a much easier time.
Suppose User 1 is looking for 'Hang Out','Friendship' and User 2 is looking for 'Friendship','Hang Out'
Your code would not match them up, because 'Friendship','Hang Out' is not in ('Hang Out','Friendship')
That's the real problem here.

php: Mysql Database Design and Workflow, need more creativity !

i was wondering if any one can help me with my php-mysql design
my current app. (is a more or less survey app) it let users store questions about targeting specific features in other products also saved in other table in database !
for example , a user can post a car: and then ask users about there opion in safty elements of his car.
car db : Id,brand,safety
brand = Fast
saftety = ABS=ABS (Anti lock braking System),DriverAirBag=Air bags
questions db: ID,Question,Answer,Target,type
eg of data:
Question:safety options you like
Answer:ABS=ABS (Anti lock braking System),DriverAirBag=Air bags"
target:saftey
type=checkbox
problem is that to display questions stored, i have to .
1) loop through all questions, echo Question and echo target in hidden input,
2) explode Answer field twice(1st w/ "," to get each answer and other with "=" to differ > between whats inside the database[0] and a user friendly text[1]
3) check type to chose display type (3 options checkbox,select,text)
4) set this display type of [0] and show [1] for user !!! (stupid i know:()
eg:
< checkbox
value=$expolde[0]>$explode[1]
All these steps make it very hard to maintain, not flexable by any mean cause display is embeded in code :(,
any ideas :) ?
I would separate the tables into a one-to-many type design like:
CarTable
ID
Brand
Model
CarInfo
CarID # Foreign key to Car Table
Category # Optional: Safety, Performance, Looks, etc...
Value # Specific Info Value: ABS, Air Bags, etc...
In this design you can have 0 to many CarInfo records for each Car making it easier to add/remove info records for a car without having to parse a potentially complex field like in your original design.
Your question table design could be similar depending on what your ultimate goal is:
Question
ID
Description
QuestionInfo
QuestionID
Category
Value
Some other things you should be considering and questions you should be asking yourself:
How are you handling custom user inputs? If user1 enters "Air Bags" and user2 requests "Driver Side AirBag" how are you going to match the two?
Make sure you understand the problem before you attempt to solve it. It was not clear to me from your question what you are trying to do (which could be just me or limited size of the question here).
Be careful when outputting raw database values (like the type field in your question table). This is fine as long as the database values cannot be input by the user or are properly sanitized. Search for "SQL Injection" if you are not familiar with it.
If you want a survey PHP application, I suppose, to be clear, that you need something where:
one user can add a subject (a car in your example).
there can be an arbitrary number of questions attached to a subject by that user
each question can accept several types of answers: yes/no (checkbox input), a number (text input, or say 10 radiobuttons with values 1 to 10 attached etc), single or multiple choice (select with or without multi attribute), arbitrary data (textarea). Moreover, some questions may accept comments / "other, please explain" field.
any other user can answer all the questions, and all of them are stored.
A more sophisticated version will require different sets of questions based on what was replied previously, but it's out of the scope of this question, I hope.
For that I think you need several tables:
Subjects
id int pri_key and anything that can come to mind: brand, type etc.
Questions
id int pri_key, text varchar, subject int f_key, type int/enum/?
QuestionOptions
id int pri_key, question int f_key, option varchar
Users
id int pri_key + whatever your authentication structure is
UserReplies
user int f_key, question int f_key, answer varchar, comments varchar
The user-creator sets up a subject and attaches several questions to it. Each question knows which type it is - the field 'type' may be an integer, or an enum value, I myself prefer storing such data as integer and defining constants in php, using something like QTYPE_MULTISELECT or QTYPE_BOOLEAN for readability.
For single/multiselect questions a user-creator also populates the QuestionOptions table, where the options for select-tag are stored.
To display all the questions there'll be something like
SELECT Questions.id, Questions.text, Questions.type, GROUP_CONCAT(CONCAT(questionOptions.id, questionOptions.option)) AS options
FROM Questions LEFT JOIN QuestionsOptions ON (Questions.type = $select AND Questions.id = QuestionsOptions.question)
WHERE Questions.subject = $subject
GROUP BY Questions.id
The GROUP_CONCAT and CONCAT here should be modified to return something like 5:Option_One;6:Option_Two etc, so that exploding the data won't be much hassle.
I realize this is not the cleanest approach in terms of performance and optimization, but It should do for a non-large-scale project.
There is also a drawback in in the above design in that the answers to the "multiple answer question" are stored imploded in the "answer" field of the UserReplies table. Better add another table, where every record holds an option value the user selected for this or that question. That way there will be no unnecessary denormalization in the database and queries for statistics will be much easier (i.e. querying which options were most popular in a single question)

Categories