I am trying to write a function in postgresql and i am getting a syntax error for the if statement:
CREATE OR REPLACE FUNCTION getallcampuses(IN a character varying, IN b character varying)
RETURNS TABLE(campusid charactervarying, campusname character varying) AS
$BODY$
BEGIN
if $1 = 'PREK' then
SELECT * from "SIS_campus";
ELSE
BEGIN
IF $2 = 'DAll' then
SELECT distinct(district_id) || 'ALL' AS CampusID, ' District' AS CampusName
UNION
SELECT campus_id, name
FROM "SIS_campus"
WHERE district_name IS NOT NULL
order by name;
Elsif $2 = 'All' then
SELECT campus_id, name
FROM "SIS_campus"
WHERE district_name IS NOT NULL
and isnumeric(name) = 0
order by name;
end if;
END
end if;
END
$BODY$
LANGUAGE sql;
Here is the error:
ERROR: syntax error at or near "if"
LINE 5: if $1 = 'PREK' then
^
The function body is PL/PgSQL, but you declared it LANGUAGE sql.
Use LANGUAGE plpgsql if you're writing PL/PgSQL.
(related prior answer)
Related
This is a working function in SQL Server 2014 Express
CREATE FUNCTION [dbo].[Func_Account_FollowingCustomer]
(#AccountNumber NVARCHAR(20))
RETURNS BIT
AS
BEGIN
DECLARE #bResult BIT
IF (SELECT COUNT(AccountNumber) FROM dbo.Account AS A
WHERE DetailByAccountObject = 1
AND AccountObjectType = 1
AND AccountNumber = #AccountNumber) > 0
SET #bResult = 1
ELSE
SET #bResult = 0
RETURN #bResult
END
I try to convert to PostgreSQL 14, I have
CREATE FUNCTION public.func_account_following_customer(IN account_number character varying)
RETURNS bit
LANGUAGE 'sql'
declare #b_result bit
begin
if(select count(account_number) from account as a where detail_by_account_object = 1 and account_object_type = 1 and account_number = #account_number) > 0
set #b_result = 1
else
set #b_result = 0
return #b_result;
end;
ALTER FUNCTION public.func_account_following_customer(character varying)
OWNER TO postgres;
Error
ERROR: syntax error at or near "declare" LINE 5: declare #b_result bit ^
How to fix it?
language sql can't use variables or procedural elements (like IF), you need language plpgsql - but the syntax for variable names is different and the assignment is not done using set
The function body is a string constant, typically specified using dollar quoting.
If you want to return true/false flags, use boolean instead of bits.
Parameters or variables are referenced using # but simply with their name.
But you don't need procedural code for such a simple SQL query that just returns true/false.
CREATE FUNCTION public.func_account_following_customer(IN p_account_number character varying)
RETURNS boolean
LANGUAGE sql
as
$$
select count(*) > 0
from account as a
where detail_by_account_object = 1
and account_object_type = 1
and account_number = p_account_number;
$$
;
As a PL/pgSQL function this would be:
CREATE FUNCTION public.func_account_following_customer(IN p_account_number character varying)
RETURNS boolean
LANGUAGE plpgsql
as
$$
declare
l_result boolean;
begin
if (select count(*)
from account as a
where detail_by_account_object = 1
and account_object_type = 1
and account_number = p_account_number) > 0
then
l_result := true;
else
l_result := false;
end if;
return l_result;
end;
$$
;
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.
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';
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$
I'm trying to create a conditional statement in a plpgsql function what will filter out only the records I want through an if statement. I am just testing now, but here is my table structure:
CREATE TABLE addresses
(
gid serial NOT NULL,
housenum character varying(30),
prefix character varying(10),
name character varying(100),
type character varying(16)
)
Here is my function:
CREATE OR REPLACE FUNCTION "geomCheck".getAllFoo() RETURNS SETOF
addresses AS
$BODY$
DECLARE
r addresses%rowtype;
BEGIN
FOR r IN SELECT * FROM addresses
WHERE gid > 0
LOOP
if name = 'BRIE' then
RETURN NEXT r;
end if;
END LOOP;
RETURN;
END
$BODY$
LANGUAGE 'plpgsql' ;
But when I go to call the function I get this error:
ERROR: column "name" does not exist
LINE 1: SELECT name = 'BRIE'
^
QUERY: SELECT name = 'BRIE'
CONTEXT: PL/pgSQL function "geomCheck".getallfoo() line 8 at IF
********** Error **********
ERROR: column "name" does not exist
SQL state: 42703
Context: PL/pgSQL function "geomCheck".getallfoo() line 8 at IF
How do I check if the name = 'BRIE' in the if statement?
You need to prefix name with r:
BEGIN
FOR r IN SELECT * FROM addresses
WHERE gid > 0
LOOP
if r.name = 'BRIE' then -- instead of "name" => "r.name"
RETURN NEXT r;
end if;
END LOOP;
RETURN;
END
I need to check whether the given text is numeric or not from the
function.
Creating function for isnumeric():
CREATE OR REPLACE FUNCTION isnumeric(text) RETURNS BOOLEAN AS $$
DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
Function from which I am calling the isnumeric() function:
create or replace function tm(var text)
returns varchar as
$$
begin
if (select isnumeric(var))=t::BOOLEAN then
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
end;
$$
language plpgsql;
Calling functon:
select tm('1');
Getting an error:
Here is the error details:
ERROR: column "t" does not exist
LINE 1: SELECT (select isnumeric(var))=t::BOOLEAN
You don't need a select (and it's actually wrong, as the error indicates) - just call isnumeric directly.
Also, by the way, your function is missing a return statement.
To sum it all up:
create or replace function tm(var text)
returns varchar as
$$
begin
if (isnumeric(var)) then -- call isnumeric directly
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
return '0'; -- missing return value in the OP
end;
$$
language plpgsql;
this will help you to identify your field is numeric or not:
select * from Table where field_name ~ '^[0-9]*$'
for decimal values you can use^[0-9.]*$ instead ^[0-9]*$
select getDataType('2021'); == Number
select getDataType('2021-05-12 23:12:10'); == Date
select getDataType('2021-05-12'); == Date
select getDataType('2X'); == String
CREATE
OR REPLACE FUNCTION getDataType ( TEXT ) RETURNS TEXT AS $$ DECLARE
x VARCHAR;
BEGIN
x = $1 :: NUMERIC;
RETURN 'Number';
EXCEPTION
WHEN OTHERS THEN
BEGIN
x = $1 :: DATE;
RETURN 'Date';
EXCEPTION
WHEN OTHERS THEN
RETURN 'String';
END;
END;
$$ STRICT LANGUAGE plpgsql IMMUTABLE;
I have a select statement that is generated dynamically based on the supplied parameter. The problem is that postgresql always says:
argument of WHERE must be type boolean, not type character varying no matter what the parameter is. Did I miss anything?
CREATE OR REPLACE FUNCTION getuid(name character varying) RETURNS integer AS $$
DECLARE
statement varchar;
uid integer;
BEGIN
IF ($1 = '') THEN
statement := 'TRUE';
statement := CAST(statement AS BOOLEAN);
ELSE
statement := 'users.keywords ILIKE''' || '%' || $1 || '%''';
END IF;
SELECT INTO uid id FROM users WHERE "statement";
RETURN uid;
END;
$$ LANGUAGE plpgsql
You need EXECUTE if you want to generate dynamic commands inside a function. You could also use two different sections:
CREATE OR REPLACE FUNCTION getuid(name character varying) RETURNS integer AS $$
DECLARE
statement varchar;
uid integer;
BEGIN
IF ($1 = '' OR $1 IS NULL) THEN -- section 1
SELECT id INTO uid FROM users;
ELSE -- section 2
SELECT id INTO uid FROM users WHERE users.keywords ILIKE '%' || $1 || '%';
END IF;
RETURN uid;
END;
$$ LANGUAGE plpgsql;
EXECUTE is a PL/pgSQL statement and not SQL statement. So you have to wrap your dynamic query into PL/pgSQL stored procedure.
Be careful about variable substitution and do not forget to use quote_literal() or quote_nullable() when building up you query.
Have look in documentation here: http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN