how to convert a varchar field value into an integer field - postgresql

for example in a table one field is character varying so how to convert that character varying to an Integer type, what exactly is I need to get the return value in Integer datatype
Database : postgresql-9.2

i would suggest to make Functions to do the job i.e
CREATE OR REPLACE FUNCTION chartoint(charparam character varying)
RETURNS integer AS
$BODY$
SELECT CASE WHEN trim($1) ~ '[0-9]+' THEN CAST(trim($1) AS integer) ELSE NULL END;
$BODY$
LANGUAGE sql IMMUTABLE STRICT

You may try like this:
SELECT NULLIF(your_value, '')::int
or extend that like thats
SELECT CAST(coalesce(column_name, '0') AS integer) as Value
from table_name

SELECT mycolumn::integer FROM mytable WHERE something
SELECT CASE WHEN mycolumn = NULL THEN NULL ELSE mycolumn :: Integer END
FROM mytable WHERE something

Related

Postgres function input parameter as TEXT Array problem

My Table looks like
CREATE TABLE dev.clbk_logs
(
id bigint NOT NULL,
clbk_typ character varying(255) COLLATE pg_catalog."default",
clbk_json json,
cre_dte timestamp without time zone,
ld_id bigint,
ld_num character varying(255) COLLATE pg_catalog."default",
mod_dte timestamp without time zone,
CONSTRAINT clbk_logs_pkey PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
My function is
CREATE OR REPLACE FUNCTION dev.my_method(p_callback_types TEXT[], p_days_ago INT)
RETURNS SETOF dev.clbk_logs
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
return query
SELECT * FROM dev.clbk_logs
WHERE (clbk_Typ::TEXT) IN (($1)) AND (current_date - cre_dte::date)< p_days_ago;
END;
$BODY
Can someone please help what is wrong in above, and should make expected result.
I wanted to pass an array of string and in query.
Error I am getting is
LINE 2: WHERE (clbk_Typ::TEXT) IN (($1)) AND (current_date - cre_...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
QUERY: SELECT * FROM dev.clbk_logs
WHERE (clbk_Typ::TEXT) IN (($1)) AND (current_date - cre_dte::date)< p_days_ago
CONTEXT: PL/pgSQL function dev.my_method(text[],integer) line 3 at RETURN QUERY
SQL state: 42883
You need to use = any() not IN with an array.
The cast to ::text is also not needed. And for readability I would recommend using the parameter name, rather than the number:
CREATE OR REPLACE FUNCTION dev.my_method(p_callback_types TEXT[], p_days_ago INT)
RETURNS SETOF dev.fourkites_clbk_logs
LANGUAGE plpgsql
AS $BODY$
BEGIN
return query
SELECT *
FROM dev.fourkites_clbk_logs
WHERE clbk_Typ = any (p_callback_type)
AND (current_date - cre_dte::date) < p_days_ago;
END;
$BODY
Note that your condition on cre_dte can't use an index if you ever create one. If you want that condition to be able to use an index, change it to:
and cre_dte >= current_date - p_days_ago;

Filter bigint values on insert Postgresql

I have 2 tables in Postgresql with the same schema, the only difference is that in one of the table id field is of type bigint. Schema of the table I need to fill with data looks like this:
create table test_int_table(
id int,
description text,
hash_code int
);
I need to copy the data from test_table with bigint id to public.test_int_table. And some of the values which are bigger than id range should be filtered out. How can I track those values without hardcoding the range?
I can do something like this, but I would like to build more generic solution:
insert into test_int_table
select * from test_table as test
where test.id not between 2147483647 and 9223372036854775808
By generic I mean without constraints on the columns names and their number. So that in case, I have multiple columns of bigint type in other tables how can I filter all of their columns values generically (without specifying a column name)?
There is no generic solution, as far as I can tell.
But I would write it as
INSERT INTO test_int_table
SELECT *
FROM test_table AS t
WHERE t.id BETWEEN -2147483647 AND 2147483647;
You can do something like this if you want to track :
Create a function like this :
CREATE OR REPLACE FUNCTION convert_to_integer(v_input bigint)
RETURNS INTEGER AS $$
DECLARE v_int_value INTEGER DEFAULT NULL;
BEGIN
BEGIN
v_int_value := v_input::INTEGER;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Invalid integer value: "%". Returning NULL.', v_input;
RETURN NULL;
END;
RETURN v_int_value;
END;
$$ LANGUAGE plpgsql;
and write a query like this :
INSERT INTO test_int_table SELECT * FROM test_table AS t WHERE convert_to_integer(t.id) is not null;
Or you can modify a function to return 0.

PostgreSQL : Cast Data Type from Text to Bigint when using WHERE IN

I've problem when try to cast data type from TEXT to BIGINT when using WHERE IN on PostgreSQL in procedure. This always gives
operator does not exist: bigint = text. Try cast the variable in the query.
But still get the same notice. This is example query:
DECLARE
-- $1 params text
BEGIN
SELECT * FROM table_a where
colId IN($1); // notice is here, colId is bigint
END
/*Call the procedure*/
SELECT my_function('1,2,3,4,5');
How do we cast the variable? Thanks!
Using strings for id list is wrong design. You can use a arrays in PostgreSQL.
For example
CREATE OR REPLACE FUNCTION foo(VARIADIC ids int[])
RETURNS SETOF table_a AS $$
SELECT * FROM table_a WHERE id = ANY($1)
$$ LANGUAGE sql;
SELECT foo(1,2,3);
But, usually wrapping simple SQL to functions looks like broken design. Procedures should not to replace views.

catching select query return value in postgresql function and use it

I want to execute this function. But it got error said
ERROR:
syntax error at or near ":="
LINE 7: select result:=MAX(path_history_id)as path INTO result from...
In this function I want to:
execute select with (MAX) and it will return maximum id from a table;
catch that value (it is an integer value);
put that value into last select query where condition.
I cant find a way in postgresql to do this.
CREATE OR REPLACE FUNCTION memcache(IN starting_point_p1 character varying, IN ending_point_p1 character varying)
RETURNS TABLE(path integer, movement_id_out integer, object_id_fk_out integer, path_history_id_fk_out integer, walking_distance_out real, angel_out real, direction_out character varying, time_stamp_out timestamp without time zone, x_coordinate_out real, y_coordinate_out real, z_coordinate_out real) AS
$BODY$
DECLARE result int;
BEGIN
select result:=MAX(path_history_id)as path INTO result from path_history_info where starting_point=starting_point_p1 and ending_point =ending_point_p1 and achieve='1';
return query
select * from movement_info where path_history_id_fk=result;
END;
$BODY$
LANGUAGE plpgsql
Syntax Error
The first query inside your function needs to be changed as follows:
select MAX(path_history_id)as path INTO result
from path_history_info
where starting_point=starting_point_p1
and ending_point =ending_point_p1 and achieve='1';
A single Query
You don't actually need a stored procedure for this. A single query can achieve the same result.
select * from movement_info where path_history_id_fk =
(SELECT MAX(path_history_id) FROM path_history_info
where starting_point=starting_point_p1
and ending_point =ending_point_p1 and achieve='1';

Can I use INSERT inside CASE in postgres

I am trying to create a function in postgres that would insert a row if it doesn't exist and return the row's id (newly created or existing).
I came up with this:
CREATE OR REPLACE FUNCTION
get_enttype(name character varying, module character varying)
RETURNS integer LANGUAGE SQL STABLE AS $$
SELECT typeid FROM enttypes WHERE name = $1 AND module = $2
$$;
CREATE OR REPLACE FUNCTION
ensure_enttype(name character varying, module character varying)
RETURNS integer LANGUAGE SQL AS $$
SELECT CASE WHEN get_enttype($1, $2) IS NULL
THEN
INSERT INTO enttypes(name, module) VALUES ($1, $2) RETURNING typeid
ELSE
get_enttype($1, $2)
END
$$;
It however raises a syntax error because of INSERT inside CASE. I managed to fix this problem by creating a separate function with this INSERT and using this function in CASE. It works as expected, but this fix seems a little strange. My question is - can I fix this without creating another function?
No, you can't use INSERT inside CASE in an sql function. You can, however:
Use a PL/PgSQL function with IF ... ELSE ... END statements; or
Use a writable common table expression (wCTE) or INSERT INTO ... SELECT query
Pure SQL can do it:
create or replace function ensure_enttype(
name character varying, module character varying
) returns integer language sql as $$
insert into enttypes(name, module)
select $1, $2
where get_enttype($1, $2) is null
;
select get_enttype($1, $2);
$$;