【问题标题】:SQL Server Stored Procedure in PostgresPostgres 中的 SQL Server 存储过程
【发布时间】:2014-12-15 08:38:58
【问题描述】:

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

【问题讨论】:

  • convert 转换为 cast(); 位于语句的end 而非开头。有关返回结果的函数示例,请参见手册:postgresql.org/docs/current/static/xfunc-sql.html
  • dateadd怎么样,有AS...你能把转换后的SP贴出来
  • 这不是免费的代码编写服务,您必须展示自己的一些努力。常用表表达式相同:postgresql.org/docs/current/static/queries-with.html 日期算术在手册中也有说明:postgresql.org/docs/current/static/functions-datetime.html
  • 让我澄清一下 - 您要求我们免费完成您的工作,而您仍然保留为完成工作而收集的钱?开始学习你的工作,然后你就不必四处请人来做你的工作了。
  • 让我澄清一下@Tom,我没有从中得到任何钱。我对这些技术很陌生,所以我问的是这个,而不是问整个工作。

标签: sql-server postgresql stored-procedures


【解决方案1】:

您的脚本中有几个错误:

  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. 没有您用于声明v_start_time的参数date_parm

  7. 赋值运算符是:= 而不是=

  8. 您永远不会为 OUT 参数赋值,因此您可以将它们声明为 IN(或完全省略限定符)

  9. cast()函数需要as关键字,参数颠倒as documented in the manual

    CAST(h.from_time AS time(0))
    

    您也可以使用 Postgres 的更短的 :: 表示法:h.from_time::time

  10. 为了清楚起见,您可能希望将函数定义为 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”,但您将其用作表中的列。是柱子吗?那么你不需要声明它。如果不是,我建议为参数使用不同的名称(但这可能是您试图混淆代码的结果)。

【讨论】:

  • 执行函数后出现错误ERROR: column reference "from_time" is ambiguous LINE 2: ...SELECT v_start_time + (row_number() OVER(ORDER BY from_time)... ^ DETAIL: 它可以参考到 PL/pgSQL 变量或表列。查询:以小时为 (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
  • @Parth:然后在列名前加上表别名(你也应该避免使用与列名相同的参数名)。
  • 是的 timestamp_col 是列名。在我的情况下,有两个表 table_1 的列 [timestamp_col,param_value] 和 table_2 的列 [from_time,to_time]。是的你写我已经更正并添加了 date_param作为参数并删除了其他实际上是列名的参数。
  • Return Table(date_param date,from_time time, to_time time, diff integer) 我想要作为函数结果的参数 date_param 也应该返回。我可以使用上面的语句吗
  • @Parth:只需在returns table (...) 部分添加一个新的列定义,并在select 语句中包含参数。
【解决方案2】:

我修改并最终解决问题得到了所需的结果。以下是正确且经过测试的存储过程。感谢大家的帮助。

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

【讨论】:

  • 不要添加其他信息(和问题)作为答案。 编辑您的问题
猜你喜欢
  • 2012-12-31
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 2018-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多