I have to store an array in one field of a db. I know how to do that technically. My questions is, which version makes sense to do that.
First a short introduction:
I have categories in a table and need translations for each category for all languages. To start, I have 2 languages (later I will have more). Ok, let's say my category is car and the structure is like that:
id name translation
My first idea was:
id name translation
1 car array('eng' => 'car', 'deu' => 'Auto')
The second idea was:
id name translation
1 car 'eng' => 'car', 'deu' => 'Auto'
The third idea was:
id name translation
1 car 'eng'='car','deu'='Auto'
At the end, the script reads the translation cell and loads into an array and returns the value for the given key 'eng' or 'deu' or whatever it comes later.
I use PHP / MySQL
Thank you for any pros and cons.
Ivo
Try adjusting your database structure. This might be ideal:
id name language word
1 car eng car
2 car deu Auto
Primary Key (`name`,`language`)
Unique Key (`id`) (auto_increment)
In this way you can have as many (or as few) languages as you like.
You need to go about this completely different. Add another table, category_translation.
You'd have category:
id name
and language:
id name
and category_translation:
id lang_id category_id translation
This way you'll have things beautifully separated.
you should have a translation table, with the language being one of the columns.
id, name, language, value
1, car, eng, car
2, car, deu, Auto
...
if you only have a single set of values, you can keep everything in this table. if you are looking up multiple values from different sources you can either add a lookup key to this table, or use the name as your lookup value (though indexing on text will not be as good as indexing on integer IDs)
Please do not store an array in your database in one column. At least serialize if it you have to do it
serialize($array)
Related
I'm building a website in PHP to share my comics. I'd like to implement categorization to allow people to filter which comics they'd like to see.
I've asked this question before, but at that time my site's architecture was not using a database.I've since implemented a database (which is amazing, btw) so I need to change things up.
I'm thinking the way to do this is:
1) Make 2 tables: 1 for categories, 1 for images
2) Insert images into their respective tables based on which filesystem folder they're in and assign that table id
3) Insert all images into All_Images table with their newly assigned category id
4) Take in user input to decide which images to show. So, if user input = cat 1, then show images with category 1 id.
So, basically I need a way to initially assign categories to the images when they come in from the filesystem. Is there an easier way to do this? Do I have to create multiple tables?
Any thoughts on this?
Thanks!!
The normal way would be to have an images table (presumably with filenames rather than the actual images?) and then a one-to-many relationship to categories so that each comic can have more than one:
Table:Image
-----------
rowid: integer identity
displayname: varchar
filename: varchar
Table:Category
--------------
rowid: integer identity
displayname: varchar
Table:ImageCategoryLink
-----------------------
imageid: integer foreign key references Image:rowid
categoryid: integer foreign key references Category:rowid
Clear?
One table category with id and name etc, one table for image with id src name etc.
Two choices after that :
If an image has one and only one category, put a field id_category in table image
If an image can has several categories make another table image_category with id_image and id_category
Since you are a beginner (no offence) and I don't think there will be millions or cartoons in the table. Use a SET field (or ENUM if your cartoon can only have one category) for you categories.
There are people who will vote this down since there are some negative side effects of using this (mainly when you want to change the categories). But with a relative small table this will not have any effect.
This will be the easiest solution. If you expect the site to grow big, use a second table for your categories and join the tables.
I want to create a site in PHP with cakephp that users can insert product manually.
The problem is for the multilanguage because I can have into my site users from all over the world and the product 'apple' in italian for example is 'mela'.
Consider that I can have many many data!
Then i have some solution for the database:
Create a table products with an id
Create a table product_aliases where I have an id the id of product language and the text(ex. apple)
In this mode users can enter into 'apple', translate ad I insert a new line into product_aliases with same id product different language and different text but same product
Define 5 language and create a table with more fields (title_en, title_it, title_es...) the translation is in the same record
Only one table but restricted language
Create a table products with an id
Create a table for every language that i want for example: prducts_en, products_it where I can store my data with same foreign key to the product but divide from language to make fast query.
Other solution are accepted!!
I never work with large multilanguage database help me and tell me what is the best solution for my database
The first one is the correct solution in general.
It's used in many enterprise applications: a table with an id field for identification of the not multilanguage information (example: unit price for a product) and a table with a row for every combination product/language.
The second one is against every db normalization rule.
The third one is a different derivation of the second one, and if you use an index on the language column in the translated labels table you should not have a great disadvantage in terms of performance.
If you need I will explain better!
I have a news system I'm designing, and it seemed straight-forward at first, but as I've pushed forward with my planned schema I've hit problems... Clearly I haven't thought it through. Can anyone help?
The system requires that the latest 20 news articles be grabbed from the database. It's blog-like in this way. Each article can have sub-articles (usually around 3) that can be accessed from the parent article. The sub-articles are only ever visible when the parent article is visible -- they're not used elsewhere.
The client needs to be able to hide/display news articles (easy), but also change their order, if they desire (harder).
I initially stored the sub-articles in a separate table, but then I realised that the fields were essentially the same: Headline, Copy, Image. So why not just put them all in one big table?
Now I've hit other problems around the ordering. It's Friday evening and my head hurts!
Can anyone offer advice?
Thanks.
Update: People have asked to see my "existing" schema:
articleID *
headline
copy
imageURL
visible
pageOrder
subArticleID *
articleID
headline
copy
imageURL
visible
pageNumber
pageOrder
Will this work? How would I go about letting users change the order? It seemed the wrong way to do it, to me, so I threw this out.
I initially stored the sub-articles in a separate table, but then I realised that the fields were essentially the same: Headline, Copy, Image. So why not just put them all in one big table?
Because referential integrities are not the same.
That is, of course, if you want to restrict the tree to exactly 2 levels. If you want more general data model (even if that means later restricting it at the application level), then go ahead and make a general tree.
This would probably look something like this:
Note how both PARENT_ARTICLE_ID and ORDER are NULL-able (so you can represent a root) and how both comprise the UNIQUE constraint denoted by U1 in the diagram above (so no two articles can be ambiguously ordered under the same parent).
Based on what you've described. I would use two tables. The first table would hold all the articles and sub-articles. The second would tie the articles to their sub-articles.
The first table (call it articles) might have these columns:
+-----------+----------+------+----------+---------+------------+-----------+
| articleID | headline | copy | imageURL | visible | pageNumber | pageOrder |
+-----------+----------+------+----------+---------+------------+-----------+
The second table (call it articleRelationships) might have these columns:
+-----------------+----------------+
| parentArticleID | childArticleID |
+-----------------+----------------+
Not sure if you already accomplish this with the pageNumber column, but if not, you could add a column for something like articleLevel and give it something like a 1 for main articles, 2 for sub-articles of the main one, 3 for sub-articles of a level 2 article, etc. So that way, when selecting the latest 20 articles to be grabbed, you just select from the table where articleLevel = 1.
I'm thinking it would probably also be useful to store a date/time with each article so that you can order by that. As far as any other ordering goes, you'll have to clarify more on that for me to be more help there.
To display them for the user, I would use AJAX. I would first display the latest 20 main articles on the screen, then when the user chooses to view the sub-articles for a particular article, use AJAX to call the database and do a query like this:
SELECT a.articleID, a.headline
FROM articles a
INNER JOIN articleRelationships ar ON a.articleID = ar.childArticleID
WHERE ar.parentArticleID = ? /* ? is the articleID that the user clicked */
ORDER BY articleID
The client needs to be able to hide/display news articles (easy), but
also change their order, if they desire (harder).
On this particular point, you'll need to store client-specific ordering in a table. Exactly how you do this will depend, in part, on how you choose to deal with articles and subarticles. Something along these lines will work for articles.
client_id article_id article_order
--
1 1067 1
1 2340 2
1 87 3
...
You'll probably need to make some adjustments to the table and column names.
create table client_article_order (
client_id integer not null,
article_id integer not null,
article_order integer not null,
primary key (client_id, article_id),
foreign key (client_id) references clients (client_id) on delete cascade,
foreign key (article_id) references articles (article_id) on delete cascade
) engine = innodb;
Although I made article_order an integer, you can make a good case for using other data types instead. You could use float, double, or even varchar(n). Reordering can be troublesome.
If you don't need the client id, you can store the article ordering in the article's table.
But this is sounding more and more like the kind of thing Drupal and Wordpress do right out of the box. Is there a compelling reason to reinvent this wheel?
Create a new field in news(article) table "parent" which will contain news id of parent article. This new field will be used as a connection between articles and sub articles.
As SlideID "owns" SubSlideID, I would use a composite primary key for the second table.
PrimaryKey: slideID, subSlideID
Other index: slideID, pageNumber, pageOrder (Or however they get displayed)
One blog post I prefer to point out about this is http://weblogs.sqlteam.com/jeffs/archive/2007/08/23/composite_primary_keys.aspx as it explains why very nicely.
If you're replying on Auto_Increment, that can be handled too (with MyISAM tables), you can still set subSlideID to auto_increment.
If you're likely to go to a third level then merge - follow Branko above. But it does start to get very complicated, so keep separate for 2 layers only.
I am am new to PHP/Databases... But I am picking it up fairly swiftly. What I would like to ask you guys is pretty simple. I want to normalize my database and am not positive how to go about it. I get the concept, but see multiple ways to do it. Figure I'd ask people with some experience.
Here is my Database (2 tables so far):
Brands
Products
***Brands Breakdown:***
1 id int(6)
**Note:** Above, I will probably use 4-Letter codes for each brand instead of primary/int/auto.
2 name text
3 logo varchar(20)
4 phone varchar(20)
5 website varchar(30)
6 contact_name text
7 contact_number varchar(20)
8 contact_email varchar(30)
9 warehouse varchar(20)
10 pricing varchar(15)
11 bio varchar(300)
***Products Breakdown***
id (INT(6) / Auto_Increment)
brand (This is where I'll insert the four letter code for brand)
category (e.g. Brakes)
subCategory (e.g. Brake Rotors)
details (e.g. Drilled and Slotteed 'Razr')
sku (Part #)
minYear
maxyear
make (e.g. Subaru)
model (e.g. Impreza)
subModel (e.g. WRX STi)
description (Paragraph on part describing it)
specs (I imagine this can be expanded on. need cells somewhere for sizes / colors / engine codes / etc.)
msrp
jobber
price
cost
weight (of part)
warehouse (Could be moved to brand's table)
image (URL of image for the part)
So My main question is: Do I make each brand have there own table similar to my current 'products' table? or have 'category' tables? 'subCategories'? How would you guys normalize this data?
I would like to have a solid database while I'm learning this stuff so I learn the right way. Any advice would be appreciated.
UPDATE:
To anyone who comes across this question who is trying to learn how to structure their database, one major thing I was unaware of when I asked this was something called "cardinality". Research this topic and learn how to apply it to your database schemas!
Don't make each brand have its own table. That's not normalization, that's partitioning. Don't do that until your data base gets very large.
It's not clear what your brand table means. I am guessing you mean parts-manufacturer, but I'm not sure. The rest of this discussion assumes that you do mean parts-manufacturer.
Here's my suggestion.
Rename your brand table. Call it "Manufacturer" and split it in two, for Manufacturer and Contact.
Manufacturer:
mfrid (your four letter code, primary key)
mfrname text
mrflogo varchar(20)
mfrwebsite varchar(30)
mfrphone varchar(20)
warehouse varchar(20)
Contact:
mfrid (four letter code) (part of primary key)
contactid (autoincrement) (part of primary key)
contact_name text
contact_number varchar(20)
contact_email varchar(30)
bio varchar(300)
Why is "pricing" an attribute of the manufacturer? What do you mean by "pricing?" Isn't it an attribute of an individual part?
Split your parts table into two. One table will have a row for each part sku. The other will have a table for each application (that is, each make and model of car in which the part may be used). Like so:
SKU:
sku (your stock-keeping unit number, primary key).
mfrid (maker of the PART, not the vehicle in which it fits, foreign key to mfr table).
mfrsku (the brand's stock keeping unit, not necessarily unique in your system)
category (e.g. Brakes)
subCategory (e.g. Brake Rotors)
details (e.g. Drilled and Slotteed 'Razr')
description (Paragraph on part describing it)
saleprice (?)
cost (?)
Application:
ApplicationID (auto incrementing primary key)
make (e.g. Subaru)
model (e.g. Impreza)
subModel (e.g. WRX STi)
firstYear.
lastYear.
Then, you'll need a join table (because each Application can have zero or more SKUs and vice versa; that is, your SKU and Application entities can have many-to-many relationships). In your example, you know that multiple models of Subarus often take the same parts. This schema allows for that.
ApplicationSKU:
ApplicationID
SKU
The trick to normalizing is to understand your application domain. Figure out what entities you have: e.g.
manufacturers like Delco and Subaru
contact people like Joe and Harry
parts like Left Front Wiper Assembly and Rear Wiper Assembly
applications like 1999-2006 Subaru Forester and 1998-2007 Subaru Impreza
Create a table that matches each entity you have. Figure out how you will uniquely identify each entity (in other words, figure out what you will use for a primary key).
Create join tables when you have many-to-many relationships between entities.
Create foreign keys to connect the various entities together.
I hope this helps.
Change products.brand to products.brand_id and have it be a foreign key to brands.id.
Create a categories table and with fields id, name and parent_id(allow NULL) which will house the categories.id of its parent (NULL means top-level category). Alternatively, you can use a nested set model. products would then have a products.category_id field (no subCategory field necessary).
And remember when you get to the part where you actually have orders or put things in the warehouse inventory, store theactual price at the time the action was taken. Price on a product is a lookup, it changes over time but the orders or the value of the item in inventory should be related to the actual costs at the time the record was entered.
One product can fit more than one car -- for example, you might have a wiper blade that fits a 2010 Toyota Camry, a 2009 Scion tC and a 2011 Acura TL. So, you will need to split year/make/model out of the products table, and make a separate table for vehicles (id, year, make, model) and a cross table (id, product_id, vehicle_id) that joins them.
I'm trying to create a web index. Every advertiser in my database will be able to appear on a few categories, so I've added a categorys column, and in that column I'll store the categories separated by "," so it will look like:
1,3,5
The problem is that I have no idea how I'm supposed to select all of the advertisers in a certain category, like: mysql_query("SELECT * FROM advertisers WHERE category = ??");
If categories is another database table, you shouldn't use a plain-text field like that. Create a "pivot table" for the purpose, something like advertisers_categories that links the two tables together. With setup, you could do a query like:
SELECT A.* FROM advertisers AS A
JOIN advertisers_categories AS AC ON AC.advertiser_id = A.id
WHERE AC.category_id = 12;
The schema of advertisers_categories would look something like this:
# advertisers_categories
# --> id INT
# --> advertiser_id INT
# --> category_id INT
You should design your database in another way. Take a look at Atomicity.
Short: You should not store your value in the form of 1,3,5.
I won't give you an answer because if you starting you use it this way now, you going to run into much more severe problems later. No offense :)
It's not possible having comma-separated values to do this strictly in an SQL query. You could return every row and have a PHP script which goes through each row, using explode($row,',') and then if(in_array($exploded_row,'CATEGORY')) to check for the existence of the category.
The more common solution is to restructure your database. You're thinking too two-dimensionally. You're looking for the Many to Many Data Model
advertisers
-----------
id
name
etc.
categories
----------
id
name
etc.
ad_cat
------
advertiser_id
category_id
So ad_cat will have at least one (usually more) entry per advertiser and at least one (usually more) entry per category, and every entry in ad_cat will link one advertiser to one category.
The SQL query then involves grabbing every line from ad_cat with the desired category_id(s) and searching for an advertiser whose id is in the resulting query's output.
Your implementation as-is will make it difficult and taxing on your server's resources to do what you want.
I'd recommend creating a table that relates advertisers to categories and then querying on that table given a category id value to obtain the advertisers that are in that category.
That is a very wrong way to define categories, because your array of values cannot be normalized.
Instead, define another table called CATEGORIES, and use a JOIN-table to match CATEGORIES with ADVERTIZERS.
Only then you will be able to properly select it.
Hope this helps!