This question already has answers here:
Basics of Foreign Keys in MySQL?
(4 answers)
Closed 3 years ago.
Let's say I have two tables:
mice
id (int) petname (varchar) gender (enum (male, female))
1 spot male
2 rice female
men
id (int) name (varchar) gender (enum (male, female))
1 bob male
2 jane female
3 steve male
The gender enum exists twice. Once for each table. So if I wanted to expand the gender enum with new values, this would mean that I would have to manually edit the enums in several tables. This is suboptimal.
Is there any way to define the enum values once and use them in several tables?
Or perhaps to create a new table named genders and put the genders there, and then during inserts and updates into mice and men, it would only allow the gender column to contain values form the gender table. This check however needs to happen automatically (like with enum column type), so I don't have to execute additional queries first to check if the used gender exists in the gender table, before each update or insert query I want to run, which inserts a value into a gender column in mice or men.
Can this be done with mysql?
You can forget about SQL's enum. Instead, just use VARCHAR(50), etc, and use const in your PHP code to define the enum values.
I seldom use SQL's enum, in most cases, its benefit is less than its complexity。
Related
I have in my database a table that Continent users ,the first field is NAME and this name can be duplicated .
I want to retrieve user's name . for example if i have in my table the name John 3 time and David 2 time and Katy 1 time,
I want the result to be john David Katy ,
If the name are duplicated i want to escape it ,and display just names once for every name, i want to do this using PHP and MYSQLI .
If you have a column with many duplicate values and only want to list the unique values you can use the DISTINCT keyword to only return those,
SELECT DISTINCT `NAME` FROM `TABLE_NAME`
This question already has answers here:
How to handle fragmentation of auto_increment ID column in MySQL
(5 answers)
how to reindex mysql table
(7 answers)
Closed 9 years ago.
I currently have a database which looks a lot like the one below:
1 citrus
2 pear
4 apple
5 melon
8 mango
The numbers represent a column that hold the row numbers but because rows are often deleted they get messed up quite often. With what MySQL query in PHP could I recount these rows so they would make sense again?
You should never re-arrange ID's in a relational database. At least not if they are to be used as a foreign key. (Which I bet they would be, otherwise what's the sense of that ID?)
Your fruits table: 1=>citrus, 2=>pear, 4=>apple, 5=>melon, 8=>mango
Consider having another table, colors holding 1=>red, 2=>yellow, 3=>green.
And now consider having a table fruit_color holding 1=>2 , 2=>3, 4=>3, 5=>2, 8=>1.
Now what would happen if I were to just go rearrange your fruits table?... The relations would get messed up.
The ID associated with each row is a primary key, and is generally auto_increment'd on each insert. This id is used as the unique identification for each row, so that a query can be used to select it, and it alone.
As you delete data, the rows will remain lined up in order from lowest id to highest id, the highest id being the last row inserted.
It is normal for the database to have gaps, but you can also manually assign the id, granted you know that it does not already exist in the database.
If you want to keep your data in a specific order, you could assign an index to each object, representing its rank, and using an order by command in the query.
SELECT id, fruit, rank FROM fruits ORDER BY rank ASC;
What you are trying to do is going to be (A) complicated code, and (B) a nightmare to update, which means that (C) odds are good it is going to screw up your database. As nl-x suggests, your best bet is to leave your PRIMARY KEYs as is. I would recommend, however, if you want to have a set ID, to assign it when you pull it with PHP.
function get_fruits() {
//SQL query
$query = ...
//SQL result
$i = 0;
while($row = $query->fetch_assoc()) {
$rows[$i] = $row;
}
return $rows;
}
Now when you cycle through your rows you'll be able to treat each array key as the rank, and the end user will be none the wiser, all while keeping your database's integrity up to snuff.
** Pulling Data by Order**
If for whatever reason you needed to be able to pull by the record number rather than the ID, you can also get the 5th record from the following table with the following query.
ID | fruit_name
----------------
1 | Apple
2 | Banana
4 | Kiwi
7 | Coconut
9 | Strawberry
The Query in PHP:
$sql = "SELECT fruit_name FROM fruit_table LIMIT $i,1"
That will pull the $i+1 record. Meaning if you want to get the first record, $i=0. This is the way most for loops are executed, and MySQL auto increments by default will start with 1.
Table one
Id subject class teacher
1 English 1 1
2 Math 1 2
3 SST 1 3
4 Computer 1 1
5 Physics 1 3
6 Chemistry 1 3
Each subject assigned to particular teacher, some subject has same teacher.
Now i want to store values in another table having these fields and other fields as well.
Table Two
id subject teacher
Whereas form only post subject ids, how can i get teacher id against each subject id from Table one and store it in table two?
Your question is very unclear. Are you asking for how to use relational databases and foreign keys? If so I would read up on how a relational database works and that will answer your question. If the question is about how to do this in code then please state that and also post your attempt at it.
What i think you want to do is get the of the subject posted, i.e. query the database :
SELECT subject, teacher FROM table_one WHERE id = 'POSTED_ID'
Then insert the new record into the table two, something like :
INSERT INTO table_two (subject, teacher) VALUES ('subject_value', 'teacher_value')
Hope this helps!
I have a DB with several tables that contain basic, static ID-to-name data. 2 Columns only in each of these reference tables.
I then have another table that will be receiving data input by users. Each instance of user input will have it's own row with a timestamp, but the important columns here will contain either one, or several of the ID's related to names in one of the other tables. For the ease of submitting and retrieving this information I opted to input it as text, in json format.
Everything was going great until I realized I'm going to need to Join the big table with the little tables to reference the names to the ID's. I need to return the IDs in the results as well.
An example of what a few rows in this table might look like:
Column 1 | Column 2 | Timestamp
["715835199","91158582","90516801"] | ["11987","11987","22474"] | 2012-08-28 21:18:48
["715835199"] | ["0"] | 2012-08-28 21:22:48
["91158582","90516801"] | ["11987"] | 2012-08-28 21:25:48
There WILL be repeats of the ID#'s input in this table, but not necessarily in the same groupings, hence why I put the ID to name pairings in a separate table.
Is it possible to do a WHERE name='any-of-these-json-values'? Am I best off doing a ghetto join in php after I query the main table to pull the IDs for the names I need to include? Or do I just need to redo the design of the data input table entirely?
First of all:
Never, ever put more than one information into one field, if you want to access them seperately. Never.
That said, I think you will need to create a full N:M relation, which includes a join table: One row in your example table will need to be replaced by 1-N rows in the join table.
A tricky join with string matching will perform acceptably only for a very small number of rows, and the WHERE name='any-of-these-json-values' is impossible in your construct: MySQL doesn't "understand", that this is a JSON array - it sees it as unstructured text. On a join table, this clause comes quite naturally as WHERE somecolumn IN (1234,5678,8012)
Edit
Assuming your Column 1 contains arrays of IDs in table1 and Column 2 carries arrays of IDs in table2 you would have to do something like
CREATE TABLE t1t2join (
t1id INT NOT NULL ,
t2id INT NOT NULL ,
`Timestamp` DATETIME NOT NULL ,
PRIMARY KEY (t1id,t2id,`Timestamp`) ,
KEY (t2id)
)
(you might want to sanity-check the keys)
And on an insert do the following (in pseudo-code)
Remember timestamp
Cycle all permutations of (Column1,Column2) given by user
Create row
So for your third example row, the SQL would be:
SELECT #now:=NOW();
INSERT INTO t1t2join VALUES
(91158582,11987,#now),
(90516801,11987,#now);
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to Store Multiple Options selected by User in a Table
I am very confused by this.
I want my users to be able to restrict who may contact them. So I need to create a new table of RESTRICTIONS for each user and their selected criteria, which will have a column for each user's restriction criteria. Those columns will include age, income, looking for, drugs, etc. Some of those columns (looking for, drugs, etc.) might contain multiple choices, and therein lies my problem. How do I structure the table in this way, considering some criteria (columns) can have multiple values while others do not?
I've been told about join tables and enum values (both of which I've never worked with before), but I am really confused as to how I would structure a table in which some columns (not all), can contain multiple choices.
How do I store those multiple choices in those specific columns of the table and how do I structure the overall table of RESTRICTIONS?
A DB column (at least theorethically) should NOT hold multiple values. Unfortunately, there are some programmers that store multiple values in a single column (values separated by comma for examples) - those programmers (in most cases) destroy the concept of DB and SQL.
I suggest you to read about Database Normalization to get a start in organizing your tables. And, do your best to achieve the Codd's Third Normal Form
This is the simplest way. Multiple attributes become rows in a second table.
CREATE TABLE restrictions (
user_id INTEGER PRIMARY KEY, -- references users (user_id), not shown
age_restriction VARCHAR(10) NULL,
income_restriction VARCHAR(20) NULL
);
CREATE TABLE looking_for (
user_id INTEGER NOT NULL REFERENCES restrictions (user_id),
looking_for VARCHAR(35) NOT NULL, -- could also be a foreign key.
PRIMARY KEY (user_id, looking_for)
);
INSERT INTO restrictions (user_id) VALUES (1);
INSERT INTO restrictions (user_id, age_restriction) VALUES (2, '> 25');
INSERT INTO looking_for VALUES (1, 'boat');
INSERT INTO looking_for VALUES (1, 'dunky fazoo');
If you wanted to accept multiple restrictions on age, such as '> 25' and '< 55', you could build another table for that, too.
To retrieve all the restrictions, use an OUTER JOIN.
SELECT r.user_id, r.age_restriction, r.income_restriction, lf.looking_for
FROM restrictions r
LEFT JOIN looking_for lf ON lf.user_id = r.user_id
You probably need more than one table.
You have a "users" table already, right? If one of your "restrictions" criteria can have just one value per user, then that column belongs in the "users" table. So you might have columns "min_age" and "max_age" in the users table, because presumably each user has only one, contiguous range of ages they are looking for.
On the other hand, for each restriction criterion that can have multiple values, you need a new table. So you might have a table "users_restrictions_drugs" in which the primary key is (user, drug). But you might also have a table "users_restrictions_lookingfor" in which the primary key is (user, lookingfor). Whatever "looking for" is.
For some of these tables it may make sense either
to define the second column (the one that isn't "user") as an enum
or (better) to have an additional table that sets out the possible values of that second column and is referenced by a foreign key.
table restrictions
user_id smoker_ok min_height max_height min_age max_age
-------------------------------------------------------
1 Y 150 200 24 34
2 N 100 180 32 57
table drug_restrictions
user_id drug_id drug_allowed
----------------------------------
1 H N
1 M Y
2 E Y
Would be an example. In the restrictions table, you can store explicit, singular values - smokers yes or no, or min and max requirements.
For each table where there are multiple choices, you can create a join table - I've given an example for drugs.
In the drug_restrictions table, user 1 says she doesn't want people using H, but does want people using M.
This solution allows you to use the "drug_id" as a foreign key to whatever table in your database populates the "drugs" field on the user interface. It allows you to use regular, standard SQL conventions for those foreign keys, and to enforce them at the database level by declaring them as foreign keys.
The drawback is, of course, that you have to query lots of tables to find matching records, and that's not much fun.
So, you could also follow Catcall's recommendation - this dramatically reduces the number of tables, but makes it impossible to use "standard" foreign key integrity constraints. This might be okay - it's certainly going to be faster.
I'd be reluctant to use enums - they tend to lead to complex queries, and are not "standard" SQL.
There's no problem to have tables where some columns have duplicate values. Consider a tbale with users; there's no problem if two users have the same birthday?
The only problem is a table where a primary key occurs more than once. For instance, a user table may very well have username as its primary key, and you wouldn't want two users with the same username.
So, make one table that lists users, one that lists restrictions, and one that joins the two. The latter will have one entry for every combination of user/permission.