I have created a sequence like below:
CREATE SEQUENCE public.shiwangini_seq
INCREMENT BY 1
MINVALUE 1
MAXVALUE 9223372036854775807
START 150037
CACHE 1
NO CYCLE;
After this - I have created a function which will use this sequence to generate next value:
create or replace function shiwangini_unq(out v_final_value2 bigint) as $$
declare
v_seq_value bigint;
v_shard_id bigint;
v_final_value2 bigint ;
begin
select nextval('shiwangini_seq') into v_seq_value ;
v_shard_id := 2;
select concat (v_seq_value , v_shard_id ) into v_final_value2 ;
end ;
$$ language plpgsql ;
Now, this function returns null whenever I call it. Like below:
select shiwangini_unq(); ----null
I checked concat() manages type conversion itself. Even after that, in my case it's returning null. I help will be really appreciated to make it working. Thanks in advance!
You can write this as normal SQL function (without OUT parameter) and eliminate all data conversations.
create or replace
function shiwangini_unq()
returns bigint
language sql
as $$
select 10*nextval('shiwangini_seq')+2;
$$;
OR just get rid of the function altogether.
create sequence shiwangini_seqX start with 12 increment by 10;
See demo
Your main problem is, that the variable v_final_value2 overshadows your out parameter.
But all that isn't needed to begin with.
You should declare a proper return type. But you are overcomplicating things here. You can make this more efficient without PL/pgSQL and a simple SQL function:
create or replace function shiwangini_unq()
return bigint
as $$
select concat(nextval('shiwangini_seq'), 2)::bigint;
$$ language sql;
You give the return type of your function as an input, that is the problem. The below code is working well for me if there any error please text me back.
Try this
create or replace function shiwangini_unq() returns bigint as $$
declare
v_seq_value bigint;
v_shard_id bigint;
v_final_value2 bigint ;
begin
select nextval('shiwangini_seq') into v_seq_value ;
v_shard_id := 2;
select concat (v_seq_value, v_shard_id ) into v_final_value2 ;
return v_final_value2;
end ;
$$ language plpgsql ;
Related
I am currently making a function, and I need to declare a variable as a result of an other function within my main_function.
CREATE OR REPLACE FUNCTION main_function(t_name varchar)
RETURNS void AS
$BODY$
DECLARE
var_1 varchar := execute format('select var_1 from sub_function(%s)' ,t_name);
BEGIN
--do something with var_1
END;
$BODY$
LANGUAGE plpgsql;
My sub_function returns one row with three colums.
select var_1 from sub_function()
returns only one result. I would like to store that result in the variable var_1 because I will need it later.
It is also important that this sub_function operates with the t_name variable, which I get from the main_function's argument.
I have tried to do it in many different ways, for example without the execute function.
var_1 varchar := format('select var_1 from sub_function(%s)' ,t_name);
Unfortunately this one returns the whole text "select var_1 from sub_function('soimething')" and not the result of the query.
What should I do?
Thanks for any help in advance!
return_column_name is the column your function should return. I don't know the name since you have said your function returns 3 columns. FYI, you can get all three values by using select ... into va1, var2, var3
CREATE OR REPLACE FUNCTION main_function(t_name varchar)
RETURNS void AS
$BODY$
DECLARE
var_1 varchar;
BEGIN
select <return_column_name> from sub_function(t_name) into var_1;
END;
$BODY$
LANGUAGE plpgsql;
Link to doc
Need Output from table with in clause in PostgreSQL
I tried to make loop or ids passed from my code. I did same to update the rows dynamically, but for select I m not getting values from DB
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying
)
RETURNS void
AS
$$
DECLARE
ArrayText text[];
i int;
BEGIN
select string_to_array(branchidcol, ',') into ArrayText;
i := 1;
loop
if i > array_upper(ArrayText, 1) then
exit;
else
SELECT
pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight,
pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE
pd.accountgroupid = accountgroupIdCol AND pd.branchid IN(ArrayText[i]::numeric);
i := i + 1;
end if;
END LOOP;
END;
$$ LANGUAGE 'plpgsql' VOLATILE;
There is no need for a loop (or PL/pgSQL actually)
You can use the array directly in the query, e.g.:
where pd.branchid = any (string_to_array(branchidcol, ','));
But your function does not return anything, so obviously you won't get a result.
If you want to return the result of that SELECT query, you need to define the function as returns table (...) and then use return query - or even better make it a SQL function:
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying )
RETURNS table(branchid integer, totallr integer, totalarticle integer, totalweight numeric, totalamount integer)
AS
$$
SELECT pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight, pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE pd.accountgroupid = accountgroupIdCol
AND pd.branchid = any (string_to_array(branchidcol, ',')::numeric[]);
$$
LANGUAGE sql
VOLATILE;
Note that I guessed the data types for the columns of the query based on their names. You have to adjust the line with returns table (...) to match the data types of the select columns.
This request:
unnest('{1,2}'::int[]);
gives to me this error:
syntax error at or near "unnest"
neither unnest('{1,2}'); works
Why?
intire:
CREATE OR REPLACE FUNCTION result() RETURNS setof users AS
$$
DECLARE
BEGIN
unnest('{1,2}'::int[]);
RETURN QUERY SELECT * FROM users;
END;
$$ LANGUAGE plpgsql;
SELECT result();
EDIT
The core idea:
To retrive and manipualate with the bigint[] which is stored inside in a column.
So, i have got this:
SELECT * FROM users WHERE email = email_ LIMIT 1 INTO usr;
Then, usr.chain contains some bigint[] data. For example, {1,2,3,4,5,6,7,8,9,10}. I want to save only the 4 last of them.
How to retrieve {7,8,9,10} and {1,2,3,4,5,6} and iterate over these arrays?
I only found the solution is to use SELECT FROM unnest(usr.chain) AS x ORDER BY x ASC LIMIT (sdl - mdl) OFFSET mchain and so on. but unnest function gives to me this stupid error. I'm really do not understand why it happends. It doesn't work in sucj easy case I wrote at the beginning of the question. subarray function doesn't work because of the data type is bigint[] not int[]
Futher more, the code unnest(ARRAY[1,2]) gives to me the same error.
http://www.postgresql.org/docs/9.2/static/functions-array.html
The same error for array_append function
to iterate over array:
CREATE OR REPLACE FUNCTION someresult(somearr bigint[] ) RETURNS setof bigint AS
$$
DECLARE
i integer;
x bigint;
BEGIN
for x in select unnest($1)
loop
-- do something
return next x;
end loop;
-- or
FOR i IN array_lower($1, 1) .. array_upper($1, 1)
LOOP
-- do something like:
return next ($1)[i];
end loop;
END;
$$ LANGUAGE plpgsql;
select someresult('{1,2,3,4}') ;
array_append ....
CREATE OR REPLACE FUNCTION someresult2(somearr bigint[],val bigint ) RETURNS bigint[] AS
$$
DECLARE
somenew_arr bigint[];
BEGIN
somenew_arr = array_append($1, $2 );
return somenew_arr;
END;
$$ LANGUAGE plpgsql;
select someresult2('{1,2,3,4}' ,222) ;
so, here you have basic example how to iterate and append arrays. Now can you write step by step what you want to do, to achieve .
I've got a postgresql stored procedure, which is returning an integer.
When I call that function, the result is returned with the function name as column name.
For example the name of the function is: "add-person". The column name, when invoking the function, is "add-person".
Is there a way to make the database return the integer with a self-choosen column name? For example "id"?
I think it is pretty easy, but I currently miss the forests for the trees..
Edit:
What i'd missed to tell, is that the return value is a variable, like so:
CREATE OR REPLACE FUNCTION "scheme"."add-person"(arggivenname character varying, argfamilyname character varying) RETURNS integer AS
$BODY$
DECLARE
varResponse integer;
BEGIN
-- Operations before
INSERT INTO "scheme"."table"
(
given_name,
family_name
)
VALUES
(
arggivenname,
argfamilyname
)
RETURNING
"id"
INTO
varResponse;
-- Operations after
RETURN varResponse;
END;
$BODY$
LANGUAGE plpgsql VOLATILE COST 100;
You can us the AS statement for that. That means:
Select add-person() AS yourcolumnname
To have a named column from a function it is necessary to create a type and return that type from the function
create type mytype as (mycolumn integer);
create or replace function ri()
returns mytype as $$
select 1;
$$ language sql;
select * from ri();
mycolumn
----------
1
Edit
Or much simpler without the type creation as in #pozs comment:
create or replace function ri(out mycolumn integer)
as $$
select 1;
$$ language sql;
Something like this:
CREATE OR REPLACE FUNCTION get(param_id integer)
RETURNS integer AS
$BODY$
BEGIN
SELECT col1 FROM TABLE WHERE id = param_id;
END;
$BODY$
LANGUAGE plpgsql;
I would like to avoid a DECLARE just for this.
Yes you can. There are a number of ways.
1) RETURN (SELECT ...)
CREATE OR REPLACE FUNCTION get_1(_param_id integer)
RETURNS integer
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN _param_id;
-- Or:
-- RETURN (SELECT col1 FROM tbl WHERE id = _param_id);
END
$func$;
2) Use an OUT or INOUT parameter
CREATE OR REPLACE FUNCTION get_2(_param_id integer, OUT _col1 integer)
-- RETURNS integer -- is optional noise in this case
LANGUAGE plpgsql AS
$func$
BEGIN
SELECT INTO _col1 col1 FROM tbl WHERE id = _param_id;
-- also valid, but discouraged:
-- _col1 := col1 FROM tbl WHERE id = _param_id;
END
$func$;
More in the manual here.
3) (Ab)use IN parameter
Since Postgres 9.0 you can also use input parameters as variables. The release notes for 9.0:
An input parameter now acts like a local variable initialized to the passed-in value.
CREATE OR REPLACE FUNCTION get_3(_param_id integer)
RETURNS integer
LANGUAGE plpgsql AS
$func$
BEGIN
SELECT INTO _param_id col1 FROM tbl WHERE id = _param_id;
RETURN _param_id;
-- Also vlaid, but discouraged:
-- $1 := col1 FROM tbl WHERE id = $1;
-- RETURN $1;
END
$func$;
Variants 2) and 3) do use a variable implicitly, but you don't have to DECLARE one explicitly (as requested).
4) Use a DEFAULT value with an INOUT parameter
This is a bit of a special case. The function body can be empty.
CREATE OR REPLACE FUNCTION get_4(_param_id integer, INOUT _col1 integer = 123)
RETURNS integer
LANGUAGE plpgsql AS
$func$
BEGIN
-- You can assign some (other) value to _col1:
-- SELECT INTO _col1 col1 FROM tbl WHERE id = _param_id;
-- If you don't, the DEFAULT 123 will be returned.
END
$func$;
INOUT _col1 integer = 123 is short notation for INOUT _col1 integer DEFAULT 123. See:
The forgotten assignment operator "=" and the commonplace ":="
5) Use a plain SQL function instead
CREATE OR REPLACE FUNCTION get_5(_param_id integer)
RETURNS integer
LANGUAGE sql AS
'SELECT col1 FROM tbl WHERE id = _param_id';
Or use use param reference $1 instead of param name.
Variant 5) one uses plain single quotes for the function body. All the same. See:
What are '$$' used for in PL/pgSQL
Insert text with single quotes in PostgreSQL
db<>fiddle here - demonstrating all (incl. call)