alter table for scope - sql

This is the code I found on a course
create type employee_type AS OBJECT
( empno number(4),
ename varchar2(40),
dept_ref REF department_type)
/
create table employee of employee_type
( empno PRIMARY KEY )
/
create type department_type AS OBJECT
( deptno number(2),
dname varchar2(20),
loc varchar(20))
/
create table employee of employee_type
( empno PRIMARY KEY )
/
create table department of department_type
( deptno PRIMARY KEY )
/
alter table employee
add (scope for (dept_ref) is department)
/
I don't understand why we need to alter employee table to add scope for to department table, I mean dept_ref has been referred to department_type already and department table is consisted of department_type object, what is the add scope statment do?

As described in the documentation, the purpose is to say that dept_ref in employee has to refer, specifically, to a department, and not to any other table that may be of department_type type.
See REF Columns: Examples:
The dept column can store references to objects of dept_t stored in any table. If you would like to restrict the references to point only to objects stored in the departments table, then you could do so by adding a scope constraint on the dept column as follows ...
(People, apparently, love drawing examples from the domain of employees and departments)

Related

Adding constraints to an SQL Table with altering

I have a defined type:
CREATE TYPE salary AS (salary numeric);
and a table holding data:
CREATE TABLE employees (
lastname text,
firstname text,
salary salary,
);
I want to use ALTER TABLEto add a constraint to the salary attribute:
ALTER TABLE employees ADD CONSTRAINT minimum_salary CHECK(salary > 1.47333);
this gives me the error ERROR: operator does not exist: salary > numeric. Why is this the case?
To start with: a type seems overkill to just store a scalar value. Why no just create a check constraint on the column?
create table employees (
lastname text,
firstname text,
salary numeric check(salary > 1.473333)
);
Coming back to your original question: I don't think that it is possible to put a check constraint on a type column. One thing you could do, however, is to create a domain. Domains extend the standard types and do accept check constraints.
Consider this demo:
create domain salary numeric check(value > 1.47333);
create table employees (lastname text, firstname text, salary salary);
insert into employees values('foo', 'bar', 1);
-- ERROR: value for domain salary violates check constraint "salary_check"

Is it possible to populate table using trigger on another table in oracle 12c

Using oracle 12c, I have a table for employee and a table for managers, if the newly inserted employee salary >=5000 then he/she is considered manager. So I'd like to create trigger on table employee that checks if the salary of the newly inserted employee >=5000 this row should be duplicated in the manager table. IS this possible? If yes, could you simply give me the right syntax.
Some general words first: This could be considered bad database design. If you consider an employee beyond a certain salary a manager, this almost screams for a column in the same table, either physical or virtual. For example, it could look like this:
CREATE TABLE employees (
id NUMBER,
first_name VARCHAR2(10),
last_name VARCHAR2(10),
salary NUMBER(9,2),
is_manager as (case when salary >= 5000 then 1 else 0 end)
CONSTRAINT employees_pk PRIMARY KEY (id)
);
If you still want to use a trigger and a second managers table, it could work like this:
CREATE OR REPLACE TRIGGER trig_emp_insert
AFTER INSERT
ON employees
FOR EACH ROW
BEGIN
if (:new.salary >= 5000) then
insert into managers (...) values (...)
end if;
END;

Oracle - Insert Stored Procedure Foreign Key

Instructions:
Create two tables, named employees and departments. Preface the table names with your initials. Link the two tables (foreign key) by a column called dept. Make up a few column names for each table.
Employees Table:
create table bsemployees(
dept number primary key,
empName varchar2(20),
salary number
);
Departments Table:
create table bsdepartments(
dept number references bsemployees(dept),
deptName varchar2(20)
);
Write the following stored procedures:
• Insert a row into the employees table. If the department does not exist. Insert it into the departments table.
create or replace procedure sp_employees(
a_dept IN number,
a_empName IN varchar2,
a_salary IN number
)
as
vCount number;
BEGIN
sp_check_dept(a_dept,vCount);
insert into bsemployees values(a_dept, a_empName, a_salary);
if vCount = 0 then
dbms_output.put_line('**DEPT DOES NOT EXIST**');
insert into bsdepartments (dept, deptName) values(a_dept, NULL);
end if;
END;
/
create or replace procedure sp_check_dept(
a_dept IN number,
vCount OUT number
)
as
BEGIN
select count(*)
into vCount
from bsdepartments
where dept = a_dept;
end;
/
• Insert a row into the departments table.
create or replace procedure sp_departments(
a_dept IN number,
a_deptName IN varchar2
)
as
BEGIN
insert into bsdepartments values(a_dept, a_deptName);
END;
/
I've got it pretty much all down for this assignment except for the fact that when I try to insert a row into the departments table I am getting a integrity constraint - parent key not found error.
If I do execute sp_employees(5, 'John Doe', 90000); It will display ***DEPT DOES NOT EXIST*** and will go ahead and insert the data into bsemployees and insert the dept# into bsdepartments and the deptName will be left blank based on my if-then statement. Doing a select(*) shows me this.
However if I go ahead and do execute sp_departments(1, 'human resources'); to place a row into departments I get the parent key error. I understand that I am trying to insert something that has no parent key but I do not know how to fix it.
Your table design isn't quite correct - the dept primary key needs to be added as a foreign key to employee (not as the primary key), and employee should have its own primary key:
create table bsdepartments(
dept number primary key,
deptName varchar2(20)
);
create table bsemployees(
empName varchar2(20) primary key,
dept number references bsdepartments(dept),
salary number
);
You can then do the 'add if not exists' logic in the check_dept proc:
create or replace procedure sp_check_dept(
a_dept IN number
)
as
vCount number
BEGIN
select count(*)
into vCount
from bsdepartments
where dept = a_dept;
if (vCount = 0) then
dbms_output.put_line('**DEPT DOES NOT EXIST**');
insert into bsdepartments (dept, deptName) values(a_dept, NULL);
end if;
end;
Which then simplifies the employee insertion proc as it should be guaranteed of a department:
create or replace procedure sp_insertEmployee(
a_dept IN number,
a_empName IN varchar2,
a_salary IN number
)
as
BEGIN
sp_check_dept(a_dept);
insert into bsemployees values(a_dept, a_empName, a_salary);
END
Notes
Recommend that you name the procs in alignment with their purpose, e.g. insertEmployee vs just employees
As you've noted, the problem with the 'add if not exists' approach is that you do not have sufficient data to completely populate the department table, hence the null column (but this is what your lecturer asked for)
Your realation to table department is bad. It should linked as below
create table bsdepartments(
dept number primary key,
deptName varchar2(20)
);
and it should be linked to employee table
create table bsemployees(
dept number references bsdepartments(dept),
empName varchar2(20),
salary number
);
Then if you try inserting execute sp_departments(1, 'human resources'); it will execute
an then you have to insert the employee.
Here the employee is related to department not the department is related to employee.

Oracle object relational DB: Access columns of referenced rows

I have some tables and need to create object views on top of them.
CREATE TABLE Person (
Nr NUMBER(4) PRIMARY KEY,
Name VARCHAR2(15));
CREATE TABLE Professor (
Nr NUMBER(4) PRIMARY KEY,
HabilThema VARCHAR2(30));
I also created types:
CREATE OR REPLACE TYPE Person_Typ AS OBJECT(
Nr INTEGER,
Name VARCHAR2(15)
);
CREATE OR REPLACE TYPE Professor_Typ AS OBJECT(
Nr INTEGER,
Habilthema VARCHAR2(30),
Person REF Person_Typ
);
As you can see there is a reference from a professor row to a person row. The view of the professors now should also include the columns of the person. Something like:
CREATE VIEW People OF Person_Typ
WITH OBJECT IDENTIFIER(Nr) AS
SELECT p.Nr, p.Name FROM Person p;
CREATE VIEW Professors OF Professor_Typ
WITH OBJECT IDENTIFIER(Nr) AS
SELECT p.Nr, p.Habilthema, p.Person.Name, MAKE_REF(People,p.Nr) FROM Professor p;
^
|_ Name of professor from Person table
But this does not work:
"P"."PERSON"."NAME" invalid identifier
Can this even be achieved by an object view? How?

SQL Oracle Inheritance Relational Database

Here is an image:
This is how far I gone into coding:
CREATE TYPE appointment_list_type AS TABLE OF REF appointment_type;
/
CREATE OR REPLACE TYPE person_type AS OBJECT (
personID NUMBER,
Surname varchar2(10),
Forname varchar2(10),
dateOfBirth date,
AddressLine1 varchar2(30),
AddressLine2 varchar2(30),
Town varchar2(10),
contacTel1 varchar2(10),
contacTel2 varchar2(10)) NOT FINAL;
/
CREATE TYPE applicant_type UNDER person_type(
applicantID NUMBER,
maxPrice number(7,2),
desiredArea varchar2(10),
Attends appointment_list_type
);
/
CREATE TYPE salesperson_type UNDER person_type(
salespersonID NUMBER,
manager varchar2(10),
Makes appointment_list_type
);
/
This is creating the types of person seperating it into inheritance of Salesperson and Applicant.
CREATE TYPE appointment_type AS OBJECT(
appointmentID NUMBER,
Appdate date,
Apptime timestamp,
appointmentType varchar2(10),
levelOfInterest varchar2(10),
offerMade varchar2(10),
Made_by REF salesperson_type,
Attends_by REF applicant_type
);
/
This is appointment type, The references work for relating them together.
For creating the table:
CREATE TABLE person_table OF person_type (
personID PRIMARY KEY NOT NULL)
NESTED TABLE Attends STORE AS attend_meeting_table;
CREATE TABLE applicant_table OF applicant_type (
personID PRIMARY KEY NOT NULL)
NESTED TABLE Attends STORE AS attend_meeting_table;
CREATE TABLE salesperson_table OF salesperson_type (
personID PRIMARY KEY NOT NULL)
NESTED TABLE Makes STORE AS makes_meeting_table;
CREATE TABLE appointment_table OF appointment_type (
appointmentID PRIMARY KEY NOT NULL,
SCOPE FOR (Made_by) IS person_table,
SCOPE FOR (Attends_by) IS person_table);
Also here is some code of what I done, I now here is my question:
How does inheritance work with doing 1 to many directly into Appointment?
I am realy confused by this. Can anyone out me help me on how to do this?
phuh, I think I finally figured whats bothering you...
Currently, the appointments REFd in applicant_table and salesperson_table are totally independent. That means that applicants could come to meetings with sales persons that are actually in a meeting with someone else :)
Of course you want all appointments to be stored in appointment_table.
That is the perfect use case for object views. You do not need these object tables at all. Relational tables are much easier to manage.
Just create normal tables and then object views, just like this one for SALESPERSON:
create view ov_salesperson as
(select personID,
salespersonID,
SALESPERSON_TYPE
(personID
Surname,
Forname,
dateOfBirth,
AddressLine1,
AddressLine2,
Town,
contacTel1,
contacTel2,
salespersonID,
manager,
CAST
(MULTISET
(Select appointment_type
(appointmentID,
Appdate,
Apptime,
appointmentType,
levelOfInterest,
offerMade,
salesperson_id,
applicant_id
)
From appointment_table A
Where A.salesperson_id = S.salesperson_id
)
as appointment_list_type
)
) as salesperson_obj
from salesperson_table S
);