繁体   English   中英

从 SQL 服务器到 PostgreSQL 的 T-SQL 存储过程

[英]T-SQL stored procedure from SQL server to PostgreSQL

对于一些上下文:我编写了一个使用两个表的存储过程, productsproduct_id 、product_name、description、price、category_id)和supplies (shipping_id、suppliers_id、product_id(FK 到products )、 supply_date 、数量)。

该过程采用product_id并在给定时间范围内(从 date1 到 date2)打印有关产品供应的描述和某些信息。

这是 T-SQL 代码:

CREATE OR ALTER PROCEDURE productInfo
    (@product_id INT,
     @date1 DATE,
     @date2 DATE)
AS
BEGIN
    DECLARE @description VARCHAR(100),
            @shipment_id INT, 
            @supply_date DATE, 
            @quantity INT;

    DECLARE product_cursor CURSOR LOCAL FOR
        SELECT description 
        FROM products 
        WHERE product_id = @product_id

    OPEN product_cursor;

    FETCH NEXT FROM product_cursor INTO @description

    CLOSE product_cursor
    
    DECLARE product_supply_cursor CURSOR LOCAL FOR 
        SELECT shipment_id, supply_date, quantity
        FROM supplies
        WHERE product_id = @product_id

    OPEN product_supply_cursor;

    FETCH NEXT FROM product_supply_cursor INTO @shipment_id, @supply_date, @quantity;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        IF @supply_date >= @date1 AND @supply_date <= @date2
        BEGIN
            PRINT 'DESCRIPTION: ' + @description
            PRINT 'SHIPMENT_ID: ' + STR(@shipment_id)
            PRINT 'SUPPLY_DATE: ' + convert(varchar, @supply_date, 23)
            PRINT 'QUANTITY: ' + STR(@quantity)
            PRINT ' '
        END;

        FETCH NEXT FROM product_supply_cursor INTO @shipment_id, @supply_date, @quantity;
    END;

    CLOSE product_supply_cursor;
END;

显然,这个过程不能在 pgSQL 中运行,而且我在这件事上没有经验,所以我想要这段代码的翻译,或者(如果我问得太多)关于需要改变什么的提示(语法或逻辑明智)以适应 pgSQL 语言。

SQL 服务器代码一开始就非常复杂。 游标的使用以及缓慢且低效的(嵌套)逐行处理可以简化为连接两个表的单个 SELECT 语句。 对 cursor 循环中的两个日期进行范围检查非常有效,最好直接在 SELECT 语句的 WHERE 子句中应用它,这样您就不必迭代超过 1000 万行。 只是为了显示 5。

一个天真的迁移会做这样的事情:

create procedure print_product_info(p_product_id int, p_date1 date, p_date2 date)
as
$$
declare
  l_row record;
begin
  for l_row in SELECT p.description, s.shipment_id, s.supply_date, s.quantity
               FROM supplies s
                 JOIN products p ON p.product_id = s.product_id
               WHERE p.product_id = p_product_id
                 AND s.supply_date >= p_date1
                 AND s.supply_date <= p_date2
  loop
    raise notice 'DESCRIPTION: %', l_row.description;
    raise notice 'SHIPMENT_ID: %', l_row.shipment_id;
    raise notice 'SUPPLY_DATE: %', to_char(l_row.supply_date, 'yyyy-mm-dd');
    raise notice 'QUANTITY: %', l_row.quantity;
  end loop;
end;
$$
language plpgsql;

但是,这不是在 Postgres 中这样做的方式。 结果不应“打印”,而应由 function 简单地“返回”(程序并非旨在返回内容)。

在 Postgres 中实现这一点的正确方法是返回集合 function:

create function get_product_info(p_product_id int, p_date1 date, p_date2 date)
  returns table(description text, shipment_id int, supply_date date, quantity int)
as
$$
  SELECT p.description, s.shipment_id, s.supply_date, s.quantity
  FROM supplies s
   JOIN products p ON p.product_id = s.product_id
  WHERE p.product_id = p_product_id
   AND s.supply_date >= p_date1
   AND s.supply_date <= p_date2
$$
language sql;

要显示数据,请使用:

select *
from get_product_info(42, date '2020-01-07', '2020-01-12');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM