Watch out, learning sql newbie. I would like to create 2 simple tables.
products: id | product_name
order_table: id | buyer_name | purchased_products
CREATE TABLE products (
id INTEGER PRIMARY KEY,
product_name TEXT
);
CREATE TABLE order_table (
id INTEGER PRIMARY KEY,
buyer_name TEXT,
purchased_products NUMERIC ARRAY
);
Currently the link is numeric, but this would require the report generation to know that purchased_products is referring to the products table. Is it possible to define that the purchased_products must be referring to the products?
Note: this is sqlite3,
Remove the field purchased_products and create one more table, like this:
order_product: id | order_id | product_id
Now, you should declare that order_id is a foreign key referring to the field id of the table order_table, and that product_id does the same for products.
Related
I need to add a constraint when creating a table, Order, such that the unique combination of fields exist within another table.
Table: Product
productId PRIMARY KEY
productNumber
and,
Table: Order
clientId FOREIGN KEY
productId FOREIGN KEY
productNumber
dateBorrowed
dateReturned
I have two tables Product and Order. The productId and productNumber create a unique combination to specify a product as multiple versions of the same product may exist.
When entering values into the Order table the unique combination of productId and productNumber must exist within the Product table, duplicates are allowed as items can be returned and borrowed again at a later date.
I'm not sure how I would go about coding the constraint when creating the Order table, hope that all made sense.
Example Data:
Product
ProductId
ProductNumber
123
1
123
2
675
1
Table
clientId
productId
productNumber
dateBorrowed
dateReturned
10
123
1
1979
1989
10
123
1
1990
2000
12
675
1
2022
2022
07
123
2
1982
2022
The unique combination of fields you describe is in fact the primary key :
CREATE TABLE Product(
productId INTEGER,
productNumber INTEGER,
...
PRIMARY KEY (productId, productNumber)
);
You can reference it in the Order table :
CREATE TABLE "Order"(
...
productId INTEGER,
productNumber INTEGER,
...
FOREIGN KEY(productId, productNumber) REFERENCES Product(productId, productNumber)
);
Please note the Order table name must be quoted, ORDER is a SQLite keyword.
Also foreign keys must be enabled :
PRAGMA foreign_keys = ON;
I have have the following three tables:
Movie Types
CREATE TYPE category AS ENUM ('comedy', 'drama', 'action', 'thriller');
CREATE TABLE movie_types (
id BIGSERIAL PRIMARY KEY,
category category NOT NULL
);
Column | Type | Modifiers
--------+--------+----------------------------------------------------
id | bigint | not null
category | category | not null
Movie to Movie types joins table
CREATE TABLE movie_categories (
id BIGSERIAL PRIMARY KEY,
movie_type_id FOREIGN KEY REFERENCES movie_type(id)
movie_id FOREIGN KEY REFERENCES movie(id)
);
Column | Type | Modifiers
--------+--------+----------------------------------------------------
id | bigint | not null
movie_type_id | category | not null
movie_id | category | not null
Movies
CREATE TABLE movies (
id BIGSERIAL PRIMARY KEY,
name varchar
);
Column | Type | Modifiers
--------+--------+----------------------------------------------------
id | bigint | not null
name | string | not null
The Movie types is limited list of categories stored as an enum. A movie can have several different categories associated with it.
What's the best practice when storing something in a similar data model? I using the enum type here good practice or is it better to just use varchar for category in movie_types?
An ENUM sets up a predetermined set of values that a column can take. A look up table provides the same restriction on a column. The problem you face is you are attempting to implement both. A solution is to choose and implement one of them. I tend to lean toward minimizing maintenance where possible, so the following implements a look table approach.
First step: Drop the ENUM.
Second alter category table category to text.
Insert the prior enum values into category table.
Adjust other tables as needed.
The result becomes a simple M:M with Movie:Movie_Types with the intersection table movie_categories.
create table movie_types (
id bigint generated always as identity primary key
, category text not null unique
);
insert into movie_types(category)
values ('comedy'), ('drama'), ('action'), ('thriller');
create table movies (
id bigint generated always as identity primary key
, name varchar
);
create table movie_categories (
movie_type_id bigint references movie_types(id)
, movie_id bigint references movies(id)
, constraint movie_categories_pk
primary key (movie_id,movie_type_id)
);
I got 2 tables:
TABLE 1
CREATE TABLE product(
p_id int NOT NULL PRIMARY KEY,
p_name varchar(50) NOT NULL
);
TABLE 2
CREATE TABLE retailer(
r_id int NOT NULL PRIMARY KEY,
r_name varchar(60) NOT NULL
);
I would like to store images for the products and for the retailers. 1-1 relationship.
I don't want to have product_images table and retailer_images table.
Product and Retailer may have the same ids.
I want 1 images table to keep all the images on it and have a relation with it.
How can I do that?
You can add an extra column to both tables, eg:
ALTER TABLE product
ADD (
p_image varchar2(100) NOT NULL,
);
do same for the retailer table to store the image_name/image_id and use join to query from both tables creating a 1-on-1 relationship.
Check the documentation example here: https://www.oracletutorial.com/oracle-basics/oracle-joins/
This question already has answers here:
How to implement one-to-one, one-to-many and many-to-many relationships while designing tables?
(4 answers)
Closed 2 years ago.
In the requirements given to me, multiple products can be assigned to a single sale. However, I need help how this can be done in SQL and how would the table look like. Below is what my schema looks like:
Sample Schema
In the sales fact, I also included a column containing the aggregate sales for all the product included in the sale.
Ps. Same case with the Products but with Official_Receipt_Id as a single sale can also have many Official_Receipt_Id.
Help will be highly appreciated.
The proper way to do this is to use multiple tables and JOIN them in your queries.
For example:
CREATE TABLE product (
`product_id` VARCHAR(20) NOT NULL PRIMARY KEY,
`product_name` VARCHAR(50)
);
CREATE TABLE sales (
`sales_id` VARCHAR(20) NOT NULL PRIMARY KEY,
`customer_id` VARCHAR(20),
`total_price` INT
);
CREATE TABLE sales_product (
`sales_id` INT NOT NULL,
`product_id` VARCHAR(20) NOT NULL,
PRIMARY KEY(`sales_id`, `product_id`)
);
The sales_product table contains one row for each product a sale is associated with and effectively links the product and sales tables together. It would look something like this.
"Sale1" | "Product1"
"Sale1" | "Product2"
"Sale1" | "Product3"
"Sale2" | "Product1"
"Sale2" | "Product2"
When you want to retrieve a sale and all of the products you can do something like this:
SELECT s.*, p.*
FROM sales s
INNER JOIN sales_product sp
ON sp.person_id = s.sales_id
INNER JOIN product p
ON p.product_id = sp.product_id
I have a "junction" table (recipe_ingredients) that I'm using to handle a many-to-many relationship in my database. Each field in that table is a reference to the PK of another table: recipe_id, ingredient_id, quantity_id, and measure_id. These are the PKs of the metadata, ingredients, quantities, and measurements tables. With the exception of the metadata table, all these tables have only two fields: the PK, and a name or number associated with that PK.
I'm trying to query recipe_ingredients for all rows that have a given recipe_id... but instead of displaying the PKs in each row with that recipe_id, I want to display the name/number associated with that PK in that table.
So instead of a query that returns this:
recipe_id | ingredient_id | quantity_id | measure_id
----------+---------------+-------------+-----------
1 | 10 | 2 | 3
----------+---------------+-------------+-----------
1 | 12 | 2 | 3
----------+---------------+-------------+-----------
1 | 13 | 5 | 6
----------+---------------+-------------+-----------
...
I'm looking for a query that returns something like this:
recipe_id | ingredient_name | quantity_num | measure_num
----------+-----------------+--------------+------------
1 | Ground cayenne | 1/2 | tsp
----------+-----------------+--------------+------------
1 | Ground paprika | 1/2 | tsp
----------+-----------------+--------------+------------
1 | Olive oil | 1 | tbsp
----------+-----------------+--------------+------------
...
I just started learning SQL, so I only know how to make simple queries to a single table. I don't even know where to begin with this query, except that I may need a kind of join statement. What query could I write to achieve this?
I'm using sqlite3 on Debian.
The recipe_ingredients "junction" table:
CREATE TABLE recipe_ingredients (
recipe_id int,
ingredient_id int,
quantity_id int,
measure_id int,
primary key (recipe_id, ingredient_id),
foreign key (recipe_id)
references metadata (recipe_id)
on update restrict
on delete restrict,
foreign key (ingredient_id)
references ingredients (ingredient_id)
on update restrict
on delete restrict,
foreign key (quantity_id)
references quantities (quantity_id)
on update restrict
on delete restrict,
foreign key (measure_id)
references measurements (measure_id)
on update restrict
on delete restrict
);
These are the foreign tables referenced by the junction table:
create table if not exists ingredients (
ingredient_id integer primary key,
ingredient_name text not null
);
create table if not exists quantities (
quantity_id integer primary key,
quantity_num int not null
);
create table if not exists measurements (
measure_id integer primary key,
measure_name text not null
);
create table if not exists metadata (
recipe_id integer primary key,
recipe_name text not null,
course_id int,
cuisine_id int,
servings int,
prep_time int,
cook_time int,
total_time int,
foreign key (course_id)
references courses (course_id)
on update restrict
on delete restrict,
foreign key (cuisine_id)
references cuisine (cuisine_id)
on update cascade
on delete cascade
);
You can join the junction table with each of the related tables like so:
select
ri.recipe_id,
i.ingredient_name,
q.quantity_num,
m.measure_num
from recipe_ingredients ri
inner join ingredients i on i.ingredient_id = ri.ingredient_id
inner join quantities q on q.quantity_id = ri.quantity_id
inner noin measurements m on m.measure_id = ri.measure_id
where ri.recipe_id = ?
The question mark (?) stands for the recipe_id that you are looking for.