WITH clause containing a data-modifying statement must be at the top level SQL-state: 0A000 - postgresql

I wrote function, which using WITH construction with insert into table like this:
CREATE OR REPLACE FUNCTION test_func()
RETURNS json AS
$BODY$
begin
return (
with t as (
insert into t(id)
select 1
returning *
)
select '{"a":"a"}'::json
);
end;
$BODY$
LANGUAGE plpgsql VOLATILE;
select test_func()
Thats return error:
ERROR: WITH clause containing a data-modifying statement must be at the top level
SQL-состояние: 0A000
If execute
with t as (
insert into t(id)
select 1
returning *
)
select '{"a":"a"}'::json
Result without errors.
Why this take place and how get round this?

You are doing subselect on that query, with is why it doesn't work.
This won't work either:
select * from (
with t as (
insert into t(id)
select 10
returning *
)
select '{"a":"a"}'::json
) as sub
There are a few solutions to this.
a) Declare it as returning setof and use return query
CREATE OR REPLACE FUNCTION test_func()
RETURNS setof json AS
$BODY$
begin
return query
with t as (
insert into t(id)
select 7
returning *
)
select '{"a":"a"}'::json;
end;
$BODY$
LANGUAGE plpgsql VOLATILE;
b) Declare it as language sql
CREATE OR REPLACE FUNCTION test_func()
RETURNS json AS
$BODY$
with t as (
insert into t(id)
select 8
returning *
)
select '{"a":"a"}'::json;
$BODY$
LANGUAGE sql VOLATILE;
c) Declare output variable(s) in argument list and assign result to them
CREATE OR REPLACE FUNCTION test_func(OUT my_out_var json)
AS
$BODY$
begin
with t as (
insert into t(id)
select 9
returning *
)
select '{"a":"a"}'::json INTO my_out_var;
end;
$BODY$
LANGUAGE plpgsql VOLATILE;

Related

Return table in stored procedure postgresql

I want to return the whole table with stored procedure not function
my code is:
CREATE OR REPLACE PROCEDURE public.test()
RETURN TABLE (
id numeric
, test varchar
) AS -- Results -- remove this
$func$
BEGIN
RETURN QUERY
SELECT *
FROM public.test
END
$func$ LANGUAGE plpgsql;
but its not works.
Stored procedures aren't meant to return anything, use a function. And you don't need PL/pgSQL for that either:
create or replace FUNCTION public.test()
returns TABLE (id numeric, test varchar)
AS
$func$
SELECT *
FROM public.test;
$func$
LANGUAGE sql;
As you return all columns of one table, you can also use returns setof
create or replace FUNCTION public.test()
returns setof public.test
AS
$func$
SELECT *
FROM public.test;
$func$
LANGUAGE sql;
Then use it like a table:
select *
from test();

Query returned successfully but i dont see anyway

I'm new to postgresql, i have a procedure block this is working but i dont see any table or column, what this problem.
CREATE PROCEDURE list3(
)
LANGUAGE sql
AS $$
select * from stok
$$;
call list3()
Functions return values.
Example:
create table table_example(col1 varchar(100),col2 int);
CREATE OR REPLACE FUNCTION get_table_example()
RETURNS TABLE (
l_col1 VARCHAR,
l_col2 INT
)
LANGUAGE plpgsql
AS $$
BEGIN
RETURN QUERY
SELECT *
FROM table_example;
END;
$$
select * from get_table_example();

postgresql: converting CTE column to array

I am trying to convert one of the columns of CTE to array. I keep on getting "syntax error at or near" followed by "ret := array(".
My objective is that the table I am returning from a_function() in example below is stored as a variable to be referred later in function. But I could not find a syntax to do so. So, instead of using CTE, if I can use something else, that would work just as nicely.
Note: I am trying this in pgAdmin III.
create or replace function a_function()
--returns int[][] as
returns table(column1 int, column2 int) as
$body$
begin
return query
select 1,2;
end;
$body$
language 'plpgsql'
;
--select * from a_function();
create or replace function test_a_function()
returns void as
$body$
declare ret int[];
begin
with ret_cte(column1, column2) as (
select * from a_function()
)
ret := array(
select column1 from ret_cte
)
;
--raise notice '%', array_to_string(ret, ',');
end;
$body$
language 'plpgsql'
;
--select test_a_function();
I am trying to convert one of the columns of CTE to array. I keep on getting "syntax error at or near" followed by "ret := array("
You could use:
ret :=array(with ret_cte(column1, column2) as (
select * from a_function()
)
select column1 from ret_cte
);
Rextester Demo
Arrays can be built and returned using the array_agg() function. For example, your second function could be written using a SQL language function that returns the array as follows:
create or replace function test_a_function()
returns int[] as
$body$
select array_agg(column1) from a_function();
$body$
language 'sql';
Alternatively, you can assign the array to a variable like this:
create or replace function test_a_function()
returns void as
$body$
declare
ret int[];
begin
select array_agg(column1)
into ret
from a_function();
raise info '%', ret;
end;
$body$
language 'plpgsql';

PostgreSql - Having trouble displaying my table using perform statment in my function

This is the perform statement I use:
perform * from table1;
But when I execute the function the doesn't display the table onto the terminal. There are no errors produced, the table just doesn't show up.
My function:
CREATE OR replace FUNCTION addToTable (number INTEGER,NAME VARCHAR(15))
RETURNS void AS $$
BEGIN
INSERT INTO table1
VALUES (
number
,NAME
);
perform *
FROM table1;
END;$$
LANGUAGE plpgsql;
CREATE OR replace FUNCTION addToTable_1 (num INTEGER,nam VARCHAR(15))
RETURNS setof table11 AS $$
BEGIN
EXECUTE format( 'insert into table11 values(%s,%s) ',num,quote_literal(nam));
RETURN QUERY
EXECUTE 'select * from table11';
END;$$
LANGUAGE plpgsql;
Call it : select * from addToTable_1(2,'User')

PostgreSQL functions select*

How can I use:
select * from <some_table>;
in a FUNCTION in Postgres?
CREATE OR REPLACE FUNCTION my_function() RETURNS INTEGER AS '
DECLARE
your_record your_table%ROWTYPE;
BEGIN
FOR your_record IN SELECT * FROM your_table
LOOP
--
-- You can access fields of your table using .
-- your_record.your_field
...
END LOOP;
END;
' LANGUAGE 'plpgsql'
STABLE;
or
CREATE OR REPLACE FUNCTION my_function() RETURNS INTEGER AS '
DECLARE
your_record your_table%ROWTYPE;
BEGIN
SELECT * INTO your_record FROM your_table;
--
-- You can access fields of your table using .
-- your_record.your_field
END;
' LANGUAGE 'plpgsql'
STABLE;
EDIT:
With join returning a record:
CREATE OR REPLACE FUNCTION my_function() RETURNS SETOF record AS '
DECLARE
your_record record;
BEGIN
--
-- You should specify a list of fields instead of *
--
FOR your_record IN SELECT * FROM your_table INNER JOIN ...
RETURN NEXT your_record;
END LOOP;
END;
' LANGUAGE 'plpgsql'
STABLE;
To use my_function(), you have to specify fields and datatypes:
See details here
There is a smipler method, if you want to use SQL in the function, use SQL language in the function:
CREATE FUNCTION getallzipcodes()
RETURNS SETOF zip AS
$BODY$
SELECT * FROM zip;
$BODY$
LANGUAGE 'sql';
And this might be useful too (how to call the function)
SELECT function_returning_setof(); -- Wrong!
SELECT * FROM function_returning_setof(); -- OK!
SELECT function_returning_scalar(); -- OK
reference