我想在Postgres中为此处显示的Microsoft SQL Server存储过程编写一个函数。 请帮忙。我想在postgres中使用这个存储过程作为函数。
USE [EMS_Demo_Db]
GO
/****** Object: StoredProcedure [dbo].[SP_HourWise] Script Date: 16-12-2014 10:48:53 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SP_HourWise]
@date_param datetime
AS
BEGIN
SET NOCOUNT ON;
DECLARE @start_time datetime = dateadd(HOUR, 6, @date_param)
; WITH Hours AS (
SELECT dateadd(HOUR, row_number() OVER(ORDER BY From_Time) - 1, @start_time) AS From_Time,
dateadd(HOUR, row_number() OVER(ORDER BY From_Time), @start_time) AS To_Time
FROM Table_2
)
SELECT CONVERT(varchar,@date_param, 103)
as Date_def, convert(time(0), h.From_Time) AS From_Time, convert(time(0), h.To_Time) AS To_Time,
MAX(t1.Param_Val) - MIN(t1.Param_Val) as Cal_ParamValue
FROM Table_1 t1
JOIN Hours h ON t1.Timestamp_col BETWEEN h.From_Time AND h.To_Time
WHERE Timestamp_col BETWEEN @start_time AND dateadd(HOUR, 24, @start_time)
GROUP BY h.From_Time, h.To_Time
HAVING COUNT(*) > 1
ORDER BY h.From_Time
END
已转换SP,但它的错误为
在输入第17行结束时意外结束了函数定义:END $ BODY $
CREATE FUNCTION sp_hourwise(OUT from_time time without time zone, OUT to_time time without time zone, OUT param_value bigint, INOUT timestamp_col timestamp without time zone) RETURNS record AS
$BODY$DECLARE v_start_time timestamp(3) = interval '6 HOUR' + @date_param;
BEGIN
With Hours As (
SELECT v_start_time + (row_number() OVER(ORDER BY from_time) - 1) * INTERVAL '1 day' AS from_time,
v_start_time + (row_number() OVER(ORDER BY from_time)) * INTERVAL '1 day' AS to_time
FROM table_2
)
SELECT CAST(time(0) h.from_time), CAST(time(0) h.to_time),
MAX(t1.param_value) - MIN(t1.param_value)
FROM Table_1 t1
JOIN Hours h ON t1.timestamp_col BETWEEN h.from_time AND h.to_time
WHERE timestamp_col BETWEEN v_start_time AND interval '24 HOUR' + v_start_time
GROUP BY h.from_time, h.to_time
HAVING COUNT(*) > 1
ORDER BY h.from_time
END$BODY$
LANGUAGE plpgsql VOLATILE NOT LEAKPROOF;
答案 0 :(得分:2)
您的脚本中有几个错误:
您需要将“美元报价”与实际关键字分开。最常见的方法是将“美元报价”写在它自己的一行:
$BODY$
DECLARE
...
END
$BODY$
需要使用;
order by h.from_time; --<< the ; makes a difference
块也需要以;
终止:
END; --<< the ; makes a difference
$BODY$
您的select语句没有目标,但由于您只想返回结果,您可以使用return query
参数不以@
为前缀,如手册中明确记载:
http://www.postgresql.org/docs/current/static/plpgsql-declarations.html
您用于date_parm
v_start_time
作业运算符为:=
而不是=
您永远不会为OUT
参数指定值,因此您只需将其声明为IN
(或完全省略限定符)
cast()
个函数需要as
个关键字,参数相反as documented in the manual:
CAST(h.from_time AS time(0))
您还可以使用Postgres的缩短版::
符号:h.from_time::time
为清楚起见,您可能希望将函数定义为returns table (...)
并在函数声明中指定列名。当您使用returns record
时,每次使用函数时都需要指定列名。
要返回结果中的一个输入参数,请将列定义添加到returns table (...)
部分,并将参数作为select语句的一部分包含在内:
考虑以下所有内容应该如下:
CREATE FUNCTION sp_hourwise(from_time time without time zone, to_time time without time zone, date_param date)
RETURNS table (some_date_column date, from_time time, to_time time, diff integer)
AS
$BODY$
DECLARE
v_start_time timestamp(3) := interval '6 HOUR' + date_param; --- I don't know which parameter you want to use here.
BEGIN
return query
With Hours As (
SELECT v_start_time + (row_number() OVER(ORDER BY from_time) - 1) * INTERVAL '1 day' AS from_time,
v_start_time + (row_number() OVER(ORDER BY from_time)) * INTERVAL '1 day' AS to_time
FROM table_2
)
SELECT date_param,
CAST(h.from_time as time),
CAST(h.to_time as time),
MAX(t1.param_value) - MIN(t1.param_value) as diff
FROM Table_1 t1
JOIN Hours h ON t1.timestamp_col BETWEEN h.from_time AND h.to_time
WHERE timestamp_col BETWEEN v_start_time AND interval '24 HOUR' + v_start_time
GROUP BY h.from_time, h.to_time
HAVING COUNT(*) > 1
ORDER BY h.from_time;
END;
$BODY$
LANGUAGE plpgsql
VOLATILE NOT LEAKPROOF;
条件WHERE timestamp_col BETWEEN v_start_time AND interval '24 HOUR' + v_start_time
看起来令人困惑。您将参数命名为“_col”,但您使用它就好像它是表中的列一样。这是一个专栏吗?那你就不需要申报了。如果不是,我会建议为参数使用不同的名称(但这可能是您尝试混淆代码的结果)。
答案 1 :(得分:0)
我修改并最终解决了问题得到了所需的结果.Below是正确的和经过测试的存储过程。谢谢大家的帮助。
CREATE OR REPLACE FUNCTION tested_sp(INOUT date_param date, OUT from_time time without time zone, OUT to_time time without time zone, OUT cal bigint)
RETURNS SETOF record AS
$BODY$
DECLARE
start_time Timestamp = interval '6 HOUR' + date_param;
BEGIN
return query
With Hours As (
SELECT INTERVAL '1 hour' * (row_number() OVER(ORDER BY table_2.from_time) - 1 ) + start_time AS from_time,
INTERVAL '1 hour' * (row_number() OVER(ORDER BY table_2.from_time)) + start_time AS to_time
FROM table_2
)
SELECT date_param::date as Date_Def,CAST(h.from_time as time) as from_time,
CAST(h.to_time as time) as to_time,
CAST(SUM(t1.param_value) AS bigint) as Cal
FROM table_1 t1
JOIN Hours h ON t1.timestamp_col BETWEEN h.from_time AND h.to_time
WHERE timestamp_col BETWEEN start_time AND interval '24 HOUR' + start_time
GROUP BY h.from_time, h.to_time
HAVING COUNT(*) > 1
ORDER BY h.from_time;
END;
$BODY$
LANGUAGE plpgsql VOLATILE