Declare variable PostgreSQL - sql

I'm trying to declare a variable which I will pass a value, but even with a single example, I got an different errors. For example: unexpected end of function definition at end of input.
I assume that the reason is that I am passing the value to a temporary table, but I don't know how to fix it
DO $$
DECLARE var2 varchar(20) := 'dzien';
BEGIN
SELECT
CASE WHEN var2 = 'dzien' THEN to_date((to_char(czasRozmowy, 'YYYY/MM/DD' )),'YYYY/MM/DD') ELSE to_date('0000/00/00', 'YYYY/MM/DD')
END as data_,
COUNT(DISTINCT(lekta_call_id)) iloscRozmow
,COUNT(DISTINCT(czasProcesu)) iloscProceso
,SUM(czySukces) iloscRozmowSukces
,SUM(czyTransfer) iloscRozmowTransfer
,SUM(czyRozlaczone) iloscRozmowRozlaczonych
,SUM(czyWsylanySMS) iloscSMS
FROM
(
SELECT
c.start_time czasRozmowy
,d.process_start_time czasProcesu
,c.l_call_id l_call_id
,CASE WHEN end_call_status=3 THEN 1 ELSE 0 END czySukces
,CASE WHEN end_call_status=2 THEN 1 ELSE 0 END czyTransfer
,CASE WHEN end_call_status=1 THEN 1 ELSE 0 END czyRozlaczone
,CASE WHEN send_sms=true THEN 1 ELSE 0 END czyWsylanySMS
FROM "Conversat" C
left join dialogues_details d on c.l_call_id=d.l_call_id
) as tabelka
group by data_
END $$;

Try this
CREATE OR REPLACE FUNCTION _get_result(
_var2 VARCHAR DEFAULT NULL
) RETURNS TABLE (
iloscRozmow INTEGER,
iloscProceso INTEGER,
iloscRozmowSukces INTEGER,
iloscRozmowTransfer INTEGER,
iloscRozmowRozlaczonych INTEGER,
iloscSMS INTEGER,
) AS $$
BEGIN
RETURN QUERY SELECT
CASE WHEN _var2 = 'dzien' THEN to_date((to_char(czasRozmowy, 'YYYY/MM/DD' )),'YYYY/MM/DD') ELSE to_date('0000/00/00', 'YYYY/MM/DD')
END as data_,
COUNT(DISTINCT(lekta_call_id)) iloscRozmow,
COUNT(DISTINCT(czasProcesu)) iloscProceso,
SUM(czySukces) iloscRozmowSukces,
SUM(czyTransfer) iloscRozmowTransfer,
SUM(czyRozlaczone) iloscRozmowRozlaczonych,
SUM(czyWsylanySMS) iloscSMS
FROM
(
SELECT
c.start_time czasRozmowy,
d.process_start_time czasProcesu,
c.l_call_id l_call_id,
CASE WHEN end_call_status=3 THEN 1 ELSE 0 END czySukces,
CASE WHEN end_call_status=2 THEN 1 ELSE 0 END czyTransfer,
CASE WHEN end_call_status=1 THEN 1 ELSE 0 END czyRozlaczone,
CASE WHEN send_sms=true THEN 1 ELSE 0 END czyWsylanySMS
FROM "Conversat" C
left join dialogues_details d on c.l_call_id=d.l_call_id
) as tabelka
group by data_;
END
$$ LANGUAGE 'plpgsql';
SELECT * FROM _get_result('dzien');

Related

Stored procedure get stuck after move database

I just dump data from production server to my local server for testing purpose. Our app uses a stored procedure with about 300 lines of sql. This procedure work fine in the server database, but it got stuck (running forever) every times i run it on my local database. Does anyone have any ideas about why it got stuck.
This is my command to dump data.
pg_dump --host localhost --port 5432 --username postgres --dbname test-new >D:\test5.sql
psql --host localhost --port 5432 --username postgres --dbname test-qa < file.sql
here is the Store Procedure
CREATE OR REPLACE FUNCTION public.insert_hm_ticket_statistic(v_sprint_id bigint)
RETURNS integer
LANGUAGE plpgsql
AS $$
DECLARE
v_ticket INT;
v_startsprint_date DATE;
v_end_date DATE;
v_current_date DATE;
v_first_activity_date DATE;
v_started DATE;
v_sprint_setting VARCHAR(255);
v_time_spent_second FLOAT;
v_remaining_estimate FLOAT;
v_time_logged_tmp FLOAT;
v_has_log INT;
v_time_logged_tk FLOAT;
v_oe_tk INT;
v_has_past_sprint INT;
v_oe_sprint INT;
v_complete_of_sprint FLOAT;
v_oe_tk_burnt FLOAT;
v_oe_sprint_burnt FLOAT;
v_project_complete FLOAT;
v_complete_tk FLOAT;
rl_cursor CURSOR FOR SELECT
tk.id,
tk.has_past_sprint,
cast(first_activity_date AS DATE)
FROM hm_ticket tk
WHERE sprint = v_sprint_id AND deleted = 0;
BEGIN
-- find start date and end date of sprint
SELECT
cast(start_date AS DATE),
cast(end_date AS DATE)
INTO v_startsprint_date, v_end_date
FROM hm_sprint
WHERE id = v_sprint_id AND status <> 'future';
-- find sprint setting
IF NOT exists(SELECT d.burn_down_statuses
FROM hm_sprint x, hm_setting c, hm_burn_down_status d
WHERE c.id = d.setting AND x.setting = c.id AND x.id = v_sprint_id)
THEN
v_sprint_setting :='xxx';
ELSE
SELECT string_agg(d.burn_down_statuses, ',')
INTO v_sprint_setting
FROM hm_sprint x, hm_setting c, hm_burn_down_status d
WHERE c.id = d.setting AND x.setting = c.id AND x.id = v_sprint_id;
END IF;
raise notice 'v_sprint_setting %', v_sprint_setting;
OPEN rl_cursor;
LOOP
FETCH rl_cursor INTO v_ticket, v_has_past_sprint, v_first_activity_date;
raise notice 'v_ticket: %', v_ticket;
EXIT WHEN NOT FOUND;
/*select cast(min(started) as date) into v_started
from hm_worklog
where ticket=v_ticket and cast(started as date) between v_startsprint_date and v_end_date;
if v_started is null then v_current_date:=v_startsprint_date;
else
v_current_date:=v_started;
end if;*/
v_current_date:=v_startsprint_date;
--- calculate remaining estimate, time logged of ticket
IF v_has_past_sprint = 0
THEN
SELECT
coalesce(remaining_estimate, 0),
coalesce(time_logged, 0)
INTO v_remaining_estimate, v_time_logged_tk
FROM hm_ticket
WHERE id = v_ticket;
ELSE
SELECT coalesce(time_logged, 0)
INTO v_time_logged_tmp
FROM hm_ticket
WHERE id = v_ticket;
--------------------------------------
SELECT
coalesce(remaining_estimate, 0),
v_time_logged_tmp - coalesce(time_logged, 0)
INTO v_remaining_estimate, v_time_logged_tk
FROM hm_ticket_past_sprint
WHERE ticket = v_ticket;
END IF;
raise notice '----------v_has_past_sprint: %', v_has_past_sprint;
raise notice '----------v_time_logged_tmp: %', v_time_logged_tmp;
raise notice '----------v_time_logged_tk: %', v_time_logged_tk;
raise notice '----------v_remaining_estimate: %', v_remaining_estimate;
-- calculate oe of ticket
IF v_has_past_sprint = 0
THEN
SELECT cast(CASE WHEN coalesce(original_estimate, 0) = 0
THEN coalesce(time_logged, 0)
ELSE original_estimate
END
AS FLOAT)
INTO v_oe_tk
FROM hm_ticket
WHERE id = v_ticket;
ELSE
SELECT coalesce(time_logged, 0)
INTO v_time_logged_tmp
FROM hm_ticket
WHERE id = v_ticket;
--------------------------------------
SELECT cast(CASE WHEN coalesce(original_estimate, 0) = 0
THEN v_time_logged_tmp - coalesce(time_logged, 0)
ELSE original_estimate
END
AS FLOAT)
INTO v_oe_tk
FROM hm_ticket_past_sprint
WHERE ticket = v_ticket;
END IF;
raise notice 'v_oe_tk: %',v_oe_tk;
/*########################################################################## START TO LOOP CURRENT DATE #############################################################################*/
WHILE v_current_date <= v_end_date LOOP
--- calculate time_spent_seconds from start sprint
IF NOT exists(SELECT id
FROM hm_worklog
WHERE ticket = v_ticket AND cast(started AS DATE) BETWEEN v_startsprint_date AND v_current_date)
THEN
v_time_spent_second:=0;
ELSE
SELECT cast(sum(time_spent_seconds) AS FLOAT)
INTO v_time_spent_second
FROM hm_worklog
WHERE ticket = v_ticket AND cast(started AS DATE) BETWEEN v_startsprint_date AND v_current_date
GROUP BY ticket;
END IF;
raise notice 'v_time_spent_second: %', v_time_spent_second;
--calculate % complete of ticket/day
IF NOT v_current_date = v_end_date THEN
IF NOT exists(SELECT date FROM hm_ticket_history WHERE ticket = v_ticket AND cast(date AS DATE) = v_current_date)
then
-- FIND STATUS OF TICKET IN SETTING. 0: NO STATUS EXIST -> FORMULAR SHOULD BE APPLIED , <>0 : EXIST--> SET COMPLETE TK = 0
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket
WHERE id = v_ticket;
ELSE
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket_history
WHERE ticket = v_ticket AND cast("date" AS DATE)= v_current_date;
END IF;
ELSE
--NOTE: IF V_CURRENT_DATE == END-DATE-OF-SPRINT, COMPLETE % WILL BE CALCULATED BASE ON LATEST TICKET STATUS, NOT LAST-DAY-OF-SPRINT TICKET STATUS
IF NOT exists(SELECT date FROM hm_ticket_history WHERE ticket = v_ticket AND cast(date AS DATE) = v_current_date)
then
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket
WHERE id = v_ticket;
else
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket_history
WHERE ticket = v_ticket order by date desc limit 1;
END IF;
END IF;
if v_complete_tk > 100 then v_complete_tk := 100;
end if;
raise notice 'v_sprint_setting: %', v_sprint_setting;
raise notice 'v_complete_tk: %', v_complete_tk;
raise notice '---------------------------------';
-- check has log
IF exists(SELECT id
FROM hm_worklog
WHERE cast(started AS DATE) = cast(v_current_date AS DATE) AND ticket = v_ticket)
THEN
v_has_log := 1;
ELSE
v_has_log := 0;
END IF;
--raise notice 'v_has_log: %', v_has_log;
-- calculate oe of sprint
SELECT sum(x.oe)
INTO v_oe_sprint
FROM
(
SELECT CASE WHEN coalesce(original_estimate, 0) = 0
THEN coalesce(time_logged, 0)
ELSE coalesce(original_estimate, 0)
END oe
FROM hm_ticket
WHERE sprint = v_sprint_id AND cast(first_activity_date AS DATE) <= v_current_date
AND has_past_sprint = 0
UNION ALL
SELECT CASE WHEN coalesce(b.original_estimate, 0) = 0
THEN coalesce(a.time_logged - b.time_logged)
ELSE coalesce(b.original_estimate, 0)
END oe
FROM hm_ticket a, hm_ticket_past_sprint b
WHERE a.id = b.ticket AND a.sprint = v_sprint_id AND cast(a.first_activity_date AS DATE) <= v_current_date
AND a.has_past_sprint = 1
) x;
-- raise notice 'v_oe_sprint: %', v_oe_sprint;
-- calculate v_oe_tk_burnt
SELECT CASE WHEN v_time_spent_second = 0 OR v_oe_tk = 0
THEN 0
ELSE round(cast((v_time_spent_second * 100 / v_oe_tk) AS NUMERIC), 2)
END
INTO v_oe_tk_burnt;
--raise notice 'v_oe_tk_burnt: %', v_oe_tk_burnt;
-- calculate v_oe_sprint_burnt
IF v_oe_sprint = 0
THEN
v_oe_sprint_burnt:=100;
ELSE
SELECT round(cast((v_time_spent_second * 100 / v_oe_sprint) AS NUMERIC), 2)
INTO v_oe_sprint_burnt;
END IF;
--raise notice 'v_oe_sprint_burnt: %', v_oe_sprint_burnt;
-- calculate v_project_complete
IF v_oe_sprint = 0
THEN
v_project_complete:=100;
ELSE
SELECT round(cast((v_complete_tk * v_oe_tk / v_oe_sprint) AS NUMERIC), 2)
INTO v_project_complete;
END IF;
-- raise notice 'v_project_complete: %', v_project_complete;
IF v_current_date >= v_first_activity_date
THEN
INSERT INTO hm_ticket_statistic (complete, date, has_log, last_modified, original_estimate_burnt, original_estimate_project_burnt, project_complete, status, ticket, sprint)
VALUES
(v_complete_tk, cast(v_current_date AS DATE), v_has_log, current_timestamp, v_oe_tk_burnt, v_oe_sprint_burnt,
v_project_complete, 1, v_ticket, v_sprint_id)
ON CONFLICT (date, ticket, sprint)
DO UPDATE
SET complete = v_complete_tk,
has_log = v_has_log,
original_estimate_burnt = v_oe_tk_burnt,
original_estimate_project_burnt = v_oe_sprint_burnt,
project_complete = v_project_complete;
END IF;
v_current_date:= v_current_date + INTERVAL '24 hours';
EXIT WHEN NOT found;
END LOOP;
END LOOP;
CLOSE rl_cursor;
RETURN 0;
END;
Also, if you see anything that can be improved in the code, please suggest me.
Try running analyze on the local database, after restoring the dump. This updates statistics.
Finally found the bug. It is a deadlock bug, i used Synchronized on function way too much, they start to get stuck. The production server still get the same problem, i just don't see it. So i try to use Synchronized more selectively, reduce the size of functions that Synchronized on. Then it is fixed.

oracle sql filter for nullable values

Is that expected behavior for oracle 11g. Can someone explain why last query does not include null value?
table
statuscode
13
null
---------------------------------------------------------
select count(*) from table -- returns 2
select count(*) from table where statuscode = 13 --returns 1
select count(*) from table where statuscode <> 13 --returns 0
Think of NULL as an unknown value and testing if something equals (or does not equal) an unknown will result in an unknown (NULL) as the answer. The SQL query will display results when the boolean filter is TRUE and this will not be the case if one value is NULL.
You can test the logic in PL/SQL (since it has an accessible BOOLEAN type):
SET SERVEROUTPUT ON;
DECLARE
FUNCTION bool_to_string( bool BOOLEAN ) RETURN VARCHAR2
AS
BEGIN
RETURN CASE WHEN bool IS NULL THEN 'NULL'
WHEN bool = TRUE THEN 'TRUE'
WHEN bool = FALSE THEN 'FALSE'
ELSE 'ERROR' END;
END;
BEGIN
DBMS_OUTPUT.PUT_LINE( 'A = A => ' || bool_to_string( 'A' = 'A' ) );
DBMS_OUTPUT.PUT_LINE( 'A <> A => ' || bool_to_string( 'A' <> 'A' ) );
DBMS_OUTPUT.PUT_LINE( 'A = NULL => ' || bool_to_string( 'A' = NULL ) );
DBMS_OUTPUT.PUT_LINE( 'A <> NULL => ' || bool_to_string( 'A' <> NULL ) );
END;
/
Which outputs:
A = A => TRUE
A <> A => FALSE
A = NULL => NULL
A <> NULL => NULL
Note that the last two tests do not return FALSE but return NULL.
If you want to count including NULLs then you can do:
select count(*) from table where statuscode <> 13 OR statuscode IS NULL

SQL stored procedure with CASE

Hello i have a quation with my stored procedure , i use 2 cases here , the first case it shows me right values and its OK, the second shows me only Null values in the field TirType , i don't understand what is the problem
CREATE VIEW dbo.YUITY
SELECT CAST(dbo.SC5116.CODE AS int) AS код, dbo.SC5116.DESCR AS Наименование,
CAST(dbo.SC3420.CODE AS int) AS TIR, dbo.SC3420.SP4947 AS Date,
CASE WHEN SC3420.SP4949 <> ' 0 ' THEN 'ПовышСтрах' ELSE 'ОснСтрах' END AS VID,
CASE WHEN dbo.SC3420.SP9214 = '714' THEN '4v' END AS TirType
FROM dbo.SC3420 INNER JOIN
dbo.SC5116 ON dbo.SC3420.SP3422 = dbo.SC5116.ID
WHERE (dbo.SC3420.SP4947 <> '01.01.1753')
Don't forget END after CASE. It will return NULL if no ELSE is specified and value is not '714'.
CREATE VIEW dbo.YUITY
AS
SELECT CAST(dbo.SC5116.CODE AS int) AS код, dbo.SC5116.DESCR AS Наименование,
CAST(dbo.SC3420.CODE AS int) AS TIR, dbo.SC3420.SP4947 AS Date,
CASE WHEN SC3420.SP4949 <> ' 0 ' THEN 'ПовышСтрах' ELSE 'ОснСтрах' END AS VID,
CASE WHEN dbo.SC3420.SP9214 = '714' THEN '4v' ELSE '' END AS TirType
FROM dbo.SC3420 INNER JOIN
dbo.SC5116 ON dbo.SC3420.SP3422 = dbo.SC5116.ID
WHERE (dbo.SC3420.SP4947 <> '01.01.1753')

How to determine whether the number is float or integer

I need to write this query in SQL Server:
IF isFloat(#value) = 1
BEGIN
PRINT 'this is float number'
END
ELSE
BEGIN
PRINT 'this is integer number'
END
Please help me out with this, thanks.
declare #value float = 1
IF FLOOR(#value) <> CEILING(#value)
BEGIN
PRINT 'this is float number'
END
ELSE
BEGIN
PRINT 'this is integer number'
END
Martin, under certain circumstances your solution gives an incorrect result if you encounter a value of 1234.0, for example. Your code determines that 1234.0 is an integer, which is incorrect.
This is a more accurate snippet:
if cast(cast(123456.0 as integer) as varchar(255)) <> cast(123456.0 as varchar(255))
begin
print 'non integer'
end
else
begin
print 'integer'
end
Regards,
Nico
DECLARE #value FLOAT = 1.50
IF CONVERT(int, #value) - #value <> 0
BEGIN
PRINT 'this is float number'
END
ELSE
BEGIN
PRINT 'this is integer number'
END
See whether the below code will help. In the below values only 9,
2147483647, 1234567 are eligible as Integer. We can create this as
function and can use this.
CREATE TABLE MY_TABLE(MY_FIELD VARCHAR(50))
INSERT INTO MY_TABLE
VALUES('9.123'),('1234567'),('9'),('2147483647'),('2147483647.01'),('2147483648'), ('2147483648ABCD'),('214,7483,648')
SELECT *
FROM MY_TABLE
WHERE CHARINDEX('.',MY_FIELD) = 0 AND CHARINDEX(',',MY_FIELD) = 0
AND ISNUMERIC(MY_FIELD) = 1 AND CONVERT(FLOAT,MY_FIELD) / 2147483647 <= 1
DROP TABLE MY_TABLE
OR
DECLARE #num VARCHAR(100)
SET #num = '2147483648AS'
IF ISNUMERIC(#num) = 1 AND #num NOT LIKE '%.%' AND #num NOT LIKE '%,%'
BEGIN
IF CONVERT(FLOAT,#num) / 2147483647 <= 1
PRINT 'INTEGER'
ELSE
PRINT 'NOT-INTEGER'
END
ELSE
PRINT 'NOT-INTEGER'

How to make a wrapper to return something other than ref cursor

I've got the following PL SQL function that returns a ref cursor but the application i am using does not support ref cursors. How can i make this code return something other than ref cursor
FUNCTION getADedIcWarningsProv(p_hos_id IN work_entity_data.hos_id%TYPE
,p_date IN DATE
)
RETURN eOdatatypes_package.eOrefcur
IS
v_refcur eOdatatypes_package.eOrefcur;
BEGIN
OPEN v_refcur FOR
SELECT IF_type IF_type
,COUNT(*) number_infected
FROM (SELECT DISTINCT bd.PT_id PT_id
,CASE WHEN NVL(O_package.get_O_code_property(pw.warning_code,'Setl'),'N') = 'Y'
THEN cd.description
ELSE 'Other'
END IF_type
FROM PT_ad pad
,BD_details bd
,PT_warnings pw
,codes cd
WHERE bd.current_record = 'Y'
AND bd.BD_location IS NOT NULL
AND bd.BD_status IN (SELECT code
FROM codes
WHERE prog_code IN (1, 1, 2)
AND code_type = 4)
AND bd.AD_no = pad.AD_no
AND pad.hos_id = p_hos_id
AND pw.PT_id = bd.PT_id
AND pw.warning_to IN ('D','Q')
AND p_date BETWEEN pw.applies_start
AND NVL(pw.applies_end,p_date)
AND NVL(O_package.get_O_code_property(pw.warning_code,'INFT'),'Y') = 'N'
AND pw.warning_code = cd.code)
GROUP BY IF_type
ORDER BY IF_type;
RETURN v_refcur;
END getADedIcWarningsProv;
OUTPUT:
IF_TYPE NUMBER_IF
---------------------------------------- ---------------
C 2
M 6
Other 4
3 rows selected
You can use a pipeline function to return a result set one record at a time, but in a way that the SQL engine can understand.
create or replace package WrapperSample is
type TResultRow is record(
if_type codes.cd%type
,number_infected Integer);
type TResultRowList is table of TResultRow;
function GetADedIcWarningsProv
(
p_hos_id in work_entity_data.hos_id%type
,p_date in date
) return TResultRowList
pipelined;
end WrapperSample;
/
create or replace package body WrapperSample is
function GetADedIcWarningsProv
(
p_hos_id in work_entity_data.hos_id%type
,p_date in date
) return TResultRowList
pipelined is
v_refcur eOdatatypes_package.eOrefcur;
currentRow TResultRow;
begin
v_refcur := YourSchema.getADedIcWarningsProv(p_hos_id, p_date);
loop
fetch v_refcur
INTO currentRow;
exit when v_refcur%NotFound;
pipe row(currentRow);
end loop;
close v_refcur;
return;
end;
end WrapperSample;
/
Using this package, you can select your ref cursor:
SELECT if_type
,number_infected
FROM table(WrapperSample.getADedIcWarningsProv(1, 2))