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
Related
I need to create a script to clean up all the objects in the schema 'myschema'.
Order will be like
All tables(FK PK order)
How do I achieve this in one PLSQL block.
set serveroutput on;
declare
lv_str varchar2(1000);
begin
for c in(select distinct a.table_name as table_name, b.table_name as parent_table_name
from
all_constraints a
left outer join all_constraints b on a.r_constraint_name = b.constraint_name and a.owner = b.owner) loop
lv_str :='DROP TABLE '||c.table_name;
--lv_str :='DROP TABLE '||c.parent_table_name;
dbms_output.put_line(lv_str);
end loop;
end;
This is a script I use to clear Scott's schema. Why? I use it for testing purposes and, as time goes by, it turns into a mess. I don't pay much attention about what I remove and in which order; I simply run it 2-3 times and everything's gone. See if you can use it, improve it if you want.
SET SERVEROUTPUT ON;
DECLARE
l_user VARCHAR2 (30) := 'SCOTT';
l_str VARCHAR2 (200);
BEGIN
IF USER = l_user
THEN
FOR cur_r IN (SELECT object_name, object_type
FROM user_objects
WHERE object_name NOT IN ('EMP',
'DEPT',
'BONUS',
'SALGRADE'))
LOOP
BEGIN
l_str :=
'drop '
|| cur_r.object_type
|| ' "'
|| cur_r.object_name
|| '"';
DBMS_OUTPUT.put_line (l_str);
EXECUTE IMMEDIATE l_str;
EXCEPTION
WHEN OTHERS
THEN
NULL;
END;
END LOOP;
END IF;
END;
/
PURGE RECYCLEBIN;
SELECT * FROM user_objects;
How to drop foreign key constraints first, and then drop tables:
SQL> set serveroutput on
SQL> declare
2 l_str varchar2(200);
3 begin
4 for cur_r in (select table_name, constraint_name
5 from user_constraints
6 where constraint_type = 'R')
7 loop
8 l_str := 'alter table ' || cur_r.table_name ||
9 ' drop constraint ' || cur_r.constraint_name;
10 dbms_output.put_line(l_str);
11
12 execute immediate l_str;
13 end loop;
14
15 --
16
17 for cur_r in (select table_name from user_tables where table_name not in ('EMP', 'DEPT'))
18 loop
19 l_str := 'drop table ' || cur_r.table_name;
20
21 dbms_output.put_line(l_str);
22
23 execute immediate l_str;
24 end loop;
25 end;
26 /
alter table TDET drop constraint SYS_C00105662
drop table BONUS
drop table SALGRADE
drop table TEST
drop table MYTABLE
drop table TABLEB
drop table TABLEA
drop table EMPLOYEES
drop table T_PRINT
drop table TMAS
drop table TDET
PL/SQL procedure successfully completed.
SQL>
My code:
create table info(str varchar2(30));
declare
cursor c(job emp_ast.job_id%type, dep emp_ast.department_id%type) is select employee_id
from emp_ast
where job_id=job and department_id=dep;
type t_job is table of emp_ast.job_id%type;
t t_job:=t_job();
emp emp_ast.employee_id%type;
i number(3);
begin
select job_id
bulk collect into t
from emp_ast;
for i in 10..270 loop
for j in 1..t.count loop
open c(i, t(j));
loop
fetch c into emp;
insert into info
values (i||' '||t(j)||' '||emp);
exit when c%notfound;
end loop;
i:=i+10;
end loop;
end loop;
end;
/
I get "expression 'I' cannot be used as an assignment target", reffering to the line where I increment i by 10. I am trying to save the department_id, employee_id and job_id as a string in a table for each department and each job.
At the point where you get that message, i refers to the loop control variable i defined in the line for i in 10..270 loop, not the int(3) variable defined earlier. In PL/SQL a loop definition defines a variable which is only accessible inside the loop, and which you cannot alter. I suggest you change the name of one or the other to make them unique.
EDIT
PL/SQL doesn't provide a way to step by more than 1 in a computed FOR loop. Instead, you will need to compute the desired department number value within the loop:
DECLARE
CURSOR c(job EMP_AST.JOB_ID%TYPE,
dep EMP_AST.DEPARTMENT_ID%TYPE)
IS SELECT EMPLOYEE_ID
FROM EMP_AST
WHERE JOB_ID = job AND
DEPARTMENT_ID = dep;
TYPE t_job IS TABLE OF EMP_AST.JOB_ID%TYPE;
t t_job := t_job();
emp EMP_AST.EMPLOYEE_ID%TYPE;
nDepartment NUMBER;
BEGIN
SELECT job_id
BULK COLLECT INTO t
FROM EMP_AST;
FOR i IN 1..27 LOOP
nDepartment := i * 10;
FOR j IN 1..t.COUNT LOOP
OPEN c(t(j), nDepartment);
LOOP
FETCH c INTO emp;
INSERT INTO info
VALUES (nDepartment || ' ' || t(j) || ' ' || emp);
EXIT WHEN c%notfound;
END LOOP; -- cursor c
CLOSE c;
END LOOP; -- j
END LOOP; -- i
END;
/
Note that in the code above the nDepartment value is computed within the i loop, which now increments from 1 to 27 instead of going from 10 to 270.
"I missing the forest through the trees..."
I want to query each column of a table which I retrieve in a FOR LOOP, but the inner query doesn't return the right thing.
Seems that the inner query not use the current column_name.
DECLARE
v_max_TS TIMESTAMP;
BEGIN
FOR cols IN (SELECT column_name FROM all_tab_cols WHERE table_name = '<tablename>')
LOOP
SELECT
MAX(CURR_TIMESTAMP) INTO v_max_TS
FROM <tablename>
WHERE cols.column_name IS NOT NULL
ORDER BY TO_TIMESTAMP(CURR_TIMESTAMP,'MM/DD/YYYY HH24:MI:SS') DESC;
dbms_output.put_line(cols.column_name || ' ' || v_max_TS);
END LOOP;
END;
Apart from the fact that your query doesn't make much sense (as Boneist wrote as a comment), that won't work as you need to use dynamic SQL (execute immediate) for such a purpose.
Here's an example based on Scott's schema. Have a look, adjust it if necessary.
SQL> set serveroutput on
SQL> declare
2 l_str varchar2(200); -- will hold the SELECT statement
3 v_max varchar2(30);
4 begin
5 for cols in (select column_name
6 from all_tab_cols
7 where table_name = 'DEPT'
8 )
9 loop
10 l_str := 'select max(' || cols.column_name ||') from dept';
11 execute immediate l_str into v_max;
12 dbms_output.put_line(cols.column_name ||': '|| v_max);
13 end loop;
14 end;
15 /
DEPTNO: 40
DNAME: SALES
LOC: NEW YORK
PL/SQL procedure successfully completed.
SQL>
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.
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;