PL/SQL insert record using max function - oracle

Create a PL/SQL block to insert a new record into the Department table. Fetch the maximum department id from the Department table and add 10 to it; take this value for department id; 'TESTING' is the value for department name and CHN-102 is the value for Location ID.
Note: Use '/' to terminate your query before compilation and evaluation
Table name : Department
Column name | Data type | Constraints
DEPARTMENT_ID | NUMBER(5) | PK
DEPARTMENT_NAME | VARCHAR2(25) | NOT NULL
LOCATION_ID | VARCHAR2(15)
Sample Output:
DEPARTMENT_ID DEPARTMENT_NAME LOCATION_ID
------------- --------------- -----------
XXXX TESTING CHN-102

The way you described it, it would look like this:
SQL> declare
2 l_department_id department.department_id%type;
3 l_department_name department.department_name%type := 'TESTING';
4 l_location_id department.location_id%type := 'CHN-102';
5 begin
6 select nvl(max(department_id), 10)
7 into l_department_id
8 from department;
9
10 insert into department (department_id, department_name, location_id)
11 values (l_department_id + 10, l_department_name, l_location_id);
12 end;
13 /
PL/SQL procedure successfully completed.
SQL> select * From department;
DEPARTMENT_ID DEPARTMENT_NAME LOCATION_I
------------- -------------------- ----------
20 TESTING CHN-102
SQL>
Note, though, that MAX + 10 is a wrong approach. If two (or more) users run the same procedure at the same time, only the first one who commits changes will be able to do that; other user(s) will violate the primary key constraint because that department_id already exists (as it was inserted moments ago by someone else). Use a sequence instead.

Related

ORA-01400: cannot insert NULL when inserting value into Oracle Database

When I try to insert into my employee table I'm getting an error:
INSERT INTO employee (department_id) VALUES (1)
Error report -
ORA-01400: cannot insert NULL into ("CYCLOPS"."EMPLOYEE"."ID")
Cyclops is my username that I've logged into the database as. I've created 2 tables. The employee table has a foreign key called department_id that refers to the department table id column.
Name Null? Type
------------- -------- ------------
ID NOT NULL NUMBER(5) -- That's the primary key
LAST_NAME VARCHAR2(20)
SALARY NUMBER
DEPARTMENT_ID NUMBER -- That's the foreign key to the department id column
This is my department table
Name Null? Type
--------------- -------- ------------
ID NOT NULL NUMBER
DEPARTMENT_NAME VARCHAR2(20)
This is a select all on my employee table:
id last_name salary
1 JONES 20000
2 SMITH 35000
3 KING 40000
4 SIMPSON 52000
5 ANDERSON 31000
This is a select all from the department table:
ID department_name
1 IT
2 HR
3 SALES
What I want to do is insert the department_id into the employee record so I can add him to a department. Why am I getting an error on this insert?
What I want to do is insert the department_id into the employee record so I can add him to a department. Why am I getting an error on this insert?
You don't need to insert a new record, you need to update an existing record.
With INSERT INTO employee (department_id) VALUES (1) you create a new row where only the columns mentioned (in this case department_id) get values, all others are given null.
As your column ID is defined as NOT NULL, it throws an exception.
If you want to change your existing data, you need to update a record like
UPDATE employee SET department_id = 1 WHERE id = 1;
UPDATE employee SET department_id = 2 WHERE id = 3;
Which will get you
id last_name salary department_id
1 JONES 20000 1
2 SMITH 35000 (null)
3 KING 40000 2
4 SIMPSON 52000 (null)
5 ANDERSON 31000 (null)
To be honest, it says pretty clear what is happening.
The "employee" table has the ID non-nullable column
ID NOT NULL NUMBER(5)
It means it's value can't be set to null
The command
INSERT INTO employee (department_id) VALUES (1)
will insert 1 to department_id and will try to populate every other column with null.
You need to provide id at least in order for making it work
INSERT INTO employee (id, department_id) VALUES (1, 1);

How to create a unique id for an existing table in PL SQL?

The situation is that, when I import a file into the database, one of the first thing I usually do is to assign an unique ID for each record.
I normally do below in TSQL
ALTER TABLE MyTable
ADD ID INT IDENTITY(1,1)
I am wondering if there is something similar in PL SQL?
All my search result come back with multiple steps.
Then I'd like to know what PL SQL programmer typically do to ID records after importing a file. Do they do that?
The main purpose for me to ID these records is to trace it back after manipulation/copying.
Again, I understand there is solution there, my further question is whether PL SQL programmer actually do that, or there is other alternative which making this step not necessary in PL SQL?
OK then, as you're on Oracle 11g, there's no identity column there so - back to multiple steps. Here's an example:
I'm creating a table that simulates your imported table:
SQL> create table tab_import as
2 select ename, job, sal
3 from emp
4 where deptno = 10;
Table created.
Add the ID column:
SQL> alter table tab_import add id number;
Table altered.
Create a sequence which will be used to populate the ID column:
SQL> create sequence seq_imp;
Sequence created.
Update current rows:
SQL> update tab_import set
2 id = seq_imp.nextval;
3 rows updated.
Create a trigger which will take care about future inserts (if any):
SQL> create or replace trigger trg_bi_imp
2 before insert on tab_import
3 for each row
4 begin
5 :new.id := seq_imp.nextval;
6 end;
7 /
Trigger created.
Check what's in the table at the moment:
SQL> select * from tab_import;
ENAME JOB SAL ID
---------- --------- ---------- ----------
CLARK MANAGER 2450 1
KING PRESIDENT 5000 2
MILLER CLERK 1300 3
Let's import some more rows:
SQL> insert into tab_import (ename, job, sal)
2 select ename, job, sal
3 from emp
4 where deptno = 20;
3 rows created.
The trigger had silently populated the ID column:
SQL> select * From tab_import;
ENAME JOB SAL ID
---------- --------- ---------- ----------
CLARK MANAGER 2450 1
KING PRESIDENT 5000 2
MILLER CLERK 1300 3
SMITH CLERK 800 4
JONES MANAGER 2975 5
FORD ANALYST 3000 6
6 rows selected.
SQL>
Shortly: you need to
alter table and add the ID column
create a sequence
create a trigger
The end.
The answer given by #Littlefoot would be my recommendation too - but still I thought I could mention the following variant which will work only if you do not intend to add more rows to the table later.
ALTER TABLE MyTable add id number(38,0);
update MyTable set id = rownum;
commit;
My test:
SQL> create table tst as select * from all_tables;
Table created.
SQL> alter table tst add id number(38,0);
Table altered.
SQL> update tst set id = rownum;
3815 rows updated.
SQL> alter table tst add constraint tstPk primary key (id);
Table altered.
SQL>
SQL> select id from tst where id < 15;
ID
----------
1
2
3
4
5
6
7
8
9
10
11
ID
----------
12
13
14
14 rows selected.
But as mentioned initially,- this only fixes numbering for the rows you have at the time of the update - your'e not going to get new id values for new rows anytime later - if you need that, go for the sequence solution.
You can add an id column to a table with a single statement (Oracle 11g, see dbfiddle):
alter table test_
add id raw( 16 ) default sys_guid() ;
Example:
-- create a table without an id column
create table test_ ( str )
as
select dbms_random.string( 'x', 16 )
from dual
connect by level <= 10 ;
select * from test_ ;
STR
ULWL9EXFG6CIO72Z
QOM0W1R9IJ2ZD3DW
YQWAP4HZNQ57C2UH
EETF2AXD4ZKNIBBF
W9SECJYDER793MQW
alter table test_
add id raw( 16 ) default sys_guid() ;
select * from test_ ;
STR ID
ULWL9EXFG6CIO72Z 0x782C6EBCAE2D7B9FE050A00A02005D65
QOM0W1R9IJ2ZD3DW 0x782C6EBCAE2E7B9FE050A00A02005D65
YQWAP4HZNQ57C2UH 0x782C6EBCAE2F7B9FE050A00A02005D65
EETF2AXD4ZKNIBBF 0x782C6EBCAE307B9FE050A00A02005D65
W9SECJYDER793MQW 0x782C6EBCAE317B9FE050A00A02005D65
Testing
-- Are the id values unique and not null? Yes.
alter table test_
add constraint pkey_test_ primary key ( id ) ;
-- When we insert more rows, will the id be generated? Yes.
begin
for i in 1 .. 100
loop
insert into test_ (str) values ( 'str' || to_char( i ) ) ;
end loop ;
end ;
/
select * from test_ order by id desc ;
-- last 10 rows of the result
STR ID
str100 0x782C806E16A5E998E050A00A02005D81
str99 0x782C806E16A4E998E050A00A02005D81
str98 0x782C806E16A3E998E050A00A02005D81
str97 0x782C806E16A2E998E050A00A02005D81
str96 0x782C806E16A1E998E050A00A02005D81
str95 0x782C806E16A0E998E050A00A02005D81
str94 0x782C806E169FE998E050A00A02005D81
str93 0x782C806E169EE998E050A00A02005D81
str92 0x782C806E169DE998E050A00A02005D81
str91 0x782C806E169CE998E050A00A02005D81
Regarding your other questions:
{1} Then I'd like to know what PL SQL programmer typically do to ID records after importing a file. Do they do that? The main purpose for me to ID these records is to trace it back after manipulation/copying.
-> As you know, the purpose of an id is: to identify a row. We don't "do anything to IDs". Thus, your usage of IDs seems legit.
{2} Again, I understand there is solution there, my further question is whether PL SQL programmer actually do that, or there is other alternative which making this step not necessary in PL SQL?
-> Not quite sure what you are asking here. Although there is a ROWID() pseudocolumn (see documentation), we should not use it to identify rows.
"You should not use ROWID as the primary key of a table. If you delete
and reinsert a row with the Import and Export utilities, for example,
then its rowid may change. If you delete a row, then Oracle may
reassign its rowid to a new row inserted later."

Number data type column is not behaving as number

I have a table in oracle which has column recid which is of number Datar type. The table is partition table and it has partition index on it.
When I query the partition like
select * from table partition (abc)
I am able to see value for rec id =50. But when I query
select * from table partition(abc) where rec id =50,
It doesn’t give any record .
If I do type casting as
select * from table partition(abc) where cast (recid as number ) =50
I am getting records.
Please let me know what might be the issue .?
The issue exist only for one partition and rest of the partition working normal.
If it's not behaving as a number, then it's not stored as a number.
Run a DESCRIBE (DESC) on your table in either SQL Developer, SQLcl, or SQL*Plus. It will show how the REC_ID column is defined.
If it's stored as a VARCHAR2, you wil get an error on your WHERE CLAUSE predicate for REC_ID, if not every REC_ID could be treated as also a number:
ORA-01722: invalid number
Like so:
SQL> DESC employees
Name Null? Type
EMPLOYEE_ID NOT NULL NUMBER(6)
FIRST_NAME VARCHAR2(20)
LAST_NAME NOT NULL VARCHAR2(25)
EMAIL NOT NULL VARCHAR2(25)
PHONE_NUMBER VARCHAR2(20)
HIRE_DATE NOT NULL DATE
JOB_ID NOT NULL VARCHAR2(10)
SALARY NUMBER(8,2)
COMMISSION_PCT NUMBER(2,2)
MANAGER_ID NUMBER(6)
DEPARTMENT_ID NUMBER(4)
SQL>
SQL> SELECT * FROM employees WHERE first_name = 50;
Error starting at line : 4 in command -
SELECT * FROM employees WHERE first_name = 50
Error report -
ORA-01722: invalid number
SQL> select * from emps_copy_num where first_name = 50;
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL PHONE_NUMBER HIRE_DATE JOB_ID SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
100 50 King SKING 515.123.4567 17-JUN-87 AD_PRES 24000 90
The first query fails - because not every value in that column can be simplicity cast as a number by the database.
The second query works, because I created a copy of the table where all of the first_name strings were values that COULD be cast as a number.
You probably have spaces in there somewhere, eg
SQL> create table t ( should_have_been_numeric varchar2(30));
Table created.
SQL>
SQL> insert into t values ('50 ');
1 row created.
SQL> insert into t values (' 50 ');
1 row created.
SQL> insert into t values (' 50');
1 row created.
SQL>
SQL> select * from t where should_have_been_numeric = '50';
no rows selected
SQL> select * from t where cast(should_have_been_numeric as number) = 50;
SHOULD_HAVE_BEEN_NUMERIC
------------------------------
50
50
50
3 rows selected.
but as already mentioned, if you are treating strings as numbers, then there is problems ahead in terms of spurious errors, not to mention potential performance issues because the optimizer also doesn't know that these are really numbers.

Combining two stored procedures into a single one using some joins

I am very new to Oracle; I have written two stored procedures where they have both different parameters. I would like to combine the queries in that two stored procedures into single query in a single stored procedure, and make sure it supports any criteria.
These are the stored procedures:
procedure usp_testsp1(RC1 OUT RCT1,
in_dep_Id IN number,
in_Org_id IN number,
in_emp_no IN number)
is
begin
select emp.Name as name,select emp.phone as phone,select emp.Race as
race
from employee emp
JOIN
Project prj ON
emp.ProjectId=prj.ProjectId
JOIN Project_Org Prorg
ON prj.ProjectId=Prorg.ProjectId
JOIN Organization Org1
ON Prorg.OrgId=Org1.OrgId
JOIN Organization Org2
ON emp.OrgId=Org2.OrgId
AND Org2.OrgType=0
WHERE (upper(emp.emp_No) in (in_emp_No ))
AND Prorg.OrgId=in_Org_id
AND Org2.OrgId=in_dep_Id
end;
procedure usp_testsp2(RC1 OUT RCT1,
in_dep_Id IN number,
in_Org_id IN number,
in_vendor_id IN raw,
in_vendor_startdate IN date,
in_vendor_enddate IN date)
is
begin
OPEN RC1 FOR
select emp.Name as name,select emp.phone as phone,select emp.Race as
race
from
from employee emp
JOIN
Project prj ON
emp.ProjectId=prj.ProjectId
JOIN Project_Org Prorg
ON prj.ProjectId=Prorg.ProjectId
JOIN Organization Org1
ON Prorg.OrgId=Org1.OrgId
JOIN Organization Org2
ON emp.OrgId=Org2.OrgId
AND Org2.OrgType=0
INNER JOIN vendor_Emp
ON emp.employeeid=vendor_emp.employeeid
INNER JOIN Vendor
ON Vendor.VendorId=Vendor_emp.VendorId
WHERE Prorg.OrgId=in_Org_id
AND Org2.OrgId=in_dep_Id
AND Vendor.VendorId=in_vendor_id
AND vendor.StartDate=in_vendor_startdate AND Vendor.EndDate=in_vendor_enddate
end;
My objective is to combine the queries within these two separate procedures into a single query such that if I combine all the parameters, I have in_emp_no, in_vendor_id, in_vendor_startdate, in_vendor_enddate apart from the common parameters any of the parameters can be null and I want to make sure that those things won't affect the rest of the query even though its not null
For ex i have only in_emp_no ='xxxx' and common inputs rest of the params like
in_vendor_id etc is null.
I would like to make my query to work even with single paramter to filter the result set
NOTEWithout using Dynamic SQL
Thanks
BJ
You can make columns in the query behave as optional, as far as your join's go, you may need to play with various combinations to make sure everything works.
Sample Table
create table sqltest (
empid number,
name varchar2(10),
orgid number,
depid number,
vendorid number);
insert into sqltest values(1,'BoB',1,1,21);
insert into sqltest values(2,'Chuck',1,1,21);
insert into sqltest values(3,'Mary',1,2,21);
insert into sqltest values(4,'Jane',1,2,22);
insert into sqltest values(5,'Rick',2,1,22);
insert into sqltest values(6,'Samir',2,6,23);
insert into sqltest values(7,'Kirk',3,6,23);
insert into sqltest values(8,'Alex',3,9,23);
commit;
Sample Proc
create or replace procedure calltest (
rc1 out SYS_REFCURSOR,
pempid number,
porgid number,
pdepid number,
pvendorid number)
is
begin
open rc1 for
select * from sqltest
where
(pempid IS NULL OR empid = pempid) and
(porgid IS NULL OR orgid = porgid) and
(pdepid IS NULL OR depid = pdepid) and
(pvendorid IS NULL OR vendorid = pvendorid);
end;
Sample Call
set autoprint on;
var vcur refcursor;
declare
begin
calltest(rc1=>:vcur,pempid=>NULL,porgid=>1,pdepid=>NULL,pvendorid=>NULL);
--calltest(rc1=>:vcur,pempid=>NULL,porgid=>1,pdepid=>2,pvendorid=>NULL);
--calltest(rc1=>:vcur,pempid=>NULL,porgid=>1,pdepid=>2,pvendorid=>22);
--calltest(rc1=>:vcur,pempid=>NULL,porgid=>NULL,pdepid=>NULL,pvendorid=>23);
end;
Sample Output 1
VCUR
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
1 BoB 1 1 21
2 Chuck 1 1 21
3 Mary 1 2 21
4 Jane 1 2 22
Sample Output 2
VCUR
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
3 Mary 1 2 21
4 Jane 1 2 22
Sample Output 3
VCUR
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
4 Jane 1 2 22
Sample Output 4
VCUR
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EMPID NAME ORGID DEPID VENDORID
--------------------------------------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
6 Samir 2 6 23
7 Kirk 3 6 23
8 Alex 3 9 23

How to update One table column values with another table's column values? [duplicate]

This question already has answers here:
Update rows in one table with data from another table based on one column in each being equal
(5 answers)
Closed 9 years ago.
i have table called Student with columns uniquename, age,department,city,Homecountry and another table called Employee with columns uniquename, exp,qualification, Homecountry.
now i want to update Student table's department column with Employee table's qualification column values under the where condition Student.uniquename = Employee.uniquename and Student.Homecountry = Employee.Homecountry.
please help me to write the update statement.
This kind of query is called a correlated sub query. For your requirement, the query would be as below....
update students s
set s.department = (
select e.qualification
from employee e
where s.uniquename = e.uniquename
and s.Homecountry = e.Homecountry
);
updating this post based on your replies below.
Again, going forward, always post the create table and insert statements (and the expected results) to reproduce your case. If you don't see the expected results or if you see an erro when you execute the query, post the exact message instead of just saying "not working". Here is the results of my sqlplus session.
---create table and insert statements
create table student(
name varchar2(20),
age number,
department varchar2(3),
HomeCountry varchar2(10)
);
Table created.
create table employee5(
name varchar2(20),
exp number,
qualification varchar2(3),
homecountry varchar2(10)
);
Table created.
insert into student values ('Mohan',25,'EEE','India');
insert into student values ('Raja',27,'EEE','India');
insert into student values ('Ahamed',26,'ECE','UK');
insert into student values ('Gokul',25,'IT','USA');
commit;
insert into employee5 values ('Mohan',25,'ECE','India');
insert into employee5 values ('Raja',24,'IT','India');
insert into employee5 values ('Palani',26,'ECE','USA');
insert into employee5 values ('Sathesh',29,'CSE','CANADA');
insert into employee5 values ('Ahamed',28,'ECE','UK');
insert into employee5 values ('Gokul',29,'EEE','USA');
commit;
Before updating the data...
SQL> select * from student;
NAME AGE DEP HOMECOUNTR
-------------------- ---------- --- ----------
Mohan 25 EEE India
Raja 27 EEE India
Ahamed 26 ECE UK
Gokul 25 IT USA
SQL> select * from employee5;
NAME EXP QUA HOMECOUNTR
-------------------- ---------- --- ----------
Mohan 25 ECE India
Raja 24 IT India
Palani 26 ECE USA
Sathesh 29 CSE CANADA
Ahamed 28 ECE UK
Gokul 29 EEE USA
Update statement and results
1 update student s set s.age =
2 ( select e.exp
3 from employee5 e
4 where e.name = s.name
5 and e.homecountry = s.homecountry
6* )
SQL> /
4 rows updated.
SQL> select * from student;
NAME AGE DEP HOMECOUNTR
-------------------- ---------- --- ----------
Mohan 25 EEE India
Raja 24 EEE India
Ahamed 28 ECE UK
Gokul 29 IT USA
SQL> commit;
Commit complete.
update student s
set s.age = (select e.exp
from employee5 e
where e.name = s.name
and e.homecountry = s.homecountry
and rownum < 2
)
where s.age in (select age from employee5)
It wont show the message subquery returns more than one record

Resources