Postgres中的SQL Server存储过程

时间:2014-12-15 08:38:58

标签: sql-server postgresql stored-procedures

我想在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;

2 个答案:

答案 0 :(得分:2)

您的脚本中有几个错误:

  1. 您需要将“美元报价”与实际关键字分开。最常见的方法是将“美元报价”写在它自己的一行:

    $BODY$
    DECLARE 
      ...
    END
    $BODY$
    
  2. 需要使用;

    终止语句
    order by h.from_time; --<< the ; makes a difference
    
  3. 块也需要以;终止:

    END; --<< the ; makes a difference
    $BODY$
    
  4. 您的select语句没有目标,但由于您只想返回结果,您可以使用return query

  5. 参数不以@为前缀,如手册中明确记载:
    http://www.postgresql.org/docs/current/static/plpgsql-declarations.html

  6. 您用于date_parm

  7. 的声明时,没有参数v_start_time
  8. 作业运算符为:=而不是=

  9. 您永远不会为OUT参数指定值,因此您只需将其声明为IN(或完全省略限定符)

  10. cast()个函数需要as个关键字,参数相反as documented in the manual

    CAST(h.from_time AS time(0))
    

    您还可以使用Postgres的缩短版::符号:h.from_time::time

  11. 为清楚起见,您可能希望将函数定义为returns table (...)并在函数声明中指定列名。当您使用returns record时,每次使用函数时都需要指定列名。

  12. 要返回结果中的一个输入参数,请将列定义添加到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
相关问题