if statement in plsql package - if-statement

I have six insert blocks (job, position, grade, etc.) in one package something like:
create or replace package body XX_package_cust
AS
PROCEDURE main_procedure( p_entity In VARCHAR2 default 'ALL')
is
begin
if p_entity='Job'
then
--execute job block
elsif p_entity='Position'
--execute postion block
elsif p_entity='Grade'
--execute grade block
end if;
end;
Now in the above if else i want to pass 'ALL' in p_entity such that if all is passed all these blocks should be executed and if 'job', grade position only the respective blocks should be executed.
In this for example in job section
begin
begin
insert into job_i
--------
end;
begin
insert into job_x
----
end;
end;
Now if I include if else in each... I will have to do something like :
begin
if p_entity ='JOB'
then
begin
insert into job_i
--------
end;
begin
insert into job_x
----
end;
end if;
end;
That is if else for each and every block. Is there any other way out

You could make each condition check for both the specific value or 'ALL'. Note that you'd have to replace the elsif statements with simple ifs:
if p_entity IN ('ALL', 'Job')
then
--execute job block
end if;
if p_entity IN ('ALL', 'Position')
--execute position block
end if;
if p_entity IN ('ALL', 'Grade')
--execute grade block
end if;

Try this
CREATE OR REPLACE PACKAGE body XX_package_cust
AS
PROCEDURE main_procedure(
p_entity IN VARCHAR2 DEFAULT 'ALL')
IS
BEGIN
IF p_entity ='Job' THEN
--execute job block
dbms_output.put_line('Job block executed');
elsif p_entity='Position' THEN
--execute postion block
dbms_output.put_line('Position block executed');
elsif p_entity='Grade' THEN
--execute grade block
dbms_output.put_line('Grade block executed');
elsif p_entity='All' THEN
--execute job block
dbms_output.put_line('Job block executed');
--execute postion block
dbms_output.put_line('Position block executed');
--execute grade block
dbms_output.put_line('Grade block executed');
END IF;
END;
END;

Related

sqlfuction to django method

I have this postgresql function. Can I convert this function to django-method?
I have implemented these functions in sql, but I would like to implement these functions so that they can be used in django or may I ask if there is a way to use the raw-query function separately in django?
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
DO $$ BEGIN
CREATE DOMAIN SHORTKEY as varchar(11);
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
CREATE OR REPLACE FUNCTION shortkey_generate()
RETURNS TRIGGER AS $$
DECLARE
gkey TEXT;
key SHORTKEY;
qry TEXT;
found TEXT;
user_id BOOLEAN;
BEGIN
qry := 'SELECT id FROM ' || quote_ident(TG_TABLE_NAME) || ' WHERE id=';
LOOP
IF NEW.id IS NOT NULL THEN
key := NEW.company_id;
user_id := TRUE;
IF length(key) <> 11 THEN
RAISE 'User defined key value % has invalid length. Expected 11, got %.', key,
length(key);
END IF;
ELSE
gkey := encode(gen_random_bytes(8), 'base64');
gkey := replace(gkey, '/', '_'); -- url safe replacement
gkey := replace(gkey, '+', '-'); -- url safe replacement
key := rtrim(gkey, '='); -- cut off padding
user_id := FALSE;
END IF;
EXECUTE qry || quote_literal(key) INTO found;
IF found IS NULL THEN
EXIT;
END IF;
IF user_id THEN
RAISE 'ID % already exists in table %', key, TG_TABLE_NAME;
END IF;
END LOOP;
NEW.id = key;
RETURN NEW;
END
$$ language 'plpgsql';
You can run SQL commands on objects like this:
MyModel.objects.raw(
"""
SQL-COMMANDS
"""
)
In migration files you can run:
migrations.RunSQL(
"""
SQL-COMMANDS
"""
)
But it's generally not recommended to do that. I would recommend to transform this SQL script to Python/Django code.

Passing an invalid user id, code should display message but the dbms_output is blank

This procedure should list all project IDs mapped to the active user, and on passing an invalid user id it should print "User is not valid". However, no message is getting displayed.
PROCEDURE get_pid_info (p_return_status_o OUT VARCHAR2,
p_error_message_o OUT VARCHAR2,
p_user_id IN VARCHAR2)
IS
CURSOR c_pid
IS
SELECT DISTINCT xpppa.project_id,
papf.person_type_id,
xpppp.end_date_active,
papf.person_id,
COUNT (DISTINCT xpppa.project_id) pid_count
FROM xxcas_prj_pa_projects_all xpppa,
xxcas_prj_pa_project_players xpppp,
per_all_people_f papf
WHERE xpppa.project_id = xpppp.project_id
AND xpppp.person_id = papf.person_id
AND papf.person_id = 61--p_user_id
AND xpppp.project_role_type = 'PROJECT MANAGER'
AND papf.person_type_id = 6
and sysdate between xpppa.start_date and nvl(xpppa.completion_date,sysdate+1)
and sysdate between xpppp.start_date_active and nvl(xpppp.end_date_active,sysdate+1)
AND EXISTS
(SELECT 1
FROM pa_lookups
WHERE lookup_type = 'XXCAS_PRJ_USER_DETAILS'
AND description=papf.email_address
AND enabled_flag = 'Y'
AND SYSDATE BETWEEN start_date_active
AND NVL (end_date_active,
SYSDATE + 1))
GROUP BY xpppa.project_id,
papf.person_type_id,
xpppp.end_date_active,
papf.person_id;
BEGIN
FOR l_rec IN c_pid
LOOP
IF l_rec.project_id IS NOT NULL
THEN
dbms_output.put_line (
'The Projects mapped to the active user ID are : '
|| l_rec.project_id);
ELSIF l_rec.end_date_active < SYSDATE
THEN
dbms_output.put_line (
'The user has been end dated in the system on : ' || l_rec.end_date_active);
ELSIF l_rec.pid_count = 0
THEN
dbms_output.put_line (
'There are no projects mapped to the user having PM role');
ELSE
dbms_output.put_line ('Please check the user ID passed');
END IF;
IF SQL%NOTFOUND
THEN
dbms_output.put_line('Entered user id is not valid');
end if;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
dbms_output.put_line ('Please provide valid user ID');
WHEN OTHERS
THEN
dbms_output.put_line ('Error in get_pid' || SQLERRM);
END get_pid_info;
Anonymous Block:
declare
status varchar2(30);
msg varchar2(30);
begin
--DBMS_OUTPUT.ENABLE('20000000');
XXCAS_PRJ_PROJECT_DTLS.GET_PID_INFO(status,msg,61);
end;
Firstly, if there are no rows to process then the loop is not entered and so any check inside it will not be executed.
Secondly, the SQL% cursor attributes apply to implicit cursors, not named ones like c_pid in your procedure. It would be simplest to declare a Boolean variable, initialise it to FALSE and set it to TRUE in the loop; then you can check its value after the loop. (Or if you want the actual number of rows, use c_pid%rowcount and initialise it to 0.)
I'm assuming this is a simplified version of your actual procedure, as dbms_output is not generally useful in production code unless the caller is set up to capture it.

Can i use REGEXP_LIKE as a condition with IF in a PL/SQL block

I'm trying to create a function designed to traverse a tree of organisational units filtering out some based on their level in the tree structure and weather they appear on our intranet page. The input to the function is the ORG_UNIT_ID of the starting unit, a flag to show if we should care about the intranet flag and a comma separated list of levels. For instance '2,3'. I'm trying to use REGEXP_LIKE in conjunction with an ELSEIF inside a loop to run up the tree until I hit the first eligible parent unit.
T_STOP is the control variable for the loop. R_ORG_UNIT_OVER is used to query meta-data on the above unit. During the loops first pass this will be the unit above the one passed as input to the function.
The cursor definition:
CURSOR C_ORG_UNIT_OVER(V_ORG_UNIT_ID ORG_UNIT.ORG_UNIT_ID%TYPE) IS
SELECT ORUI.ORG_UNIT_ID
, ORUI.ORG_LEVEL
, ORUI.SHOW_ON_INTRANET
FROM ORG_UNIT ORUI
JOIN ORG_UNIT_PARENT OUPA ON ORUI.ORG_UNIT_ID=OUPA.ORG_UNIT_ID_PARENT
WHERE OUPA.ORG_UNIT_ID = V_ORG_UNIT_ID;
The failing code segment in the loop:
IF R_ORG_UNIT_OVER.SHOW_ON_INTRANET = 'N' THEN
T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSEIF REGEXP_LIKE (P_SKIP_LEVEL, '(^|,)' || R_ORG_UNIT_OVER.ORG_LEVEL || '($|,)') THEN
T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSE
T_STOP := 'Y';
END IF;
However this code always throws a PLS-00103 error on the REGEXP_LIKE symbol. Is there some sort of limitation or alternate way in which REGEXP_LIKE works when used as a condition in a PL/SQL IF/ELSEIF block as opposed to in a regular query?
PL/SQL uses ELSIF, not ELSEIF. With your edit your code does get the error you described; with this it doesn't:
IF R_ORG_UNIT_OVER.SHOW_ON_INTRANET = 'N' THEN
T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSIF REGEXP_LIKE (P_SKIP_LEVEL, '(^|,)' || R_ORG_UNIT_OVER.ORG_LEVEL || '($|,)') THEN
T_ORG_UNIT_ID := R_ORG_UNIT_OVER.ORG_UNIT_ID;
ELSE
T_STOP := 'Y';
END IF;
Yes you can.
declare
testvar varchar2(20) := 'Kittens';
begin
if regexp_like(testvar, '^K') then
dbms_output.put_line(testvar || ' matches ''^K''');
end if;
end;
Kittens matches '^K'
PL/SQL procedure successfully completed.
Include some test data and I'll try to see what's not working as expected. For example,
declare
p_skip_level number := 2;
org_level number := 3;
begin
if regexp_like (p_skip_level, '(^|,)' || org_level || '($|,)')
then
dbms_output.put_line('Matched');
else
dbms_output.put_line('Not matched');
end if;
end;

unit automat:the following signal(s) form a combinatorial loop

I have some problems with this unit and I don't know why it's not working. The platform ISE Project Navigator gives me this error: unit automat:the following signal(s) form a combinatorial loop.I would like to receive some advice and if you can tell me how to resolve this problem.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
entity automat is
port(CLK,EN,SEN,MONED:in STD_LOGIC;
COMP:STD_LOGIC_VECTOR(2 DOWNTO 0);
REN,MEN,ENR,IM_REST,REST,BILET,CLK_EN,RESET: out STD_LOGIC;
S1,S2,com:out STD_LOGIC_VECTOR(1 downto 0)
);
end automat;
architecture arh_automat of automat is
type STARE is(A,B,C,D,E,F,G,H,I,J);
signal ST,NXST:STARE;
begin
tranzitie:process(CLK,ST,EN,SEN,MONED,COMP)
begin
REN<='0';MEN<='0';clk_en<='0';RESET<='0';
ENR<='0';IM_REST<='0';REST<='0';BILET<='0';
S1<="00";S2<="00";com<="00";
case ST is
when A=>NXST<=B;
com<="00";
if(CLK'EVENT and CLK='1') then
if EN='1' then
ST<=B;
else
ST<=A;
end if;
END IF;
when B=>NXST<=C ;
RESET<='1';
com<="01";
if(CLK'EVENT and CLK='1') then
if EN='1' then
ST<=C;
else
ST<=B;
end if;
end if;
when C=>NXST<=D;
REN<='1';
CLK_EN<='1';
com<="10";
if(CLK'EVENT and CLK='1') then
if SEN ='1' then
ST<=D;
else
ST<=C;
end if;
end if;
when D=>NXST<=E ;
s1<="01";
s2<="10";
com<="10";
if(CLK'EVENT and CLK='1') then
if MONED='1' then
ST<=E;
else
ST<=F;
end if;
end if;
when E=>NXST<=F;
com<="00";
if(CLK'EVENT and CLK='1') then
ST<=F;
end if;
when F=>NXST<=G ;
MEN<='1';
com<="00";
if(CLK'EVENT and CLK='1') then
if COMP="010" or COMP="100" then
ST<=G;
else
ST<=C;
end if;
end if;
when G=>NXST<=H;
ENR<='1';
S1<="00";
S2<="11";
com<="00";
if(CLK'EVENT and CLK='1') then
if COMP="100" OR COMP="001" OR COMP="010" then
ST<=H;
else
ST<=I;
end if;
END IF;
when H=>NXST<=J;
REST<='1';
BILET<='1';
com<="00";
if(CLK'EVENT and CLK='1') then
ST<=J;
end if;
when I=>NXST<=J;
IM_REST<='1';
BILET<='1';
com<="00";
if(CLK'EVENT and CLK='1') then
ST<=J;
end if;
when J=>NXST<=A;
com<="00";
if(CLK'EVENT and CLK='1') then
ST<=A;
end if;
end case;
end process tranzitie;
end arh_automat;
You don't say which signals are forming the loop but your process & case construct are not written well.
Try splitting the combinatorial and synchronous signals into separate processes. Your clocking is messed up too. In the syncronous process, use just one "CLK'EVENT and CLK = '1'" statement with the case statement under it.
A combinatorial loop is when you have the output of some combinatorial logic fed back into itself. The most basic example I can think of is:
My_PROC : process(A)
begin
A <= not A;
end process;
Its obviously not possible to synthesize this.
Its pretty difficult to figure out what's going on in your code but you need to look for a case where the output of some combinatorial logic is fed back into itself. Like #lsf_design said, you should split up the combinatorial and clock synchronous logic. I would recommend using the format described here.
I would try to give your signals more descriptive names. Instead of using A, B, C, etc. for your state names, name them something that actually describes what that case does.

pl sql How to make my code less

Can anyone help me to make my code less? (If you can notice to both if-elsif statements I make the same Select.. so I wish there was a way to make this select once. and update with 1 or 0 depending on the pilot_action).
Below its my code.
create or replace
PROCEDURE F_16 (TRK_ID NUMBER, pilot_action NUMBER) IS
BEGIN
BEGIN
IF pilot_action=0 THEN
UPDATE "ControlTow"
SET "Intention"=0
WHERE "Id" IN (
SELECT "Id" FROM "ControlTow" WHERE "Id"=TRK_ID );
ELSIF pilot_action=1 THEN
UPDATE "ControlTow"
SET "Intention"=1
WHERE "Id" IN (
SELECT "Id" FROM "ControlTow" WHERE "Id"=TRK_ID );
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN dbms_output.put_line('False Alarm');
COMMIT;
END;
END F_16;
thank you , in advance.
Your code has several issues I have addressed in the comments below. Note that transaction management is not discussed as it's not clear based on the question when commit/rollback should take place.
-- #1 use of explicit parameter mode
create or replace procedure f_16(p_trk_id in number, p_pilot_action in number) is
begin
-- #2 use of in
if p_pilot_action in (0, 1)
then
-- #3 unnecessary subquery removed
update controltow
set intention = p_pilot_action
where id = p_trk_id;
-- #4 use pl/sql implicit cursor attribute to check the number of affected rows
if sql%rowcount = 0
then
dbms_output.put_line('false alarm');
end if;
end if;
end;
Since you seem to be assigning pilot_action to Intention, I would do following:
create or replace
PROCEDURE F_16 (TRK_ID NUMBER, pilot_action NUMBER) IS
BEGIN
BEGIN
IF pilot_action IN (0, 1) THEN
-- if the only condition in subselect is the ID then use it directly
UPDATE "ControlTow"
SET "Intention"= pilot_action
WHERE "Id"=TRK_ID;
-- if there are more conditions than just the ID then subselect may be the way to go
--(hard to say without more information)
-- WHERE "Id" IN (
-- SELECT "Id" FROM "ControlTow" WHERE "Id"=TRK_ID AND ... )
ELSE
Null; -- do whatever you need in this case. Raise exception?
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN dbms_output.put_line('False Alarm');
COMMIT;
END;
END F_16;
EDIT: As #user272735 said, there was room for more improvement on the code. Specifically rewriting the if condition to use in and simplifying the where clause (supposing Id is really the only condition to select rows to be updated).