Syntax error in postgresql function - postgresql

I am a beginner for postgresql and I would like to create a procedure in sql.
I created a function that inserts a record into a table and it returns the id.
But there is something wrong, I don't want any result except for the output parameter.
CREATE OR REPLACE FUNCTION public."InsertVideo"
(
OUT out_scope_id integer,
IN in_youtubeidvideo varchar[],
IN in_title varchar,
IN in_rating double precision,
IN in_viewcount integer
)
RETURNS integer AS
$$
DECLARE
id INTEGER;
INSERT INTO Video
(
YoutubeIdVideo,
Title,
Rating,
ViewCount,
DataAdded,
ConvertedFlag,
SchedulingFlag
)
VALUES
(
in_youtubeidvideo,
in_title,
in_rating,
in_viewcount,
now(),
false,
false
);
SELECT id := CURRVAL(pg_get_serial_sequence('public.video','IDVideo'));
RETURN id;
$$
LANGUAGE 'sql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;

A SQL function can't use variables and you don't need them for this. Changed it to:
CREATE OR REPLACE FUNCTION public."InsertVideo" (
IN in_youtubeidvideo varchar[],
IN in_title varchar,
IN in_rating double precision,
IN in_viewcount integer
) RETURNS integer AS $$
INSERT INTO Video (
YoutubeIdVideo,
Title,
Rating,
ViewCount,
DataAdded,
ConvertedFlag,
SchedulingFlag
) VALUES (
in_youtubeidvideo,
in_title,
in_rating,
in_viewcount,
now(),
false,
false
);
SELECT CURRVAL(pg_get_serial_sequence('public.video','IDVideo'));
$$ LANGUAGE 'sql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER;

Related

query has no destination for result data i am facing this error

PostgreSQL 14
TABLE
CREATE TABLE IF NOT EXISTS settings.tbl_tmp
(
pk_sys_qr_settings_id bigint NOT NULL DEFAULT nextval('settings.tbl_tmp_pk_sys_qr_settings_id_seq'::regclass),
sin_product smallint DEFAULT 0,
vhr_key character varying(10) COLLATE pg_catalog."default" NOT NULL,
vhr_value character varying(250) COLLATE pg_catalog."default",
CONSTRAINT tbl_tmp_pkey PRIMARY KEY (pk_sys_qr_settings_id),
CONSTRAINT tbl_tmp_vhr_key_key UNIQUE (vhr_key)
)
--FUNCTION 1 - CALL FROM fn_test
CREATE OR REPLACE FUNCTION fn_test1(sinProduct SMALLINT,
vhrKey VARCHAR(10),
vhrValue VARCHAR(250))
RETURNS VOID AS $$
BEGIN
INSERT INTO settings.tbl_tmp
(sin_product, vhr_key, vhr_value)
VALUES
(sinProduct, vhrKey, vhrValue);
END;
$$ LANGUAGE plpgsql;
FUNCTION 2
CREATE OR REPLACE FUNCTION fn_test(sinProduct SMALLINT,
vhrKey VARCHAR(10),
vhrValue VARCHAR(250))
RETURNS VOID AS $$
DECLARE
a SMALLINT;
BEGIN
BEGIN
SELECT * FROM fn_test1(1::SMALLINT, 'Anil-5'::VARCHAR(10), 'KV-5'::VARCHAR(250));
INSERT INTO settings.tbl_tmp
(sin_product, vhr_key, vhr_value)
VALUES
(sinProduct, vhrKey, vhrValue);
END;
END;
$$ LANGUAGE plpgsql;
--ERROR
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function fn_test(smallint,character varying,character varying) line 7 at SQL statement
SQL state: 42601
Quote from the manual
Sometimes it is useful to evaluate an expression or SELECT query but discard the result, for example when calling a function that has side-effects but no useful result value. To do this in PL/pgSQL, use the PERFORM statement:
As the called function doesn't return anything to begin with, it's safe to use perform.
So use:
perform fn_test1(1::SMALLINT, 'Anil-5'::VARCHAR(10), 'KV-5'::VARCHAR(250));
Instead of select * from fn_test(..)
As you are using Postgres 14, you could also use a procedure in both cases, as you don't want to return a result.

Return data from Common Table Expression in postgres

I am trying to return some data I have from Common Table Expression to my backend but unable to because Postgres doesn't see the table.
CREATE OR REPLACE FUNCTION request(
question_id_func INTEGER,
requester_account_id_func INTEGER,
counter_func NUMERIC
) RETURNS INTEGER AS $$
with notif AS (
INSET INTO notification(...) VALUES (...) RETURNING *
)
UPDATE question....
RETURN (SELECT notif_id FROM notif);
END $$ LANGUAGE PLPGSQL
Does anyone has a better idea how you can extract the data from CTE and return it?
Much appreciated.
You will need to put your UPDATE statement into a CTE, and then assign the output to a function variable using a final SELECT statement.
For example:
CREATE OR REPLACE FUNCTION request(
question_id_func INTEGER,
requester_account_id_func INTEGER,
counter_func NUMERIC
) RETURNS INTEGER AS $body$
DECLARE
result integer;
BEGIN
WITH notif AS (
INSERT INTO notification(...) VALUES (...) RETURNING *
),
question_update AS (
UPDATE question....
)
SELECT notif.notif_id INTO result FROM notif;
RETURN result;
END $body$ LANGUAGE PLPGSQL

Postgres function must have return type record because of OUT parameters

I have written the following function in postgresql and am facing the below mentioned error. Can anyone help me how to fix it?
ERROR: function result type must be record because of OUT parameters
SQL state: 42P13
CREATE OR REPLACE FUNCTION fun_audit_trail(in as_on_date date, out mail_id varchar, out user_id varchar, out user_name varchar,
out last_login_time timestamp, out last_logout_time timestamp, out logout_flag varchar, out user_available_flag varchar)
RETURNS setof ret_cursor AS
$BODY$
DECLARE ref_cursor ret_cursor;
BEGIN
open ref_cursor for
select am.am_usrmailid,am.am_usr_loginid,am.am_usr_name,am.am_last_login_time,am.am_last_logout_time,am.am_logout_flag,am.am_usr_available_flag
into mail_id,user_id,user_name,last_login_time,last_logout_time,logout_flag,user_available_flag
from auth_monitor am where am_last_login_time <= as_on_date
return next ref_cursor;
END $BODY$
LANGUAGE 'plpgsql' COST 100.0 SECURITY INVOKER
Why use a refcursor at all? And returns setof ref_cursor means you want to return more than one refcursor which you clearly don't want to do.
A language sql function declared as returns table() is the correct choice if you want to return a result from a function:
CREATE OR REPLACE FUNCTION fun_audit_trail(in as_on_date date)
RETURNS table(mail_id varchar, user_id varchar, user_name varchar,
last_login_time timestamp, last_logout_time timestamp,
logout_flag varchar, user_available_flag varchar)
$BODY$
select am.am_usrmailid,am.am_usr_loginid,am.am_usr_name,am.am_last_login_time,am.am_last_logout_time,am.am_logout_flag,am.am_usr_available_flag
from auth_monitor am
where am_last_login_time <= as_on_date
$BODY$
LANGUAGE sql;
Then you can use it like this:
select *
from fun_audit_trail(date '2019-10-20');

Insert within function fails with "query has no destination for result data"

Here is the complete example code:
CREATE TABLE testtbl (
id integer NOT NULL,
intval integer,
strval varchar(64)
);
CREATE SEQUENCE testtbl_id_seq
START WITH 1 INCREMENT BY 1
NO MINVALUE NO MAXVALUE CACHE 1;
ALTER SEQUENCE testtbl_id_seq OWNED BY testtbl.id;
ALTER TABLE ONLY testtbl ALTER COLUMN id SET DEFAULT
nextval('testtbl_id_seq'::regclass);
ALTER TABLE ONLY testtbl ADD CONSTRAINT testtbl_pkey PRIMARY KEY (id);
CREATE FUNCTION insert_testtbl (p_intval integer, p_strval varchar(64))
RETURNS integer AS $$
DECLARE
v_new_id integer;
BEGIN
INSERT INTO testtbl (intval, strval) VALUES (p_intval, p_strval)
RETURNING v_new_id;
RETURN v_new_id;
END;
$$ LANGUAGE plpgsql;
SELECT insert_testtbl(1, 'One');
When I run this (PostgreSQL version is 9.6.1), I get:
ERROR: query has no destination for result data
CONTEXT: PL/pgSQL function insert_testtbl(integer,character varying) line 5 at SQL statement
This doesn't make sense; I AM specifying a destination for the result!
What am I doing wrong here? Thanks!!!
I am specifying a destination for the result!
No you are not.
RETURNING v_new_id; simply means:
"return the current value of the variable v_new_id from this insert statement"
(which is null as the variable was never assigned a value)
You are not storing the generated value anywhere.
You either need to use an into clause:
CREATE FUNCTION insert_testtbl (p_intval integer, p_strval varchar(64))
RETURNS integer AS $$
DECLARE
v_new_id integer;
BEGIN
INSERT INTO testtbl (intval, strval) VALUES (p_intval, p_strval)
RETURNING id
INTO v_new_id; --<<< HERE
RETURN v_new_id;
END;
$$ LANGUAGE plpgsql;
Or convert everything it simple SQL function:
CREATE FUNCTION insert_testtbl (p_intval integer, p_strval varchar(64))
RETURNS integer AS
$$
INSERT INTO testtbl (intval, strval) VALUES (p_intval, p_strval)
RETURNING id;
$$ LANGUAGE sql;

Insert Function Postgresql how to test with parameters?

I have the following insert function in postgresql 9.4.
I am totally unable to test it with parameters.
DROP FUNCTION "Public".cash_inserts(integer, bigint, timestamp without time zone, character varying, numeric, numeric);
CREATE OR REPLACE FUNCTION "Public".cash_inserts(
cashid integer,
cashserial bigint,
cashdate timestamp without time zone,
cashmemo text,
cashcredit numeric,
cashdebit numeric)
RETURNS integer AS
$BODY$
INSERT INTO "Public"."CashAccounts"
VALUES
(
CashId,
CashSerial,
CashDate,
CashMemo,
CashCredit,
CashDebit
) RETURNING CashId ;
$BODY$
LANGUAGE sql VOLATILE
COST 100;
ALTER FUNCTION "Public".cash_inserts(integer, bigint, timestamp without time zone, text, numeric, numeric)
OWNER TO robert100;
Because the fields 'cashid,cashserial,cashdate' are either auto-incrementing or created by the database, I did not enter any values. However, Cashmemo is'Not NUll' and 'Cashcredit,Cashdebit' are nullable or optional.
Why include cashid,cashserial,cashdate in the function insert statement if they are either auto-incrementing or created by the database as you said and the function returns int?
Maybe try:
DROP FUNCTION "Public".cash_inserts(integer, bigint, timestamp without time zone, character varying, numeric, numeric);
CREATE OR REPLACE FUNCTION "Public".cash_inserts(
cashmemo text,
cashcredit numeric,
cashdebit numeric)
RETURNS integer AS
$BODY$ INSERT INTO "Public"."CashAccounts"
VALUES
(
CashMemo,
CashCredit,
CashDebit
) RETURNING CashId ; $BODY$
LANGUAGE sql VOLATILE
COST 100;
ALTER FUNCTION "Public".cash_inserts(text, numeric, numeric)
OWNER TO robert100
Then call the function with the variable parameters and cashid, cashserial and cashdate will be auto generated by the database.
It appears my original question was correct.What I discovered is that when you supply parameters, they must all be in quotes like this:
SELECT "Public".cash_inserts(
'10',
'4',
'12-12-12',
'COOL',
'200',
'300'
);