0

I need to replace schema and table name by parameters in following function (that is currently working perfectly):

CREATE OR REPLACE FUNCTION public.my_function_119()
 RETURNS integer
 LANGUAGE plpgsql
AS $function$
                DECLARE _check INTEGER;
                BEGIN
                    SELECT SUM("length"/1000)
                    FROM public."National_Grid_multiline"
                    INTO _check;
                    RETURN _check;
                END
                $function$

I have tried following solution (and its numerous variations) :

CREATE OR REPLACE FUNCTION public.my_function_119(schema text, tablename text)
 RETURNS INTEGER
 LANGUAGE  plpgsql
AS
$function$
                DECLARE _check INTEGER;
                BEGIN
                  RETURN
                    '(SELECT SUM((length/1000))::integer FROM ' || schema || '."' || tablename || '")::integer INTO _check' ;
                RETURN _check;
                END
                $function$

but keep running into following error code :

psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type integer: "(SELECT SUM((length/1000))::integer FROM public."National_Grid_multiline")::integer INTO _check"

CONTEXT:  PL/pgSQL function my_function_119(text,text) while casting return value to function's return type

Why is this not working ? The 'length' column contains float values.

2 Answers 2

1

You have to use dynamic SQL, because you cannot use a parameter for an identifier.

Also, make sure to avoid SQL injection by using format rather than concatenating strings:

EXECUTE
   format(
      'SELECT SUM((length/1000))::integer FROM %I.%I',
      schema,
      table_name
   )
   INTO _check';
Sign up to request clarification or add additional context in comments.

7 Comments

script is running on my local machine, no SQL injection danger
That doesn't necessarily help. You may have a table with a non-standard name...
okay, but that is not really the probelm right now. My issue remains that my original function without parameters (see code above) works fine, but that - as soon as I use the two paramaters -- I get all kinds of errors that seem not to be related to the paramaters itself.
Yes. And that is what my answer solves.
unfortunatly, your solution throws a parenthesis mismatch. after orrecting, it throws follwing error : .... psycopg2.errors.UndefinedObject: type "format" does not exist LINE 1: SELECT format('(SELECT SUM((length/1000))::integer FROM %I.%... ^ QUERY: SELECT format('(SELECT SUM((length/1000))::integer FROM %I.%I', schema, table_name) 'INTO _check' CONTEXT: PL/pgSQL function my_function_119(text,text) line 4 at EXECUTE
|
0

You can try this :

CREATE OR REPLACE FUNCTION public.my_function_119(schema text, tablename text)
 RETURNS INTEGER
 LANGUAGE  plpgsql
AS
$function$
DECLARE
res integer ;
BEGIN
EXECUTE E'
(SELECT SUM((length/1000))::integer INTO res FROM ' || schema || '."' || tablename || '"):: integer' ;
RETURN res ;
END ;
$function$

7 Comments

non of the two solutions above fix this issue. they just produce other error messages
What is the data type of the column 'length' in the table public.National_Grid_multiline ?
What is the result when you execute : SELECT SUM(length/1000) FROM public.National_Grid_multiline ?
data type of the column in database is double precision (but replacing that in the function by integer does not solve the issue neither. The answer posted by you throws following error : -> syntax error at or near "END" SELECT SUM(length/1000) FROM public.National_Grid_multiline -> relation "public.national_grid_multiline" does not exist SELECT SUM(length/1000) FROM public."National_Grid_multiline" -> 684921.2474125557 SELECT SUM("length"/1000) FROM public."National_Grid_multiline" 684921.2474125557
I have updated the function my_function in my previous answer to make it working. The error "relation "public.national_grid_multiline" does not exist" means the table public.national_grid_multiline doesn't exist in the database you are connected to, so you have to solve this issue before going further.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.