SQL. Create one big table or different tables for earch client "client stock portfolio"? It is training project - mysql

What is better for multiply clients?
I create training project and can't understand what's better. Create one big stock portfolio table for all broker's clients or create individual table for each client? Individual table will require add brokerage agreement id for each table's name for it indentification.
DROP TABLE IF EXISTS portfolio;
CREATE TABLE common_portfolio (
common_portfolio_id serial,
brokerage_agreement_id BIGINT UNSIGNED NOT NULL,
type_assets_id BIGINT UNSIGNED NOT NULL,
stock_id BIGINT UNSIGNED NOT NULL,
stock_num BIGINT UNSIGNED NOT NULL,
FOREIGN KEY (brokerage_agreement_id) REFERENCES brokerage_agreement (brokerage_agreement_id),
FOREIGN KEY (type_assets_id) REFERENCES type_assets (type_assets_id),
FOREIGN KEY (stock_id) REFERENCES stock (stock_id)
);
VS
DROP TABLE IF EXISTS portfolio_12345612348; -- number generate from brokerage_agreement_id
CREATE TABLE portfolio_12345612348 (
position_id serial,
type_assets_id BIGINT UNSIGNED NOT NULL,
stock_id BIGINT UNSIGNED NOT NULL,
stock_num BIGINT UNSIGNED NOT NULL,
FOREIGN KEY (type_assets_id) REFERENCES type_assets (type_assets_id),
FOREIGN KEY (stock_id) REFERENCES stock (stock_id)
);

It is always better to keep all them in same table.
Keeping each client's data in a separate table will provide you with best performance only in case when you're looking for this particular customer.
But in all other cases it will be hell: creating/deleting a client will require you to build a dynamical create/drop table statement.
When sometime later you decided to add a column, you'll need to find ALL of those tables somehow and add new column to each one of them.
Even counting number of clients will cause you to write way more code rather than just "select count" statement.
And many more cases
So, use only one table

Related

Why are there are two rows in MariaDB database violating unique constraint?

I have written an application in Javascript which inserts data into two tables via a connection to a MariaDB server.
There should be a 1:1 correspondance between the rows in these tables when first running the application.
One table stores (simulated) data about properties, the other table stores data about prices. There should be 1 price for each property. At a later date, the price might change, so there could be more than one entry for the price, but this cannot happen when the application is first run. These entries also cannot be in violation of a unique index - but they are.
Perhaps I have misconfigured something in MariaDB? Here is the code which generates the tables.
drop table if exists property_price;
drop table if exists property;
create table property
(
unique_id bigint unsigned not null auto_increment primary key,
web_id bigint unsigned not null,
url varchar(256),
street_address varchar(256),
address_country varchar(64),
property_type varchar(64),
num_bedrooms int,
num_bathrooms int,
created_datetime datetime not null,
modified_datetime datetime not null
);
create table property_price
(
property_unique_id bigint unsigned not null,
price_value decimal(19,2) not null,
price_currency varchar(64) not null,
price_qualifier varchar(64),
added_reduced_ind varchar(64),
added_reduced_date date,
created_datetime datetime not null
);
alter table property_price
add constraint fk_property_unique_id foreign key(property_unique_id)
references property(unique_id);
alter table property
add constraint ui_property_web_id
unique (web_id);
alter table property
add constraint ui_url
unique (url);
alter table property_price
add constraint ui_property_price
unique (property_unique_id, price_value, price_currency, price_qualifier, added_reduced_ind, added_reduced_date);
Below is a screenshot from DBeaver showing that a select statement returns two identical rows.
I don't understand why the unique constraint appears to be violated. The constraint does sometimes work, because if I run my application again, it fails because it attempts to insert a duplicate row which already exists in the DB. (Not the same as the one shown below.)
Can anyone point me in the right direction as to how I might debug this?
MariaDB permits multiple values on columns which form part of a unique constraint.
My solution would be to put the logic for checking for duplicate rows into the application, rather than this being on the database side. Essentially this means the unique constraint is not being used.

MySQL for 1-to-1 relation with relational integrity

I'm trying to write a create table statement for the relationship above. I'm not sure if I've represented it correctly but basically every outlet has one manager and every manager manages one outlet. I believe that either one of the primary keys from either table would be able to supply the primary key to the relationship table, can I just pick either of them?
I've also been told that I don't even need to create a separate table for the relationship unless it was a many-to-many relationship?
I'd also like to have some sort of constraint (if thats the right word) where if a store cant be deleted if a manager is attached and also can't delete a manager if they are attached to an outlet.
I've written a create table statement which I think is right but i've been doing this stuff for about 2 weeks and I really have no idea if it is going to behave the way I want:
CREATE TABLE Managers
(
mgr_id int(10) NOT NULL auto_increment,
mgr_name varchar(255),
PRIMARY KEY (mgr_id)
);
CREATE TABLE Outlet
(
store_id int(10) NOT NULL auto_increment,
store_name varchar(255),
PRIMARY KEY (store_id)
);
CREATE TABLE Store_Manager
(
mgr_id int(10) DEFAULT '0' NOT NULL,
store_id int(10) DEFAULT '0' NOT NULL,
PRIMARY KEY (store_id),
FOREIGN KEY (mgr_id) REFERENCES Managers(mgr_id)
ON DELETE NO ACTION
);
Will those statements create tables that behave according to the requirements?
Thanks

How do you create a constraint on parent tables that also constrains the child tables?

I am not sure how to phrase the question so I'll illustrate the tables and the explain what I want to achieve.
-- static table of the entity classes supported by the application
create table entity_type (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- static table of statuses supported by the application
create table entity_status (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- table of valid combinations
create table entity_type_entity_status_link (
entity_type_id integer not null,
entity_status_id integer not null,
unique key(entity_type_id, entity_status_id),
foreign key(entity_type_id) references entity_type(id),
foreign key(entity_status_id) references entity_status(id),
);
-- The tables where user types and statuses are defined
create table user_type (
id integer not null auto_increment,
name varchar(30) not null,
entity_type_id integer not null,
primary key(id),
foreign key(entity_type_id) references entity_type(id)
);
create table user_status (
id integer not null auto_increment,
name varchar(30) not null,
entity_status_id integer not null,
primary key(id),
foreign key(entity_status_id) references entity_status(id)
);
-- table of valid pairs
create table user_type_user_status_link (
user_type_id integer not null,
user_status_id integer not null,
unique key(user_type_id, user_status_id),
foreign key(user_type_id) references user_type(id),
foreign key(user_status_id) references user_status(id),
);
The basic premise behind these tables is that the system supports core types and statuses and the user is able to create their own user types and statues that derive from these.
The question I have is that I cannot see a way of creating any database constraints on the user_type_user_status_link table to ensure that the you cannot insert a file_type - file_status pair where the parent entity_type - entity_status is itself not valid. Or is this something that would have to be done with triggers.
The basic premise behind these tables is that the system supports core
types and statuses and the user is able to create their own user types
and statues that derive from these.
Although that sounds like a laudable goal on the surface, the effect is to delegate database design to your users. Database design, because the effect of your desire to set foreign key references to a subset of the rows in entity_type_entity_status_link means each of those subsets is a defacto, unnamed table.
This approach never ends well.
What you've developed is the "One True Lookup Table". Google that for a host of reasons why OTLT is an anti-pattern.
The best solution is to model real things in your tables. (Entity isn't a real thing. It's an abstraction of a real thing.) Something along the lines of either
create table file_status (
file_status varchar(30) primary key
);
or
create table file_status (
file_status_id integer primary key,
file_status varchar(30) not null unique
);
would work well for file statuses.
In the case of the second one, you can set a foreign key reference to either the id number (saves space, requires an additional join) or to the status text (takes more space, eliminates a join). Note that you need the unique constraint on the status text; your original design allows the user to enter the same text multiple times. (You could end up with 30 rows where entity_type.name is 'File'.
You should use triggers for that.
MySQL does not support constraints of the form that will prevent what you want.

Having trouble with foreign key

I am trying to have categories in my budget2000 table be the foreign key to category in mainBudget. Category is not a unique number so it cannot be a primary key. When I run the code I get the famous error 1005. When I make category part of the primary key in mainBudget with id the code runs, however this will create problems later on. What can I do to make categories a foreign key. I am using mysql 5.5.
Here is my code
create table mainBudget(
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
year Year NOT NULL,
amount double(10,2) NOT NULL,
category SMALLINT UNSIGNED NOT NULL,
primary key(id)
)ENGINE=INNODB;
create table budget2000(
id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
categories SMALLINT UNSIGNED NOT NULL,
INDEX categoryNumber (categories),
subCategory SMALLINT NOT NULL,
amount FLOAT(10,2) NOT NULL,
date DATE NOT NULL,
description VARCHAR(300) NOT NULL,
primary key(id),
FOREIGN KEY (categories) REFERENCES mainBudget(category)
)ENGINE=INNODB;
category is not indexed in mainBudget. The column in the referenced table has to be indexed (or the left prefix of an index).
Incidentally, are you sure it isn't better to have an additional table category and have mainBudget.category and budget200.categories both foreign keys to this table? Your current setup looks a little odd, particularly with the referenced column in mainBudget not being unique.
Having FKs referencing non-unique columns is not standard SQL. Even when MySQL InnoDB allows this, it does not mean that it is a good idea.
Make some ER-Diagrams and normalize your tables. (Use 3.NF if nothing else forces you not to do.) Having a separate table for Category seems to be the way to go. On the other hand the naming of your exiting tables makes me thinking these should be only one table or their naming is bad.
And when this 2000 has something to do with a year or what then forget about it. You can select this easy in your Queries. Just put everything in one table no matter what year it is.
Your question/problem seems to be design-related to me.

help with database modeling

I have two tables: one for areas (like science, sport, education), and another for professions (like scientist, designer, golf player). There is a foreign relationship between the two tables, which works without any problems at the moment.
But now I need another table to put "number of workers", "average age", "years in the company" (this list is possibly different for each profession). What is the best way to do this? Create another table? What would be the parent? Basically, it is a third statement.
CREATE TABLE group (
id smallint(5) unsigned NOT NULL auto_increment,
area varchar(30),
PRIMARY KEY (id)
)
CREATE TABLE job (
ref int(10) unsigned NOT NULL auto_increment,
jobid smallint(5) unsigned NOT NULL,
job varchar(50),
PRIMARY KEY (ref)
)
ALTER TABLE job
ADD CONSTRAINT FK_job
FOREIGN KEY (jobid) REFERENCES group(id)
ON UPDATE CASCADE
ON DELETE CASCADE;
From what I understand I would set up a third table as follows
Table: Employee
First_Name varchar(30)
Last Name varchar(30)
Age (int(3))
Employment Date (DATE)
Active (Yes/No)
JobFK (Points to emprego.PK)
With this kind of setup you can use joins on your tables to calculate how many workers are in the same profession. The average age of those employees, and how long they have been with the company. Given more information about your current tables I could even describe the sql queries for that information.