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
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
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
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
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;
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.