I have a categories table like this for my forum:
CREATE TABLE categories (
category_id TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(60) NOT NULL,
PRIMARY KEY (category_id),
UNIQUE (name)
) ENGINE = MYISAM;
As you can see, I set up the name column as UNIQUE because I intended to allow users to freely create new categories as they wish when they create new posts.
Now, I am creating the edit.php page to enable users to edit their own posts, in which I allow them to change the category of the posts if they wish.
Assume that everything goes smoothly with my UPDATE query for the edit.php page.
However, The problem arised here is that when the user accesses the edit.php page to update the his own post's category, he immediately changes his mind that he does not want to change it anymore. The he clicks the submit button. The error occurs saying Duplicate entry 'x' for key y. I guessed that the root cause was at the unique(name) in the table.
So, should I remove the UNIQUE type for the name column and sacrify the feature of allowing users to create new categories freely?
Or, If I can keep it, your help for a piece of code will be appreciated!
Thanks
This is not a database problem which you can solve with SQL. This is an application problem. If no category must be changed or added, the application should not try to change or add categories. Removing the UNIQUE attribute would probably allow the application to do an unwanted change, which doesn't seem to me a great solution.
Anyway, I suggest you use InnoDB. MyISAM does not provide any benefit for this kind of tables.
Add duplicate validation before update the category this is mandatory
For this case append another condition name != '$_POST["name"]' in the update query.
UPDATE categories SET name = '$_POST["name"]'
WHERE category_id = '$_POST["category_id"]'
AND name != '$_POST["name"]'
Related
I have question about changing value in child table automatically if value of table mother change value.
I have two tables are brand(mother) and cat(child).
I add foreign key is brand_id in table cat related to primary key id in table brand.
If I change brand_name from brand table, I also want brand_name in table cat changed automatically. Is it possible? and how can I do it.
Thank you so much.
Brand:
Cat:
You could create a custom trigger on the brand table which before update would perform the necessary updates on the cat table.
Here is a link to the documentation for MySQL triggers:
https://dev.mysql.com/doc/refman/8.0/en/create-trigger.html
UPDATE:
As commented by #kerbholz, proper data modeling would suggest that the brand name column shouldn't exist in the cat column as it creates duplication of data. If this is purely for your client to see the data, perhaps building them a custom view using properly modeled tables is a better solution.
Link to appropriate documentation:
https://dev.mysql.com/doc/refman/8.0/en/create-view.html
I have a little issue that has been bothering me, I get the excess of the whole foreign key ideal, owever , could there be any way to get Laravel forign key to a defualt value whenever the reference table is deleted.
One reason I ask this is say for instance say a category is deleted, and the category has alot of say products, when ever the category is deleted the whole product goes along with it.
And then the use has to a new category and then recreate the product that was deleted.
If you want to set null on delete:
$table->...->onDelete('set null');
First make sure you set the foreign key field as nullable:
$table->integer('foreign_id')->unsigned()->nullable();
Right now I'm working on a small blog project and I have 2 tables in my database: users and posts. I want to display name of the author of the post so I thought I should make foreign key for user in post table. But what if I would create normal column called for example user_id and just save there id of the author. Then while I would like to display post i could join both tables and display content of post and name of the author.
Does creating foreign key have some adventages?
Either way, you are going to need a "normal" column, such as user_id.
The advantage of making the user_id a foreign key is that then, the database will enforce referential integrity. This means it won't allow you to set on a post a user that does not exist, nor will it allow you to delete a user who has one or more posts (without also deleting the relevant posts).
Database:
Table: news
With the columns: Unique and Primary Key which auto increments called ID, content and title
Code:
-> Creates a form with a textfield, where the user can put in his value for the ID and thus the position of the item
$form->textField("Position of the item item", "id", false, 30, false, getIfExists("id", $originalValues));
-> Posts the new ID as a query to the database
$queryvalues["id"] = $_POST[ "id" ];
It works when I post an ID that isn't in use by another item. However, if I try to overwrite an ID, it gives me an error and doesn't change anything. Obviously, I'd need to update the IDs, so that it'll increment all the conflicting IDs and thus allowing the edited ID to be posted.
I'm kinda annoyed as how to be doing this. I had the idea of adding an index number that defines the position, then switched to sorting the list with the database ID and changing the ID in the CMS will be able to update that whenever the user of the CMS wishes.
However, I'm not too sure how to approach this and whether there is a better option/solution.
Does anyone have any ideas/tips/hints?
I've tried using ON DUPLICATE KEY UPDATE, but I'm having no luck with it so far.
EDIT:
Alright, so ordering works now. I made a new column called Position and just used that to order the items with and it works fine.
However, if I add a new item, with a same position, it'll put it under the other position. So basically the New "0" gets listed under the old "0", while sharing the same key. Any suggestions on how to fix this? I was thinking of incrementing the old duplicate key. But have no idea how this would work exactly.
Don't touch the id column, leave it as it is. Create a new column called "position" and use that, it will then allow non-unique values.
Your ID is setup to always be unique for a reason and having it auto-increment won't help either. Your id column will inevitably have gaps in it when you delete things but this isn't a problem.
"Primary Key" is forced to be unique and permanently persist. It's an identifier of the Entity and not intend to use as sorting/ordering.
to satisfied your requirement, simply add int or datetime/timestamp field then SELECT * FROM yoour_table ORDER BY field_name
I understand that you want to use the ID to ordering your items : don't do that.
Instead, add a new columns named "ordering" :
When INSERT-ing an item, set this field value to the ID value
When UPDATE-ing the item position, swap the position value between the two items that are moving
I was just wondering if I might get some advice on the following:
I'm building a site in CodeIgniter in which exists a content type "portfolio_item".
The same portfolio item may be displayed in 3 places via checkbox controls:
Homepage, Member Page and Client Page.
I'm just wondering what the best way to implement this relationship in the database is. I could have 3 relationship tables for each of the above scenarios, but to me this seems overkill (the site is quite small).
I was thinking of using one relationship table with the following fields:
type (homepage, client or member)
show_on_id
portfolio_id
The intent of the type field is to determine which table to retrieve the "show_on_id" from (either clients or member), if the type is homepage then show_on_id is not required.
Is there any obvious disadvantage of doing it this way?
Yes, there is a bit of a disadvantage. You could end up with multiple rows for the same setting, each might contradict each other. So, how you insert rows into this table, is very important.
If you will not add any more sections, might as well have the portfolio table:
CREATE TABLE `portfolio`
(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`content` TEXT NULL,
`showHome` BOOLEAN NULL,
`showClient` BOOLEAN NULL,
`showMember` BOOLEAN NULL)
And then the table which links the users to their portfolios,
CREATE TABLE `portfolio_user`
(`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`portfolio` INT NOT NULL,
`user` INT NOT NULL)
If you are going to add more places where the portfolio can be displayed later, or if these places are dynamic, your method will work. I would just change 'type' to 'place' as that is easier to understand, then either use ENUM or another table to define the places that the portfolio can be shown.
Can there be one or many portfolio items for each location?
If many, use link tables, if only one use direct foreign key field to link to the portfolio.
I would advice against using one link table for all three based on personal experience with exactly such designs and the problems that can surface later.