I have many shops in Shop table and many users in User table in DB.
User can subscribe to any stores.
How can I create table for this task? First column with shop name and second column - string with comma separated user ids?
This is generally referred to as a many-to-many relationship. In a standard relational database, this is usually represented by a table with user_id and shop_id, one row for each user -> shop relationship.
You will never want to use a comma-separated string to represent multiple items in a database, as this will make queries very inefficient. For example, to find which stores user a subscribes to, you would have to parse each row of the table to find which of the comma-separated values contains a.
This is a many-to-many relationship. You need a third table, say it's called Subscription. The fields will be two foreign keys, one referencing the primary key of the User table and the other referencing the primary key of the Shop table.
You can create a table where each row represents a subscription (i.e., a pair (user,shop)).
So, you will have (at least) two columns in the table: the id of the shop and the id of the user.
Assuming that a user can subscribe to a shop only once, the pair (user_id,shop_id) should be the primary key of the table (in case you need to define a surrogate key for the table, you could add a unique constraint to the pair (user_id,shop_id)).
If you have many data and need to quickly get all the shops to which a user has subscribed, you should add an index to the user_id column.
On the other hand, if you need to quickly get all the user that subscribed to a shop, you should add an index to the shop_id column.
I believe user can subscribe to multiple shops, and one shop can have multiple users subscribed to it. In this case, it is best to use map table with shop_id from shop table and user_id from user table. ( keep the foreign key constraints) . For each subscription ,this table will keep an entry, hence no comma separated string is necessary.
It sounds like you have a classic situation in databases which marks the change between a "flat file" database and "relational database" like MySQL, Oracle or MS's SQL Server. A similar situation is Authors and Books. An author can have more than one book and some books have more than one Author.
A simple comma delimited database is a flat file and you are going to need a separate line for each relationship. For example,
ShopA, UserA
ShopB, UserA
ShopA, UserB
ShopB, UserB
In a relational database, you can isolate the user table and shop table in two separate tables and form a third table, a relations table that describes the relation and so remove redundancy in the user and shop tables,
ShopTable
ShopA, SA
ShopB, SB
UserTable
UserA, UA
UserB, UB
ShopUserRelationTable
SA, UA
SA, UB
SB, UA
SB, UB
When you want records displaying the relationship, you apply the SQL language to create a sequence of records displaying this.
This basic problem of removing redundancy in tables is what motivates the development of relational database software.
It sometimes happens that a table is complicated enough to contain "many to many" relationship like this and SQL can be further applied to analyzing and creating records reflecting these relationships. Such a table may also serve as a many to many relationship table for other tables.
Related
I'm looking to have a GUI where when I click an Invoice it displays the information from both Customer and Product also, such as name, brand etc all in one row.
Do I have to put Name, brand, etc into Invoice too and inner join everything?
Invoice Table Customer Table Product Table
EDIT:
No, no need to modify the tables you're referring to. They all contain a unique primary key column which are referenced from the invoice table. Based on them the INNER JOIN can be formulated.
Maybe also worth mentioning: Don't confuse the INNER JOIN with the SELF JOIN which also exists.
The difference is that the INNER JOIN is still joining two different tables based on specific columns (e.g. id) whereby the SELF JOIN is joining a single table with itself.
Yes what you'll need is the INNER JOIN combining the information from your invoice table with the one from the customer table as well as the product table - all based on your given invoice id (column: idInvoice).
To obtain the needed information you don't need to add - and therefore repeat - it in the invoice table. Due to the join they'll be available for selection in one single query.
Your query should look like:
SELECT *
FROM invoice inv, customer cust, product prod
WHERE
inv.idCustomer = cust.idCostumer
AND
inv.idProduct = prod.idProduct
AND
inv.idInvoice = ${theIdOfTheInvoiceTheUserClickedOn}
Note: If you don't need all the information (columns) from the three tables (what the "*" stands for) you can replace the "*" with an enumeration explicitly stating only the columns you want to show. E.g. inv.id, cust.FirstName, cust.LastName.
Depending on the database technology/ dialect you're exactly using. The example above would be suitable for an Oracle database and should also suite most other databases, since only basic SQL features are being used in the query.
I'm assuming you're not using any ORM framework like Hibernate and that you'll need to write the query yourself (since you didn't provide any more detail on your technology stack). In case youre using an ORM framework the approach would need to look different, but the final generated query should look similar.
In the query above the first two conditions in the WHERE clause are forming the INNER JOIN implicitly, whereby the last third one is specifying which exact entry you're looking for.
Although you've asked only if an INNER JOIN is needed, I've provided the query here to you since your question implied you're not sure how to write one.
You might take it as an working example you can compare your solution with. You should try to understand how it's working and how it can be written and also research more on the SQL basics so that you can write it on your own as well.
Tip: PreparedStatements are the way to go to execute such queries to a database from Java in a safe way
In my opinion, based on your application, you can use a flat table that includes what you need and doesn't need to join tables. This solution is applicable when you are in a situation that you have small datasets (E.g. in banking, relationships between Terminal table and ATMTerminal, POSTerminal and CashlessTerminal tables).
And for situations that you have a relationship that one side is static data (like the above example) and another side is transactional data (like Banking Transactions), you should use the foreign key from the transaction table to the static data table.
I recommend you to use the second solution for your problem and handle relationships using foreign keys and get the columns you need using the join strategy.
So I have a MySQL database schema where there is a USERS table which contains the ID as a primary key for that table, I also have a USER_PASSWORDS table which references the USERS table where the USER_ID will act as a foreign key in this table.
The issue that I am facing is that I am writing an application where the user will be able to sign up and specify a username and password. But I would like to insert the user into the database with one query.
I was thinking I had to insert the username first into the USERS table and see what ID has been given to that username and then insert the hash of the password that the user has entered into the USER_PASSWORDS table and specifying the ID that was queried.
I dont like this approach because it means that I have to:
INSERT into the database
QUERY the database
INSERT into the database again
Is there a better way of doing this?
Thanks
You can't insert into two tables with one insert statement, and you would have to query the users table anyway to get the ID value to insert as a foreign key for the user_passwords table.
Really the only way to do what you want is the solution you've already identified:
Insert into the Users table
Query to get the ID of the User you just inserted
Insert into the USER_PASSWORDS table with the ID you obtained for the User.
You could wrap all this up in a stored procedure that takes user data and password as parameters, which would be the "better" way of doing it.
As you didnt really tell for what system / programming language you need this and you did not provide any code example either, I can only give you some theory what you could do:
Its impossible to insert data into two different MySQL tables with one queries but you can reduce your script atleast by the SELECT query:
1.) There is a function in most mysql apis (Depending on what programming language and MySQL Library you are using) that says "getLastInsertId()", "lastInsertId()" or similar.
This will return the ID that was inserted by the auto-increment of the table after the insert is completed.
Just check the docs of your MySQL-api it will have such a function.
2.)
The second possibility is using a UUID - a very large (commonly 128-bit) long string which is generated totally random. There are more so many possible combinations it will happen more probably that you win in the lottery 10 times in a row then you generate two times the same UUID that is already in your table.
So you just generate the UUID and insert it as a key in both tables and you are done.
Just use google to find out-of-the-box libraries to generate UUID's you dont need to build the alogrithm on your own.
An UUID could looks like this:
4a34fe87-f577-4ea9-9557-1bc8f779a68c
One solution: since the hash is unique you can use the hash as a primary key in the USERS table. Then you know what the primary key (id) is at the time of the insert and can reuse when INSERTING in the USER_PASSWORDS table.
That way you can avoid the id query at least.
my question is involving database and application scope. I am currently running an web application that stores user info(for login), item info and purchase info. The way I am currently doing storing the data is by putting them in a List. I am thinking of storing the data to a database (mysql) and replace the lists. In thinking about it, i thought of whether it would make sense to store data in the database, but also store it in the Lists. Basically, i would be adding to the List via the database. Would it make sense to do this?Thanks!
You should not save the entire list into the field but each element in the list should be a separate row in the table. This is object-oriented design and it would be good practice to do so.
To achieve this, you need to have a one-to-many mapping for the user table to the purchase table. One user can make multiple purchases but each purchase can only be tied to one user. Therefore, your purchase table should contain a foreign key which is the ID for your user table.
For example, table A should be the list of all your users. Table B should contain all your purchases. We can see that Doug has made 3 purchases, (PA,WV and DE) while Bob has made 2 purchases (TN and NC).
I have some four database tables One table has two fields of interest which are set by the user at first download - first run.
The user sets his name and date of birth - after processing I assign this name and DOB to various records in other tables(In other tables there are only two possibilities either the record is associated with the owner who sets the name and DOB or user can associate a record with his friend using his friends name and DOB). Now I want to give the use a functionality to edit this record which is his name and DOB. However editing this one record should also trigger a change in all other records in other tables which are associated. Is there something inbuilt in SQLite to make this happen or do I have to loop through all records in all tables and change them manually?
Why don't you normalize your tables?
You could do:
table USER:
UserId(key), name, dateOfBirth
table OTHER:
fieldA, fieldB, fieldC, UserId (foreignKey)
That way you don't have to update the other tables accordingly. Depending on your usage scenario this might be the better way to go (e.g. in a traditional transactional setting). If you are in data-warehousing,... it might be better to denormalize your tables
If you have the user's name and DOB set as a foreign key to those other tables, you can also set a cascading trigger in the foreign key. When you create the table with that foreign key, you can set the ON UPDATE attribute to cascade, which will mirror that change in the user's information across any other entries that have it set as the foreign key.
https://www.sqlite.org/foreignkeys.html has more information on the topic.
The normal way is to introduce a (hidden to user) primary key, an autoincrement counter, and use that to access the record. UserID or such. Other tables then relate to the user via a UserID.
SQLite uses ROWID aka INTEGER PRIMARY KEY (specific to SQLite).
I'm working on a small feature in a Java web application that very closely resembles the vote up/down feature here at stackoverflow.com. I have a database that looks like the following:
VOTE TABLE
id (bigint): surrogate primary key
question_id (bigint):: the question the vote is for
vote_type (int): whether the vote is up or down
user_id (varchar): the username of the person who the vote belongs to
I want to ensure that there is only one vote in the DB per person, per question. What is the best way to enforce this? How would enforce it with the database schema I have described above?
I am currently having problems where a user fires off two vote-up requests and the database then contains 2 'up votes' for that user, when they should only have one vote.
You can enforce is via a Primary Key or Unique index - both concepts are pretty univeresal within databases. Place it on the two columns together, Question_id and User_id. That would only permit 1 entry per user, per question. This will be enforced by the database, even if your application codes lets them vote twice, the database will throw an error on the second record attempting to be inserted. (Even if you are using transactions etc, the database will enforce it correctly.)
If you want to enforce it via database schema, the correct way would be to make (question_id, user_id) an unique key.
Only do the INSERT when user_id and question_id NOT EXISTS e.g.
INSERT INTO TABLE
-- ALL YOUR FIELDS HERE
WHERE NOT EXISTS (
SELECT * FROM TABLE WHERE
QUESTION_ID = ? AND USER_ID = ?
)
However you could make user_id and question_id the Primary Key (or another Unique key) so only one record is physically allowed.