How to declare for loop in postgreSQL - postgresql

Am getting error for "for loop".
FOR I IN 1 .. W_SPLIT_MSG.COUNT LOOP
My code is like this
IF W_SIM_VALI_REQ = 'Y' THEN
IF position('###' in trim(both P_SIM_SL)) > 0 THEN
--W_SPLIT_MSG := FN_SPLIT(trim(both P_SIM_SL), '###');
W_SPLIT_MSG := split(trim(both P_SIM_SL), '###');
FOR I IN 1 .. W_SPLIT_MSG.COUNT LOOP
SELECT * FROM pkg_mobile_users_sp_check_imei(
P_ENTITY_CODE,
P_IMEI,
W_SPLIT_MSG(I),
P_OS, P_SUC_FLG,
P_ERROR,
P_ERROR_MSG)
INTO STRICT P_SUC_FLG, P_ERROR, P_ERROR_MSG;
IF P_SUC_FLG = 'S' THEN
RETURN;
END IF;
END LOOP;
END IF;
But am getting error like
FOR with integer loop variable* *record "w_split_msg" has no field "count"
But I have declared w_split_msg as:
W_SPLIT_MSG SPLITSTR_TYPE;

Related

debugging psql - session procedure

I am trying to modify an existing sessions procedure to add cycle count.The error I am getting is
SQL Error [42601]: ERROR: syntax error at or near "END"
Position: 3587
--call transactions_packs.tep_session()
CREATE OR REPLACE PROCEDURE transactions_packs.tep_session()
LANGUAGE plpgsql
AS $procedure$
DECLARE
session "transactions_packs"."simple_sessions";
"session_toSearch" TEXT;
"end_timestamp" TIMESTAMP WITH TIME ZONE;
"energy" NUMERIC;
"charge" NUMERIC;
"duration" NUMERIC;
"cycle_count" numeric;
"f" record ;
BEGIN
cycle_count = '0';
-- go to statement fore session reset
FOR session IN SELECT * FROM "transactions_packs"."simple_sessions" WHERE "sessionDuration" IS NULL
LOOP
BEGIN
IF session."sessionType" = 0 THEN
"session_toSearch" := 'Charging';
ELSIF session."sessionType" = 1 THEN
"session_toSearch" := 'Discharging';
END IF;
-- Session_count:Start
EXECUTE FORMAT('
FOR f IN select (current' || '%s' || '), "timestamp"
FROM "transactions_packs"."basic_measurements_packs" a order by a."timestamp" desc
LOOP
BEGIN
IF AVG((current' || '%s' || '))
OVER (ORDER BY "f"."timestamp" ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) > 0.01
then cycle_count = cycle_count + 1;
END IF;
END
END LOOP;',"session_toSearch","session_toSearch")
-- get value from If and else statement to fetch records from charging and discharging col
--Session_count :End
END ;
END LOOP;
end;
$procedure$
;
where -
schema is transactions_packs
tables are -
simple_sessions
basic_measurements_packs
Please let me know if there is any part of query is which cannot be understood.
The variable "hell" sounds like useless here, try something like this :
create or replace procedure "public"."extract"(arg json)
language plpgsql as $$
begin
raise notice 'test:%', arg->'global'->>'packetType';
raise notice 'test1:%', arg-> 'transactional'->>'A';
-- freeze the input
end ;
$$;

why am i getting an error in this for each in PL/pgSQL

I have this function applying jaccard index in some text strings
CREATE OR REPLACE FUNCTION jaccard(INPUT text, INPUT2 text) RETURNS real
LANGUAGE plpgsql
AS $$
DECLARE
trigrama1 text[];
trigrama2 text[];
union text[];
interception text[];
palabra1 text;
palabra2 text;
coincidencias int=0;
inicio int=1;
fin int=3;
longitud int;
longitud2 int;
resultado real;
item text;
item2 text;
BEGIN
palabra1=replace(INPUT,' ','');
palabra2=replace(INPUT2,' ','');
palabra1=regexp_replace(palabra1, '[^a-zA-Z]', '', 'g');
palabra2=regexp_replace(palabra2, '[^a-zA-Z]', '', 'g');
longitud=char_length(palabra1);
WHILE fin <= longitud LOOP
trigrama1=array_append(trigrama1,substr(palabra1, inicio,3));
fin=fin+1;
inicio=inicio+1;
END LOOP;
inicio=1;
fin=3;
longitud=char_length(palabra2);
WHILE fin <= longitud LOOP
trigrama2=array_append(trigrama2,substr(palabra2, inicio,3));
fin=fin+1;
inicio=inicio+1;
END LOOP;
union=array_cat(ARRAY[]::text[],trigrama1);
FOREACH item IN ARRAY trigrama2 LOOP
coincidencias=0;
FOREACH item2 IN ARRAY union LOOP --line error
IF item=item2 THEN
coincidencias = coincidencias +1;
END IF;
END LOOP;
IF coincidencias =0 THEN
union=array_append(union,item);
END IF;
END LOOP;
FOREACH item IN ARRAY trigrama2 LOOP
coincidendencias=0;
FOREACH item2 IN ARRAY trigrama1 LOOP
IF item=item2 THEN
coincidencias = coincidencias +1;
END IF;
END LOOP;
IF coincidencias >0 THEN
interception=array_append(interception,item);
END IF;
END LOOP;
longitud=array_length(union,1);
longitud2=array_length(interception,1);
resultado=longitud/longitud1;
RETURN resultado;
END;
$$;
This is the error message :-
ERROR: Syntax Error at End of Entry Line 48: FOREACH item2 IN ARRAY
union LOOP
the error happens in the nested foreach what iterates a
text array postgres 11 all arrays have content
jadshkjashdkhaskdhasdajksdhkashdkasd kalsjdlkashdlkasd kashdjlkashdlkashdaksjdhahgasdddddddddddddddddddddddasadjkfhkasdhfkshdfkhdskfhdksfhkshdfkhsdkfhsdkfhsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaassssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaassssssssssssssssssssssssssssssssssssssssssssssdaaksuhydhfiuoasdyfiuasydbfuioshdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddiasssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss

using variable as part of the statement

I want to use a variable as part of the statement, but it says that "tableref" doesn't exist.
CREATE OR REPLACE FUNCTION ff(tipo_acta integer, hasta date)
RETURNS void AS
$BODY$
DECLARE
tableref varchar;
r record;
BEGIN
if tipo_acta = 1 then
tableref = 't1';
elsif tipo_acta = 2 then tableref = 't2';
else tableref = 't3';
end if;
for r select id from tableref where somedate >= hasta loop
--
end loop;
I tried to use EXECUTE 'select id from ' || tableref || ' where....' but doesn't work either
I thought to get the record first with select id into r from t1 where .. and then use it in the loop, but there seems to be no way to use a record in a loop like that:
FOR r LOOP
....
END LOOP;
You need to use dynamic sql for that. You need to use execute command to do that in PLPG/SQL.
In your code it should be something like:
EXECUTE 'SELECT id FROM ' || tableref || ' WHERE somedate >= $1'
INTO c
USING hasta;

query result based loop syntax in if condition

I am new to PGSQL and trying to start a loop in database function that iterates on the basis of query result as shown below. I am using 8.2 version.
CREATE OR REPLACE FUNCTION demo(text)
RETURNS SETOF activityhistoryview
LANGUAGE plpgsql STABLE
AS $_$
DECLARE
tilldate ALIAS for $1;
actrec revpro_500.activity%ROWTYPE;
BEGIN
IF tilldate != '' THEN
FOR actrec IN
SELECT activity.* from revpro_500.activity WHERE activity.householdid = 950
LOOP
ELSE
FOR actrec IN
SELECT activity.* from revpro_500.activity WHERE activity.householdid = 500
LOOP
END IF;
BEGIN
/* rest code goes here */
END
END LOOP;
RETURN;
END;$_$;
After executing above function, I am getting below error.
ERROR: syntax error at or near "ELSE"
What I am missing here?
You can not nest loop queries like that. Instead, first evaluate what you want to do with tilldate, then make a single loop query:
CREATE OR REPLACE FUNCTION demo(tilldate text) RETURNS SETOF activityhistoryview
LANGUAGE plpgsql STABLE AS $_$
DECLARE
actrec revpro_500.activity%ROWTYPE;
hhid integer;
BEGIN
IF tilldate != '' THEN
hhid = 950;
ELSE
hhid = 500;
END IF;
FOR actrec IN
SELECT * from revpro_500.activity WHERE householdid = hhid
LOOP
BEGIN -- Do you really need a transaction block? If not, remove BEGIN/END
-- rest code goes here
END
END LOOP;
RETURN;
END;$_$;
Like in most languages you can't have your control structures overlapping, so on the line before the ELSE you open a LOOP, but do not close it before the ELSE, so the ELSE doesn't have an attached IF paired to it.
You can put the IF/ELSE block inside the loop, or outside it, but not overlapping.
Example:
-- Good
LOOP
-- some computations
IF tilldate != '' THEN
EXIT; -- exit loop
ELSE
-- some computations
END IF;
END LOOP;
-- Good
IF tilldate != '' THEN
LOOP
-- some computations
END LOOP;
ELSE
LOOP
-- some computations
END LOOP;
END IF;
-- Bad
IF
LOOP
-- some computations
ELSE
-- some computations
END IF;
END LOOP;

How to pass stored procedure parameter into EXECUTE statement

CREATE OR REPLACE FUNCTION "Test"(character varying[],character varying[])
RETURNS refcursor AS
$BODY$
DECLARE
curr refcursor;
filter text;
counter integer;
BEGIN
counter = 1;
filter = '';
IF array_length($1,1) > 0 THEN
filter = 'AND ';
WHILE ($1[counter] <> '') LOOP
filter = filter||'LOWER('||$1[counter]||'::character varying) LIKE ''%''||LOWER($2['||counter||'])||''%'' AND ';
counter = counter + 1;
END LOOP;
filter = substring(filter FROM 1 FOR (char_length(filter)-4));
OPEN curr FOR
EXECUTE 'SELECT "Reservation".* FROM "Reservation" WHERE "Reservation"."id" > 0 '||filter;
return curr;
END IF;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
SELECT "Test"(ARRAY['"Reservation"."status"'],'{"waiting"}');
FETCH ALL IN "<unnamed portal 1>";
I tried to print out the query:
"SELECT "Reservation".* FROM "Reservation" WHERE "Reservation"."id" > 0 AND LOWER("Reservation"."status"::character varying) LIKE '%'||LOWER($2[1])||'%' "
But when it's executed it said that there was no parameter $2. So I realize that it can't access that stored procedure's parameter.
I don't have to worry about the first parameter of sql injection since it's hard coded. But the second param has to be passed into the execution. How do I do that?
I've found out that I could pass the parameter into EXECUTE using the "USING" statement.
Here's the final working code:
CREATE OR REPLACE FUNCTION "Test"(character varying[],character varying[])
RETURNS refcursor AS
$BODY$
DECLARE
curr refcursor;
filter text;
counter integer;
BEGIN
counter = 1;
filter = '';
IF array_length($1,1) > 0 THEN
filter = 'AND ';
WHILE ($1[counter] <> '') LOOP
filter = filter||'LOWER('||$1[counter]||'::character varying) LIKE ''%''||LOWER($1['||counter||'])||''%'' AND ';
counter = counter + 1;
END LOOP;
filter = substring(filter FROM 1 FOR (char_length(filter)-4));
OPEN curr FOR
EXECUTE 'SELECT "Reservation".* FROM "Reservation" WHERE "Reservation"."id" > 0 '||filter USING $2;
return curr;
END IF;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
SELECT "Test"(ARRAY['"Reservation"."status"'],ARRAY['no-show']);
FETCH ALL IN "<unnamed portal 1>";
Note that I have $1 as the value in the EXECUTE statement, because it accepts $2 as its first parameter.