I have the following stored procedure or function defined in my Postgresql database:
CREATE OR REPLACE FUNCTION insert_val(int)
$body$
BEGIN
FOR i IN 1..10 LOOP
insert into test (val)
values($23);
END LOOP;
END;
$body$ Language 'plpgsql' VOLATILE;
I just want to insert this data inside of a loop, but I get always this error:
Syntaxfehler bei »begin«
Is maybe that I missed something in my function?
I don't understand the error message since it's not in English, but I can see a few problems in your code
CREATE OR REPLACE FUNCTION insert_val(IN val int) RETURNS VOID AS
$body$
BEGIN
FOR i IN 1..10 LOOP
insert into test (val)
values($23);
END LOOP;
END;
$body$ Language 'plpgsql' VOLATILE;
You were missing the return type, you were missing AS and you have forgotten to name the in argument.
You forgot
RETURNS void AS
between the first and the second line.
But that will only take care of the syntax. The $23 is clearly wrong since there are no 23 function arguments. Did you mean $1?
Related
I have this code:
DO $$
DECLARE
NODE_ID bigint := 46;
BEGIN
CREATE OR REPLACE FUNCTION funk(VAL bigint)
RETURNS bigint AS $f$
BEGIN
RETURN VAL;
END; $f$ LANGUAGE plpgsql;
RAISE NOTICE '%', funk(NODE_ID);
END $$;
I works as expected and prints 46 to the console.
I want to get rid of the parameters, because the variable is global. But I am getting errors:
DO $$
DECLARE
NODE_ID bigint := 46;
BEGIN
CREATE OR REPLACE FUNCTION funk()
RETURNS bigint AS $f$
BEGIN
RETURN NODE_ID;
END; $f$ LANGUAGE plpgsql;
RAISE NOTICE '%', funk();
END $$;
I'm getting "NODE_ID not exist". Is there a way to access the outer variable in the function?
No, that won't work, because the function has no connection to your DO block whatsoever. It is a persistent database object that will continue to exist in the database after the DO block has finished.
In essence, a function is just a string with the function body (and some metadata, see pg_proc); in this case, the function body consists of the text between the opening and the closing $f$. It is interpreted by the language handler when the function is run.
The only database data you can reference in a function are other persistent database objects, and a variable in a DO block isn't one of those.
There are no global variables in PostgreSQL except for – in a way – the configuration parameters. You can access these with the SET and SHOW SQL commands and, more conveniently in code, with the set_config and current_setting functions.
Or use dynamic SQL:
DO $$
DECLARE
NODE_ID bigint := 46;
src text := format('
CREATE OR REPLACE FUNCTION funk()
RETURNS bigint AS $f$
BEGIN
RETURN %s;
END;
$f$ LANGUAGE plpgsql;
', NODE_ID::text);
BEGIN
execute src;
RAISE NOTICE '%', funk();
END $$;
(works for me, landing on your question searching for solution of same problem)
I am trying to write a "generic" function that will return labels of any enum (in any schema)...
But I am not having much luck because I am not sure what should argument type be...
The goal would be to be able to call function like this
SELECT common.get_enum_labels('public.rainbow_colors');
SELECT common.get_enum_labels('audit.user_actions');
This is what I have so
CREATE OR REPLACE FUNCTION common.get_enum_labels(enum_name regtype)
RETURNS SETOF text AS
$$
BEGIN
EXECUTE format('SELECT unnest(enum_range(NULL::%s))::text AS enum_labels ORDER BY 1', enum_name);
END;
$$
LANGUAGE plpgsql
STABLE
PARALLEL SAFE
;
Any tips would be appreciated
The argument type should be regtype, do not forget to return something from the function
CREATE OR REPLACE FUNCTION get_enum_labels(enum_name regtype)
RETURNS SETOF text AS
$$
BEGIN
RETURN QUERY
EXECUTE format('SELECT unnest(enum_range(NULL::%s))::text ORDER BY 1', enum_name);
END;
$$
LANGUAGE plpgsql
create or replace function get_enum_labels(enum_name regtype)
returns setof text language sql stable
as $$
select enumlabel::text
from pg_enum
where enumtypid = enum_name
order by enumsortorder
$$;
I'm currently doing a test in PostgreSQL using PGTAP.
In order to minimize redundancy in my code I placed duplicate code inside a
function. I have functions that both returns a SETOF TEXT.
CREATE FUNCTION _create_common_test(
this_argument varchar
) RETURNS SETOF TEXT AS $$
DECLARE
RETURN NEXT IS(this_argument, 'i_am_argument1', 'Checking Argument 1');
MORE RETURN NEXT STATEMENTS HERE....
END;
$$ LANGUAGE plpgsql;
CREATE FUNCTION test_create_common_test_1() RETURNS SETOF TEXT AS $$
BEGIN
RETURN NEXT _create_common_test('i_am_argument1');
END
$$ LANGUAGE plpgsql;
CREATE FUNCTION test_create_common_test_2() RETURNS SETOF TEXT AS $$
BEGIN
RETURN NEXT _create_common_test('i_am_argument2');
END
$$ LANGUAGE plpgsql;
test_create_common_test_1 and test_create_common_test_2 calls the same function _create_common_test() inside their function varying only in the value passed in the argument.
As for my question, Is it possible to return the returned value of _create_common_test() which is a SETOF TEXT in the functions test_create_common_test_1 and test_create_common_test_2?
I have tried using PERFORM _create_common_test('i_am_argument2'),
CREATE FUNCTION test_create_common_test_2() RETURNS SETOF TEXT AS $$
BEGIN
PERFORM _create_common_test('i_am_argument2');
END
$$ LANGUAGE plpgsql;
but it does not enumerate the results I had inside the _create_common_test().
As correctly answered by #a_horse_with_no_name in the comments:
return query select * from _create_common_test('i_am_argument2');
Is it possible to declare hstore as an argument type while creating a function in postgresql?
CREATE FUNCTION samplehstore(uname hstore)
RETURNS SETOF void AS
DECLARE
BEGIN
RAISE NOTICE 'uname : %', uname ;
END;
LANGUAGE plpgsql
Yes. Just tested:
create or replace function samplehstore(_h hstore)
returns text as
$$
begin
return _h->'a';
end
$$
language plpgsql;
select samplehstore('a=>1'::hstore)
>>> 1
Your example is ideally right, but you just forgot to surround the function body inside a string (the hstore part is ok). I recommend doing that this way (see $$ added):
CREATE FUNCTION samplehstore(uname hstore)
RETURNS SETOF void AS $$
DECLARE
BEGIN
RAISE NOTICE 'uname : %', uname ;
END;
$$
LANGUAGE plpgsql;
The PostgreSQL's functions are basically an string, and dollar-quoting is an syntax similar to single quotes, try this:
SELECT $$my string$$, $id$my string$id$, 'my string';
The three are equivalents. See the docs for more information.
"hstoredata" is a variable of type hstore which contains key value pairs.
i.e. for ex: "hstoredata" variable contains the key value pairs '"ed"=>"1", "id"=>"1", "age"=>"27"'.
If "hstoredata" variable is passed to the function i.e select sampletest(hstoredata), function is returning as null.
-- Function: sampletest(hstore)
-- DROP FUNCTION sampletest(hstore)
CREATE OR REPLACE FUNCTION sampletest(hstoredata hstore)
RETURNS SETOF void AS
$BODY$
DECLARE
newhstoredata hstore;
BEGIN
newhstoredata := samplehstore(hstoredata);
RAISE NOTICE 'newhstoredata: %', newhstoredata;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION sampletest(hstore)
OWNER TO postgres;
Below is the program for function samplehstore(hstore)
-- Function: samplehstore(hstore)
-- DROP FUNCTION samplehstore(hstore)
CREATE OR REPLACE FUNCTION samplehstore(hstoredata hstore)
RETURNS SETOF void AS
$BODY$
BEGIN
RAISE NOTICE 'hstoredata: %', hstoredata;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
ROWS 1000;
ALTER FUNCTION samplehstore(hstore)
OWNER TO postgres;
It's unclear what you're asking precisely, but based on the title, I assume you'd like your function to return something.
If so, the issue here is that you're declaring your function as returning setof void.
Declare it as returning whatever it should, and use return ... or return query ..., depending on what you actually need.