Storing multiple values in a single column - sql

I have two columns in my table: [Employee_id, Employee_phno].
Employee_id: primary key, data type = int
Employee_phno: allows null, data type = int
Now, how can I insert two phone numbers in the same employee_id?
For example:
employee_id employee_phno()
1 xxxxxxxxx
yyyyyyyyyy

For me, if you want multiple data for column Employee_phno better make another table for Employee_phno. In your second table, set a foreign key as relation for your first table.
Example:
1st table
Employee_id
1
2
3
2nd table
Employee_id Employee_phno
1 1234
2 1512
2 4523
Here you can see the employee with id = 2 has multiple Employee_phno

It is never possible to insert data in such way in single table.

If Employee_id is primary key then you can have only 1 record for an employee.Since you have only one field for Employee_phno,it's not possible to store 2 phone numbers for the same employee.
For doing so, you will have to do any one of the following:
1.Add another column in the data as Employee_Alternate_phno and if all the employees won't have 2 numbers you can make this column allow NULLs.
2.Create another mapping table say EmployeeNumbers where you will have EmployeeId as Foreign key and then the numbers field. Anytime if you want the 2 Employee_phno you can do a join on the mapping table and retrieve the values.

Related

How to reference foreign key from more than one column (Inconsistent values)

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.

Create a table containing PK and FK

I am trying to explain what this table does, but unable to see what is happening here. Any suggestion?
CREATE TABLE EMP
(
ID INT NOT NULL PRIMARY KEY,
MGID INT REFERENCES EMP (ID),
NAME VARCHAR(30) NOT NULL
);
It's creating a table called EMP which describes employees. Each employee is identified by a surrogate ID number, has a NAME attribute, and a relationship with a manager identified by MGID.
This code creates a table that's called EMP, with a primary key column called ID of type int, a foreigen key referencing that column called MGID, and a string column called NAME.
Using a foriegn key to the same table enables you to create parent/child relationship for rows in that table.
For instance, if you have an employee that's called Raza, and his manager is calld Far, You will have a row for the manager and a row for Raza and the value of MGID in that row would point to the ID of Far
Assuming that you have some basic knowledge of DBMS, I think you stuck with 'REFERENCES' keyword.
It creates a Parent/Child relationship between ID and MGID.
As you know, the table is for Employee(as the name suggested 'Emp'), Manager is also an employee.
So,before referencing to any employee as a manager it must have entry in table as employee. To perform this kind of validations, 'REFERENCES' keyword can be used.
For example,
ID MGID NAME
1 null a
2 1 b
3 1 c
Above data is valid but,
ID MGID NAME
1 null a
2 3 b
3 1 c
Above data will violate the referential integrity constraints as any employee with ID 3 is not existed yet.
Hope it helps.

Existing table design change in SQL Server

My existing table structure is below:
Students table and columns are below:
Year
Student_Id
Subject_Type_Id
Quarter
Complete_DTTM
Column1
Existing data like below:
Students:
Year Student_Id Quarter Subject_Type_Id Complete_DTTM Column1
---------------------------------------------------------------------------------------
2006 1 1 1 Null x
2006 1 2 1 10/2/2006 xyz
2006 1 2 2 10/30/2006 abc
2006 1 2 3 11/20/2006 def
One student can take multiple subjects by saving each subject separately by picking from DropDownList.
Now new requirement is one student can take multiple subjects by selecting from Checkboxes and provide data for Column1 and Complete_DTTM and save.
The difference between old and new requirement is how user selecting subject types, in old from Drop down list, able to pick one subject only, Column1 and Complete_DTTM are different for each subject.
With the new requirement, they can pick multiple subjects from check boxes for a student and column1 and Complete_DTTM is same for all subjects.
NEW data going to be like below:
Year Student_Id Quarter Subject_Type_Id Complete_DTTM Column1
--------------------------------------------------------------------------
2015 1 1 1, 2, 3, 4 12/31/2015 abcdef
2015 1 2 1, 2, 3, 4, 5 1/1/2016 xyz
How do I change ‘Students’ table (I can add new table) to support multiple subject Ids and also needs to support old data (shown above for year 2006)?
Thanks in advance
You need to make a table that will house just the student data. Then you will need to make a table that will house Subject Type data. The a table to link them together.
CREATE TABLE Student (ID INT NOT NULL PRIMARY KEY, NAME VARCHAR(50) NOT NULL,n...)
Create Table for subject
CREATE TABLE Subject (ID INT NOT NULL PRIMARY KEY, Subject_Name VARCHAR(50)NOT NULL,n...)
Then You will need a table to link these two together.
CREATE TABLE Student_Suject_Link (Student_ID INT NOT NULL, SUBJECT_ID INT NOT NULL)
The link table will need to have a foreign key realtionship to the Student table and the Subject table. Student_ID needs to be a foreign key to the ID column in the student table and same for the subject table. The SUbject_ID needs to be a foreign key to the ID in the Subject table. This should satisfy 3rd normal form. And if you need to grab data it is easy enough to join tables to get what you need. I relaize it seems to create more work but it is infinately easier to manage that adding lists to tables. You can of course add other fields you deem necessary into the table it is just necessary to have the ID's to relate on. Hope this helps.
You now have a one to many relationship and you need a child table for the many part of the relationship. Do not ever store data in a comma delimited list. This is a way to totally break your performance when you want to find data int hose tables. It is just bad deign. You need to normalize those tables and I am sure that this is why you have been given this particular exercise.

Constrain a table such that each account can have one of another table

I have a table which has these columns:
Id (Primary Key): the id.
OwnerId (Foreign Key): the id of the owner, which resides in another table.
TypeId (Foreign Key): the type of thing this record represents. There are a finite number of types, which are represented in another table. This links to that table.
TypeCreatorId (ForeignKey): the owner of the type represented by TypeId.
SourceId (Foreign Key): this isn't important to this question.
I need to constrain this table such that for each Id, there can be only one of each TypeCreatorId. I hope that makes sense!
For SQL Server, you have two options:
create a UNIQUE CONSTRAINT
ALTER TABLE dbo.YourTable
ADD CONSTRAINT UNIQ_Id_TypeCreator UNIQUE(Id, TypeCreatorId)
create a UNIQUE INDEX:
CREATE UNIQUE INDEX UIX_YourTable_ID_TypeCreator
ON dbo.YourTable(Id, TypeCreatorId)
Basically, both things achieve the same thing - you cannot have two rows with the same (Id, TypeCreatorId) values.
Simply create a unique index on OwnerId and TypeCreatorId.
An example using MySQL (sorry, I don't use SQL Server):
alter table yourTable
add unique index idx_newIndex(OwnerId, TypeCreatorId);
Example. I'll just put here what would happen with this new unique index:
OwnerId | TypeCreatorId
--------+--------------
1 | 1
1 | 2 -- This is Ok
2 | 1 -- Ok too
2 | 2 -- Ok again
1 | 2 -- THIS WON'T BE ALLOWED because it would be a duplicate

SQL DB table Relationship

I am trying to create a small DB based on flat files that I import from a non Database System. The Import is working, the DB is good but I added a new table that contains data from another system. I am trying to create a relationship between the tables but because one table has duplicate rows (flat file is the source) I am not able to set that relationship.
Example: Table 1 lists all procedures done for a patient by a physician.. the patient can have many of the same procedures on the same day by the same physician (hence the duplicate rows) ... Table 2 has a list of Physicians and their ID #s ... I want to set up a relationship between the two tables based on the physician's name but I am getting errors because of the non unique data.
Anyone has a tip?
Thanks
the patient can have many of the same procedures on the same day by the same physician (hence the duplicate rows)
Normally, you should be able to set a foreign key relationship from Table1 to Table2 even in the presence of duplicate rows. This kind of error usually means you're trying to set the foreign key in the wrong table.
-- Your "Table2"
create table physicians (
physician_id integer primary key,
physician_name varchar(35) not null -- names are not unique
);
insert into physicians values
(1, 'Doctor Who'), (2, 'Dr. Watson');
create table patients (
patient_id integer primary key,
patient_name varchar(35) not null -- names are not unique
);
insert into patients values
(100, 'Melville, Herman'), (101, 'Poe, Edgar Allen');
-- Your "Table1"
-- Allows multiple physicians per date.
create table patient_procedures(
patient_id integer not null references patients (patient_id),
physician_id integer not null references physicians(physician_id),
procedure_date date not null default current_date,
procedure_name varchar(15) not null,
primary key (patient_id, physician_id, procedure_date, procedure_name)
);
insert into patient_procedures values
(100, 1, '2012-01-02', 'CBC'),
(100, 1, '2012-01-02', 'Thyroid panel');
I'm not sure from your description where the duplicate-data problem is. You have:
Table 1: procedures. Could be lots of rows for same physician
Table 2: physicians. Should be 1 row per physician (but there may be duplicates)
The relationship that would make sense would be 1[table 2 physician row] -> many[table 1 procedures rows]. i.e. table 2 would be the primary key table in the relationship: each table 2 row relating to between 0 and "many" table 1 rows. If you try to create this kind of relationship, then multiple duplicate table 1 rows are not a problem.
If, however, you have multiple rows per physician in table 2, then you won't be able to create this kind of relationship, because table 2 rows are not unique and thus can't act as the primary key element in the relationship. The problem then is one of data-cleansing: figuring out which rows in table 2 are duplicates, updating the table 1 rows to point to just ONE physician out of the duplicates, and then deleting the duplicate rows from table 2.
You mention physician ID#s and physician names. Physician name would be a bad choice for a unique key; if a user tries to add a new physician called "John Smith" when there already is another physician of that name, either
You've set up a unique index on PhysicianName, their change gets rejected, and you have an irate user; or
You haven't, and all the existing physician's (let's call him John A. Smith) procedures will be associated with the other physician (let's call him John B. Smith) and vice versa.
The relationship should be set up using the physician ID. If Table 1 (Procedures) includes a physician ID column, you're in luck. If it only includes physician Name, then you may have a data-cleansing problem, if there are already duplicate physician Names in Table 2.