Error: ORA-00937 - plsql

I want to create a table NEW_DEPTS. I have DEPARTMENT_ID and DEPARTMENT_NAME which is in DEPARTMENTS table.
desc departments
Name Null? Type
------------------------------- -------- ----
DEPARTMENT_ID NOT NULL NUMBER(4)
DEPARTMENT_NAME NOT NULL VARCHAR2(30)
MANAGER_ID NUMBER(6)
LOCATION_ID NUMBER(4)
My EMPLOYEES table contains:
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)
Now, I want to create a table NEW_DEPTS which should contain DEPARTMENT_ID and DEPARTMENT_NAME along with total SALARY that each Department has. Every department have certain number of employees, so, for department number 10, 20, 30, and so on, total Salary should be calculated.
My main query is:
create table new_depts as
select d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id;
I got an Error:
select d.department_id,d.department_name,sum(e.salary) dept_sal
*
ERROR at line 2:
ORA-00937: not a single-group group function
So, I googled it. I found that group function like sum, avg, max, min can't be used in select statement. I needed GROUP BY clause. So, I wanted to solve it individually. Therefore, I skipped the "create table..." statement and wrote:
select distinct d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id
group by department_id;
I got Error:
group by department_id;
*
ERROR at line 4:
ORA-00911: invalid character
Then I wrote:
select d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id
group by d.department_id;
I got Error:
select d.department_id,d.department_name,sum(e.salary) dept_sal
*
ERROR at line 1:
ORA-00979: not a GROUP BY expression
Then I wrote:
select d.department_id,d.department_name,sum(e.salary) dept_sal
from employees e,departments d
where e.department_id = d.department_id
group by department_id;
I got Error:
group by department_id
*
ERROR at line 4:
ORA-00918: column ambiguously defined
I know that its a "join". But not getting how should I place GROUP BY clause so that my GROUP FUNCTION may run correctly.

You need to group by all columns not in an aggregate function and since you have defined a table alias you must use that in your columns. The error ORA-00918: column ambiguously defined is because you have two columns named department_id so you must specify the table the department_id is from:
select d.department_id,
d.department_name,
sum(e.salary) dept_sal
from employees e
inner join departments d
on e.department_id = d.department_id
group by d.department_id, d.department_name;
You will notice that I altered the query to use ANSI JOIN syntax (INNER JOIN).

Related

Check if rows were selected PLSQL

Well I have a procedure were I add two the salary of two employees. I get the salary with the id of the employee. If the employee was not found I should set the salary to 0. This is my code
PROCEDURE private_salaries(
sal_res OUT NUMBER,
emp_1 NUMBER,
emp_2 NUMBER)
IS
sal_1 NUMBER;
sal_2 NUMBER;
BEGIN
SELECT salary INTO sal_1 FROM employees WHERE employee_id = emp_1;
SELECT salary INTO sal_2 FROM employees WHERE employee_id = emp_2;
END;
The procedure can be simplified as below,
create or replace PROCEDURE private_salaries(
emp_1 NUMBER,
emp_2 NUMBER,
sal_res out NUMBER)
is
begin
select sal1 + sal2 into sal_res
from
(
select
nvl((SELECT salary FROM employees WHERE employee_id = emp_1),0) sal1,
nvl((SELECT salary FROM employees WHERE employee_id = emp_2),0) sal2
from dual);
end;
Test Cases :
When both of them exists - Returns sum of the salary
When either one doesn't exists - Returns salary of one that exists
When none of them exists - Returns zero.
Recommendation - Use function instead of procedure and you may use them in SQL,for procedure a PL/SQL block is required though.

sqlite not returning values selected from table not in other table

I have two tables whose relevant columns look more or less like the following:
table1.id:
zIXuJeY-qH
zJrcULGLXK
zXyIgnlylb
zZ7MYDGDAV
zbCFI4wKpe
ziGeauO-0O
zmzWbaGSb7
table2.id
zIXuJeY-qH
zIXuJeY-qH
zIXuJeY-qH
zIXuJeY-qH
zJrcULGLXK
zJrcULGLXK
in which table1.id is a primary key and table2.id is not a primary key. I'm trying to grab all the IDs from table 1 that are not in table 2, but am having trouble. If, for instance, I select a count of all the values that are in table two, I get:
>SELECT COUNT(id) FROM table1 WHERE id IN (SELECT id FROM table2);
>2
But if I try to find the IDs not in table2, I get 0:
>SELECT COUNT(id) FROM table1 WHERE id NOT IN (SELECT id FROM table2);
>
There are 503 unique IDs in table1 and only 163 in table2. What am I doing wrong?
I suppose there can be nulls in table2.id?
NOT IN ( ..., null, ...)
does never result in true unfortunately (because - so the argumentation - null is the unknown value, and we cannot guarantee that the unknown value is not the value you are looking for obviously). A bad trap.
Try
SELECT COUNT(id) FROM table1 WHERE id NOT IN (SELECT id FROM table2 where id is not null);
or an EXISTS clause instead.

Substitution Variable: Specifying Column Names, Expressions, and Text

When I type & execute this query in PL/SQL Developer:
select employee_id, first_name, last_name, job_id, &column_name
from employees WHERE &condition ORDER BY &order_column
I got the error message:
ORA-00936:missing expression.
Although when I execute this query, variables field prompt up on my screen with three field names respectively column_name, condition and order_column.
After entering the values in the above three fields respectively-- salary, >10000, employee/-id When I click ok, I get the above mentioned error message.
Can anyone please help to sort out this issue?
If you try to run your query in SQLPlus, it will show you how your query is transformed by the usage of the values you give to the variables:
SQL> select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column;
Enter value for column_name: salary
Enter value for condition: >1000
Enter value for order_column: employee/-id
old 1: select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column
new 1: select employee_id, first_name, last_name, job_id, salary from employees WHERE >1000 ORDER BY employee/-id
select employee_id, first_name, last_name, job_id, salary from employees WHERE >1000 ORDER BY employee/-id
*
ERROR at line 1:
ORA-00936: missing expression
So, your query becomes the following:
select employee_id, first_name, last_name, job_id, salary from employees
WHERE >1000 ORDER BY employee/-id
which is obviously wrong.
You need to give a well format condition ( for example salary > 1000) and to use the right column identifiers for the ORDER BY clause ( say employee_id); for example:
SQL> select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column;
Enter value for column_name: salary
Enter value for condition: salary > 10000
Enter value for order_column: employee_id
old 1: select employee_id, first_name, last_name, job_id, &column_name from employees WHERE &condition ORDER BY &order_column
new 1: select employee_id, first_name, last_name, job_id, salary from employees WHERE salary > 10000 ORDER BY employee_id
EMPLOYEE_ID FIRST_NAME LAST_NAME JOB_ID SALARY
----------- -------------------- ------------------------- ---------- ----------
100 Steven King AD_PRES 24000
101 Neena Kochhar AD_VP 17000
...
15 rows selected.
SQL>
Is that your column name? employee/-id? That may be part of your problem here.
Basically using anything different than:
Alphabets
Numbers (not at start of the column name)
Underscore (_)
is not recommended as it is not a good way to name fields and some datasources might throw errors on other characters.

how to do you assign an anonymous variable to a column in plsql?

I am trying to assign an input variable into pl/sql.
I want to query the database by letting the user input department_id and outputs the first name, last name, and salary. The salary is second highest salary in the table.
declare
v_dept_id int;
Begin
Select emp1.first_name, emp1.last_name, emp1.salary, emp1.department_id
From employees emp1
Where (1) =
(select count(distinct(emp1.salary))
From employees emp2
Where emp2.salary > emp1.salary) ;
End;
clarification
EDIT: I edited the code to include V_dept_id however it doesnt run
declare
v_dept_id int;
Begin
Select emp1.first_name, emp1.last_name, emp1.salary, emp1.department_id
into v_dept_id
From employees emp1
Where ((1) =
(select count(distinct(emp1.salary))
From employees emp2
Where emp2.salary > emp1.salary)) and v_dept_id = '&Enter_dept_id' ;
End;
error:
Error starting at line : 4 in command -
declare
v_dept_id int;
Begin
Select emp1.first_name, emp1.last_name, emp1.salary, emp1.department_id
into v_dept_id
From employees emp1
Where ((1) =
(select count(distinct(emp1.salary))
From employees emp2
Where emp2.salary > emp1.salary)) and v_dept_id = '&Enter_dept_id' ;
End;
Error report -
ORA-06550: line 6, column 16:
PL/SQL: ORA-00947: not enough values
ORA-06550: line 5, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Edit2 based on answer below feedback with the error
I don't know how to let the enter a number into the prompt correctly
declare
v_dept_id number;
v_fname varchar(50);
v_lname varchar(50);
v_salary NUMBER(8,2);
Begin
Select emp1.department_id, emp1.first_name, emp1.last_name, emp1.salary
into v_dept_id, v_fname, v_lname, v_salary
From employees emp1
Where ((1) =
(select count(distinct(emp1.salary))
From employees emp2
Where emp2.salary > emp1.salary)) and v_dept_id = '&Enter_dept_id' ;
End;
Error starting at line : 1 in command -
declare
v_dept_id number;
v_fname varchar(50);
v_lname varchar(50);
v_salary NUMBER(8,2);
Begin
Select emp1.department_id, emp1.first_name, emp1.last_name, emp1.salary
into v_dept_id, v_fname, v_lname, v_salary
From employees emp1
Where ((1) =
(select count(distinct(emp1.salary))
From employees emp2
Where emp2.salary > emp1.salary)) and v_dept_id = '&Enter_dept_id' ;
End;
Error report -
ORA-01403: no data found
ORA-06512: at line 8
01403. 00000 - "no data found"
*Cause: No data was found from the objects.
*Action: There was no data from the objects which may be due to end of fetch.
Raj_Te has explained why your code will not compile. But I don't much like your method of retrieving the second highest salary. I guess your method works but it's not clear what that section of code is trying to achieve.
In the following code the DENSE_RANK function will return the salary ranking of each row. Any rows that have the same salary will get the same rank :
SELECT
emp.first_name
,emp.last_name
,emp.salary
,emp.department_id
FROM
(SELECT
emp1.first_name
,emp1.last_name
,emp1.salary
,emp1.department_id
,DENSE_RANK() OVER (PARTITION BY emp1.department_id ORDER BY emp1.salary DESC) dr
FROM
employees emp1
WHERE emp1.department_id = &dept_id
) emp
WHERE 1=1
AND emp.dr = 2
;
By stating emp.dr = 2 we are saying we want all rows where the salary is ranked second highest.
You are selecting 4 fields in a single variable. Thats why its givng not enough values. You must decalre either 4 variables or create a records with 4 columns and then capture the values.
Select emp1.first_name, emp1.last_name, emp1.salary, emp1.department_id
into v_dept_id <--- trying to fetch 4 columns values to a single varibale.
You can decalre new variables of same datatype as of your selection and do it:
Select emp1.first_name, emp1.last_name, emp1.salary, emp1.department_id
into v_emp_first_nm,v_emp_last_nm ,v_emp_sal,v_dept_id

how to retrieve data from multiple colums from bulk collect

DECLARE
TYPE two_cols IS RECORD
(
family_id family_members.family_id %TYPE,
city family_members.city%TYPE
);
TYPE family_members_t IS TABLE OF two_cols;
l_family_members family_members_t;
BEGIN
SELECT family_id,city
BULK COLLECT INTO l_family_members
FROM (SELECT x.family_id, x.City, x.Member_count,row_number()
OVER (PARTITION BY x.family_id ORDER BY x.Member_count DESC) rn
FROM (SELECT family_id, City, COUNT(*) Member_count
FROM FAMILY_MEMBERS
GROUP BY family_id, City) x) y
WHERE y.rn = 1;
for rec in 1..l_family_members.count
loop
dbms_output.put_line('majority mem of family id'
|| l_family_members.family_id(rec)
|| 'stay in '||l_family_members.city(rec));
end loop;
END;
Error:
ORA-06550: line 23, column 69: PLS-00302: component 'FAMILY_ID' must
be declared ORA-06550: line 23, column 1: PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I am confused at the output line.. I am not getting how to retrieve data from bulk collect as there are two columns in it..how to distinguish them and retrieve them?
you are trying to select 2 columns into 1 record which doesn't work.
depending on your database version, you may be able to select records which then get bulk collected into a table as follows
DECLARE
TYPE two_cols IS RECORD
(
family_id family_members.family_id %TYPE,
city family_members.city%TYPE
);
TYPE family_members_t IS TABLE OF two_cols;
l_family_members family_members_t;
BEGIN
SELECT two_cols(family_id,city )
BULK COLLECT INTO l_family_members
FROM (SELECT x.family_id, x.City, x.Member_count,row_number()
OVER (PARTITION BY x.family_id ORDER BY x.Member_count DESC) rn
FROM (SELECT family_id, City, COUNT(*) Member_count
FROM FAMILY_MEMBERS
GROUP BY family_id, City) x) y
WHERE y.rn = 1;
for rec in 1..l_family_members.count
loop
dbms_output.put_line('majority mem of family id'
|| l_family_members(rec).family_id
|| 'stay in '||l_family_members(rec).city);
end loop;
END;
NB: I also fixed the reference in the output loop to put the (rec) after the table and before column

Resources