Query to insert array of json object into postgres - postgresql

I have a table with field fields json[]. I have created a function to insert the record into that table and here is the call
select * from add('[{"name":"Yes","value":"yes"},{"name":"No","value":"no"},{"name":"Neutral","value":"neutral"}]') as result;
and here is the function itself
CREATE OR REPLACE FUNCTION public.add(
_fields json[]) RETURNS SETOF json
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
query text;
BEGIN
insert into my_table(fields)
values(_fields);
query = 'SELECT json_build_object(''message'', ''Added.'')';
RETURN QUERY EXECUTE query;
END;
$BODY$;
but this is showing
malformed array literal: "[{"name":"Yes","value":"yes"},{"name":"No","value":"no"},{"name":"Neutra
then I tried this
select * from add('{"name":"Yes","value":"yes"},{"name":"No","value":"no"},{"name":"Neutral","value":"neutral"}') as result;
and this insert statement in function like
insert into polls(fields) values(array([''||_fields||'']::json[]));
and this is showing
syntax error at or near "["

I was missing " for each individual object. This is how to create json object
{"{\"name\":\"Yes\",\"value\":\"yes\"}","{\"name\":\"No\",\"value\":\"no\"}","{\"name\":\"Neutral\",\"value\":\"neutral\"}"}
so the final query is
select * from add('{"{\"name\":\"Yes\",\"value\":\"yes\"}","{\"name\":\"No\",\"value\":\"no\"}","{\"name\":\"Neutral\",\"value\":\"neutral\"}"}') as result;

Related

how to iterate and append jsonb in postgres db function

I have a DB function say "myFunction(input integer)" which takes an input and returns a set of json as below
select * from myFunction(1)
>> [{"a":"b","c":"d"},{"e":"f"}]
I have a DB table "table1" with column 'column1'.
I need to pass the values from table1.column1 into myFunction as an argument and append its result to build one json array
I have created the below db function and it works fine with only one problem, as it appends an empty json at begining.
[{},{"a":"b","c":"d"},{"e":"f"},{"k":"l"}]
kindly help me to provide some optimal solutions or get rid of empty json object in array.
CREATE OR REPLACE FUNCTION myWrapperFunction()
RETURNS SETOF json
LANGUAGE 'plpgsql'
COST 100
STABLE STRICT
ROWS 1000
AS $BODY$
DECLARE
_elements INTEGER[];
_element INTEGER;
_results json;
_result json;
_all_result jsonb;
val json ='{}'::json;
BEGIN
SELECT ARRAY_AGG( DISTINCT column1) into _elements from table1;
FOREACH _element IN ARRAY _elements
LOOP
SELECT * FROM myFunction(_element) into _results;
IF _results IS NOT null THEN
val=val::jsonb||_results::jsonb;
END IF;
END LOOP;
RETURN QUERY select val;
RETURN ;
END; $BODY$;
ALTER FUNCTION myWrapperFunction()
OWNER TO postgres;

How to fetch all data from dynamic table using Function & Stored Procedure in the PostgreSQL database? table name passed in parameter

I am tryign to fetch data from dynamic table using Function but getting error: "SQL Error [42704]: ERROR: type "schemaName.p_dynamictablename" does not exist".
CREATE OR REPLACE FUNCTION schemaName."GetAllDataFromDynamicTable"(IN P_DynamicTableName text, IN id integer)
RETURNS SETOF schemaName."P_DynamicTableName"
AS $$
BEGIN
return query
SELECT * FROM schemaName."P_DynamicTableName" WHERE "Id" = id;
END;
$$
LANGUAGE plpgsql;
I am tryign to fetch data from dynamic table using Stored Procudure but getting error: "SQL Error [42704]: ERROR: type "ml.tableName" does not exist"
Note: able to fetch data from table. ex: select * from schemaName."TableName";
CREATE OR REPLACE FUNCTION schemaName."GetAllDataFromDynamicTable"(tableName character varying)
RETURNS SETOF schemaName."tableName"
as $$
BEGIN
return query
select * from schemaName."tableName";
END;
$$
LANGUAGE plpgsql;
As stated by #Adrian, dynamic sql could be a solution :
CREATE OR REPLACE FUNCTION GetAllDataFromDynamicTable(IN P_DynamicTableName text, IN id integer)
RETURNS SETOF record
AS $$
BEGIN
RETURN QUERY
EXECUTE FORMAT('SELECT * FROM %I WHERE id = %s', P_DynamicTableName, id) ;
END;
$$
LANGUAGE plpgsql;
But calling this function will lead to an error until you can explicitly define the output columns of the function. This is possible only in the case where all the tables to be queried dynamically have the same columns definition.
There is a workaround which consists in converting the output record into a json object :
CREATE OR REPLACE FUNCTION NewGetAllDataFromDynamicTable(IN P_DynamicTableName text, IN id integer)
RETURNS SETOF jsonb
AS $$
BEGIN
RETURN QUERY
EXECUTE FORMAT('SELECT to_jsonb(t.*) FROM %I AS t WHERE t.id = %s', P_DynamicTableName, id) ;
END;
$$
LANGUAGE plpgsql;
Then you can call the function in different ways :
SELECT t.* FROM NewGetAllDataFromDynamicTable ('test', 1) AS t will return a json object
SELECT (jsonb_populate_record(NULL :: "test", t.*)).* FROM NewGetAllDataFromDynamicTable ('test', 1) AS t will return the columns of the table test
see dbfiddle

How can I read keys from a json variable in postgres

I have json object that is structured like this
{
item_id:"f1e00bae-40b1-4bb6-ab21-fc8b5426ad0a"
item_amount:8978
}
now I have a function that looks something like this:
create or replace function update_item(
update_item JSON,
username text
)
RETURNS item
as $$
DECLARE
inserted item;
begin
UPDATE item
set amount=amount+update_item.item_amount
WHERE
item.owner=username
AND
item.id=update_item.item_id
RETURNING * INTO inserted;
RETURN inserted;
END $$
language plpgsql;
But it gives me this error:
missing FROM-clause entry for table "update_item"
So how can I get the required values from the JSON paramter?
You can access a key's value using the ->> operator. But as everything is "text" in JSON, you will have to cast the values when you use them:
create or replace function update_item(update_item JSON, username text)
RETURNS item
as $$
DECLARE
inserted item;
begin
UPDATE item
set amount = amount + (update_item ->> 'item_amount')::int
WHERE item.owner = username
AND item.id = (update_item ->> 'item_id')::uuid
RETURNING * INTO inserted;
RETURN inserted;
END $$
language plpgsql;

Dynamically access RECORD value in pl/pgsql function

Why does accessing a value of the RECORD argument like this works:
CREATE OR REPLACE FUNCTION TT_GetVal1(a RECORD)
RETURNS text AS $$
DECLARE
BEGIN
RETURN a.val1::text;
END;
$$ LANGUAGE plpgsql VOLATILE;
SELECT TT_GetVal1(foo.*)
FROM (SELECT 1 id, 'a' val1) foo;
But not like this:
CREATE OR REPLACE FUNCTION TT_GetVal2(a RECORD)
RETURNS text AS $$
DECLARE
query text;
result text;
BEGIN
query = 'SELECT ($1).val1::text';
EXECUTE query INTO result USING a;
RETURN result;
END;
$$ LANGUAGE plpgsql VOLATILE;
SELECT TT_GetVal2(foo.*)
FROM (SELECT 1 id, 'a' val1) foo;
which returns:
ERROR: could not identify column "val1" in record data type
LINE 1: SELECT ($1).val1::text
How can I dynamically access RECORD values?
The RECORD only lives inside the plpgsql scope. The values are passed to the execute but not the column names.
You can - if the record is from a table - do something like this:
create table table1 (
id integer,
val1 text
);
CREATE OR REPLACE FUNCTION TT_GetVal2(a RECORD)
RETURNS text AS $$
DECLARE
query text;
result text;
BEGIN
query = 'SELECT ($1::text::table1).val1';
EXECUTE query INTO result USING a;
RETURN result;
END;
$$ LANGUAGE plpgsql VOLATILE;
SELECT TT_GetVal2(foo)
FROM (SELECT 1 id, 'a' val1) foo;
Best regards,
Bjarni

PostgreSQL: How to pass table/view name as a parameter to function in PostgreSQL?

For example: I have a VIEW called "view1" which contains 'name' and 'slno' columns, now i want it to be display using FUNCTION called "f1" as shown below:
--Function
create or replace function f1(viewname varchar)
returns table (name varchar,slno integer) as
$body$
begin
return query
select * from viewname;
end;
$body$
language plpgsql;
This is dynamic SQL, so you need EXECUTE.
RETURN QUERY EXECUTE format('SELECT * FROM %I', "name");
Separately, that's a weird thing to want to do.