Oracle table creation missing right parenthesis - oracle

This should be a pretty simple problem but I just can't see what is wrong. I am trying to create a table with a few check and not null constraints on said table, however I am getting a missing right parenthesis error when trying to execute the command.
CREATE TABLE students (
studentID NUMBER(5) PRIMARY KEY,
forename VARCHAR2(15) NOT NULL,
surname VARCHAR2(15) NOT NULL,
street VARCHAR2(20),
city VARCHAR2(15),
postcode VARCHAR2(10) NOT NULL,
dateOfBirth DATE() NOT NULL CHECK(dateOfBirth BETWEEN DATE '1999-01-01' AND SYSDATE),
gender VARCHAR2(10) CHECK(gender = 'male' OR gender = 'female' OR gender = 'both'),
category VARCHAR2(15) NOT NULL CHECK(category = 'first year undergraduate' OR caregory = 'postgraduate'),
fulltimeStudent VARCHAR(5) NOT NULL CHECK(fulltimeStudent = 'yes' OR fulltimeStudent = 'no'),
nationality VARCHAR(25) NOT NULL,
smoker VARCHAR(5) CHECK(smoker = 'yes' OR smoker = 'no') AND NOT NULL,
specialNeeds VARCHAR(30),
additionalComments VARCHAR(50),
status VARCHAR(15) NOT NULL CHECK(status = 'placed' or status = 'waiting')
);
Full error below -

There's no need for parenthesis at "DATE()".
Also, you cannot use SYSDATE in check constraints, you may wish to use a trigger instead, and there's a typo at "CAREGORY".
You can run it like this:
CREATE TABLE students (
studentID NUMBER(5) PRIMARY KEY,
forename VARCHAR2(15) NOT NULL,
surname VARCHAR2(15) NOT NULL,
street VARCHAR2(20),
city VARCHAR2(15),
postcode VARCHAR2(10) NOT NULL,
dateOfBirth DATE NOT NULL,
gender VARCHAR2(10) CHECK(gender = 'male' OR gender = 'female' OR gender = 'both'),
category VARCHAR2(15) NOT NULL CHECK(category = 'first year undergraduate' OR category = 'postgraduate'),
fulltimeStudent VARCHAR(5) NOT NULL CHECK(fulltimeStudent = 'yes' OR fulltimeStudent = 'no'),
nationality VARCHAR(25) NOT NULL,
smoker VARCHAR(5) NOT NULL CHECK(smoker = 'yes' OR smoker = 'no'),
specialNeeds VARCHAR(30),
additionalComments VARCHAR(50),
status VARCHAR(15) NOT NULL CHECK(status = 'placed' or status = 'waiting')
);
Edit-Added docs reference on sysdate in check constraints:
https://docs.oracle.com/cd/B28359_01/server.111/b28286/clauses002.htm
Conditions of check constraints cannot contain the following
constructs:
Subqueries and scalar subquery expressions
Calls to the functions that are not deterministic (CURRENT_DATE, CURRENT_TIMESTAMP, DBTIMEZONE, LOCALTIMESTAMP, SESSIONTIMEZONE, SYSDATE, SYSTIMESTAMP, UID, USER, and USERENV)
Calls to user-defined functions
Dereferencing of REF columns (for example, using the DEREF function)
Nested table columns or attributes
The pseudocolumns CURRVAL, NEXTVAL, LEVEL, or ROWNUM
Date constants that are not fully specified

Related

How to implement this trigger on Oracle SQL?

I have found an exercise in the SQL book I study, which is not solved and I can not solve it.
The goal is to implement a trigger that avoids overlapping contracts. If a customer with a current contract signs a new one, the end date of the previous one will be one day before the new start date.
Tables given are:
CREATE TABLE CLIENTS (
clientId VARCHAR2(15),
DNI VARCHAR2(9),
name VARCHAR2(100) NOT NULL,
surname VARCHAR2(100) NOT NULL,
sec_surname VARCHAR2(100),
eMail VARCHAR2(100) NOT NULL,
phoneN NUMBER(12),
birthdate DATE,
CONSTRAINT PK_CLIENTS PRIMARY KEY (clientId),
CONSTRAINT UK1_CLIENTS UNIQUE (DNI),
CONSTRAINT UK2_CLIENTS UNIQUE (eMail),
CONSTRAINT UK3_CLIENTS UNIQUE (phoneN),
);
CREATE TABLE contracts(
contractId VARCHAR2(10),
clientId VARCHAR2(15),
startdate DATE NOT NULL,
enddate DATE,
contract_type VARCHAR2(50),
address VARCHAR2(100) NOT NULL,
town VARCHAR2(100) NOT NULL,
ZIPcode VARCHAR2(8) NOT NULL,
country VARCHAR2(100) NOT NULL,
CONSTRAINT PK_contracts PRIMARY KEY (contractId),
CONSTRAINT FK_contracts1 FOREIGN KEY (clientId) REFERENCES CLIENTS
);
Any suggestions?
I agree with the posted comments that it helps to have some specifics about what is failing in the prior attempts, and I would also recommend not using a TRIGGER at all for this kind of thing.
But as this is for a study exercise, here are some examples that might be a starting place.
I've modified your tables to disallow NULL PRIMARY KEYs in these examples.
To get started, create the tables:
CREATE TABLE CLIENTS (
CLIENTID VARCHAR2(15) NOT NULL,
DNI VARCHAR2(9),
NAME VARCHAR2(100) NOT NULL,
SURNAME VARCHAR2(100) NOT NULL,
SEC_SURNAME VARCHAR2(100),
EMAIL VARCHAR2(100) NOT NULL,
PHONEN NUMBER(12),
BIRTHDATE DATE,
CONSTRAINT PK_CLIENTS PRIMARY KEY (CLIENTID),
CONSTRAINT UK1_CLIENTS UNIQUE (DNI),
CONSTRAINT UK2_CLIENTS UNIQUE (EMAIL),
CONSTRAINT UK3_CLIENTS UNIQUE (PHONEN)
);
CREATE TABLE CONTRACTS (
CONTRACTID VARCHAR2(10) NOT NULL,
CLIENTID VARCHAR2(15) NOT NULL,
STARTDATE DATE NOT NULL,
ENDDATE DATE,
CONTRACT_TYPE VARCHAR2(50),
ADDRESS VARCHAR2(100) NOT NULL,
TOWN VARCHAR2(100) NOT NULL,
ZIPCODE VARCHAR2(8) NOT NULL,
COUNTRY VARCHAR2(100) NOT NULL,
CONSTRAINT PK_CONTRACTS PRIMARY KEY (CONTRACTID),
CONSTRAINT FK_CONTRACTS1 FOREIGN KEY (CLIENTID) REFERENCES CLIENTS
);
Then, create the first CLIENTs:
INSERT INTO CLIENTS VALUES (1,NULL,'Frodo','Baggins',NULL,'the.real.frodo#adventure.com',NULL,NULL);
INSERT INTO CLIENTS VALUES (2,NULL,'Chewbacca','UNKNOWN',NULL,'chewio.#kashyyyk.org',NULL,NULL);
COMMIT;
Then create a TRIGGER. In this first example, the TRIGGER is an AFTER STATEMENT type.
It is simple but inefficient since it evaluates every CLIENT after each INSERT statement.
Against a large data set, or in the face of multiple TRIGGERs, this could be a problem.
This TRIGGER will check for the prior contract and will set its ENDDATE to one day before the new contract, if it is null or after the start of the new contract.
CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
AFTER INSERT ON CONTRACTS
BEGIN
MERGE INTO CONTRACTS
USING (
SELECT CONTRACTID,
CANDIDATE_ENDDATE AS ENDDATE
FROM
(SELECT CONTRACTS.CONTRACTID,
(TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
FROM CONTRACTS)
WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
END;
/
Then, test it out.
Add the initial contracts. No enddate changes expected, as these are the first. Frodo's contract here has an end-date already set.
INSERT INTO CONTRACTS VALUES('Break-Ring',1,TO_DATE('19560511','YYYYMMDD'), TO_DATE('19851014','YYYYMMDD'), NULL, 'No 1', 'Doom Mountain', 'MORD', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('SaveGalaxy',2,TO_DATE('19770615','YYYYMMDD'), NULL, NULL, 'No 75', 'Rwookrrorro', 'RWKR', 'Kashyyyk');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 14-OCT-85
SaveGalaxy 2 15-JUN-77
Then add new contracts.
Frodo's new contract starts before the end of his existing contract, so the enddate will be adjusted.
Chewie's initial contract had no ENDDATE, so it will be adjusted as well.
INSERT INTO CONTRACTS VALUES('GoBackHome',1,TO_DATE('19570219','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('DefendHoth',2,TO_DATE('19801115','YYYYMMDD'), NULL, NULL, 'Meteor Crater', 'Ice Ridge', 'METEO', 'Hoth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80
And as other contracts are signed, the pattern continues:
INSERT INTO CONTRACTS VALUES('GoWedding',2,TO_DATE('19830309','YYYYMMDD'), NULL, NULL, 'Main Hall', 'Grand Palace', 'ALLNC', 'Coruscant');
INSERT INTO CONTRACTS VALUES('Gardening',1,TO_DATE('19570503','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57 02-MAY-57
Gardening 1 03-MAY-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80 08-MAR-83
GoWedding 2 09-MAR-83
To stabilize the workload on this query, a COMPOUND TRIGGER may be used instead. This second example achieves the same result as the first, but only interrogates the CONTRACTs of CLIENTs that have changed:
First, ROLLBACK;
Then, create a type to be used by the TRIGGER:
CREATE OR REPLACE TYPE NUMBER_LIST IS TABLE OF NUMBER;
/
Then create the COMPOUND TRIGGER:
CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
FOR INSERT ON CONTRACTS
COMPOUND TRIGGER
V_CLIENTS NUMBER_LIST;
BEFORE STATEMENT
IS
BEGIN
V_CLIENTS:= NUMBER_LIST();
END BEFORE STATEMENT;
AFTER EACH ROW
IS
BEGIN
V_CLIENTS.EXTEND();
V_CLIENTS(V_CLIENTS.COUNT) := :NEW.CLIENTID;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
MERGE INTO CONTRACTS
USING (
SELECT CONTRACTID,
CANDIDATE_ENDDATE AS ENDDATE
FROM
(SELECT CONTRACTS.CONTRACTID,
(TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
FROM CONTRACTS
WHERE CONTRACTS.CLIENTID IN (SELECT * FROM TABLE(V_CLIENTS)))
WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
END AFTER STATEMENT;
END CONTRACT_ENDDATE_ADJUSTER;
/
After repeating the above inserts, the result is the same:
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57 02-MAY-57
Gardening 1 03-MAY-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80 08-MAR-83
GoWedding 2 09-MAR-83

Table using Foreign Key Oracle

I am having a problem linking two tables in oracle 11g express addition. I have looked on this site for assistance, but I am unable to find what I need.
My BOOKS table was loaded up using the following statement:
CREATE TABLE STATES(
ST VARCHAR2(2) PRIMARY KEY,
STATES VARCHAR2(20) NOT NULL
);
The CUSTOMERS table that I am trying to load is written as such:
CREATE TABLE CUSTOMERS(
CUST_ID NUMBER(10) PRIMARY KEY,
FIRST_NAME VARCHAR2(20) NOT NULL,
LAST_NAME VARCHAR2(20) NOT NULL,
STREET_ADDRESS_1 VARCHAR2(30) NOT NULL,
STREET_ADDRESS_2 VARCHAR2(20),
CITY VARCHAR2(20) NOT NULL,
ST VARCHAR2(2),
ZIP_CODE VARCHAR2(10) NOT NULL,
PHONE_NUMBER_1 VARCHAR2(20)NOT NULL,
PHONE_NUMBER_2 VARCHAR2(20),
EMAIL VARCHAR2(40) NOT NULL,
CREDIT_LIMIT NUMBER(7,2) NOT NULL,
FOREIGN KEY ST REFERENCES STATES(ST)
);
However, when I run the statement I get the following error:
ORA-00906: missing left parenthesis
00906. 00000 - "missing left parenthesis"
*Cause:
*Action:
I believe that the error is in the FOREIGN KEY portion of the statement, as I can load the table without that statement.
You have syntax error while declaring foreign key constraint
Correct one:
CREATE TABLE CUSTOMERS(
CUST_ID NUMBER(10) PRIMARY KEY,
FIRST_NAME VARCHAR2(20) NOT NULL,
LAST_NAME VARCHAR2(20) NOT NULL,
STREET_ADDRESS_1 VARCHAR2(30) NOT NULL,
STREET_ADDRESS_2 VARCHAR2(20),
CITY VARCHAR2(20) NOT NULL,
ST VARCHAR2(2),
ZIP_CODE VARCHAR2(10) NOT NULL,
PHONE_NUMBER_1 VARCHAR2(20)NOT NULL,
PHONE_NUMBER_2 VARCHAR2(20),
EMAIL VARCHAR2(40) NOT NULL,
CREDIT_LIMIT NUMBER(7,2) NOT NULL,
CONSTRAINT FK_CUSTOMERS FOREIGN KEY (ST) REFERENCES STATES(ST)
);
or
CREATE TABLE CUSTOMERS(
CUST_ID NUMBER(10) PRIMARY KEY,
FIRST_NAME VARCHAR2(20) NOT NULL,
LAST_NAME VARCHAR2(20) NOT NULL,
STREET_ADDRESS_1 VARCHAR2(30) NOT NULL,
STREET_ADDRESS_2 VARCHAR2(20),
CITY VARCHAR2(20) NOT NULL,
ST VARCHAR2(2),
ZIP_CODE VARCHAR2(10) NOT NULL,
PHONE_NUMBER_1 VARCHAR2(20)NOT NULL,
PHONE_NUMBER_2 VARCHAR2(20),
EMAIL VARCHAR2(40) NOT NULL,
CREDIT_LIMIT NUMBER(7,2) NOT NULL,
FOREIGN KEY (ST) REFERENCES STATES(ST)
);

Insert my data from Relational Tables to Object-Relational Tables

I tried with the command insert into select... but it didn't work. How can I load the data from the Relational tables to the Object-Relational tables?
Example for table Categories:
insert into CATEGORIES_NEW select * from Categories;
The above worked,but the similar way doesn't work for the other tables.
Below are all the tables:
Relational Tables
CREATE TABLE Customers (
CUSTOMERID NUMBER NOT NULL,
FIRSTNAME VARCHAR2 (20) NOT NULL,
LASTNAME VARCHAR2 (20) NOT NULL,
ADDRESS1 VARCHAR2 (40) NOT NULL,
ADDRESS2 VARCHAR2 (40),
CITY VARCHAR2 (20) NOT NULL,
STATE VARCHAR2 (20) NOT NULL,
ZIP VARCHAR2 (20) NOT NULL,
COUNTRY VARCHAR2 (20) NOT NULL,
REGION VARCHAR2 (20) NOT NULL,
EMAIL VARCHAR2 (20) NOT NULL,
PHONE VARCHAR2 (20) NOT NULL,
CREDITCARDTYPE VARCHAR2 (20) NOT NULL,
CREDITCARD VARCHAR2 (20) NOT NULL,
CREDITCARDEXPIRATION VARCHAR (10) NOT NULL,
USERNAME VARCHAR2 (20) NOT NULL,
"PASSWORD" VARCHAR2 (20) NOT NULL,
AGE NUMBER NOT NULL,
INCOME NUMBER NOT NULL,
GENDER VARCHAR2 (8) NOT NULL,
PRIMARY KEY (CUSTOMERID));
CREATE TABLE Orders (
ORDERID NUMBER NOT NULL,
ORDERDATE DATE NOT NULL,
CUSTOMERID NUMBER NOT NULL REFERENCES Customers,
NETAMOUNT NUMBER NOT NULL,
TAX NUMBER NOT NULL,
TOTALAMOUNT NUMBER NOT NULL,
PRIMARY KEY (ORDERID));
CREATE TABLE Categories (
"CATEGORY" NUMBER NOT NULL,
CATEGORYNAME VARCHAR (20) NOT NULL,
PRIMARY KEY ("CATEGORY"));
CREATE TABLE Products (
PROD_ID NUMBER NOT NULL ,
"CATEGORY" NUMBER NOT NULL REFERENCES Categories,
TITLE VARCHAR (40) NOT NULL,
ACTOR VARCHAR (40) NOT NULL,
PRICE VARCHAR (40) NOT NULL,
PRIMARY KEY (PROD_ID));
CREATE TABLE Orderlines (
ORDERLINEID NUMBER NOT NULL,
ORDERID NUMBER NOT NULL REFERENCES Orders,
PROD_ID NUMBER NOT NULL REFERENCES Products,
QUANTITY NUMBER NOT NULL,
ORDERDATE VARCHAR2 (80) NOT NULL,
PRIMARY KEY (ORDERLINEID,ORDERID));
Object-Relational Tables
CREATE TYPE Customer_obj AS OBJECT (
CUSTOMERID NUMBER,
CUST_NAME NAME,
CUST_ADDRESS ADDRESS_TYPE,
CUST_CONTACT CONTACT_INFO,
CUST_CREDITCARD CREDITCARD_INFO,
CUST_PERSONALINFO PERSONAL_INFO
);
CREATE TYPE NAME AS OBJECT (
FIRSTNAME VARCHAR2(80) ,
LASTNAME VARCHAR2(80)
);
CREATE TYPE ADDRESS_TYPE AS OBJECT (
ADDRESS VARCHAR2(280) ,
CITY VARCHAR2(80) ,
STATE VARCHAR2(20),
ZIP VARCHAR2(40) ,
COUNTRY VARCHAR2(40) ,
REGION VARCHAR2(40)
);
CREATE TYPE CONTACT_INFO AS OBJECT (
EMAIL VARCHAR2(40),
PHONE VARCHAR2(40)
);
CREATE TYPE CREDITCARD_INFO AS OBJECT (
CREDITCARDTYPE VARCHAR2(40) ,
CREDITCARD VARCHAR2(40) ,
CREDITCARDEXPIRATION VARCHAR2(40)
);
CREATE TYPE PERSONAL_INFO AS OBJECT (
USERNAME VARCHAR2(80) ,
PASSWORD VARCHAR2(80) ,
AGE NUMBER ,
INCOME NUMBER ,
GENDER VARCHAR(20)
);
CREATE TABLE CUSTOMERS_NEW OF Customer_obj(
PRIMARY KEY (CUSTOMERID));
CREATE TYPE Categories_obj AS Object(
CATEGORY NUMBER ,
CATEGORYNAME VARCHAR2(80) );
CREATE TABLE CATEGORIES_NEW OF Categories_obj(
PRIMARY KEY (CATEGORY));
CREATE TYPE Orders_obj AS Object(
ORDERID NUMBER ,
ORDERDATE VARCHAR2(400),
CUSTOMERID NUMBER,
NETAMOUNT NUMBER ,
TAX NUMBER,
TOTALAMOUNT NUMBER
);
CREATE TABLE ORDERS_NEW OF Orders_obj(
PRIMARY KEY (ORDERID),
FOREIGN KEY(CUSTOMERID) REFERENCES CUSTOMERS_NEW
);
CREATE TYPE Products_obj AS Object(
PROD_ID NUMBER ,
CATEGORY NUMBER ,
TITLE VARCHAR2 (40) ,
ACTOR VARCHAR2 (40) ,
PRICE VARCHAR2 (40)
);
CREATE TABLE PRODUCTS_NEW OF Products_obj(
PRIMARY KEY (PROD_ID),
FOREIGN KEY (CATEGORY) REFERENCES CATEGORIES_NEW
);
CREATE TYPE Orderlines_obj AS Object(
CUST_ID_INFO ID_INFO,
QUANTITY NUMBER,
ORDERDATE VARCHAR2 (80)
);
CREATE TYPE ID_INFO AS Object (
ORDERLINEID NUMBER ,
ORDERID NUMBER ,
PROD_ID NUMBER
);
CREATE TABLE ORDERLINES_NEW OF Orderlines_obj(
PRIMARY KEY (CUST_ID_INFO.ORDERLINEID,CUST_ID_INFO.ORDERID),
FOREIGN KEY (CUST_ID_INFO.ORDERID) REFERENCES ORDERS_NEW,
FOREIGN KEY (CUST_ID_INFO.PROD_ID) REFERENCES PRODUCTS_NEW
);
Object tables are tricky, and probably not worth the effort. But anyway.
You're working with objects, which means you need to instantiate them. When the object table is defined on a type which just has scalar attributes Oracle is clever enough to implicitly instantiate the object. But when the Type is complex, with attributes which are themselves Types ypu need to instantiate them explicitly.
Here is the insert for CUSTOMERS_NEW
insert into CUSTOMERS_NEW
select Customer_obj (
c.CUSTOMERID ,
c.FIRSTNAME||' '||c.LASTNAME ,
ADDRESS_TYPE(
c.ADDRESS1||' ' ||c.ADDRESS2 ,
c.CITY ,
c.STATE ,
c.ZIP ,
c.COUNTRY ,
c.REGION
),
CONTACT_INFO(
c.EMAIL,
c.PHONE
),
CREDITCARD_INFO (
c.CREDITCARDTYPE ,
c.CREDITCARD ,
c.CREDITCARDEXPIRATION
),
PERSONAL_INFO (
c.USERNAME,
c.PASSWORD,
c.AGE ,
c.INCOME ,
c.GENDER
)
)
from customers ;

How to create a view

I was trying to create a view with information of latest hired employee in each branch. But i was not succeed in that. Can anyone direct me towards the right path.
CREATE TABLE BRANCH(
BRANCH_ID NUMBER(8) PRIMARY KEY,
BRANCH_NAME VARCHAR2(100) NOT NULL,
SCHEDULE_LINK_NUM NUMBER(8),
MAIN_BRANCH_ID number(8),
BRANCH_MGR_ID NUMBER(8),
BRANCH_OPEN_DATE DATE,
EMAIL VARCHAR2(50),
URL VARCHAR2(50)
);
CREATE TABLE EMPLOYEE(
EMPLOYEE_ID NUMBER(8) PRIMARY KEY,
FIRST_NAME VARCHAR2(50),
LAST_NAME VARCHAR2(50),
MIDDLE_NAME VARCHAR2(50),
GENDER CHAR(1),
SSN NUMBER(9) NOT NULL,
DOB DATE,
MARITAL_STATUS VARCHAR2(30),
SPOUSE_NAME VARCHAR2(50),
HOME_PHONE NUMBER(10),
CELL_PHONE NUMBER(10),
OFFICE_PH_EXTN NUMBER(6),
EMPLOYEE_TYPE VARCHAR2(40),
SALARY NUMBER(10,2),
TAX_DEDUCTION NUMBER(10,2),
BRANCH_ID NUMBER(8),
MGR_ID NUMBER(8),
CONSTRAINT EMP_BRANCH_FKEY FOREIGN KEY(BRANCH_ID) REFERENCES BRANCH(BRANCH_ID),
CONSTRAINT EMP_EMPTYPE_CHECK CHECK(EMPLOYEE_TYPE IN ('MANAGER', 'MECHANIC', 'SECRETARY', 'SALES PERSON')),
CONSTRAINT EMP_MARITSTATUS_CHECK CHECK(MARITAL_STATUS IN ('SINGLE', 'MARRIED', 'DIVORCED'))
);
CREATE TABLE EMP_WORK_HISTORY(
BRANCH_EMP_NUM NUMBER(8) PRIMARY KEY,
BRANCH_ID NUMBER(8),
EMPLOYEE_ID NUMBER(8),
JOIN_DATE DATE NOT NULL,
RELIEVING_DATE DATE,
EMPLOYEE_TYPE VARCHAR2(40),
DESCRIPTION VARCHAR2(200),
CONSTRAINT BRANCH_WRKHIS_BID_FKEY FOREIGN KEY(BRANCH_ID) REFERENCES BRANCH(BRANCH_ID),
CONSTRAINT BRANCH_WRKHIS_EID_FKEY FOREIGN KEY(EMPLOYEE_ID) REFERENCES EMPLOYEE(EMPLOYEE_ID),
CONSTRAINT EMP_WRKHIS_EMPTYPE_CHECK CHECK(EMPLOYEE_TYPE IN ('MANAGER', 'MECHANIC', 'SECRETARY', 'SALES PERSON'))
);
I have written the view like below:
CREATE VIEW LAST_EMPLOYEE_BRANCH AS
WITH LAST_EMP_BRANCH AS
(SELECT MAX(EWH.JOIN_DATE) AS LAST_HIRED_DATE, EWH.BRANCH_ID
FROM EMP_WORK_HISTORY EWH GROUP BY EWH.BRANCH_ID)
SELECT E.FIRST_NAME || E.LAST_NAME AS EMPLOYEE_NAME,
B.BRANCH_NAME, LEB.LAST_HIRED_DATE, E.SALARY,
EXTRACT(YEAR FROM NUMTOYMINTERVAL(MONTHS_BETWEEN(TRUNC(SYSDATE),E.DOB),'MONTH')) AS AGE
FROM EMPLOYEE E, BRANCH B, LAST_EMP_BRANCH LEB
WHERE E.BRANCH_ID = B.BRANCH_ID
AND LEB.BRANCH_ID = E.BRANCH_ID;
By running the above view i am getting all employees records. Can anyone help on this?
Looks like you forgot to include the EMP_WORK_HISTORY table and the LAST_HIRED_DATE column in the join. Try the query below:
CREATE OR REPLACE VIEW LAST_EMPLOYEE_BRANCH AS
WITH LAST_EMP_BRANCH AS
(SELECT MAX(EWH.JOIN_DATE) AS LAST_HIRED_DATE, EWH.BRANCH_ID
FROM EMP_WORK_HISTORY EWH GROUP BY EWH.BRANCH_ID)
SELECT E.FIRST_NAME || E.LAST_NAME AS EMPLOYEE_NAME,
B.BRANCH_NAME, LEB.LAST_HIRED_DATE, E.SALARY,
EXTRACT(YEAR FROM NUMTOYMINTERVAL(MONTHS_BETWEEN(TRUNC(SYSDATE),E.DOB),'MONTH')) AS AGE
FROM EMPLOYEE E, BRANCH B, LAST_EMP_BRANCH LEB, EMP_WORK_HISTORY EWH
WHERE E.BRANCH_ID = B.BRANCH_ID
AND LEB.BRANCH_ID = E.BRANCH_ID
AND E.EMPLOYEE_ID = EWH.EMPLOYEE_ID
AND B.BRANCH_ID = EWH.BRANCH_ID
AND LEB.LAST_HIRED_DATE = EWH.JOIN_DATE;

Oracle Natural Joins and Count(1)

Does anyone know why in Oracle 11g when you do a Count(1) with more than one natural join it does a cartesian join and throws the count way off?
Such as
SELECT Count(1) FROM record NATURAL join address NATURAL join person WHERE status=1
AND code = 1 AND state = 'TN'
This pulls back like 3 million rows when
SELECT * FROM record NATURAL join address NATURAL join person WHERE status=1
AND code = 1 AND state = 'TN'
pulls back like 36000 rows, which is the correct amount.
Am I just missing something?
Here are the tables I'm using to get this result.
CREATE TABLE addresses (
address_id NUMBER(10,0) NOT NULL,
address_1 VARCHAR2(60) NULL,
address_2 VARCHAR2(60) NULL,
city VARCHAR2(35) NULL,
state CHAR(2) NULL,
zip VARCHAR2(5) NULL,
zip_4 VARCHAR2(4) NULL,
county VARCHAR2(35) NULL,
phone VARCHAR2(11) NULL,
fax VARCHAR2(11) NULL,
origin_network NUMBER(3,0) NOT NULL,
owner_network NUMBER(3,0) NOT NULL,
corrected_address_id NUMBER(10,0) NULL,
"HASH" VARCHAR2(200) NULL
);
CREATE TABLE rates (
rate_id NUMBER(10,0) NOT NULL,
eob VARCHAR2(30) NOT NULL,
network_code NUMBER(3,0) NOT NULL,
product_code VARCHAR2(2) NOT NULL,
rate_type NUMBER(1,0) NOT NULL
);
CREATE TABLE records (
pk_unique_id NUMBER(10,0) NOT NULL,
rate_id NUMBER(10,0) NOT NULL,
address_id NUMBER(10,0) NOT NULL,
effective_date DATE NOT NULL,
term_date DATE NULL,
last_update DATE NULL,
status CHAR(1) NOT NULL,
network_unique_id VARCHAR2(20) NULL,
rate_id_2 NUMBER(10,0) NULL,
contracted_by VARCHAR2(50) NULL,
contract_version VARCHAR2(5) NULL,
bill_address_id NUMBER(10,0) NULL
);
I should mention this wasn't a problem in Oracle 9i, but when we switched to 11g it became a problem.
My advice would be to NOT use NATURAL JOIN. Explicitly define your join conditions to avoid confusion and "hidden bugs". Here is the official NATURAL JOIN Oracle documentation and more discussion about this subject.
If it happens exactly as you say then it must be an optimiser bug, you should report it to Oracle.
you should try a count(*)
There is a difference between the two.
count(1) signifies count rows where 1 is not null
count(*) signifies count the rows
Just noticed you used 2 natural joins...
From the documentation you can only use a natural join on 2 tables
Natural_Join

Resources