I have a main large table which I have had to put into 3rd normal form and into smaller tables (with primary and foreign keys linking them). The table is about renting books.
I have a customer table which I need to create a primary key for. In the main large table there are duplicates of the customer_id, as the table as a whole is for renting the books, so one customer may have more than one renting.
The table I am currently trying to add a primary key for will not have any nulls or duplicates, however i am unsure how to create the primary key for this without the error- unsure how to make it unique.
CREATE TABLE customer AS
SELECT cust_id, country_id, name, address, postcode
FROM BOOKS
WHERE cust_id != 0;
ALTER TABLE customer
ADD PRIMARY KEY (cust_id);
Is anyone able to help me in how to create the primary key on my customer table, but just taking each unique cust_id from the main table.
In SQL Server the straightforward way to add unique keys is to use IDENTITY. Identity fields are integer fields that auto populate successive values by a specified start value and interval. If you don't specify the interval it will start at 1 and increase the value by 1 each time a value is assigned.
While it's usually done when creating a table, you can do it in your ALTER TABLE step, and it will assign values when added to an existing table. I've explicitly specified the start value and interval that matches the default to show the syntax :
ALTER TABLE customer
ADD cust_id int not null PRIMARY KEY IDENTITY(1,1)
Related
One of the values to be inserted into a table is a foreign key. I need to figure out how to, inside the CHECK clause, check if a value in another table is equal to a specific value using the foreign key (which is unique in the other table).
Example Diagram
As an example, the MonkeySpecies table has a unique primary key. I need to make it so that the Monkey table can only be added to if the SpeciesID in the MonkeySpecies table is not 'extinct'.
I have a project to create a simple database for a made-up business. I need to create all the tables and all the connections between them and fill in the tables.
I was able to create tables pretty easily and setting up primary and foreign keys where I want the tables to connect, but now I need to fill the tables with customers/orders/products, etc.
How would I fill a table with foreign keys and other things if all my tables are empty?
Example of a table I don't understand how to fill (all 'ID's are numbers):
Create table Orderdetails(
OrderDetailsID int Primary Key Identity(1,1),
InvoiceID int Foreign Key Invoices(InvoiceID),
Product int Foreign Key Products(ProductID),
Quantity int not null,
Price money not null
)
I've only managed to fill my Customers table because it has no foreign keys and doesn't rely on any other table. I'm new to SQL, I understand the code pretty well but I don't understand how to build a database. Please help!
You need to fill up the dependent tables first and then the reference table data.
here you have created the orderDetails table which has foreign key of InvoiceId and ProductId.
In this perticilar case If you want to insert a new orderDetails.
1st: Your have to insert product details to the product table.
2nd: Invoice details to the invoice table.
3rd: Now you have both priduct as well as invoice id which you can use while inserting order details.
Then you are able to insert all the data quite easyly.
Question may be basic, I don't have any experience with databases.
I have a postgres db with some tables. Two of them are dates and accounts.
The date table has an account_id field referencing an id table in an account table and a balance field that represents the balance that account had at that date. So, many date entities may reference one account entity, many-to-one, okay.
But an account table also has an actual_date field, that must reference the date entity, with actual balance this account has. One account entity may reference one actual date entuty, but date entity can have one or zero account entities referncing it. And if it does have an account referencing it with it's actual_date, it will always be the same account, date itself referencing with account_id.
What kind of relathinship is this? Is it even possible to implement? And if it is, how do I do it?
I came up with this piece of code, but I have no clue if it does what I think it does.
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users,
actual_date_id DATE UNIQUE REFERENCES dates
);
CREATE TABLE dates (
id SERIAL PRIMARY KEY,
account_id INT REFERENCES accounts,
date DATE,
balance INT,
unconfirmed_balance INT
);
P.S. I create tables with init.sql but work with them with sqlalchemy and it would be greate if someone could also show how to define such model with it.
As written the SQL script would never work for two reasons:
a foreign key can only reference the primary key of a table, not any arbitrary column in it. So actual_date_id should be an integer in order to be able to reference the primary key of the dates table.
you can't reference a table that hasn't been created yet, so the foreign key between accounts and dates must be created after both tables are created.
With circular foreign keys it's usually easier to define at least one of them as deferrable, so that you can insert them without the need of e.g. an intermediate NULL value.
So something along the lines (assuming that users already exists)
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users,
actual_date_id integer UNIQUE -- note the data type
);
CREATE TABLE dates (
id SERIAL PRIMARY KEY,
account_id INT REFERENCES accounts,
date DATE,
balance INT,
unconfirmed_balance INT
);
-- now we can add the foreign key from accounts to dates
alter table accounts
add foreign key (actual_date_id)
references dates (id)
deferrable initially deferred;
It might be better to avoid the circular reference to begin with. As you want to make sure that only one "current balance" exists for each account, this could be achieved by adding a flag in the dates table and getting rid of the actual_date_id in the accounts table.
CREATE TABLE accounts (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users
);
CREATE TABLE dates (
id SERIAL PRIMARY KEY,
account_id INT REFERENCES accounts,
is_current_balance boolean not null default false,
date DATE,
balance INT,
unconfirmed_balance INT
);
-- this ensures that there is exactly one row with "is_current_balance = true"
-- for each account
create unique index only_one_current_balance
on dates (account_id)
where is_current_balance;
Before you change a row in dates to be the "current one", you need to reset the existing one to false.
Unrelated, but:
With modern Postgres versions it's recommended to use identity columns instead of serial
I Have table three tables:
The first one is emps:
create table emps (id number primary key , name nvarchar2(20));
The second one is cars:
create table cars (id number primary key , car_name varchar2(20));
The third one is accounts:
create table accounts (acc_id number primary key, woner_table nvarchar2(20) ,
woner_id number references emps(id) references cars(id));
Now I Have these values for selected tables:
Emps:
ID Name
-------------------
1 Ali
2 Ahmed
Cars:
ID Name
------------------------
107 Camery 2016
108 Ford 2012
I Want to
Insert values in accounts table so its data should be like this:
Accounts:
Acc_no Woner_Table Woner_ID
------------------------------------------
11013 EMPS 1
12010 CARS 107
I tried to perform this SQL statement:
Insert into accounts (acc_id , woner_table , woner_id) values (11013,'EMPS',1);
BUT I get this error:
ERROR at line 1:
ORA-02291: integrity constraint (HR.SYS_C0016548) violated - parent key not found.
This error occurs because the value of woner_id column doesn't exist in cars table.
My work require link tables in this way.
How Can I Solve This Problem Please ?!..
Mean: How can I reference tables in previous way and Insert values without this problem ?..
One-of relationships are tricky in SQL. With your data structure here is one possibility:
create table accounts (
acc_id number primary key,
emp_id number references emps(id),
car_id number references car(id),
id as (coalesce(emp_id, car_id)),
woner_table as (case when emp_id is not null then 'Emps'
when car_id is not null then 'Cars'
end),
constraint chk_accounts_car_emp check (emp_id is null or car_id is null)
);
You can fetch the id in a select. However, for the insert, you need to be explicit:
Insert into accounts (acc_id , emp_id)
values (11013, 1);
Note: Earlier versions of Oracle do not support virtual columns, but you can do almost the same thing using a view.
Your approach should be changed such that your Account table contains two foreign key fields - one for each foreign table. Like this:
create table accounts (acc_id number primary key,
empsId number references emps(id),
carsId number references cars(id));
The easiest, most straightforward method to do this is as STLDeveloper says, add additional FK columns, one for each table. This also bring along with it the benefit of the database being able to enforce Referential Integrity.
BUT, if you choose not to do, then the next option is to use one FK column for the the FK values and a second column to indicate what table the value refers to. This keeps the number of columns small = 2 max, regardless of number of tables with FKs. But, this significantly increases the programming burden for the application logic and/or PL/SQL, SQL. And, of course, you completely lose Database enforcement of RI.
I am designing the database for an accounting system, currently working on the Expenses table.
According to IRS rules, whenever you update a row in any accounting table, you need to cancel out the existing row by negating its values, and create a new row with the modified information, like so:
Set the row's Status flag to "Modified"
Create an identical copy of this row, with all Money fields negated, so that the sum of the two rows is 0
Create a 3rd row, identical to the first one, with the modified data
Each expense has an identity field called ID for internal identification purposes, and an ExpenseID field, which identifies the transaction to the users. The two cannot be the same, because
ExpenseID can be repeated twice if the transaction was modified and its row was duplicated.
ExpenseIDs MUST be consecutive and NEVER have gaps, while identity fields can skip numbers if a transaction is rolled back and the identity is not reseeded.
In general, I believe the primary key should have no business meaning whatsoever.
My problem is that there are other tables used to link these expenses Many-To-Many to other objects in our system. E.g.: each expense can be linked to documents, folders, users, etc.
So it looks something like this:
create table Expenses (
ID int not null identity(1,1),
ExpenseID int not null,
Amount Money not null,
Status tinyint not null,
[...]
)
create table Expenses_Users (
ExpenseID int not null,
UserID int not null
)
alter table Expenses_Users add constraint FK_Expenses_Users_Expenses
foreign key (ExpenseID) references Expenses (ID)
alter table Expenses_Users add constraint FK_Expenses_Users_Users
foreign key (UserID) references Users (ID)
Now, because of the IRS guidelines, I have to duplicate not only rows in the Expenses table, but also in Expenses_Users, and any other table that links Expenses to other tables.
I have two ideas on how to solve this:
Option One: Normalize Expenses like this:
create table Expenses (
ID int not null identity(1,1),
ExpenseID int not null,
Status tinyint not null,
[...]
)
create table ExpensesNormalized (
ExpenseID int not null,
Amount Money not null
)
alter table ExpensesNormalized add constraint FK_ExpensesNormalized_Expenses
foreign key (ExpenseID) references Expenses(ExpenseID)
This means I'll only have to link external tables to Expenses, not ExpensesNormalized. Also, when updating an expense, I'll only duplicate and negate the data in ExpensesNormalized, which means I'll have far less redundant data in the Expenses table.
However, I'll have to use a JOIN clause every single time I SELECT from Expenses. I fear a performance hit because of this.
Option Two: Use the same tables I use now, but have the field Expenses_Users.ExpenseID point to the field Expenses.ExpenseID. This means that I won't have to duplicate any external objects because they'll point to ExpenseID, which may occur several times.
However, this will not be a real foreign key because SQL Server does not allow foreign keys to non-unique fields, so I'll have to implement foreign key logic in a trigger.
I'm having a hard time deciding between these two options. Any feedback would be appreciated.