2 solutions - CS-People by full name

advertisement
CS 460 : Assignment # 2
Due: Tue Feb 20th, 6pm in CS460 Drop-off Box
(30% penalty/day for late submissions upto Wenesday Feb 21, 5pm)
Problem 1: [20 pts]
Consider the following schema:
WORKS ( person-name, company-name, salary)
LIVES ( person-name, street, city)
LOCATED-IN ( company-name, city)
MANAGES ( person-name, manager-name)
The WORKS relation contains information about where an employee
works and with what salary, the LIVES relation tells us where an
employee lives, the LOCATED-IN relation gives the location of each
company, while the MANAGES relation provides the employees and
their managers.
Give an expression in Relational Calculus for each of the queries below:
1.1. Find the names of all employees who work for First Bank Corporation.
1.2. Find the names and city of all employees who work for First Bank Corporation.
1.3. Find the names of all employees who live in the same city as the
company they work for.
1.4. Find the names of all employees who live in the same city and on
the same street as their manager.
Programming Exercises:
1. Login to csa3.bu.edu
2. At command prompt type:
oraenv
When prompted for ORACLE_SID=? type “orcl”
3. In your .cshrc add the following:
setenv ORACLE_HOME /fs/local/oracle/app/oracle/product/10.2.0/db_1
setenv ORACLE_SID orcl
set path = ( $path /fs/local/oracle/app/oracle/product/10.2.0/db_1/bin)
4. source .cshrc
SQL*PLUS
 SQL*Plus is a text editor available in all Oracle
 Except inside quotation marks of strings, Oracle commands are case-insensitive
 The semicolon (;) terminates a SQL statement


The right-leaning slash (/) executes SQL statement stored in Oracle buffer
SQL*Plus can be used to
– Enter SQL statements
e.g., SQL> select * from emp;
– Submit SQL files created by text editors, e.g., notepad, to Oracle
e.g., SQL > @myhw.sql
– Spool output to an output file in the OS filesystem.
e.g., SQL > spool myhw.log
5. Login to oracle and run your SQL commands using SQL*PLUS:
sqlplus <username_in_your_email>/< username_in_your_email> @orcl
(i.e., if the email is lodrina@cs.bu.edu, then the username is lodrina and
password is lodrina too).
(e.g. sqlplus lodrina/lodrina@orcl or sqlplus sumeet/sumeet@orcl etc.)…
-- Change your password
Sqlplus will then ask you to set a new password which you will use to login from
Next time. If you set the password to ‘myname’ and your username is lodrina, next
Time you will login as “sqlplus lodrina/myname”.
-- You can explicitly change your password using the following command:
alter user <username> identified by <mynewpassword>;
6. Running sql commands at SQL prompt:
SQL> select tname from tab;
SQL> select owner, table_name from all_tables;
7. To quit from a sqlplus session:
- just type “quit” and it will put you in shell prompt.
Now at “SQL>” prompt you can run your SQL statements.
Basic commands to look at tables and their descriptions:
- Select tname from tab ;
- Or select table_name from user_tables;
-- Or select owner, table_name from all_tables;
- Describe scott.emp;
Write SQL and show the sql, output for following. Use order by to sort the results
Problem 2: [80 pts]
[5pts each]
2.1 Identify all the tables in scott; along with their primary keys.
Answer:
SELECT table_name FROM all_tables
WHERE owner = ‘SCOTT’;
Possible primary keys:
DESC emp;
EMP
EMPNO
DESC dept;
DEPT
DEPTNO
DESC BONUS;
BONUS ENAME;
DESC SALGRADE:
SALGRADE (LOSAL, HISAL);
Finding views for your queries:
SELECT view_name FROM ALL_VIEWS WHERE view_name LIKE
‘%KEYS%’;
SELECT view_name FROM ALL_VIEWS WHERE view_name LIKE
‘%CONS%’;
Finding primary keys:
SELECT b.table_name, b.column_name
FROM all_constraints a, all_cons_columns b
WHERE a.owner = 'SCOTT'
AND a.constraint_type = 'P'
AND a.constraint_name = b.constraint_name;
2.2 Identify the different job categories for employees.
SELECT DISTINCT job FROM scott.emp;
2.3 For each job category, how many employees exist.
SELECT job, count(*) FROM scott.emp GROUP BY job;
[7pts each]
2.4 For each dept (name), determine how many employees exist.
SELECT deptno, count(*) from scott.emp GROUP BY deptno;
 But no dept name; So Join to dept table
SELECT d.dname, count(*) num_employees
FROM scott.emp e, scott.dept d
WHERE e.deptno = d.deptno
GROUP BY d.dname ;
2.5 For each dept, determine the mean and stddev in salaries of employees
SELECT d.dname, sum(sal)/count(*) mean, stddev(sal) dev
FROM scott.emp e, scott.dept d
WHERE e.deptno = d.deptno
GROUP BY d.dname ;
2.6 For each job category find out the min, max, avg of the commission as a
percentage of the salaries.
SELECT job, min(comm*100/sal), max(comm*100/sal),
avg(comm*100/sal) FROM scott.emp GROUP BY job;
SELECT job, nvl(min(comm*100/sal), 0), nvl(max(comm*100/sal), 0),
nvl(avg(comm*100/sal), 0) FROM scott.emp GROUP BY job;
2.7 Identify how many days each employee is working. Assume current date is
‘7-Feb-2007’.
SELECT ename, to_date(‘7-FEB-2007’) – hiredate “num_work days” FROM
scott.emp;
2.8 Find all employees whose names have the pattern ‘AM’.
SELECT ename FROM scott.emp WHERE ename LIKE ‘%AM%’;
[10pts each]
2.9 Identify all employees in each dept that earn more than the avg in their dept.
SELECT ename FROM scott.emp e
WHERE sal > (SELECT avg(sal) FROM scott.emp e2 WHERE e2.deptno =
e.deptno);
2.10 Identify names of depts. that have an avg salary > 2500.
SELECT dname, avg(sal) asal FROM scott.dept a, scott.emp b
WHERE a.deptno = b.deptno
GROUP BY dname
HAVING avg(sal) > 2500;
2.11 Identify all employees in depts. that have an avg salary > 2000 and the employees
have salary greater than the avg for the dept.
2.9 + 2.10
SELECT ename FROM scott.emp e
WHERE sal > (SELECT avg(sal) FROM scott.emp e2 WHERE e2.deptno =
e.deptno
And e2.deptno in
(SELECT deptno FROM scott.emp GROUP BY deptno HAVING
avg(sal)>2000));
but simpler:
SELECT ename FROM scott.emp e
WHERE sal >
(SELECT avg(sal) FROM scott.emp e2 WHERE e2.deptno = e.deptno
GROUP BY deptno HAVING avg(sal) > 2000);
Problem 3: [21 pts]
3.1 Identify all employees reporting to ‘CLARK’;
SELECT ename FROM scott.emp
START WITH MGR =
(SELECT empno FROM scott.emp WHERE ename=’CLARK’)
CONNECT BY NEXT mgr = empno;
3.2 Identify the manager of manager of ‘ALLEN’
SELECT ename, LEVEL FROM scott.emp
START WITH ename=’ALLEN’
CONNECT BY empno = PRIOR mgr;
Refine that to select only the manager’s manager which is level=3.
SELECT ename FROM (
SELECT ename, LEVEL lvl FROM scott.emp
START WITH ename=’ALLEN’
CONNECT BY empno = PRIOR mgr
)
WHERE lvl = 3 ;
3.3 Identify all bosses (managers and higherups) of ‘ADAMS’;
SELECT ename FROM (
SELECT ename, LEVEL lvl FROM scott.emp
START WITH ename=’ADAMS’
CONNECT BY empno = PRIOR mgr
)
WHERE lvl > 1 ;
OR
SELECT mgr FROM scott.emp
START WITH ename=’ADAMS’
CONNECT BY empno = PRIOR mgr;
And join it with emp to get the name of the mgr
OR
SELECT ename FROM scott.emp
START WITH empno =
(SELECT mgr FROM scott.emp WHERE ename = ‘ADAMS’)
CONNECT BY empno = PRIOR mgr;
Problem 4: [ 24pts]
4.1 Copy the tables from scott to your schema. Specify primary keys and non-null
constraints.
CREATE TABLE emp AS SELECT * FROM SCOTT.EMP;
CREATE TABLE dept AS SELECT * FROM SCOTT.DEPT;
4.2 In your schema, create views one per dept that shows the salaries, commissions for
all
employees in that dept.
CREATE VIEW sal_view_accounting AS
SELECT e.ename, e.empno, comm, sal, d.deptno, d.dname FROM emp e, dept d
WHERE e.deptno = d.deptno and d.dname = ‘ACCOUNTING’;
In PL/SQL:
Set serverout on
DECLARE
CURSOR dcur IS SELECT * FROM dept;
Dname varchar2(32);
Vname varchar2(32);
Stmt varchar2(256);
BEGIN
FOR d IN dcur LOOP
vname := ‘salary_view_’ || d.dname;
stmt := ‘ CREATE VIEW ‘ || vname ||
‘ AS SELECT e.ename, e.empno, comm, sal, d.deptno, d.dname ‘ ||
‘ FROM emp e, dept d ‘ ||
‘ WHERE e.deptno = d.deptno and d.dname = ‘’’ ||
DBMS_ASSERT.SIMPLE_SQL_NAME(d.dname) || ‘’’’ ;
dbms_output.put_line(stmt);
EXECUTE IMMEDIATE stmt;
END LOOP;
EXCEPTION WHEN OTHERS THEN
RAISE;
END;
/
4.3. In your schema (i.e., the schema you logged in as: halo/halo, sumeet/sumeet,
etc...), create a table of all managers with an additional column to store their
‘direct’ reportees.
CREATE TYPE employees_type AS TABLE of VARCHAR2(32);
/
CREATE TABLE mgr_emp_tab
(mgrname VARCHAR2(32),
employees EMPLOYEES_TYPE)
NESTED TABLE employees STORE AS emptab;
1)
-- First populate the managers names
INSERT INTO mgr_emp_tab SELECT ename, EMPLOYEES_TYPE( ) FROM emp
WHERE empno IN (SELECT mgr FROM emp);
-- Insert the employees for each employee manually
-- Insert into the ‘table’ of each specific employee
insert into mgr_emp_tab values ('KING', EMPLOYEES_TYPE(‘JONES’, ‘BLAKE’,
‘CLARK’));
…
-- Do the same for each manager
OR
2)
-- First populate the managers names
INSERT INTO mgr_emp_tab SELECT ename, EMPLOYEES_TYPE( ) FROM emp
WHERE empno IN (SELECT mgr FROM emp);
-- Populate the employees for each manager automatically using a query
-- Insert into the ‘table’ of each specific employee
INSERT INTO
TABLE(SELECT employees FROM mgr_emp_tab WHERE mgrname = ‘BLAKE’) p
(SELECT ename FROM emp where mgr =
(SELECT empno FROM emp WHERE ename = ‘BLAKE’));
-- Do the same for each manager
-- You can put the insertion for each manager in a PL/SQL loop.
3)
OR the most simplest way: USE CAST of subquery results to EMPLOYEES_TYPE
and insert.
Truncate table mgr_emp_tab;
INSERT INTO mgr_emp_tab (
SELECT ename, CAST(MULTISET
(
SELECT e1.ename FROM emp e1 WHERE e1.mgr = e2.empno
) AS EMPLOYEES_TYPE)
FROM emp e2 WHERE empno in (SELECT mgr FROM emp));
4.4. In the table created in 4.3, show the direct reportees of ‘BLAKE’.
SELECT * FROM
TABLE( SELECT employees FROM mgr_emp_tab
WHERE mgrname=’BLAKE’);
Download