Insert statement and create table oracle - oracle

My tables are been created, but when I am trying to put the insert statements it's giving me an error saying parent not found.
This is my create table:
Create table patient (
Patient_ID Number(9) primary key,
First_name varchar2(15),
Last_name varchar2(10),
Contact number(10),
City varchar2(20),
Doctor_ID Number(9) references Doctor(Doctor_ID)
);
This is the insert statement:
insert into patient (Patient_ID, First_name, Last_name, Contact, City, Doctor_ID) values ('21345', 'John', 'Smith', '1111111111', 'NY', '30111');

Try :
insert into patient (Patient_ID, First_name, Last_name, Contact, City, Doctor_ID) values (21345, 'John', 'Smith', 1111111111, 'NY', 30111);
Don't use quotes for numbers.

Related

Inserting multiple rows into table - getting error ORA-00933: SQL command not properly ended

create table employee (
employee_id number (5),
first_name varchar2(100),
last_name varchar2(100),
salary number (10),
department_id number(5),
hire_date date,
constraint pk_emp primary key (employee_id)
)
insert into employee (employee_id, last_name, salary )
values
(129, 'khaj', 19000),
(130, 'ravi', 20000);
enter image description here
Wrong syntax.
Either
insert into employee (employee_id, last_name, salary)
values (129, 'khaj', 19000);
insert into employee (employee_id, last_name, salary)
values (130, 'ravi', 20000);
or
insert into employee (employee_id, last_name, salary)
select 129, 'khaj', 19000 from dual union all
select 130, 'ravi', 20000 from dual;
or even
insert all
into employee (employee_id, last_name, salary) values (129, 'khaj', 19000)
into employee (employee_id, last_name, salary) values (130, 'ravi', 20000)
select * from dual;

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;

How do I quickly load a complex collection with nested tables in PL/SQL

Let's say I have a collection that contains nested tables:
CREATE TYPE address_type AS OBJECT (
address_code VARCHAR2(1),
address VARCHAR2(30),
city VARCHAR2(30),
state VARCHAR2(3),
zip VARCHAR2(10));
CREATE TYPE addresses_type AS TABLE OF address_type;
-- You can see here that the person may have multiple addresses (addrs)
CREATE TYPE person_type AS OBJECT (
personID NUMBER,
name VARCHAR2(30),
birthdate DATE,
gender VARCHAR2(1),
addrs addresses_type);
CREATE TYPE people_type as TABLE OF person_type;
If I had a PLSQL block and I wanted to create and load an object of people with their address from the tables below, what is the easiest way to do this? Would I have to perform multiple queries?
DECLARE
the_people people_type;
BEGIN
-- want to Query and load "the_people" with everybody in the tables below:
..
END;
Tables: Foreign key is PERSON_ID
PERSON
------
PERSON_ID
NAME
BIRTHDATE
GENDER
ADDRESSES
---------
PERSON_ID
ADDRESS_CODE
ADDRESS
CITY
STATE
ZIP
You can do it in one query:
CREATE TABLE person (
person_ID NUMBER,
name VARCHAR2(30),
birthdate DATE,
gender VARCHAR2(1)
);
CREATE TABLE addresses (
person_id NUMBER,
address_code VARCHAR2(1),
address VARCHAR2(30),
city VARCHAR2(30),
state VARCHAR2(3),
zip VARCHAR2(10)
);
INSERT INTO person VALUES (1, 'Brown', SYSDATE, 'M');
INSERT INTO person VALUES (2, 'Smith', SYSDATE, 'M');
INSERT INTO addresses VALUES (1, 'A', 'B', 'C', 'D', '1');
INSERT INTO addresses VALUES (1, 'A', 'BB', 'CC', 'DD', '1');
INSERT INTO addresses VALUES (2, 'B', 'E', 'F', 'G', '1');
COMMIT;
DECLARE
the_people people_type;
BEGIN
SELECT
person_type(
person_id,
name,
birthdate,
gender,
(SELECT CAST(MULTISET (
SELECT
address_code,
address,
city,
state,
zip
FROM addresses
WHERE person_id = p.person_id) AS addresses_type
)
FROM dual
)
)
BULK COLLECT INTO the_people
FROM
person p
;
dbms_output.put_line(the_people.COUNT);
dbms_output.put_line(the_people(1).name);
dbms_output.put_line(the_people(1).addrs(1).address);
dbms_output.put_line(the_people(1).addrs(2).address);
dbms_output.put_line(the_people(2).name);
dbms_output.put_line(the_people(2).addrs(1).address);
END;
Sample output produced by the block to test if the solution works:
2
Brown
B
BB
Smith
E

detecting if a part of a string matches another string

hi guys this is the question:
Display the employee ID and email of employees whose email address has their full last name in it.
what do you think can I use? Can I use substr? if not, any other suggestions? Thanks guys peace!
I'd use regular expressions, for example
CREATE TABLE employees (
emp_id NUMBER PRIMARY KEY,
first_name VARCHAR2(30),
last_name VARCHAR2(30),
email VARCHAR2(255)
);
INSERT INTO employees VALUES (1, 'Joseph', 'Ratzinger', 'benedictxvi#vatican.va');
INSERT INTO employees VALUES (2, 'Tim', 'Cook', 'tcook#apple.com');
INSERT INTO employees VALUES (3, 'Larry', 'Ellison', 'Ellison#oracle.com');
INSERT INTO employees VALUES (4, 'Michael', 'Dell', 'Michael#dell.com');
SELECT emp_id, email FROM employees WHERE regexp_like(email, last_name);
3 Ellison#oracle.com
To include case independent results, use:
SELECT emp_id, email FROM employees WHERE regexp_like(email, last_name, 'i');
2 tcook#apple.com
3 Ellison#oracle.com
4 Michael#dell.com
If you need to exclude the hostname, either append an '#' to the pattern ...
SELECT emp_id, email FROM employees WHERE regexp_like(email, last_name||'#', 'i');
2 tcook#apple.com
3 Ellison#oracle.com
... or extract the hostname from the email:
SELECT emp_id, email
FROM employees
WHERE regexp_like(regexp_substr(email,'.*#'), last_name, 'i');

How to Duplicate multiple rows (Oracle)

I'm trying to make a Procedure that will duplicate multiple rows of a table (or only one single row) and incrementing the ID for each row insertion.
My problem is that inside my procedure I used a cursor to select the rows to duplicate, when i select all rows without WHERE condition in that cursor everything works fine.
But when i set a WHERE condition to select only one row... nothing happens
Here is my procedure
CREATE OR REPLACE PROCEDURE DuplicateEmployee (p_EmployeeID IN Employee.id%TYPE)
AS
p_New_EmployeeID Employee.id%TYPE;
CURSOR c_DuplicateEmployee IS
SELECT *
FROM Employee
WHERE Employee.id = p_EmployeeID; -- if this line is deleted all content is duplicated
row_Employee c_DuplicateEmployee%ROWTYPE;
BEGIN
FOR myEmployee IN c_DuplicateEmployee LOOP
p_New_EmployeeID := employee_seq.NEXTVAL;
INSERT INTO Employee(id, first_name, last_name, start_date, end_date, salary, city, description)
VALUES(p_New_EmployeeID, myEmployee.first_name, myEmployee.last_name, myEmployee.start_date, myEmployee.end_date, myEmployee.salary, myEmployee.city, myEmployee.description);
END LOOP;
COMMIT;
END DuplicateEmployee;
I know in this example having a procedure selecting a primary key to duplicate is pointless but in my production base it will be used to select a Foreign key.
Bellow is the code require to create a the test table and SEQUENCE I used for this procedure
CREATE TABLE Employee
(
ID VARCHAR2(4 BYTE) NOT NULL,
First_Name VARCHAR2(10 BYTE),
Last_Name VARCHAR2(10 BYTE),
Start_Date DATE,
End_Date DATE,
Salary NUMBER(8,2),
City VARCHAR2(10 BYTE),
Description VARCHAR2(15 BYTE)
);
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('01', 'Jason', 'Martin', to_date('19960725','YYYYMMDD'), to_date('20060725','YYYYMMDD'), 1234.56, 'Toronto', 'Programmer');
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('02', 'Alison', 'Mathews', to_date('19760321','YYYYMMDD'), to_date('19860221','YYYYMMDD'), 6661.78, 'Vancouver', 'Tester');
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('03', 'James', 'Smith', to_date('19781212','YYYYMMDD'), to_date('19900315','YYYYMMDD'), 6544.78, 'Vancouver', 'Tester');
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('04', 'Celia', 'Rice', to_date('19821024','YYYYMMDD'), to_date('19990421','YYYYMMDD'), 2344.78, 'Vancouver', 'Manager');
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('05', 'Robert', 'Black', to_date('19840115','YYYYMMDD'), to_date('19980808','YYYYMMDD'), 2334.78, 'Vancouver', 'Tester');
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('06', 'Linda', 'Green', to_date('19870730','YYYYMMDD'), to_date('19960104','YYYYMMDD'), 4322.78, 'New York', 'Tester');
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('07', 'David', 'Larry', to_date('19901231','YYYYMMDD'), to_date('19980212','YYYYMMDD'), 7897.78, 'New York', 'Manager');
INSERT
INTO Employee
(ID, First_Name, Last_Name, Start_Date, End_Date, Salary, City, Description)
VALUES
('08', 'James', 'Cat', to_date('19960917','YYYYMMDD'), to_date('20020415','YYYYMMDD'), 1232.78, 'Vancouver', 'Tester');
Here for the Sequence that will manage Primary key (ID)
CREATE SEQUENCE "TEST"."EMPLOYEE_SEQ" MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE ORDER NOCYCLE ;
And here the code to execute the procedure
BEGIN
employeepackage.duplicateemployee(5);
END;
I really don't understand why it doesn't properly work for a single row when it's working to plicate all rows ? It there a limitation for cursors having less than 2 rows ?
Any help would be much appreciated ;)
Why do you need a cursor? You can do this with SQL directly:
INSERT INTO Employee(id, first_name, last_name,
start_date, end_date,
salary, city, description)
SELECT employee_seq.NEXTVAL, e.first_name, e.last_name,
e.start_date, e.end_date,
e.salary, e.city, e.description
FROM Employee e
WHERE e.id = p_EmployeeID;
Anyway, the actual problem is that your ID is a VARCHAR2(4), whereas you think it is a NUMBER. You actually do not have an employee with ID = 5, but you do have one with ID = '05'. So without changing anything, your procedure already works:
BEGIN
employeepackage.duplicateemployee('05');
END;
Of course, it would make sense to change the data type of ID.
Solution from Lukas if fine for my first and last table that will not need to call others PROCEDURE to duplicate multiple children, though for intermediate table I used :
PROCEDURE Duplicate_Company (p_IdCity IN City.IdCity%TYPE) AS
p_New_IdCompany Company.IdCompany%TYPE;
CURSOR c_DuplicateCompany IS
SELECT *
FROM Company c
WHERE c.IdCity = p_IdCity;
row_Company c_DuplicateCompany%ROWTYPE;
BEGIN
FOR c1 IN c_DuplicateCompany LOOP
p_New_IdCompany := company_seq.NEXTVAL;
INSERT INTO Company(IdCompany, IdCity, Name, CreationDate)
VALUES(p_New_IdCompany, c1.IdCity, c1.Name, c1.CreationDate);
-- Call the procedure to duplicate current employee
Duplicate_Employee(c1.IdCompany);
END LOOP;
END Duplicate_Company;
Is it a good approach ?

Resources