How to create function in Vertca? - sql

I began to study vertiсa. I tryis created customer function but getting error. Help me pliase
My code sql
create or REPLACE FUNCTION itog_report_status.get_warn_lvl(day_count NUMERIC)
returns varchar
AS $function$
DECLARE res varchar ;
BEGIN
select status::varchar
from itog_reports_status.status_warn_level
where days = (
select MIN(days)
from itog_reports_status.status_warn_level
where day_count <= days);
RETURN COALESCE(res, 'RED')
END;

Related

How to compare two values in PL/pgSQL?

I have this code where I try to load a dimension table if the date of the current day has not been loaded yet. It is not loading any record, is my comparison wrong?
CREATE OR REPLACE PROCEDURE load_dimDate()
LANGUAGE plpgsql AS
$$
DECLARE
_date date := get_fecha();
_year int = get_year();
_month int = get_month();
_day int = get_day();
BEGIN
if _date <> (SELECT MAX(date) from dimDate) then
INSERT INTO dimfechas(date, year, month, day)
VALUES(_date, _year, _month, _day);
end if;
END
$$;
Both the variable _date and the select statement are of type DATE.

How to recursively return table in postgres function using plpgsql? Without using CTE/With Recursive

I tried implementing it here as follows
create or replace function getTextEditRecord(textId integer)
RETURNS Table (
text_id integer,
text_details character varying,
new_text_id integer) AS $$
DECLARE
curr_rec record;
temp_rec record;
BEGIN
curr_rec :=
(select tm.text_id, tm.text_details, tm.new_text_id from text_master tm
where tm.text_id = textId);
IF FOUND THEN
IF curr_rec.text_id != curr_rec.new_text_id THEN
temp_rec := getTextEditRecord(curr_rec.new_text_id);
--RETURN TABLE HERE
ELSE
-- No Recursive call directly return table
--RETURN TABLE HERE
END IF;
END IF;
--RETURN TABLE HERE
END;
$$ Language plpgsql;
Now I tried searching on google but could find that how to typecast record type to table type.
As in convert temp_rec to table type and return.
Doing this via a recursive function is the most inefficient way of doing it.
But anyhow, you can do something like this:
create or replace function get_text_edit_record(p_text_id integer)
RETURNS Table (
text_id integer,
text_details varchar,
new_text_id integer)
AS $$
DECLARE
curr_rec record;
BEGIN
select tm.text_id, tm.text_details, tm.new_text_id
into curr_rec
from text_master tm
where tm.text_id = p_text_id;
IF FOUND THEN
return query
select curr_rec.text_id, curr_rec.text_details, curr_rec.new_text_id;
--- IS DISTINCT FROM properly deals with NULL values
IF curr_rec.text_id IS DISTINCT FROM curr_rec.new_text_id THEN
return query
select *
from get_text_edit_record(curr_rec.new_text_id);
END IF;
END IF;
END;
$$ Language plpgsql;

Oracle sql to pgsql with table() function issue

I am doing the migration from Oracle to pgsql and I've the the oracle sql like below:
select code,product_no,qty qty from t_ma_tb_inventory
where code is not null and status=2
and update_type in (select * from table(splitstr(:types,',')))
and tb_shop_id=:shopId
order by update_time
and the splitstr function like below:
CREATE OR REPLACE FUNCTION splitstr (p_string text, p_delimiter text) RETURNS SETOF STR_SPLIT AS $body$
DECLARE
v_length bigint := LENGTH(p_string);
v_start bigint := 1;
v_index bigint;
BEGIN
WHILE(v_start <= v_length)
LOOP
v_index := INSTR(p_string, p_delimiter, v_start);
IF v_index = 0
THEN
RETURN NEXT SUBSTR(p_string, v_start);
v_start := v_length + 1;
ELSE
RETURN NEXT SUBSTR(p_string, v_start, v_index - v_start);
v_start := v_index + 1;
END IF;
END LOOP;
RETURN;
END
$body$
LANGUAGE PLPGSQL
SECURITY DEFINER
;
-- REVOKE ALL ON FUNCTION splitstr (p_string text, p_delimiter text) FROM PUBLIC;
can someone help me to write the equivalent code in pgsql?Thank you very much
You don't need to write your own function - Postgres already has a built-in function for that: string_to_array
select code, product_no, qty qty
from t_ma_tb_inventory
where code is not null and status=2
and update_type = any ( string_to_array(:types,',') )
and tb_shop_id = :shopId
order by update_time;
If you are passing a text, but you need to compare that to an integer, you need to cast the resulting array:
select code, product_no, qty qty
from t_ma_tb_inventory
where code is not null and status=2
and update_type = any ( string_to_array(:types,',')::int[] )
and tb_shop_id = :shopId
order by update_time;
However: that is a pretty ugly workaround that is only necessary in Oracle because it has no support for real arrays in SQL (only in PL/SQL).
In Postgres it would be much better to pass an array of integers directly (e.g. make :types an int[]). Then no parsing or casting would be necessary:
select code, product_no, qty qty
from t_ma_tb_inventory
where code is not null and status=2
and update_type = any ( :types )
and tb_shop_id = :shopId
order by update_time;

A column definition list is required for functions returning "record" in Postgresql

In the Below Postgresql Function i am trying to get results from 2 different tables but it throws error ERROR: 42601: a column definition list is required for functions returning "record".Can anyone please help me.
CREATE OR REPLACE FUNCTION load_page_record(IN _session INT) RETURNS RECORD AS
$$
DECLARE r1 RECORD;
DECLARE r2 RECORD;
DECLARE RESULT RECORD;
BEGIN
SELECT array_agg(sq.*) AS arr INTO r1
FROM (SELECT user_id, user_name
FROM "user"
) sq;
SELECT array_agg(sq.*) AS arr INTO r2
FROM (SELECT client_id, client_name
FROM "clients"
) sq;
SELECT r1.arr, r2.arr INTO RESULT;
RETURN RESULT;
END;
$$ LANGUAGE plpgsql;
It returns a record,
so you should call the function as below,
select load_page_record(5);
The error come if you call it as a table
select * from load_page_record(5);
If you want to return a table place you query with join inside the body as follows,
CREATE OR REPLACE FUNCTION load_page_record1(IN _session INT)
RETURNS TABLE (column1 integer, column2 integer) as
$BODY$
SELECT column1, column2
FROM
table1 a
join
table2 b
ON a.id = b.id
$BODY$
LANGUAGE plpgsql;
try this, procedur return table
CREATE OR REPLACE FUNCTION load_page_record(IN _session INT)
RETURNS table(col1 record[],col2 record[]) AS
$BODY$
BEGIN
RETURN QUERY
select
(SELECT array_agg(sq.*)
FROM (SELECT user_id, user_name
FROM "user"
) sq
),
(SELECT array_agg(sq.*)
FROM (SELECT client_id, client_name
FROM "clients"
) sq
);
END;
$BODY$ LANGUAGE plpgsql stable;
edit: convert to text, try it
CREATE OR REPLACE FUNCTION load_page_record(IN _session INT)
RETURNS table(col1 text,col2 text) AS
$BODY$
BEGIN
RETURN QUERY
select
(SELECT array_agg(sq.*)
FROM (SELECT user_id, user_name
FROM "user"
) sq
)::text,
(SELECT array_agg(sq.*)
FROM (SELECT client_id, client_name
FROM "clients"
) sq
)::text;
END;
$BODY$ LANGUAGE plpgsql stable;
try with text:
CREATE OR REPLACE FUNCTION load_page_record(IN _session INT) RETURNS text AS
$$
DECLARE r1 RECORD;
DECLARE r2 RECORD;
DECLARE RESULT text;
BEGIN
SELECT array_agg(sq.*) AS arr INTO r1
FROM (SELECT 'fdfdfd','fdfdd'
) sq;
SELECT array_agg(sq.*) AS arr INTO r2
FROM (SELECT 'dsds','sdsd'
) sq;
SELECT r1.arr, r2.arr INTO RESULT;
RETURN RESULT;
END;
$$ LANGUAGE plpgsql;
and then simply:
select * from load_page_record(8);
but I hope you are aware of the fact that this instruction SELECT r1.arr, r2.arr INTO RESULT; will only assign the first column to RESULT?

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.