SQL insert command in relation table - sql

Sorry I am newbie in SQL and I need help with a sql relation table.
I need to insert query to my relation table.
In my program, I have a book and this book has many categories.
Should I create a one to many, or many to many relations for that?
And how can I make insert command for adding a book to my table.
I tried to do somethings but i dont know its correct or not.
tblBook: BookID, BookName , CategoryID
tblCat : CatID, CatName,
I create foreign key
tblCat.CatID -> tblBook.CatID like as that. Do I need third table? Or is that enough?
Then I didn't understand how I will insert many category to book table?
Could you help me? thanks for advices.

You have to use a relation many to many, because one book can have different categories and one is for different book.
You need 3 tables:
tblBook: BookID, BookName
tblCat : CatID, CatName
tblRelationBookCat : BookID, CatID
To insert, you have to:
Add a book in your tblBook
INSERT INTO tblBook(BookID, BookName) VALUES(1, 'Star-Wars');
Add a category in your tblCat
INSERT INTO tblCat(CatID, CatName) VALUES(1, 'Sci-Fi');
Add the relation in your tblRelationBookCat
INSERT INTO tblRelationBookCat(BookID, CatID) VALUES(1,1);

Simply, you did a relation with two tables. You also should make one-to-many relation. That's OK and there is no need to create third table. In insertion, you need rows on category table. Because, when you adding a row with value of foreign key on book table logically you have to add a exists category id on category table's primary key.
Example :
tblCat | tblBook
-------------- | ---------
CatID CatName | BookID BookName CategoryID
1 Sci-Fi | 1 Star-Wars 1
2 Adventure | 2 Witcher 2
| 3 Romeo & Juliet 3 (???)
SQL Query :
INSERT INTO tblBook(BookName, CategoryID) VALUES('Star-Wars',1);

Related

SQL Table Relations

We have lots of tables in MS SQL that created without table relations many years ago. Now we are trying to create a relationship between these tables. The problem is in many of these developers used fake ids in the tables.
For example:
TABLE A, ID(primary key) -> TABLE B, AID needs to be relational. But developers used some fake ids like -1,-2 to solve some problems in their side. And now when I try to create a relation between TABLE A, ID(primary key) -> TABLE B, AID, I am getting errors.
TABLE A
ID | NAME
1 | name01
2 | name02
TABLE B
ID | NAME | AID
1 | name01 | 1
2 | name02 | -1
3 | name03 | -2
Is there way to solve this problem and is it meaning full what developers did, they didn't use any relations in sql, they are controlling everything in code-behind.
Thanks
You need to add those to your reference table. Something like this:
insert into a (id, name)
select distinct aid, 'Automatically Generated'
from b
where not exists (select 1 from a where b.aid = a.id) and
a.id is not null;
Then you can add the foreign key relationship:
alter table b add constraint fk_b_aid foreign key (aid) references a(id);
The general idea of referential integrity is exactly that you can't have invalid references.
So the best course of action here would be to suck it up and manually clean it up. Create the missing entries in the other table, or delete the records.
You can also ignore checks on existing data. If you are using sql server management studio to create relations there is option to do that just like in this screen shot
Hope it helps

Update, Insert, or Delete a Set into table

I have a n : m relationship between two tables, Product and Tag, called ProductTag. It has only two columns: ProductId and TagId.
The primary key is a composite of these two columns.
Inserting into this table is straight forward.
But, having a new set of tags that should be associated with the product, what are my options of updating the table in one go?
Right now, inside a transaction, I delete all product tags associated with a product, and insert the 'updated' ones. This works, is simple, and did not take a long time to code.
I'm still curious how it could be solved more elegantly, maybe even with PostgreSQL specific functionality?
Example:
Say you had 3 entries in this table:
product_id | tag_id
-----------+-------
1 | 2
1 | 3
1 | 6
A request arrives to update the product tags to look as follows:
product_id | tag_id
-----------+-------
1 | 3
1 | 6
1 | 7
Tag with tag_id 2 was removed, and a new tag with tag_id 7 was added. What is the best way of achieving this state in a single statement?
If we are talking about the "usual" amount of tags - say "tens" of tags, rather than "thousands" - then the delete/insert approach isn't such a bad idea.
You can however do it in a single statement, that applies the changes:
with new_tags (product_id, tag_id) as (
values (1,3),(1,6),(1,9)
), remove_tags as (
delete from product_tag pt1
using new_tags nt
where pt1.product_id = nt.product_id
and pt1.tag_id <> ALL (select tag_id from new_tags)
)
insert into product_tag (product_id, tag_id)
select product_id, tag_id
from new_tags
on conflict do nothing;
The above assumes that (product_id,tag_id) is defined as the primary key in product_tag.
Online example: https://rextester.com/VVL1293

Join Table vs Foreign Key/Ref

Imagine I have two tables and they have a 1-to-Many relationship. Is it better to have a Join table storing the relationship, or issuing a foreign key in one of these tables? Take a look of these two situations:
Situation A:
Table 1: CreditCard
Table 2: Person
It seems to me quite making sense to put the creditCard_id as part of the Person table
Situation B:
Table 1: Order
Table 2: Person
This time I think I will put the order_id and person_id in a Join table?
Am I making a mistake in the above? Is there a standard/better way of determining this?
For 1 to Many relation, people usually put the foreign key into the heavier table or the "Many" table.
So from your example, both go CreditCard and Order tables, by doing so you will remove duplicate data.
Imagine you which one is better:
FK goes to the "Many" table
Table People:
ID NAME
1 A
2 B
Table CreditCard:
ID PEOPLE_ID
1 1
2 1
FK goes to "1" table:
Table People:
ID NAME CreditCard_ID
1 A 1
1 A 2
2 B 3
Table CreditCard:
ID
1
2
3
Note: See how the ID and Name are repeated(ID=1, NAME=A) in the second example, that happens if you put the FK in the wrong table.
I would make three tables; a person table with all their info( name, address, etc. ), a credit card table with all the info( expiration date, security number?, etc.. ) then another table connecting them with the PersonID and CreditCardID. But what do I know, I'm still in school lol so wait for someone else to answer you.

SQL field with multiple id's of other table

Could someone give me an idea how to create this database structure.
Here is an example:
Table "countries":
id, countryname
1, "US"
2, "DE"
3, "FR"
4, "IT"
Now I have another table "products" and in there I would like to store all countries where this product is available:
Table "products":
id,productname,countries
1,"product1",(1,2,4) // available in countries US, DE, IT.
2,"product2",(2,3,4) // available in countries DE, FR, IT.
My question:
How do I design the table structure in "products" to be able to store multiple countries?
My best idea is to put a comma-separated string in there (i.e. "1,2,4"), then split that string to look up each entry. But I doubt that this the best way to do this?
EDIT: Thank you all for your help, amazing! It was difficult to choose the right answer,
I finally chose Gregs because he pointed me to a JOIN explanation and gave an example how to use it.
You need an intersection table for that many-to-many relationship.
Table Country
CountryID, CountryName
Table CountryProduct
CountryID, ProductID
Table Product
ProductID, ProductName
You then Inner Join all 3 tables to get your list of Countries & Products.
Select * From Country
Inner Join CountryProduct On Country.CountryID = CountryProduct.CountryID
Inner Join Product On CountryProduct.ProductID = Product.ProductID
Without denormalizing, you'll need to add an extra table
Table Product countries
ProductID CountryID
1 1
1 2
1 4...
What you're talking about is normalisation. You have a many-to-many structure, so you should create another table to link the two. You should never (ok, pretty much never) use delimited strings to store a list of values in a relational database.
Here's an example of the setup:
product_countries table
productid | countryid
----------+-----------
1 | 1
1 | 2
1 | 4
2 | 2
2 | 3
2 | 4
You can use a foreign key to each other table, then make them both into a composite primary key.
You can then get a list of supported products for a country ID like this:
SELECT * FROM products, product_countries
WHERE products.id = product_countries.productid
AND product_countries.countryid = $cid
You could also make a third table countries_products with fields country_id and product_id.
the best approach for relational databases is the following :
One table for coutries, let's say
country_id, country_desc (country_id is primary)
one table for products, let's say
product_id, product_desc and as many columns as you want (product_id is primary)
if you had only one country for sure, it'd be enough to have a foreign key pointing to country_id in each product row. Having a foreign key asserts that there is an actual country behing a country_id referring to country table.
In your case you have several countries for a product, so add a separate association table
product_id, country_id
both keys primary and both foreign as well.

Storing and retrieving multiple values from a foreign table

I have one table "Books", with a column "genres" where I want to reference to another table that contains list of genres.
The problem is that want to store more then one genres in column.
E.g,
ID | Author | Title | Genres
2 | David Baldacci |Stone Cold | 1,4 (action thriller )
table "Books Genres" with 2 columns Id and Genre.
1 Action
2 Drama
3 Comedy
4 Thriller
5 Horror
Can something like this be done? or it's not practical and I should store genres as simple string?
The best way to solve this problem is with what is called a linking table.
A linking table would look like this:
ID (optional) | BookID| GenreID
1 2 1
2 2 4
Then each book could have multiple rows (or one) in this table.
(The optional ID would be useful if you care about row-level auditing of your tables, or transaction auditing -- you could use it to uniquely id this row -- for your problem it is not needed).
It can be done, but shouldn't.
It is bad database design - your database should be normalized.
I suggest an many-to-many table - with genreId and bookId columns (being foreign keys each, and together forming a composite primary key). This will work as the link you need (a book can have many genres, each genre can write many books).
Giving your book as an example with the Book Genres table, this would look like:
bookId genreId
2 1
2 4
You need a third table, perhaps called BookGenre which acts as a "resolver" for the many-many relationship. BookGenre would have two columns, BookID and GenreID. A row would be added to BookGenre for each book for each genre.
There would be two rows in BookGenre for the example data you provided:
BookID GenreID
2 1
2 4