PostgreSQL error 22P02 invalid input syntax for integer - postgresql

I keep getting the 22P02 error: invalid input syntax for integer: "{1,2,3}" (see comment in service call).
Here is my service call:
...
using (var command = new NpgsqlCommand("mediabase.create_media", connection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Add("title", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.title;
command.Parameters.Add("uniqueFilename", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.uniqueFilename;
command.Parameters.Add("description", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.description;
command.Parameters.Add("categoryIds", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.categoryIds; /* here the value is "1,2,3" */
command.Parameters.Add("typeId", NpgsqlTypes.NpgsqlDbType.Integer).Value = media.typeId;
command.Parameters.Add("ownerId", NpgsqlTypes.NpgsqlDbType.Integer).Value = media.ownerId;
command.Parameters.Add("statusId", NpgsqlTypes.NpgsqlDbType.Integer).Value = media.statusId;
command.Parameters.Add("gpsLocation", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.gpsLocation;
command.Parameters.Add("locationNameId", NpgsqlTypes.NpgsqlDbType.Integer).Value = media.locationId;
command.Parameters.Add("uploadUserId", NpgsqlTypes.NpgsqlDbType.Integer).Value = media.uploadUserId;
command.Parameters.Add("uploadDate", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.uploadDate;
command.Parameters.Add("uploadIp", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.uploadIp;
command.Parameters.Add("metadataId", NpgsqlTypes.NpgsqlDbType.Integer).Value = metadataId;
command.Parameters.Add("sysEnvironment", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.sysEnvironment;
command.Parameters.Add("languageId", NpgsqlTypes.NpgsqlDbType.Integer).Value = media.languageId;
command.Parameters.Add("publicationIds", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.publicationIds;
command.Parameters.Add("limitations", NpgsqlTypes.NpgsqlDbType.Varchar).Value = media.limitations;
mediaId = Convert.ToInt32(command.ExecuteScalar());
}
pgTransaction.Commit();
...
And the stored procedure:
CREATE OR REPLACE FUNCTION mediabase.create_media(
title character varying,
uniquefilename character varying,
description character varying,
categoryids character varying,
typeid integer,
ownerid integer,
statusid integer,
gpslocation character varying,
locationnameid integer,
uploaduserid integer,
uploaddate character varying,
uploadip character varying,
metadataid integer,
sysenvironment character varying,
languageid integer,
publicationids character varying,
limitations character varying)
RETURNS integer AS
$BODY$
declare _mediaId integer;
declare _point varchar;
declare _gps_location geometry;
declare _id text;
begin
IF (gpslocation <> '') THEN
_point = 'POINT(' || gpslocation || ')';
_gps_location = ST_Transform(ST_GeomFromText(_point, 4326), 900913);
ELSE
_gps_location = NULL;
END IF;
insert into mediabase.media (
title,
unique_filename,
description,
owner_id,
status_id,
gps_location,
type_id,
location_name_id,
upload_user_id,
upload_date,
upload_ip,
metadata_id,
system_environment,
language_id,
limitations)
values (
title,
uniqueFilename,
description,
ownerId,
statusId,
_gps_location,
typeId,
locationNameId,
uploadUserId,
uploadDate,
uploadIp,
metadataId,
sysEnvironment,
languageid,
limitations)
returning id into _mediaId;
-- insert category ids
FOR _id IN SELECT string_to_array (categoryids,',')
LOOP
INSERT into mediabase.media_categories (media_id, category_id)
values (_mediaId, (_id::int));
END LOOP;
-- insert publication ids
FOR _id IN SELECT string_to_array (publicationids,',')
LOOP
INSERT into mediabase.media_publications (media_id, publication_id)
values (_mediaId, (_id::int));
END LOOP;
return _mediaId;
end;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
As you can see in the service method, the input of parameter categoryids is the string "1,2,3", and the NpgsqlDbType is Varchar. And at the stored procedure the input type is character varying.
Here is the execution log:
2013-01-17 08:56:42 CET ERROR: invalid input syntax for integer: "{1,2,3}"
2013-01-17 08:56:42 CET CONTEXT: SQL statement "INSERT into mediabase.media_categories (media_id, category_id)
values (_mediaId, (_id::integer))"
PL/pgSQL function "create_media" line 54 at SQL statement
2013-01-17 08:56:42 CET STATEMENT: select * from mediabase.create_media(('Penguins')::varchar,('079117ec-676f-4022-9950-69e55c2a2600_Penguins.jpg')::varchar,('Description...')::varchar,('1,2,3')::varchar,(1)::int4,(1)::int4,(1)::int4,('')::varchar,(1)::int4,(1)::int4,('17/01/2013 08:56:42')::varchar,('::1')::varchar,(399)::int4,('dev')::varchar,(1)::int4,('1,2')::varchar,('Limitations...')::varchar)
Why is this error poping up?

I've solved the problem using #dezso and #CraigRinger tips. I'm now using an array of integers instead of comma seperated string. Here are the changes:
On the service call:
...
/* media.categoryIds is of type int[] now */
command.Parameters.Add("categoryIds", NpgsqlTypes.NpgsqlDbType.Array | NpgsqlTypes.NpgsqlDbType.Integer).Value = media.categoryIds;
...
On the stored procedure:
...
CREATE OR REPLACE FUNCTION mediabase.create_media(
title character varying,
uniquefilename character varying,
description character varying,
categoryids integer[], -- changed type
typeid integer,
ownerid integer,
statusid integer,
gpslocation character varying,
locationnameid integer,
uploaduserid integer,
uploaddate character varying,
uploadip character varying,
metadataid integer,
sysenvironment character varying,
languageid integer,
publicationids integer[], -- changed type
limitations character varying)
...
...
declare i integer;
...
...
-- insert category ids
FOR i IN SELECT generate_subscripts( categoryids, 1 )
LOOP
INSERT into mediabase.media_categories (media_id, category_id)
values (_mediaId, categoryids[i]);
END LOOP;
-- insert publication ids
FOR i IN SELECT generate_subscripts( publicationids, 1 )
LOOP
INSERT into mediabase.media_publications (media_id, publication_id)
values (_mediaId, publicationids[i]);
END LOOP;
...
Thanks again for the help on this.

Related

Using IF EXISTS (SELECT 1 FROM vw_pse_top_active) in function is returning ERROR: syntax error at or near "SELECT"

-- create or replace function iq_get_pse_top_active()
-- RETURNS TABLE`enter code here`
-- (
symbol character varying,
orderbook integer,
company_name character varying,
logo_url character varying,
display_logo boolean,
base_url character varying,
stock_value real,
volume integer,
last_trade_price numeric(20,4),
last_trade_date timestamp without time zone,
prev_close_price numeric(20,4),
gain_loss numeric(20,4),
percentage numeric(20,2)
)
VOLATILE
AS $body$
BEGIN
RETURN query
select symbol,
orderbook,
company_name,
logo_url,
display_logo,
base_url,
stock_value,
volume,
last_trade_price::numeric(20,4),
last_trade_date,
prev_close_price::numeric(20,4),
gain_loss::numeric(20,4),
percentage::numeric(20,2)
FROM
(
/* This is where the error. What is a good replacement for this condition? */
IF EXISTS (SELECT 1 FROM vw_pse_top_active)
THEN
(select v.symbol,
v.orderbook,
v.company_name,
v.logo_url,
v.display_logo,
v.base_url,
v.stock_value,
v.volume,
v.last_trade_price::numeric(20,4),
v.last_trade_date,
v.prev_close_price::numeric(20,4),
v.gain_loss::numeric(20,4),
v.percentage::numeric(20,2)
from vw_pse_top_active ) as v
ELSE
/* If the table above is empty then this table will be used */
(select h.symbol,
h.orderbook,
h.company_name,
h.logo_url,
h.display_logo,
h.base_url,
h.stock_value,
h.volume,
h.last_trade_price::numeric(20,4),
h.last_trade_date,
h.prev_close_price::numeric(20,4),
h.gain_loss::numeric(20,4),
h.percentage::numeric(20,2)
prod_stock_daily_top_history ) as h
END IF;
) as t;
END;
$body$
/* end of code */

PostgreSQL - how to use equals for null in routine

I have a routine with 4 parameters passed in. Sometimes the last parameter "membership_type " is null but when I use equals it does not return records with null value, it does work if I use "is null" but looking for advice how to make sure both work in the same routine:
create or replace function fitnessone_master.get_location_cancellation_count(club_number double precision, date date, member_profile character varying, membership_type character varying) returns integer
language plpgsql
as $$
declare
member_count integer;
begin
return (select count(distinct a.agreement_number) as member_count
from fitnessone_master.cancelled_accounts a
where cancel_date = get_location_cancellation_count.date
and a.club_number = get_location_cancellation_count.club_number
and a.member_profile = get_location_cancellation_count.member_profile
and a.membership_type = get_location_cancellation_count.membership_type);
end;
$$;
Instead of using = x, which will never match NULL, you can use IS NOT DISTINCT FROM x:
create or replace function fitnessone_master.get_location_cancellation_count(club_number double precision, date date, member_profile character varying, membership_type character varying) returns integer
language plpgsql
as $$
declare
member_count integer;
begin
return (select count(distinct a.agreement_number) as member_count
from fitnessone_master.cancelled_accounts a
where cancel_date = get_location_cancellation_count.date
and a.club_number = get_location_cancellation_count.club_number
and a.member_profile = get_location_cancellation_count.member_profile
and a.membership_type is not distinct from get_location_cancellation_count.membership_type);
end;
$$;

I am having a data insertion problem in tables "pm_feature_id" is primary key from table and it interlinked with other 2 tables

I am having a data insertion problem in tables "pm_feature_id" is primary key from table and it interlinked with other 2 tables.the primary key is auto increment and it declared as variable, i am inserting the data in tables by using below the code"
i am inserting the data but i am trying to return the data "pm_feature_name,pm_component_id" by using select statement
-- FUNCTION: project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
-- DROP FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer);
CREATE OR REPLACE FUNCTION project.fn_insert_features(
featurename character varying,
compntid integer,
descrptn character varying,
helpfilename character varying,
mediatypeid integer,
accntemplyid integer)
RETURNS TABLE(pm_feature_name character varying, pm_component_id integer)
LANGUAGE "sql"
COST 100
VOLATILE
ROWS 1000
AS $BODY$
DECLARE
v_id integer;
BEGIN
Insert into project.pm_features
(pm_feature_name,pm_component_id,pm_description)values (featurename,compntid,descrptn)
RETURNING pm_feature_id INTO v_id;
Insert into project.pm_help_files
(component_feature_id,help_file_name, media_type_id)values (v_id,helpfilename,mediatypeid);
Insert into project.pm_point_of_contacts
(component_feature_id,pm_account_employee_id)values(v_id,accntemplyid);
select pm_feature_name,pm_component_id from project.pm_features
END;
$BODY$;
ALTER FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
OWNER TO pattesaadmin;
ERROR ERROR: syntax error at or near "integer" LINE 21: v_id integer;
^ SQL state: 42601 Character: 637
Try this out:
CREATE OR REPLACE FUNCTION project.fn_insert_features(
featurename character varying,
compntid integer,
descrptn character varying,
helpfilename character varying,
mediatypeid integer,
accntemplyid integer)
RETURNS TABLE(pm_feature_name character varying, pm_component_id integer)
LANGUAGE plpgsql
COST 100
VOLATILE
ROWS 1000
AS $BODY$
DECLARE
v_id integer;
BEGIN
Insert into project.pm_features
(pm_feature_name,pm_component_id,pm_description)values (featurename,compntid,descrptn)
RETURNING pm_feature_id INTO v_id;
Insert into project.pm_help_files
(component_feature_id,help_file_name, media_type_id)values (v_id,helpfilename,mediatypeid);
Insert into project.pm_point_of_contacts
(component_feature_id,pm_account_employee_id)values(v_id,accntemplyid);
return query select pm_features.pm_feature_name, pm_features.pm_component_id from project.pm_features;
END;
$BODY$;
ALTER FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
OWNER TO pattesaadmin;
Note that I changed "sql" to plpgsql and added "return query" in front of the select statement and a semicolon at the end of the statement.
Hopefully this will be enough, I don't have the table descriptions to test completely.
Best regards,
Bjarni

Postgres mistakes parameter for column

I am new to Postgres DBs, and I am trying to write a function (like a stored procedure) to all inserting a user into my database. I know I must be missing something obvious, but I keep getting an error in the code shown where Postgres says { error: column "p_organizationsid" does not exist }. This is the snippet of code that appears to be causing the problem.
CREATE OR REPLACE FUNCTION userupsertget(
p_id uuid,
p_username character varying,
p_organizationid uuid,
p_organizationsid character varying,
p_lastname character varying,
p_firstname character varying,
p_middleinitial character varying,
p_emailaddress character varying,
p_sid character varying,
p_languageid integer,
p_forcepasswordreset bit,
p_salt character varying,
p_hash character varying,
p_statusid uuid,
p_createdby uuid,
p_modifiedby uuid,
p_lastsessionuguid uuid,
p_roleids uuid[],
p_applicationid uuid)
RETURNS SETOF users
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
BEGIN
DO
$do$
DECLARE establishedOrgID uuid;
BEGIN
SELECT org.id FROM organization AS org
WHERE org.sid = p_organizationsid
OR org.id = p_organizationid;
IF EXISTS (SELECT 1 FROM users WHERE id = p_id) THEN
--update statement;
UPDATE users
SET username = p_username,
lastname = p_lastname,
firstname = p_firstname,
middleinitial = p_middleinitial,
emailaddress = p_emailaddress,
sid = p_sid,
languageid = p_languageid,
forcepasswordreset = p_forcepasswordreset,
statusid = p_statusid,
datemodified = current_timestamp,
createdby = p_createdby,
modifiedby = p_modifiedby,
lastsessionguid = p_lastsessionguid
WHERE id = p_id;
IF EXISTS (SELECT 1 FROM users WHERE id = p_id AND statusid <> p_statuid) THEN
UPDATE users SET statusid = p_statusid, datestatusmodified = current_timestamp WHERE id = p_id;
END IF;
ELSE
INSERT INTO users (id, organizationid, username, lastname, firstname, middleinitial,
emailaddress, sid, languageid, forcepasswordreset, statusid, datecreated,
datemodified, createdby, modifiedby, lastsessionguid)
SELECT p_id, establishedOrgID, p_username, p_lastname, p_firstname, p_middleinitial, p_emailaddress, p_sid,
p_languageid, p_forcepasswordreset, p_statusid, current_timestamp, current_timestamp,
p_createdby, p_modifiedby, p_lastsessionuguid
FROM users
WHERE id = p_id;
-- DECLARE newid uuid := LASTVAL();
INSERT INTO users (id, userid, roleid, applicationid, startdate, enddate, createdby, modifiedBy)
SELECT LASTVAL(), roleid, p_applicationid, current_timestamp, current_timestamp, p_createdby, p_modifiedby
FROM UNNEST (p_roleids) AS roleids;
END IF;
END
$do$;
RETURN QUERY
SELECT usr.*, org.uselogin
FROM users AS usr
INNER JOIN organization AS org On org.id = usr.organizationid
WHERE id = p_id;
END;
$BODY$;
As you can see in the PostgreSQL documentation about Creating a function: https://www.postgresql.org/docs/9.1/sql-createfunction.html
you should get better luck if you replace your parameter's name by $n where n is the number of the function parameter:
CREATE FUNCTION add(integer, integer) RETURNS integer
AS 'select $1 + $2;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
or...
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$
DECLARE passed BOOLEAN;
BEGIN
SELECT (pwd = $2) INTO passed
FROM pwds
WHERE username = $1;
RETURN passed;
END;
$$ LANGUAGE plpgsql
SECURITY DEFINER
-- Set a secure search_path: trusted schema(s), then 'pg_temp'.
SET search_path = admin, pg_temp;
Now, if you wish to continue using parameter names, you should declare them as alias:
CREATE or REPLACE FUNCTION data_ctl(opcao char, fdata date, fhora time) RETURNS char(10) AS $$
DECLARE
opcao ALIAS FOR $1;
vdata ALIAS FOR $2;
vhora ALIAS FOR $3;
retorno char(10);
BEGIN
IF opcao = 'I' THEN
insert into datas (data, hora) values (vdata, vhora);
retorno := 'INSERT';
END IF;
IF opcao = 'U' THEN
update datas set data = vdata, hora = vhora where data='1995-11-01';
retorno := 'UPDATE';
END IF;
IF opcao = 'D' THEN
delete from datas where data = vdata;
retorno := 'DELETE';
ELSE
retorno := 'NENHUMA';
END IF;
RETURN retorno;
END;
$$
LANGUAGE plpgsql;
--select data_ctl('I','1996-11-01', '08:15');
select data_ctl('U','1997-11-01','06:36');
select data_ctl('U','1997-11-01','06:36');

postgresql procedure multiple select statement results as output

How do we get multiple result sets from Postgresql procedure. Below is the Procedure i created which is not working. I know that this is not how it works in Postgresql but unable to find the required answer anywhere. After this i need to get these multiple resultsets in Java JDBC.
CREATE OR REPLACE PROCEDURE public.validate_user_login(
a_username character varying,
a_password character varying,
a_ip character varying,
a_uuid character varying,
a_appid integer,
a_osname character varying,
a_osversion character varying,
a_devicemake character varying,
a_devicemodel character varying,
a_devicelat numeric,
a_devicelong numeric
)
LANGUAGE 'plpgsql'
AS $BODY$
DECLARE
v_tenant_id INTEGER;
v_user_id INTEGER;
v_tenant_device_id INTEGER;
statuscode INTEGER;
BEGIN
select user_id , tenant_id into v_tenant_id , v_user_id
from public.users
where username = a_username
and password = a_password;
if v_tenant_id > 0 AND v_user_id > 0
then
statuscode := 1;
select tenant_device_id into v_tenant_device_id from tenant_devices
where tenant_id = v_tenant_id
and uuid = a_uuid;
insert into login_history (user_id , app_id , geo_lat , geo_long ,ip_address , tenant_device_id)
VALUES (v_user_id, a_appid,a_devicelat ,a_devicelong , a_ip, v_tenant_device_id );
else
statuscode := -1;
end if;
select user_id , username , email , phone_no, alt_phone_no
from public.users
where username = a_username
and password = a_password
limit 1;
select role_id from
public.user_roles
where user_id = v_user_id;
select statuscode;
END
$BODY$;