Check atribute value from another table using a foreign key in table creation - sql

Is it possible to check the value of an attribute in a different table in table creation? For example I have this table ticket:
CREATE TABLE ticket
(
id_ticket_pk NUMBER(4) PRIMARY KEY,
hand_in_date DATE NOT NULL,
num_clothes NUMBER(4) NOT NULL,
deposite NUMBER (8,2) NOT NULL,
comment VARCHAR2(40),
tax NUMBER(5,3) NOT NULL,
status VARCHAR2(15) NOT NULL,
id_counter_fk1 NUMBER(4),
id_client_fk2 NUMBER(4),
CONSTRAINT ticket_id_counter_fk1
FOREIGN KEY (id_counter_fk1) REFERENCES empleado(id_employee_pk),
CONSTRAINT ticket_id_client_fk2
FOREIGN KEY(id_client_fk2) REFERENCES client(id_client_pk)
);
This table relates to the employee table which has an attribute called type that can be equal to C - for counter, S- for secretary etc... I would like to know if its possible to add a constraint in the creation of the table that verifies that the employee inserted has an employee.type = 'C' where employe.id_pk = ticket.id_counter_fk2. Or do I have to create an external function or client App that manages this?

You seem to be asking whether you can use the foreign keying mechanism to ensure that only people with the job title of "counter" can create support tickets.
The short answer is no, you can't have a foreign key on this table that checks the employee table pk for the value given in id_counter_fk1 and enforces that the employee type be C
You could do it several other ways, the most direct being a trigger that prevents the insert if the employee linked is not a C type, but the FK mechanism exists to ensure that a remote record exists or not, not that it exists and has particular properties

Related

Primary Key of Child Table as Foreign Key in Parent Table in Oracle

I have two tables:
Store
(PK: StoreID)
Store is overall parent and
Product
Product (PK: ProductID, FK: StoreID)
is a child.
I am stuck in a requirement where for an application Primary Key ProductID should be foreign key in table Store . Not sure if this is gonna work. I have tried this from a custom framework with Oracle backend, but that is not working as expected.
Note: I cannot change schema.
I fail to fully understand your question, but it's possible to have multiple references between two tables. For example:
create table store (
storeid number(6) primary key not null,
name varchar2(20) not null,
last_productid number(6) not null -- not yet a FK, but later it is.
);
create table product (
productid number(6) primary key not null,
name varchar2(50) not null,
storeid number(6) not null,
constraint fk1 foreign key (storeid) references store (storeid)
);
alter table store add
constraint fk2 foreign key (last_productid) references product (productid);
The column last_productid you want to add (do you want to?) is a little bit tricky. You have two options:
It's not nullable. This happens when you want every store to ALWAYS have a last_productid. You'll need to declare it DEFERRABLE to be able to insert the store and first product.
It's nullable. Then some stores will point to a product, and other ones will not. This is the easy case, since you can insert/update the store table easily.

Why is my create table failing? - does not match primary key

This is what I am trying to create:
CREATE TABLE VEHICLEREPORT
(
DeptID char(2) not null,
Vin# char(3) not null,
Miles varchar(6) not null,
Bill# char(3) not null,
EID char(3) not null,
PRIMARY KEY (DeptID, Vin#),
FOREIGN KEY (bill#) REFERENCES billing,
FOREIGN KEY (EID) REFERENCES Employee
);
The issue is with my reference to billing. The error says:
The number of columns in the referencing column list for foreign key 'FK__VEHICLERE__Bill#__5AEE82B9' does not match those of the primary key in the referenced table 'Billing'.
but my billing table entered fine:
CREATE TABLE BILLING
(
VIN# char(3),
BILL# char(3),
PRIMARY KEY (VIN#, Bill#),
FOREIGN KEY (VIN#) REFERENCES vehicle
);
What am i missing with this?
Appreciate the help.
If you think of the foreign key as establishing a parent-child relationship between two tables, then the parent side column(s) need to be unique.
From Wikipedia:
In the context of relational databases, a foreign key is a field (or collection of fields) in one table that uniquely identifies a row of another table or the same table. ... In simpler words, the foreign key is defined in a second table, but it refers to the primary key or a unique key in the first table.
In your example, there is no guarantee that VIN# is unique in VEHICLEREPORT. Below are your options
VIN# is guaranteed to be unique in VEHICLEREPORT. In this case add a UNIQUE constraint on VIN# on the VEHICLEREPORT table. The error will go away.
VIN# is not unique in VEHICLEREPORT (doesn't seem likely). If this is the case, then likely there is a flaw in the design of your BILLING table as it could likely point to more than one row in VEHICLEREPORT. You should consider adding DeptID column to BILLING and creating a composite foreign key.
Also if VIN# is unique (case 1 above), you should think of why DeptID is present in the PK. Maybe the right fix at the end is to drop DeptID from the primary key.

Oracle SQL queries for subclass-table - Inheritance

I have a Staff table with staffNo as the primary key
and staff details present in two other tables inheriting from it: FTLecturer and PTLecturer. I used the Optional Or relationship there.
My question is: how to write Oracle SQL queries for these sub-classes?
I think I do not need a PK for them again because they inherit from `Staff'. Is it so?
This is the Staff table
CREATE TABLE Staff
(staffNo number(10) NOT NULL,
firstName varchar2(50) NOT NULL,
lastName number(2) ,
address varchar2(50) NOT NULL,
CONSTRAINT courseID_pk PRIMARY KEY (staffNo),
CONSTRAINT fk_Module
FOREIGN KEY (moduleID)
REFERENCES Module(Module Module ID)
);
I need to create the FTLecturer table with the Optional Or relationship.
Inheritance is a concept from Object-Oriented Programming: it has no meaning in relational databases. The most important impact of this is that child tables do need a primary key.
"I need to create the FTLecturer table with the Optional Or relationship."
What you're describing is called an Arc in relational databases: a lecturer can be full-time or part-time but not both. We can enforce this with a decent set of constraints.
First add a column to the parent table to identify the Lecturer type.
alter table staff add staffType varchar2(10);
This should be validated with a foreign key against a reference data table, and at a pinch a check constraint. Then we add a unique constraint (yes, as well as a primary key):
alter table staff add constraint staff_uk unique(staffNo, staffType);
We can use this to enforce the arc on the child tables.
create table FTLecturer (
staffNo number not null,
staffType varchar2(10) not null,
tenure varchar2(3) not null,
constraint FTLecturer_pk primary key (staffNo),
constraint FTLecturer_ck check (staffType = 'FTL'),
constraint FTLecturer_Staff_fk foreign key (staffNo, staffType)
references staff (staffNo, staffType);
Note that the foreign key means we can only insert rows in this table which have a parent of the correct type in the STAFF table. This is why we need the StaffType column and that unique constraint on the STAFF table.
Likewise for Part-Time Lecturers:
create table PTLecturer (
staffNo number not null,
staffType varchar2(10) not null,
hours number not null,
constraint PTLecturer_pk primary key (staffNo),
constraint PTLecturer_ck check (staffType = 'PTL'),
constraint PTLecturer_Staff_fk foreign key (staffNo, staffType)
references staff (staffNo, staffType);
Since Oracle 11g we can use a virtual column to apply a constant value for the staffType on the child tables. This avoids the need for the check constraints. Find out more.
To create a record for a specific member of staff it is good practice to populate the parent and child in the same action; we can use the INSERT ALL syntax to populate multiple tables. Find out more.
Finally, you can build a helpful API with views. For instance:
create or replace view fulltimeLecturer as
select staff.*
, ftl.tenure
from staff
join ftlecturer ftl
on staff.staffno = ftl.staffno
and staff.stafftype = ftl.stafftype;
create or replace view parttimeLecturer as
select staff.*
, ptl.hours
from staff
join ptlecturer ptl
on staff.staffno = ptl.staffno
and staff.stafftype = ptl.stafftype;
This may strike you as a lot of work, and inflexible to boot. Here is the difference between Object Programming and Relational Databases. OOP is primarily driven by helping developers to write code; RDBMS is focused on guaranteeing the integrity of the stored data.

create foreign key in oracle

is there anyone who can help me to create a foreign key for my Status table. I need to PLACE a foreign key constraint on the code in the status table, referring to the id in the Building table.
TABLE building
(
build_name VARCHAR2(50,0) NOT NULL,
id NUMBER (38,0) NOT NULL,
mapid NUMBER (10,0) NOT NULL
);
TABLE STATUS
(
code VARCHAR(2 BYTE) NOT NULL,
status_name VARCHAR2(40 BYTE) NOT NULL,
);
Bulding table has constraint building_gmidx with id as primary key.
Here is a quick syntax for your current requirement, however I recommend you to go through the oracle documentation for a proper understanding of what this means.
ALTER TABLE STATUS ADD (
CONSTRAINT status_fk_building FOREIGN KEY (code)
REFERENCES building (id)
ENABLE VALIDATE);
Did you leave out CREATE TABLE *name* to save time when writing the question? The first thing I see is that your Foreign key has to have the same data type and size as your Primary key. If the Tables already exist the code would be:
ALTER TABLE status MODIFY (code NUMBER(38));
From there you would need to
ALTER TABLE status ADD FOREIGN KEY (code) REFERENCES (building_gmidx)
Why is the constraint for building Primary key named building_gmidx and the column plain id?? All Normalized table attributes should be Unique. Wouldn't it be better if you just named the column "id" building_gmidx instead. Just in case there are other types of id's added later you do not have to think about which table "id" pertains to. Let me know if this works.

Foreign key referring to more than one primary key values(from one table) - Oracle SQL PLUS

I am still a beginner in SQL and i'm facing an issue. hope you can help me.
I have a table called Department where it has an attribute DEPARTMENT_NO as its primary key.
CREATE TABLE DEPARTMENT(
DEPARTMENT_NO INT NOT NULL,
NAME VARCHAR(25) NOT NULL,
LOCATION CHAR(15),
PRIMARY KEY(DEPARTMENT_NO));
I have another table called Doctor where it has an attribute DNUM as a foreign key referring to DEPARTMENT_NO :
CREATE TABLE DOCTOR(
DOCTOR_ID CHAR(9) NOT NULL,
DNUM INT NOT NULL,
NAME VARCHAR(20) NOT NULL,
DOB DATE,
SPECIALTY VARCHAR(20) NOT NULL,
SALARY INT,
CITY VARCHAR(15),
STREET VARCHAR(15),
START_DATE DATE,
PRIMARY KEY(DOCTOR_ID))
FOREIGN KEY(DNUM) REFERENCES DEPARTMENT(DEPARTMENT_NO));
A doctor can be working in one or two departments. So, if I have a doctor working in department 1 and 4 (the values for DNUM will include 1 and 4).
I initially chose the data type of DNUM to be INT(same as DEPARTMENT_NO data type). But INT is not ideal for multiple values.
What should the data type be? or what other solution i have if,for example, I run a query for returning the name of the doctors working in department 4.
The query should return all the names of doctors working in department 4(only) and the ones who work in multiple departments(including 4).
Thanks very much in advance and sorry for the long message.
The standard way to represent a "many to many" relationship is via a "junction" (aka "link") table:
CREATE TABLE DOCTOR_DEPARTMENT (
DOCTOR_ID INT REFERENCES DOCTOR(DOCTOR_ID),
DEPARTMENT_NO INT REFERENCES DEPARTMENT (DEPARTMENT_NO),
PRIMARY KEY (DOCTOR_ID, DEPARTMENT_NO)
);
Note the key on {DOCTOR_ID, DEPARTMENT_NO}, which ensures the same doctor cannot be connected to the same department twice.
It also implicitly creates a composite (aka. "concatenated") index on these fields in that order, which makes it very quick to find departments of a given doctor (via an index range scan). If you need to query in the opposite "direction" (for doctors of the given department), flip the order of fields. If you need both queries, then you'll need both indexes (i.e. you'll need to create one index explicitly).
Consider adding ORGANIZATION INDEX clause, if you need just one of these indexes.
You need an additional table called doctor_department
create table doctor_department
(doctor_id integer references doctor(doctor_id) not null,
dnum integer references department(dnum) not null
)
You can create another table with relation to these 2 tables
Say,
Create table Dept_Doctors(
ID int not null,
DOCTOR_ID char(9) not null,
DEPARTMENT_NO INT NOT NULL,
PRIMARY KEY (ID),
FOREIGN KEY(DEPARTMENT_NO) REFERENCES DEPARTMENT(DEPARTMENT_NO),
FOREIGN KEY(DOCTOR_ID) REFERENCES DOCTOR(DOCTOR_ID));
You can join the 3 tables and get the desired result.