passing table name as parameter in postgresql - plpgsql

I have below table and records i have to pass the table names ("LandXML_QCC_ParcelMarks", "LandXML_QCC_ParcelInformation") as a input parameters (tblparcelmarks, tblparcelinfo) to the below function.
how can i use the this table name parameter in my query in below function. I tried but it is not working.
create table "LandXML_QCC_ParcelMarks"("DPID" TEXT,"From" TEXT,"Name" Text);
insert into "LandXML_QCC_ParcelMarks" values('1','ram','kumar');
create table "LandXML_QCC_ParcelInformation"("DPID" TEXT,"Pntref" Text);
insert into "LandXML_QCC_ParcelInformation" values('1','ram');
CREATE OR REPLACE FUNCTION public.getparcelnonparcelfinal(planid text, tblparcelmarks text, tblparcelinfo text)
RETURNS text AS
$BODY$
declare
tblmark RECORD;
parCount integer;
parNonCount integer;
totalParNonCount text;
tblCou integer;
begin
parCount = 0;
parNonCount = 0;
FOR tblmark IN (SELECT "From", "Name" FROM tblParcelMarks where "DPID" = planid) LOOP
SELECT COUNT(*) into tblCou FROM tblParcelInfo where "DPID" = PlanID and ("Pntref" like '%' || tblMark."From" || ',' || CAST(tblMark."Name" As text) || '%' or "Pntref" like '%' || CAST(tblMark."Name" As text) || ',' || tblMark."From" || '%');
IF tblCou > 0 THEN
parCount = parCount + 1;
ELSE
parNonCount = parNonCount + 1;
END IF;
END LOOP;
totalParNonCount = CAST(parCount As text) || ',' || CAST(parNonCount As text);
return totalParNonCount;
end;
$BODY$
LANGUAGE plpgsql;

Related

Delete is not performed after an insertion - postgres

I'm writing a function where I can store specific fields from a table before to delete the record, to keep an historical.
The insertion is working well, but the Delete sometimes is returning Delete 0, even if I have hardcode the id field that I want to delete.
This is my function:
create or replace function deletefromtable(_schema text, _table text, _filter text, _userid int)
returns json as
$func$
DECLARE _record json;
DECLARE target text;
DECLARE mykey TEXT;
DECLARE newvalue TEXT;
DECLARE oldvalue TEXT;
DECLARE columnname TEXT;
begin
SET session_replication_role = replica;
execute format ('select row_to_json(t) from (select * from ' || _schema ||'.' || _table || ' WHERE ' || _filter || ' ) t') into _record;
raise notice 'record: %', _record;
FOR target IN SELECT col from track_settings(_table) LOOP
with vw_listing (new_record) as ( values
(_record::jsonb)
)
SELECT (new_record ->> target)::text INTO newvalue
FROM vw_listing LIMIT 1;
raise notice 'newvalue: %', newvalue;
execute format ('insert into track_history (created_at, table_name, column_name, table_id, user_id, new_val, old_val, pg_user)
values (''' || Now() || ''', ''' || _table || ''', ''' || target || ''', ''' || _filter || ''' ,' || _userid || ', null, ''' || newvalue || ''', current_user )');
END LOOP;
execute ('DELETE FROM public.user WHERE id = 1 ;'); -- THIS LINE IS NOT EXECUTED
SET session_replication_role = default;
RETURN _record;
COMMIT;
end
$func$ language plpgsql;
I tried to enable SET session_replication_role = replica; or SET session_replication_role = default; but is still not working.
The function hasn't any errors and is executing all the statements.
Can someone help me to fix it?

Concurrent Usage of Function

I have a function called "ChallanNoGenerator" which created sequential number with combination with other columns.
This function is called from multiple other functions, the problem is that at concurrent call it generate duplicate "ChallanNo"
-- DROP FUNCTION "Fee"."ChallanNoGenerator"(uuid);
CREATE OR REPLACE FUNCTION "Fee"."ChallanNoGenerator"(
admissionformid uuid)
RETURNS text
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
declare "ChallanNumber" TEXT;
"CampusCode" TEXT;
"SessionCode" TEXT;
"BusinessUnitCode" TEXT;
"ChallanNumberEx" TEXT;
BEGIN
SELECT
CONCAT(bu."DigitCode", cm."DigitCode"), sn."FullName" INTO "CampusCode", "SessionCode"
FROM
"Admission"."AdmissionForm" AS af,
"Setup"."CampusProgramLink" AS cpl,
"Setup"."ProgramDetails" AS pd,
"Setup"."Campus" AS cm,
"Setup"."SubCity" AS sc,
"Setup"."City" AS ct,
"Setup"."Institution" AS ins,
"Setup"."Session" as sn,
"Setup"."BusinessUnit" AS bu
WHERE
af."CampusProgramId" = cpl."CampusProgramId"
AND pd."ProgramDetailId" = cpl."ProgramDetailId"
AND cpl."CampusId" = cm."CampusId"
AND cm."SubCityId" = sc."SubCityId"
AND sc."CityId" = ct."CityId"
AND cm."InstitutionId" = ins."InstitutionId"
AND cpl."SessionId" = sn."SessionId"
AND af."AdmissionFormId" = admissionformid;
-- SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT ((RIGHT(COALESCE(MAX("ChallanNo"), '000000'), 6)::INT4) + 1) INTO "ChallanNumber" FROM "Fee"."StudentChallan"
WHERE "ChallanNo" LIKE "CampusCode" || "SessionCode" || '%';
SELECT ((RIGHT(COALESCE(MAX("ChallanNo"), '000000'), 6)::INT4) + 1) INTO "ChallanNumberEx" FROM "Fee"."StudentChallanEx"
WHERE "ChallanNo" LIKE "CampusCode" || "SessionCode" || '%';
IF (("ChallanNumber"::INT4) < ("ChallanNumberEx"::INT4)) THEN
"ChallanNumber" := "ChallanNumberEx";
END IF;
IF(LENGTH("ChallanNumber") = 1) THEN
"ChallanNumber" := '00000' || "ChallanNumber";
ELSIF(LENGTH("ChallanNumber") = 2) THEN
"ChallanNumber" := '0000' || "ChallanNumber";
ELSIF(LENGTH("ChallanNumber") = 3) THEN
"ChallanNumber" := '000' || "ChallanNumber";
ELSIF(LENGTH("ChallanNumber") = 4) THEN
"ChallanNumber" := '00' || "ChallanNumber";
ELSIF(LENGTH("ChallanNumber") = 5) THEN
"ChallanNumber" := '0' || "ChallanNumber";
END IF;
RETURN "CampusCode" || "SessionCode" || "ChallanNumber";
END
$BODY$;
ALTER FUNCTION "Fee"."ChallanNoGenerator"(uuid)
OWNER TO postgres;
this is the first function that I have created to generate challan no.
Now I have modify it with
-- DROP FUNCTION "Fee"."ChallanNoGenerator"(uuid, uuid);
CREATE OR REPLACE FUNCTION "Fee"."ChallanNoGenerator"(
admissionformid uuid,
studentchallanid uuid)
RETURNS text
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
declare "ChallanNumber" TEXT;
"CampusCode" TEXT;
"SessionCode" TEXT;
"BusinessUnitCode" TEXT;
"ChallanNumberEx" TEXT;
BEGIN
SELECT pg_advisory_xact_lock(1982);
SELECT
CONCAT(bu."DigitCode", cm."DigitCode"), sn."FullName" INTO "CampusCode", "SessionCode"
FROM
"Admission"."AdmissionForm" AS af,
"Setup"."CampusProgramLink" AS cpl,
"Setup"."ProgramDetails" AS pd,
"Setup"."Campus" AS cm,
"Setup"."SubCity" AS sc,
"Setup"."City" AS ct,
"Setup"."Institution" AS ins,
"Setup"."Session" as sn,
"Setup"."BusinessUnit" AS bu
WHERE
af."CampusProgramId" = cpl."CampusProgramId"
AND pd."ProgramDetailId" = cpl."ProgramDetailId"
AND cpl."CampusId" = cm."CampusId"
AND cm."SubCityId" = sc."SubCityId"
AND sc."CityId" = ct."CityId"
AND cm."InstitutionId" = ins."InstitutionId"
AND cpl."SessionId" = sn."SessionId"
AND af."AdmissionFormId" = admissionformid;
-- SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT ((RIGHT(COALESCE(MAX("ChallanNo"), '000000'), 6)::INT4) + 1) INTO "ChallanNumber" FROM "Fee"."StudentChallan"
WHERE "ChallanNo" LIKE "CampusCode" || "SessionCode" || '%';
SELECT ((RIGHT(COALESCE(MAX("ChallanNo"), '000000'), 6)::INT4) + 1) INTO "ChallanNumberEx" FROM "Fee"."StudentChallanEx"
WHERE "ChallanNo" LIKE "CampusCode" || "SessionCode" || '%';
IF (("ChallanNumber"::INT4) < ("ChallanNumberEx"::INT4)) THEN
"ChallanNumber" := "ChallanNumberEx";
END IF;
SELECT CONCAT("CampusCode", "SessionCode", LPAD("ChallanNumber", 6, '000000')) INTO "ChallanNumber";
UPDATE "Fee"."StudentChallan" SET "ChallanNo" = "ChallanNumber" WHERE "StudentChallanId" = studentchallanid;
RETURN CONCAT('Challan No: ', "ChallanNumber", ' has been generated successfully');
END
$BODY$;
ALTER FUNCTION "Fee"."ChallanNoGenerator"(uuid, uuid)
OWNER TO postgres;
Can any one with good experience to achieve what I want

postgresql insert dynamic query result into table in cursor

i have the following function, that generates dynamic query and at the end i want to insert result of dynamic query into table, but the error i get is `
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function report_get_result(integer) line 46 at SQL statement
SQL statement "SELECT report_get_result(20150131)"
PL/pgSQL function inline_code_block line 2 at PERFORM
********** Error **********'
body of the function is:
CREATE OR REPLACE FUNCTION report_get_result (
datekey integer
) returns setof logic_result_rcd
AS
$body$
DECLARE
LogicID integer;
SheetName text;
Row_ID text;
Column_ID text;
FromTable text;
Operation text;
Amount text;
CriteriaType_1 text;
Function_1 text;
Criteria_1 text;
CriteriaType_2 text;
Function_2 text;
Criteria_2 text;
CriteriaType_3 text;
Function_3 text;
Criteria_3 text;
sql text;
INC Integer;
begin
DROP TABLE IF EXISTS loans;
create temp table loans as
select * from loan.vfact_state_principal where "DateKey" = datekey;
DECLARE cursor_logic REFCURSOR;
BEGIN
OPEN cursor_logic for execute ('SELECT "LogicID" FROM logic_table_rcd');
LOOP
FETCH cursor_logic INTO INC;
if not found then exit;
end if;
BEGIN
SELECT LogicID = "LogicID"
,SheetName = "SheetName"
,Row_ID = "Row_ID"::text
,Column_ID = "Column_ID"::text
,FromTable = "FromTable"
,Operation = "Operation"
,Amount = "Amount"
,CriteriaType_1 = CASE WHEN "CriteriaType_1" <> '' THEN ('WHERE
' || "CriteriaType_1") ELSE '' END
,Function_1 = CASE WHEN "Function_1" is null THEN 'Empty' ELSE
"Function_1" END
,Criteria_1 = CASE WHEN "Criteria_1" is null THEN 'Empty' ELSE
"Criteria_1" END
,CriteriaType_2 = CASE WHEN "CriteriaType_2" <> '' THEN ' AND '
|| "CriteriaType_2" ELSE '' END
,Function_2 = CASE WHEN "Function_2" is null THEN 'Empty' ELSE
"Function_2" END
,Criteria_2 = CASE WHEN "Criteria_2" is null THEN 'Empty' ELSE
"Criteria_2" END
,CriteriaType_3 = CASE WHEN "CriteriaType_3" <> '' THEN ' AND '
|| "CriteriaType_3" ELSE '' END
,Function_3 = CASE WHEN "Function_3" is null THEN 'Empty' ELSE
"Function_3" END
,Criteria_3 = CASE WHEN "Criteria_3" is null THEN 'Empty' ELSE
"Criteria_3" END
FROM public.logic_table_rcd WHERE "LogicID" = INC;
sql:= 'INSERT INTO public.logic_result_rcd SELECT ' || INC::text || ', 1, '
|| EntityID::text || ', ' || DateKey::text || ', ' || 'RCD' || ', ' ||
SheetName::text || ', ' || Row_ID::text || ', ' || Column_ID::text || ', '
|| Operation || '(' || Amount || ')' || ' FROM ' || FromTable
|| CriteriaType_1 || ' ' || Function_1 || ' ' || Criteria_1
|| CriteriaType_2 || ' ' || Function_2 || ' ' || Criteria_2
|| CriteriaType_3 || ' ' || Function_3 || ' ' || Criteria_3;
RETURN QUERY EXECUTE sql;
END;
END LOOP;
CLOSE cursor_logic;
END;
END;
$body$
LANGUAGE plpgsql;
assign value with VAR_NAME := ''; construct, here is an example:
t=# create function f(_i int) returns table (a int) as $$
declare sql text;
begin
sql := format('select %s',_i);
return query execute sql;
end;
$$
language plpgsql
;
CREATE FUNCTION
t=# select * From f(3);
a
---
3
(1 row)

postgresql cannot open INSERT query as cursor

i'm trying to generate dynamic query to insert results of dynamic select into table. my code is the following.
CREATE OR REPLACE FUNCTION public.report_get_result(
datekey integer)
RETURNS setof public.logic_result_rcd
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
DECLARE
LogicID text;
SheetName text;
Row_ID text;
Column_ID text;
FromTable text;
Operation text;
Amount text;
CriteriaType_1 text;
Function_1 text;
Criteria_1 text;
CriteriaType_2 text;
Function_2 text;
Criteria_2 text;
CriteriaType_3 text;
Function_3 text;
Criteria_3 text;
sql text;
INC Integer;
begin
DROP TABLE IF EXISTS loans;
create temp table loans as
select * from loan.vfact_state_principal where "DateKey" = datekey;
DECLARE cursor_logic REFCURSOR;
BEGIN
OPEN cursor_logic for SELECT "LogicID" FROM logic_table_rcd;
LOOP
FETCH cursor_logic INTO INC;
if not found then exit;
end if;
BEGIN
select into LogicID "LogicID" from public.logic_table_rcd WHERE
"LogicID" = 1;
select into SheetName "SheetName" from public.logic_table_rcd WHERE
"LogicID" = 1;
select into Row_ID "Row_ID" from public.logic_table_rcd WHERE "LogicID"
= 1;
select into Column_ID "Column_ID" from public.logic_table_rcd WHERE
"LogicID" = 1;
select into FromTable "FromTable" from public.logic_table_rcd WHERE
"LogicID" = 1;
select into Operation "Operation" from public.logic_table_rcd WHERE
"LogicID" = 1;
select into Amount "Amount" from public.logic_table_rcd WHERE "LogicID"
= 1;
select into CriteriaType_1 CASE WHEN "CriteriaType_1" <> '' OR
"CriteriaType_1" is not null THEN (' WHERE "' || "CriteriaType_1" || '"')
ELSE '' END from public.logic_table_rcd WHERE "LogicID" = 1;
select into Function_1 CASE WHEN "Function_1" is null THEN '' ELSE
"Function_1" END from public.logic_table_rcd WHERE "LogicID" = 1;
select into Criteria_1 CASE WHEN "Criteria_1" is null THEN '' ELSE
"Criteria_1" END from public.logic_table_rcd WHERE "LogicID" = 1;
select into CriteriaType_2 CASE WHEN "CriteriaType_2" <> '' OR
"CriteriaType_2" is not null THEN ' AND "' || "CriteriaType_2" || '"' ELSE
'' END from public.logic_table_rcd WHERE "LogicID" = 1;
select into Function_2 CASE WHEN "Function_2" is null THEN '' ELSE
"Function_2" END from public.logic_table_rcd WHERE "LogicID" = 1;
select into Criteria_2 CASE WHEN "Criteria_2" is null THEN '' ELSE
"Criteria_2" END from public.logic_table_rcd WHERE "LogicID" = 1;
select into CriteriaType_3 CASE WHEN "CriteriaType_3" <> '' or
"CriteriaType_3" is not null THEN ' AND "' || "CriteriaType_3" || '"' ELSE
'' END from public.logic_table_rcd WHERE "LogicID" = 1;
select into Function_3 CASE WHEN "Function_3" is null THEN '' ELSE
"Function_3" END from public.logic_table_rcd WHERE "LogicID" = 1;
select into Criteria_3 CASE WHEN "Criteria_3" is null THEN '' ELSE
"Criteria_3" END from public.logic_table_rcd WHERE "LogicID" = 1;
sql:= 'INSERT INTO public.logic_result_rc SELECT ' || INC::text || ', 1, '
|| DateKey::text || ', ''' || 'RCD' || ''', ''' || SheetName::text || ''', '
|| Row_ID::text || ', '
|| Column_ID::text || ', ' || Operation || '("' || Amount || '")' || ' FROM
' || FromTable
|| CriteriaType_1 || ' ' || Function_1 || ' ' || Criteria_1
|| CriteriaType_2 || ' ' || Function_2 || ' ' || Criteria_2
|| CriteriaType_3 || ' ' || Function_3 || ' ' || Criteria_3;
RETURN QUERY EXECUTE sql;
END;
END LOOP;
CLOSE cursor_logic;
END;
END;
$BODY$;
ALTER FUNCTION public.report_get_result(integer)
OWNER TO postgres;
But after execution I get the next error:
cannot open INSERT query as cursor
All variables are assigned correctly. may be insert must be somewhere else outside cursor? does INSERT INTO .... FETCH ALL statement exist?
INSERT by default doesn't return any rows, so there is nothing to fetch. You can fix this by appending your sql string with RETURNING *, with should return contents inserted into public.logic_result_rc.
So it would like this: RETURN QUERY EXECUTE concat(sql, ' RETURNING *');
Basic syntax is:
INSERT INTO table_name ( column_name [, ...] )
VALUES ( ) | query
RETURNING * --or list of columns, same syntax like for SELECT

after update the table insert data like arrays

I have two tables
Table A
col1 col2 col3
Table B
table_name column_name new_value old_value
if any update happened on table A it will insert the data on table B
the output of table B is==>
table_name column_name new_value old_value
---------------- ------------------ -------------- -----------
A {col1}
A {col1,col2} {col1.new_value, {col1.old_value,
col2.new_value} col2.old_value},
so anyone can tell me how to capture the column_names and it store data target table like arrays
Try this
Use Trigger Function
CREATE OR REPLACE FUNCTION update_history()
RETURNS trigger AS
$BODY$
DECLARE col_name VARCHAR[];
DECLARE od_value VARCHAR[];
DECLARE ne_value VARCHAR[];
DECLARE each_column RECORD;
DECLARE each_entity RECORD;
DECLARE column_name VARCHAR;
DECLARE old_value VARCHAR;
DECLARE new_value VARCHAR;
FOR each_column IN
select c.column_name --- Get the all column names in affected table
from information_schema.columns c
where(table_name = tg_relname And c.TABLE_SCHEMA = TG_TABLE_SCHEMA)
LOOP
FOR each_entity IN --- Its used to get old and new columns value
EXECUTE 'SELECT text((' || quote_literal(OLD.*) || '::"' || tg_table_schema || '"."' || tg_relname || '")."' || each_column.column_name || '") as old_val,
text((' || quote_literal(NEW.*) || '::"' || tg_table_schema || '"."' || tg_relname || '")."' || each_column.column_name || '")
AS new_val
FROM "' || tg_table_schema || '"."' || tg_relname || '";'
LOOP
old_value = each_entity.old_val;
new_value = each_entity.new_val;
IF old_value != new_value THEN
i=i+1;
col_name[i]=each_column.column_name;
od_value[i]=old_value;
ne_value[i]=new_value;
END IF;
END LOOP;
END LOOP;
INSERT INTO B
(
tablename,
columnnames,
oldvalues,
newvalues
)
VALUES
(
tg_relname,
col_name,
od_value,
ne_value
);
End if;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
I thinks it's a good case to use hstore extension of PostgreSQL:
create or replace function history_trigger_func()
returns trigger AS
$$
begin
insert into TableB
select
tg_relname,
case when tg_op in ('UPDATE', 'INSERT') then hstore(new) end,
case when tg_op in ('UPDATE', 'DELETE') then hstore(old) end;
return null;
end;
$$
language plpgsql;
create trigger tr_history_trigger after insert or update or delete on TableA
for each row execute procedure history_trigger_func();
sql fiddle demo
You can extend this further by removing columns which are not changing, or, if you're using PostgreSQL 9.3, you can use JSON instead of hstore.