How to implement this trigger on Oracle SQL? - oracle

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

Related

Oracle Trigger on two tables

I am trying to create a BEFORE UPDATE trigger on the two tables purchaseorderdetail and purchaseorderheader as shown below. I would like to implement this trigger on PurchaseOrderHeader table that prohibits updates of the PurchaseOrderHeader.SubTotal column if the corresponding data in the PurchaseOrderDetail table is not consistent with the new value of the PurchaseOrderHeader.SubTotal column.
CREATE TABLE purchaseorderheader(
purchaseorderid NUMBER(4),
revisionnumber NUMBER(2),
status NUMBER(1),
employeeid NUMBER(3),
vendorid NUMBER(4),
shipmethodid NUMBER(1),
orderdate TIMESTAMP,
shipdate TIMESTAMP,
subtotal FLOAT(10),
taxamt FLOAT(10),
freight FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderid)
);
CREATE TABLE purchaseorderdetail(
purchaseorderid NUMBER(4),
purchaseorderdetailid NUMBER(4),
duedate TIMESTAMP,
orderqty NUMBER(6),
productid NUMBER(6),
unitprice FLOAT(10),
receivedqty FLOAT(10),
rejectedqty FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderdetailid),
CONSTRAINT fk_orderid FOREIGN KEY (purchaseorderid) REFERENCES purchaseorderheader(purchaseorderid)
);
What I have come up with so far, any help?
CREATE OR REPLACE TRIGGER Header_Before_Subtotal BEFORE UPDATE
ON purchaseorderheader
FOR EACH ROW
BEGIN
IF(:NEW.subtotal <> (SELECT unitprice*orderqty FROM purchaseorderdetail GROUP BY purchaseorderid)) THEN
RAISE_APPLICATION_ERROR(-20001, 'Subtotal is not equal to unitprice * order quantity, check again.');
END IF;
END;
Compute total separately (and reference the master key), and then compare that value to new subtotal.
CREATE OR REPLACE TRIGGER Header_Before_Subtotal
BEFORE UPDATE
ON purchaseorderheader
FOR EACH ROW
DECLARE
l_total number;
BEGIN
SELECT d.unitprice * d.orderqty
INTO l_total
FROM purchaseorderdetail d
WHERE d.purchaseorderid = :new.purchaseorderid;
IF :NEW.subtotal <> l_total THEN
RAISE_APPLICATION_ERROR(-20001, 'Subtotal is not equal to unitprice * order quantity, check again.');
END IF;
END;
/

TRIGGERS_function

please help me to find the solution i have a project .
so my project is about a mobile repair store , we have some tables :
customers, mobiles, repairjob
//customer table
CREATE TABLE CUSTOMERS (
CUSTOMER_CPR NUMBER(9) PRIMARY KEY,
FIRST_NAME VARCHAR2(30) NOT NULL,
MID VARCHAR2(30)
LAST_NAME VARCHAR2(30) NOT NULL,
EMAIL VARCHAR2(30) NOT NULL UNIQUE,
HOME_TEL NUMBER(8) UNIQUE,
HOUSE_NO VARCHAR2(30) NOT NULL,
ROAD_NO VARCHAR2(30) NOT NULL,
BLOCK_NO VARCHAR2(30) NOT NULL,
CITY VARCHAR2(30) NOT NULL
);
//mobiles table
CREATE TABLE MOBILES (
MOB_ID NUMBER(8,0) PRIMARY KEY,
MODEL VARCHAR2(30) NOT NULL,
MOB_DECRIPTION VARCHAR2(100),
SERIAL_NUM VARCHAR2(30) UNIQUE,
MAKE VARCHAR2(50),
customer_cpr number(9),
);
//repair job table
CREATE TABLE REPAIR JOB (
JOB_NUM NUMBER primary key,
customer_cpr number(9)
EMP_ID NUMBER(8,0) NOT NULL,
DATE_RECEIVED DATE,
DATE_TO_RETURN DATE,
ITEM_ID NUMBER
);
so my question is to make a trigger function , we have assumed that the customer cannot have more than 3 repair jobs or can't fix more than 3 mobiles at one time until it finishes all. so how i make a triiger function ?

Oracle table creation missing right parenthesis

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

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