SQL Query error insert into - sql

I'm trying to do this function:
CREATE OR REPLACE FUNCTION "SA_PRJ".usp_verify_allocated_time(p_uid integer, p_project_id integer, p_allocated_time numeric, p_achieved_time numeric, p_task_desc character varying, p_obs character varying, p_date timestamp without time zone)
RETURNS void AS
$BODY$
declare alloc_id integer;
BEGIN
if not "SA_ADM".usp_check_permission(p_uid, 'SA_PRJ', 'usp_add_timesheet_record') then
raise exception 'User ID % nu are permisii pentru aceasta operatie!', p_uid;
end if;
SELECT *,
case when SUM(fld_allocated_time) / 24 < fld_allocated_days
then
INSERT INTO "SD_PRJ".tbl_project_timesheet(fld_emp_id, fld_project_id, fld_is_allocated,fld_allocated_time, fld_achieved_time, fld_task_desc, fld_obs)
VALUES (p_uid,p_project_id,coalesce(alloc_id,0), p_allocated_time, p_achieved_time,p_task_desc, p_obs);
else 'Not OK'
end as Alocated
from
(
SELECT p.fld_id, p.fld_allocated_days, t.fld_allocated_time
FROM "SD_PRJ".tbl_project p
INNER JOIN "SD_PRJ".tbl_project_timesheet t
ON p.fld_id=t.fld_id
where t.fld_project_id = p_project_id
)AS Alias
GROUP BY fld_id, fld_allocated_days, fld_allocated_time
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION "SA_PRJ".usp_usp_verify_allocated_time(integer, integer, numeric, numeric, character varying, character varying, timestamp without time zone)
OWNER TO postgres;
I want to make a function to join two columns from tables "SD_PRJ".tbl_project and "SD_PRJ".tbl_project_timesheet and make the compare SUM(fld_allocated_time) / 24 < fld_allocated_days
from an input parameter p_project_id (WHERE t.fld_project_id = p_project_id) and make the insert if its ok or not.
The input column fld_project_id can have more than 1 appear in the table.
tbl_ = table name
fld_ = column / field name
"SD_PRJ" = my schema name
\ERROR: syntax error at or near "INTO"
Error:
LINE 12: INSERT INTO "SD_PRJ".tbl_project_timesheet(fld_emp_id, fl...
^
********** Error **********
ERROR: syntax error at or near "INTO" SQL state: 42601 Character: 550

Yeah, you're trying to write an insert inside a select statement.
What you probably want is something like this:
INSERT INTO "SD_PRJ".tbl_project_timesheet(fld_emp_id, fld_project_id, fld_is_allocated,fld_allocated_time, fld_achieved_time, fld_task_desc, fld_obs)
select p_uid,p_project_id,coalesce(alloc_id,0), p_allocated_time, p_achieved_time,p_task_desc, p_obs
from
(
SELECT p.fld_id, p.fld_allocated_days, t.fld_allocated_time
FROM "SD_PRJ".tbl_project p
INNER JOIN "SD_PRJ".tbl_project_timesheet t
ON p.fld_id=t.fld_id
where t.fld_project_id = p_project_id
)AS Alias
GROUP BY fld_id, fld_allocated_days, fld_allocated_time
having SUM(fld_allocated_time) / 24 < fld_allocated_days
Not completely sure if everything there is right, but that's the general gist of it I think.

Related

ERROR: null values cannot be formatted as an SQL identifier Where: PL/pgSQL function inline_code_block line 17 at EXECUTE

I'm trying this script, in ? passed GeoJson
DO $$
DECLARE
lib_table_name text;
lib_table_id text;
geom geometry;
BEGIN
SELECT
point_node_libs.lib_type,
point_node_libs.lib_type_id,
nodes.geometry
INTO lib_table_name, lib_table_id, geom
FROM point_nodes AS nodes
LEFT JOIN point_node_libs
ON point_node_libs.id = nodes.node_lib_id
WHERE ST_DWithin(geom, ST_GeomFromGeoJSON(?), 0);
EXECUTE format('
SELECT
id,
geometry,
metadata,
draft,
node_lib_id AS nodeLibId,
created_at AS createdAt,
updated_at AS updatedAt,
point_node_libs.*,
lib_table.*
FROM point_nodes AS points
LEFT JOIN point_node_libs
ON point_node_libs.id = points.node_lib_id
LEFT JOIN (
SELECT *
FROM %I
WHERE id=%s
) lib_table
WHERE $1;', lib_table_name, lib_table_id) USING (ST_DWithin(geom, ST_GeomFromGeoJSON(?), 0));
END $$;
and the error is
[22004] ERROR: null values cannot be formatted as an SQL identifier Where: PL/pgSQL function inline_code_block line 17 at EXECUTE
DB: Postgre 13.9

Parse function param to inner query is not possible?

I am trying to execute this query but for some reason I seem to get this error
ERROR: syntax error at or near "$1"
LINE 8: FROM $1
Which I am not sure makes sense?
The function which should execute it is this
CREATE OR REPLACE FUNCTION tsrange_aggregate(_tbl regclass, selected_entity_id uuid, foreign_tsrange tsrange, OUT result Boolean)
RETURNS BOOLEAN AS
$$
BEGIN
EXECUTE
'SELECT $3 <# (SELECT tsrange(min(COALESCE(lower(valid), ''-infinity'')), max(COALESCE(upper(valid), ''infinity'')))
FROM (
SELECT *, count(nextstart > enddate OR NULL) OVER (ORDER BY valid DESC NULLS LAST) AS grp
FROM (
SELECT valid
, max(COALESCE(upper(valid), ''infinity'')) OVER (ORDER BY valid) AS enddate
, lead(lower(valid)) OVER (ORDER BY valid) As nextstart
FROM $1
where entity_id = $2
) a
) b
GROUP BY grp
ORDER BY 1);'
INTO result
USING _tbl, selected_entity_id, foreign_tsrange ;
END
$$ LANGUAGE plpgsql;
SELECT tsrange_aggregate('parent_registration'::regclass, '0006f79d-5af7-4b29-a200-6aef3bb0105f', tsrange('2011-05-23 02:00:00', '2013-05-23 02:00:00' ));
is it not possible to function parameter to inner query? or am I missing something here?
The error message suggests that postgres cannot cope with a table called $1. You have to concatenate the table name in the variable with the string, e.g. using FORMAT:
CREATE OR REPLACE FUNCTION myfunc(text)
RETURNS BOOLEAN AS
$$
DECLARE res boolean;
BEGIN
EXECUTE FORMAT('SELECT b FROM %I',$1) INTO res;
RETURN res;
END
$$ LANGUAGE plpgsql;
%I treats the argument value as an SQL identifier.
Demo: db<>fiddle

What's the error in this PostgreSQL function code at line 17?

PostgreSQL is throwing an unrecognized error at line 17 in pgpAdmin and I have no idea why. I checked all the documentation and I'm sure I have all the statements right.
I'm using the following PostgreSQL version:
PostgreSQL 9.3.4, compiled by Visual C++ build 1600, 64-bit
Here's the code:
Tried commenting out the surrounding offending lines. Double checked all syntax.
CREATE OR REPLACE FUNCTION sp_test_crud (
op VARCHAR,
test_id INTEGER,
part_id BIGINT,
station_id BIGINT,
pass_val BOOLEAN,
name_val VARCHAR(50),
start_datetime timestamp with time zone,
end_datetime timestamp with time zone
)
RETURNS SETOF public.test
AS $$
DECLARE return_test_id BIGINT;
BEGIN
IF op = 'SELECT' THEN
RETURN QUERY (SELECT * FROM public.test WHERE id = test_id);
ELSIF op = 'DELETE' THEN
DELETE FROM public.test WHERE id = test_id RETURNING id INTO return_test_id;
RETURN QUERY SELECT * FROM return_test_id;
ELSIF (op = 'UPDATE') THEN
UPDATE public.test SET partid = part_id, stationid = station_id, pass = pass_val, name = name_val, startdatetime = start_datetime, enddatetime = end_datetime
WHERE testid = test_id RETURNING id INTO return_test_id;
RETURN QUERY SELECT * FROM return_test_id;
ELSIF op = 'INSERT' THEN
INSERT INTO public.test (partid, stationid, name, startdatetime, enddatetime, pass)
VALUES (part_id, station_id, name_val, start_datetime, end_datetime, pass_val) RETURNING id INTO return_test_id;
RETURN QUERY SELECT * FROM return_test_id;
ELSE
RAISE ERROR 'Operation ' + op + ' not valid.';
END IF;
RETURN;
END;
$$
LANGUAGE 'plpgsql';
It keeps generating this error.
ERROR: unrecognized exception condition "error"
CONTEXT: compilation of PL/pgSQL function "sp_test_crud" near line 18
SQL state: 42704
ERROR is not a pre-defined level for RAISE. According to the PostgreSQL documentation, you can use
DEBUG, LOG, INFO, NOTICE, WARNING, and EXCEPTION

How to dynamically select into query

EXECUTE format(
'SELECT MAX(sum)
FROM table 1
WHERE %s = %s') INTO max_value USING id_column, id_value;
Getting error: ERROR: operator does not exist: character varying =
integer.
Also, when I try to run the below code:
update table1 set column2 = max_value + sum;
I get another error:
"ERROR: column "max_value" does not exist"
You can use this:
CREATE OR REPLACE FUNCTION maxvaloftable ()
RETURNS integer AS
$BODY$
DECLARE
resultat integer = 2;
BEGIN
resultat= (SELECT MAX(sum) FROM table) ;
RETURN resultat;
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT
COST 100;
ALTER FUNCTION maxvaloftable()
OWNER TO postgres;
update table1 set column2 = (select maxvaloftable ()) + sum;

Error column reference is ambiguous

I have a function which:
compare two columns from different tables
make the insert
How can I get some improvement on this code because I get this error:
ERROR: column reference "fld_id" is ambiguous
SQL state: 42702
line 17 at PERFORM
CREATE OR REPLACE FUNCTION "SA_PRJ".usp_add_timesheet_test(p_uid integer, p_project_id integer, p_allocated_time numeric, p_achieved_time numeric, p_task_desc character varying, p_obs character varying, p_date timestamp without time zone)
RETURNS void AS
$BODY$
BEGIN
DECLARE sum_alloc_time numeric;
DECLARE alloc_hours integer;
DECLARE fld_id integer;
SELECT #sum_alloc_time = SUM(fld_allocated_time)
from "SD_PRJ".tbl_project_timesheet
where fld_project_id = p_project_id;
SELECT #alloc_hours = p.fld_allocated_days, #fld_id = p.fld_id
FROM "SD_PRJ".tbl_project p
INNER JOIN "SD_PRJ".tbl_project_timesheet t
ON p.fld_id=t.fld_id
where t.fld_project_id = p_project_id;
IF #sum_alloc_time <= #alloc_hours THEN
INSERT INTO "SD_PRJ".tbl_project_timesheet(fld_emp_id, fld_project_id, fld_is_allocated,fld_allocated_time, fld_achieved_time, fld_task_desc, fld_obs, fld_date)
VALUES (p_uid,p_project_id,coalesce(alloc_id,0), p_allocated_time, p_achieved_time,p_task_desc, p_obs, p_date);
RAISE NOTICE 'INSERT OK!';
ELSE
RAISE NOTICE 'NOT OK';
END IF;
END;
$BODY$ LANGUAGE plpgsql;
There are two tables:
"SD_PRJ".tbl_project (
fld_id
,fld_allocated_days)
"SD_PRJ".tbl_project_timesheet (
fld_id
, fld_project_id
,fld_allocated_time)
Working version:
CREATE OR REPLACE FUNCTION "SA_PRJ".usp_add_timesheet_test(
p_uid integer, p_project_id integer, p_allocated_time numeric
, p_achieved_time numeric, p_task_desc varchar, p_obs varchar, p_date timestamp)
RETURNS void AS
$func$
DECLARE
_sum_alloc_time numeric;
_alloc_hours integer;
_fld_id integer;
BEGIN
SELECT SUM(fld_allocated_time)
INTO _sum_alloc_time
FROM "SD_PRJ".tbl_project_timesheet
WHERE fld_project_id = p_project_id;
SELECT p.fld_allocated_days, p.fld_id
INTO _alloc_hours, _fld_id
FROM "SD_PRJ".tbl_project p
JOIN "SD_PRJ".tbl_project_timesheet t USING (fld_id)
WHERE t.fld_project_id = p_project_id;
IF _sum_alloc_time <= _alloc_hours THEN
INSERT INTO "SD_PRJ".tbl_project_timesheet
(fld_emp_id, fld_project_id, fld_is_allocated, fld_allocated_time
, fld_achieved_time, fld_task_desc, fld_obs, fld_date)
VALUES (p_uid, p_project_id, coalesce(alloc_id,0), p_allocated_time
, p_achieved_time, p_task_desc, p_obs, p_date);
-- alloc_id is undefined, you probably need to use SELECT .. FROM .. instead
RAISE NOTICE 'INSERT OK!';
ELSE
RAISE NOTICE 'NOT OK';
END IF;
END
$func$ LANGUAGE plpgsql;
But this is still needlessly inefficient. Could be done in a single DML statement with data-modifying CTEs. Try a search for related questions.
You need to study the basics first.