How to raise an exception when value is NULL - plsql

How can I raise an exception if loadid is null when I compare loadid = V_LOAD_ID?
E_NULL_ID is the exception which I then wanted to use.
Here is my procedure:
CREATE OR REPLACE PROCEDURE GET_INFO(P_CURDATE DATE)
AS
V_LOAD_ID CARSALES.LOADID%TYPE;
E_NULL_ID EXCEPTION;
BEGIN
-- Get load id from LoadIds table for current date.
SELECT LoadId
INTO V_LOAD_ID
FROM LoadIds
WHERE DateLoad = P_CURDATE;
-- Select brand name and total sales.
SELECT BrandName, SUM(Cost)
FROM CarSales Sales INNER JOIN
CarLables Lables ON Lables.CarBrandId = Sales.CarBrandId
WHERE LoadId = V_LOAD_ID
GROUP BY CarBrandId
EXCEPTION
WHEN E_NULL_ID THEN
DMBS.OUTPUT.PUT_LINE('No loadId found');
END;

First, your select statement is missing into clause, it should be something like:
SELECT BrandName, SUM(Cost)
into l_brand, l_sum
FROM CarSales Sales INNER JOIN
CarLables Lables ON Lables.CarBrandId = Sales.CarBrandId
WHERE LoadId = V_LOAD_ID;
Second, comparisons to null in Oracle always evaluate to FALSE, so the only way to detect that some of the LoadId is null is to check for null explicitly:
declare
...
l_nulls number;
begin
...
SELECT count(*) into l_nulls
FROM CarSales Sales INNER JOIN
CarLables Lables ON Lables.CarBrandId = Sales.CarBrandId
WHERE LoadId IS NULL;
if l_nulls > 0 then
raise E_NULL_ID;
end if;
...
end;

gosh there are a lot of ways to do that
here is one way, using raise_application_error, maybe it is not how you want to do it
it will throw an exception for sure but maybe you want to do something when it errors out
you might want to check if you get no rows (or too many rows) from your select by wrapping it in a begin-exception-end block?
CREATE OR REPLACE PROCEDURE GET_INFO(P_CURDATE DATE)
AS
V_LOAD_ID CARSALES.LOADID%TYPE;
E_NULL_ID EXCEPTION;
BEGIN
-- Get load id from LoadIds table for current date.
SELECT LoadId
INTO V_LOAD_ID
FROM LoadIds
WHERE DateLoad = P_CURDATE;
IF (V_LOAD_ID IS NULL) THEN
RAISE_APPLICATION_ERROR(-20001,'V_LOAD_ID is null');
END IF;
-- Select brand name and total sales.
SELECT BrandName, SUM(Cost)
-- you need an into here?
FROM CarSales Sales INNER JOIN
CarLables Lables ON Lables.CarBrandId = Sales.CarBrandId
WHERE LoadId = V_LOAD_ID
GROUP BY CarBrandId;
--EXCEPTION
-- WHEN E_NULL_ID THEN
-- DMBS.OUTPUT.PUT_LINE('No loadId found');
END;

Related

PLSQL STORED PROCEDURE does not give result

select count(*)
INTO countExceed
from uid_emp_master k
where k.unique_id in (select k.reviewer_uid
from uid_rm_hierarchy k
where k.unique_id in ('||p_ID_list||'))
and k.band IN( 'A','B','C','D');
if (countExceed > 0) then
quer :='UPDATE UID_RM_HIERARCHY I
SET I.REVIEWER_UID in (SELECT L.REVIEWER_UID
FROM UID_RM_HIERARCHY L
WHERE L.UNIQUE_ID in ('||p_ID_list||') )
WHERE I.REVIEWER_UID in('||p_ID_list||')
and isdeleted=0';
EXECUTE IMMEDIATE quer ;
END IF;
the above stored procedure does not show any result the variable countExceed declared as a number please help me to correct the query.
The issue is in
where k.unique_id in ('||p_ID_list||'))
Here you are saying to look for records
where unique_id = '||p_ID_list||'
exactly as its typed, but what you need is to handle that variable as a list of values.
Say you have a table like this
create table tabTest(id) as (
select 'id1' from dual union all
select 'id2' from dual union all
select 'id3' from dual union all
select 'id4' from dual
)
and your input string is 'id1,id3,1d8';
I see two ways to do what you need; one is with dynamic SQL, for example:
declare
vResult number;
vList varchar2(199) := 'id1,id3,1d8';
vSQL varchar2(100);
begin
vSQL :=
'select count(*)
from tabTest
where id in (''' || replace (vList, ',', ''', ''') || ''')';
--
execute immediate vSQL into vResult;
--
dbms_output.put_line('Result: ' || vResult);
end;
Another way could be by splitting the string into a list of values and then simply using the resulting list in the IN.
For that, there are many answers about how to split a comma separated list string in Oracle.

SQL Developer - Bind Variable "prmMediaDate" is Not Declared

I am running the below PL/SQL block in SQL Developer. I am getting the error Bind Variable "prmMediaDate" is Not Declared. Someone please tell what is missing here:
set serveroutput on;
/* RUN the following as a SCRIPT (F5) */
DECLARE
VARIABLE prmMediaDate varchar2(10);
VARIABLE prmSchdDiv varchar2(2);
VARIABLE prmSchdStore varchar2(4);
VARIABLE prmSchdAssoc varchar2(8);
BEGIN
select '07/17/2017' into :prmMediaDate FROM DUAL;
select '91' into :prmSchdDiv FROM DUAL;
select '91916559' into :prmSchdAssoc FROM DUAL;
SELECT
NVL(ODIV,LA.LABORLEV1NM) AS "schd_division"
,NVL(OLOC,LA.LABORLEV4NM) AS "schd_location"
,NVL(OZONE,LA.LABORLEV5NM) AS "schd_dept"
,NVL(O.ORGPATHTXT,LA.LABORLEV1NM||'-'||LA.LABORLEV4NM||'-'||LA.LABORLEV5NM) AS "orgpath_of_shift"
,SA.SHIFTASSIGNID AS "shiftassignid"
,SA.SHIFTCODEID AS "shiftcodeid"
,SA.ENTEREDONDTM AS "assignmnt_add_dtm"
,ST.ENTEREDONDTM AS "assignmnt_edit_dtm"
,CASE WHEN ST.ACTIONTYPEID IS NULL THEN SA.ENTEREDONDTM ELSE ST.ENTEREDONDTM END as "last_action_dt"
,ST.ACTIONTYPEID AS "last_action_cd"
,AT.SHORTNM AS "last_action_descr"
,SA.DELETEDSW AS "deletedsw"
,TRUNC(SA.SHIFTSTARTDATE) AS "shift_start_date"
,TRUNC(SA.SHIFTENDDATE) AS "shift_end_date"
,TO_CHAR(SA.SHIFTSTARTDATE, 'HH24:MI:SS') AS "shift_start_time"
,TO_CHAR(SA.SHIFTENDDATE, 'HH24:MI:SS') AS "shift_end_time"
,CASE SA.SHIFTTYPEID WHEN 1 THEN 'WORK SHIFT' WHEN 2 THEN 'UNAVAIL' WHEN 3 THEN 'HIDE SHFT' WHEN 4 THEN 'SCHD PAYCD EDIT' WHEN 5 THEN 'HIDE WRK SHFT' WHEN 6 THEN 'HIDE UNAVAIL DAY' ELSE 'UNDEFINED' END as "segment"
,NVL(LA.LABORLEV2DSC,'9999') AS "sell_nonsell"
,P.PERSONNUM AS "assoc_nbr"
,SA.ENTEREDONDTM AS "entered_on_dtm"
from PERSON P
JOIN SHIFTASSIGNMNT SA on SA.EMPLOYEEID = P.PERSONID
JOIN COMBHOMEACCT HA on (P.PERSONID = HA.EMPLOYEEID)
LEFT JOIN SHFTSEGORGTRAN SSOT on SSOT.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ORGX O on O.ORGIDSID = SSOT.ORGIDSID
LEFT JOIN SHFTASGNMNTTRC ST on ST.SHIFTASSIGNID = SA.SHIFTASSIGNID
LEFT JOIN ACTIONTYPE AT on AT.ACTIONTYPEID = ST.ACTIONTYPEID
LEFT JOIN LABORACCT LA on (LA.LABORACCTID = HA.LABORACCTID)
WHERE
TRUNC(SA.SHIFTSTARTDATE) = :prmMediaDate
AND :prmMediaDate BETWEEN HA.EFFECTIVEDTM AND (HA.EXPIRATIONDTM - 1)
AND ((:prmMediaDate BETWEEN O.EFFECTIVEDTM AND (O.EXPIRATIONDTM - 1)) OR (O.EFFECTIVEDTM IS NULL))
AND (SSOT.SEGMENTNUM = 1 OR SSOT.SEGMENTNUM IS NULL)
AND (TRUNC(SSOT.SHIFTSTARTDATE) = :prmMediaDate OR SSOT.SHIFTSTARTDATE IS NULL)
AND SA.DELETEDSW = 0
AND (O.ODIV = :prmSchdDiv OR LA.LABORLEV1NM = :prmSchdDiv)
AND P.PERSONNUM = :prmSchdAssoc;
end;
/
I have tried multiple options like declaring VARIABLE as var, set Scan ON etc.. But it didnt help.
You need to understand that declare is pl/sql and variable is part of sql*plus program commands.
So to successfully execute that code you need to remove DECLARE command.
Set Serveroutput On;
/* RUN the following as a SCRIPT (F5) */
--DECLARE
Variable Prmmediadate Varchar2(10);
Begin
Select '07/17/2017' Into :Prmmediadate From Dual;
End;
/
print :Prmmediadate
PL/SQL procedure successfully completed.
PRMMEDIADATE
--------------------------------------------------------------------------------
07/17/2017

oracle 11 :want to pass cursor variable to variable defined in procedure

Previously i used a temp table which created outside the procedure and inserted data in SP and used,,,but if i want to create a temp table inside procedure it throwing some errors..to avoid that trying to using cursor..
CREATE OR REPLACE PROCEDURE P_EMAIL_update
AS
I NUMBER := 1;
J NUMBER := 0;
ID NUMBER;
BEGIN
INSERT INTO ENTITY_TEMP --(RN,ENTITY_ID)
SELECT ROWNUM, e.id
FROM entity e, company c
WHERE e.companyid = c.id AND e.status = 3;
SELECT MAX (rn) INTO j FROM ENTITY_TEMP;
WHILE i <= j
LOOP
SELECT entity_id
INTO id
FROM ENTITY_TEMP
WHERE rn = i;
INSERT INTO ACTIONS_EMAIL_MAPPING (ID,
ISACTIVE,
ACTIONNAME,
EMAILFROM,
EMAILSUBJECT,
EMAILBODY
)
(SELECT SEQ_ENT.NEXTVAL,
'N',
ACTIONNAME,
EMAILFROM,
EMAILSUBJECT,
EMAILBODY || var_id
FROM ACTIONS
WHERE ISACTIVE = 'T' AND ACTIONNAME NOT IN ('sample'));
I := I + 1;
END LOOP;
END;
The procedure in your question could be rewritten more simply as:
CREATE OR REPLACE PROCEDURE p_email_update AS
BEGIN
INSERT INTO actions_email_mapping (id, isactive, actionname, emailfrom, emailsubject, emailbody)
SELECT seq_ent.nextval,
'N',
a.actionname,
a.emailfrom,
a.emailsubject,
a.emailbody || ent.id -- assuming var_id is a column of actions
FROM actions a
CROSS JOIN (SELECT e.id
FROM entity e
inner join company c on e.companyid = c.id
WHERE e.status = 3) ent -- maybe this should be an inner join with some join conditions?
WHERE a.isactive = 'T'
AND a.actionname NOT IN ('sample');
END p_email_update;
/
There is no need to reinvent a cross join (which is what your code was doing, in a very roundabout way). There is also no need to store the data in a temp table either, based on what you've told us in your question, since you can just reference the subquery directly in the insert-as-select.
I would question why there aren't any join conditions between your actions table, and the subquery on the entity and company tables, though.

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

PL/SQL: How to delete records in a specific manner, for example if records of specific type X exist, delete all but one record

I'm trying to create a PL/SQL procedure where by I delete records that are grouped and selected by cursor but I only want one record remaining. I want to delete first by Xcomment, if there are multiple entries with id_number, activity_code, start_dt, activity_participation_code exist, then delete all but ONE entry with blank/null xcomment. If there are multiple entries with blank xcomment, then delete all but one with blank table_nmb. If multiple entries with blank table_nmb then delete highest sequence until only one is left. Essentially, I only want one record per all these fields. I'm having trouble thinking of how to do this so any help would be appreciated.
Here is my code so far:
Create Or Replace Function Y_Cleanup_Cursor
Return Sys_Refcursor
As
My_Cursor Sys_Refcursor;
Begin
Open My_Cursor For
Select Q.Id_Number, Q.Activity_Code, Q.Start_Dt, Q.Activity_Participation_Code, Q.Rec_Count, A.Xcomment, A.Table_Nmb, A.Xsequence
From (Select Id_Number, Activity_Code, Start_Dt, Activity_Participation_Code, Count(0) As Rec_Count
From Activity A
Group By Id_Number, Activity_Code, Start_Dt, Activity_Participation_Code
Having Count(0) > 1) Q,
Activity A
Where
Q.Id_Number = A.Id_Number And
Q.Activity_Code = A.Activity_Code And
Q.Start_Dt = A.Start_Dt And
Q.Activity_Participation_Code = A.Activity_Participation_Code;
Return My_Cursor;
End Y_Cleanup_Cursor;
Create Or Replace Procedure Help_Me_Please(Code In Varchar2)
Is
-- Declare Variables
-- I Stands For Internal Variable
L_Cursor Sys_Refcursor;
I_Id_Number Varchar2(10 Byte);
I_Xsequence Number (6);
I_Activity_Code Varchar2(05 Byte);
I_Start_Dt Varchar2(08 Byte);
I_Activity_Participation_Code Varchar2(02 Byte);
I_Table_Nmb Varchar2(15 Byte);
I_Xcomment Varchar2(255 Byte);
I_Rec_Count Number (6);
L_Counter Integer;
Begin
L_Cursor := Y_Cleanup_Cursor;
Loop
Fetch L_Cursor Into
I_Id_Number, I_Activity_Code, I_Start_Dt, I_Activity_Participation_Code, I_Rec_Count, I_Xcomment, I_Table_Nmb, I_Xsequence;
Select Count (Id_Number)
Into L_Counter
From Activity Where
Id_Number = I_Id_Number
And Activity_Code = I_Activity_Code
And Start_Dt = I_Start_Dt
And Activity_Participation_Code = I_Activity_Participation_Code
And Trim(Xcomment) Is Null;
If L_Counter <> I_Rec_Count Then
Begin
Delete From Activity
Where
Id_Number = I_Id_Number
And Activity_Code = I_Activity_Code
And Start_Dt = I_Start_Dt
And Activity_Participation_Code = I_Activity_Participation_Code
And Trim(Xcomment) Is Null;
end;
End If;
Exit When L_Cursor%Notfound;
End Loop;
Close L_Cursor;
End Help_Me_Please;
From what I gather you want to delete all rows except 1 where there are repeating columns
first make sure to backup your table:
create table [backup_table] as select * from [table];
Try This:
DELETE FROM backup_table
WHERE rowid not in
(SELECT MIN(rowid)
FROM backup_table
GROUP BY [col1], [col2]);
Col1 and col2, etc are the columns that should be identical

Resources