pgsql integer out of range for negative values - postgresql

It might sound an easy question to most of you. However, I'm unable to avoid this error. I have a table with id(primary_key) with bigint datatype and we started feeding records into that from min -negative value (-9223372036854775808).
Now, I need to do some operation on that table based on each record data. So, I need to iterate through all records. This is the sample loop, I'm using and I'm getting below error with that:
psql:update-migration2.sql:39: ERROR: integer out of range
CONTEXT: PL/pgSQL function inline_code_block line 5 at FOR with integer loop variable
Below , is the sample loop where I'm getting this error:
do $$
declare
i bigint;
begin
for i in -9223372036854775808 .. -9223372036852105062 loop
-- my logic
i := i + 1;
end loop;
end;$$
Any immediate help/solution will be really appreciated.

FOR ... LOOP only works on integer (-2147483648 to +2147483647)
This is OK:
do $$
declare
i bigint;
begin
for i in -2147483648 .. -2147483647 loop
-- my logic
end loop;
end;$$
DO
This fails:
do $$
declare
i bigint;
begin
for i in -2147483649 .. -2147483647 loop
-- my logic
end loop;
end;$$
ERROR: integer out of range
CONTEXT: PL/pgSQL function inline_code_block line 5 at FOR with integer loop variable

Related

pgsql concat for number returning null

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 ;

How can I assign the value returned from an insert query to a variable in PL/pgSQL

I am trying to create a function in Postgres which does a simple insert, and i want the id of the insert for later usage. But I'm being said 'Synatx error near (' at line question_key := INSERT INTO QUESTIONS(question, status, questionword) values (in_question, 'unanswered', in_questionword) RETURNING q_key;
Is this the right way to assign?
CREATE OR REPLACE FUNCTION insert_new_record_hackathon(
in_keywords character varying[],
in_question text,
in_questionword character varying)
RETURNS void AS
$BODY$
DECLARE
i integer;
question_key integer;
keyword_key integer;
BEGIN
question_key := INSERT INTO QUESTIONS(question, status, questionword) values (in_question, 'unanswered', in_questionword) RETURNING q_key;
FOREACH i in ARRAY in_keywords
LOOP
keyword_key := INSERT INTO keywords(keyword) VALUES (in_keywords[i]) RETURNING k_key;
INSERT INTO qnkeywordmap(q_key, k_key) values (question_key, keyword_key)
END LOOP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
The correct way it to use INSERT ... RETURNING with the INTO clause:
INSERT INTO keywords ...
RETURNING k_key INTO keyword_key;

Syntax error at or near "unnest"

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 .

Syntax error in declaration of PL/pgSQL function

Can anyone help me with this procedure? It's a pretty simple one, just want to insert some data into a table, but pgAdmin is giving me some errors.
This is the procedure code:
CREATE OR REPLACE FUNCTION FILL_INVOICE2(IN_NUM integer)
RETURNS void AS
DECLARE
counter numeric := 0;
BEGIN
IF in_num > 1 THEN
WHILE counter < 10
LOOP
INSERT INTO INVOICE(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,RECORD_DATE,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
VALUES(counter,counter,counter,100,current_date,current_date,1,100,'Telco services',1111);
counter := counter + 1;
RAISE NOTICE 'The counter is %', counter;
END LOOP;
END IF;
RETURN;
END;
Error is:
ERROR: syntax error at or near "DECLARE counter numeric"
LINE 3: DECLARE
^
********** Error **********
ERROR: syntax error at or near "DECLARE counter numeric"
SQL state: 42601
Character: 75"
This would work:
CREATE OR REPLACE FUNCTION fill_invoice2(in_num integer)
RETURNS void AS
$func$
DECLARE
counter numeric := 0;
BEGIN
IF in_num > 1 THEN
WHILE counter < 10
LOOP
INSERT INTO invoice(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,RECORD_DATE
,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
VALUES(counter,counter,counter,100,current_date,current_date
,1,100,'Telco services',1111);
counter := counter + 1;
RAISE NOTICE 'The counter is %', counter;
END LOOP;
END IF;
END
$func$ LANGUAGE plpgsql;
Major points
Missing language declaration.
Missing quotes around function body. Preferrably, use dollar-quoting - like #Eelke advised. Details:
Insert text with single quotes in PostgreSQL
But the whole function looks needlessly expensive.
Use a single INSERT based on generate_series() to replace the expensive loop with inserts per row. Optionally, you can wrap it in a function. Example with simple SQL function:
CREATE OR REPLACE FUNCTION fill_invoice2(in_num integer)
RETURNS void AS
$func$
INSERT INTO invoice(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,RECORD_DATE
,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
SELECT g,g,g,100,current_date,current_date,1,100,'Telco services',1111
FROM generate_series(0,10) g
WHERE $1 > 1;
$func$ LANGUAGE sql;
Does the same as your original.
I would also consider column defaults for some of your columns. For instance:
ALTER TABLE invoice
ALTER COLUMN invoice_date SET DEFAULT current_date
, ALTER COLUMN record_date SET DEFAULT current_date;
Details:
converting mysql scripts to postgresql script
Then just don't mention those column in the INSERT statement and defaults are filled in automatically.
The body should be passed as a string
CREATE OR REPLACE FUNCTION FILL_INVOICE2(IN_NUM integer) RETURNS void AS
$$
DECLARE
counter numeric := 0;
BEGIN
IF in_num > 1 THEN
WHILE counter < 10 LOOP
INSERT INTOI NVOICE(ID,INVOICE_ID,SUBSCRIBER_ID,AMOUNT,INVOICE_DATE,
RECORD_DATE,INVOICE_TYPE,REST_TO_PAY,DESCRIPTION,INVOICE_REFERENCE)
VALUES(counter,counter,counter,100,current_date,current_date,1,100,
'Telco services',1111);
counter := counter + 1;
RAISE NOTICE 'The counter is %', counter;
END LOOP;
END IF;
RETURN;
END;
$$
You can use $$ to mark the beginning en end of a multiline string.

I am trying to unnet an array in other to query the postgres DB

I am call the function but it is returning error that array value must start with "{" or dimension information using
Create or Replace Function get_post_process_info(IN v_esdt_pp character varying[])
Returns setof Record as
$$
Declare
post_processes RECORD;
esdt_value character varying;
v_sdsname character varying[];
v_dimension character varying[];
counter int := 1;
Begin
-- to loop through the array and get the values for the esdt_values
FOR esdt_value IN select * from unnest(v_esdt_pp)
LOOP
-- esdt_values as a key for the multi-dimensional arrays and also as the where clause value
SELECT distinct on ("SdsName") "SdsName" into v_sdsname from "Collection_ESDT_SDS_Def" where "ESDT" = esdt_values;
raise notice'esdt_value: %',esdt_value;
END LOOP;
Return ;
End
$$ Language plpgsql;
Select get_post_process_info(array['ab','bc]);
Your function sanitized:
CREATE OR REPLACE FUNCTION get_post_process_info(v_esdt_pp text[])
RETURNS SETOF record AS
$func$
DECLARE
esdt_value text;
v_sdsname text[];
v_dimension text[];
counter int := 1;
BEGIN
FOR esdt_value IN
SELECT * FROM unnest(v_esdt_pp) t
LOOP
SELECT distinct "SdsName" INTO v_sdsname
FROM "Collection_ESDT_SDS_Def"
WHERE "ESDT" = esdt_value;
RAISE NOTICE 'esdt_value: %', esdt_value;
END LOOP;
END
$func$ Language plpgsql;
Call:
Select get_post_process_info('{ab,bc}'::text[]);
DISTINCT instead of DISTINCT ON, missing table alias, formatting, some cruft, ...
Finally the immediate cause of the error: a missing quote in the call.
The whole shebang can possibly be replaced with a single SQL statement.
But, obviously, your function is incomplete. Nothing is returned yet. Information is missing.