在postgresql函数中查询变量

时间:2017-12-12 08:35:25

标签: sql postgresql plpgsql

我试图在psql上创建一个函数。它将在桌面上插入时触发。我想在我的选择上注入一个变量。无法工作......

CREATE OR REPLACE FUNCTION updateHistoricLongTime()
RETURNS void AS $$
    DECLARE 
        hour_nb     int; 
        index_hour  int;
        saved_hours int;
        tmp_counter int; 
    BEGIN
        hour_nb     := 0;
        index_hour  := 1;
        saved_hours := 2160;
        tmp_counter := 0;
        SELECT COUNT(*) FROM locationhistoric WHERE type='hour' AND idLocation=6  INTO hour_nb;
        IF (hour_nb<saved_hours) THEN
            FOR i IN 1 .. saved_hours LOOP
                SELECT COUNT(*) FROM visits 
WHERE stend < (timestamp '2017-11-29 15:00' - interval **>> index_hour<<<** - 1 ' hour') AND stend > (timestamp '017-11-29 15:00' - interval **>>index_hour <<<**' hour') AND location_id=6 AND duration>0 INTO tmp_counter;
                    index_hour := index_hour + 1;
                END LOOP;
            END IF;
    END;
    $$
    LANGUAGE 'plpgsql' IMMUTABLE;

如何在SELECT COUNT(*)FROM Visits ...

中注入变量index_hour

编辑:这只是语法问题,但我无法找到正确的方法!

命令行中的结果:

ERROR:  syntax error at or near "index_hour"
LINE 16: ... stend < (timestamp '2017-11-29 15:00' - interval index_hour...

非常感谢, 解决方案

CREATE OR REPLACE FUNCTION updateHistoricLongTime()
RETURNS void AS $$
    DECLARE 
        hour_nb             int; 
        index_hour          int;
        saved_hours         int;
        tmp_counter         int; 
        index_hour_minor    int;
    BEGIN
        hour_nb             :=  0;
        index_hour          :=  1;
        index_hour_minor    :=  0;
        saved_hours         :=  2160;

        SELECT COUNT(*)
            INTO hour_nb
        FROM locationhistoric 
        WHERE type='hour' 
            AND idLocation=6;

        IF (hour_nb<saved_hours) THEN
            FOR i IN 1 .. saved_hours LOOP

                SELECT COUNT(*) 
                    INTO tmp_counter 
                FROM visits
                WHERE start > timestamp '2017-11-29 15:00' - ( interval '1 hour' * index_hour ) 
                    AND start < timestamp '2017-11-29 15:00' - ( interval '1 hour' * index_hour_minor) 
                    AND location_id=6 
                    AND duration>0;

                INSERT INTO locationhistoric
                    (type, date, counter, idLocation)
                VALUES( 'hour',
                        timestamp '2017-11-29 15:00' - ( interval '1 hour' * index_hour_minor),
                        tmp_counter,
                        6);

                index_hour_minor    := index_hour_minor + 1;
                index_hour          := index_hour + 1;
            END LOOP;
        END IF;
END;
$$
LANGUAGE plpgsql;

3 个答案:

答案 0 :(得分:2)

为间隔指定的值不能作为变量传递。但是,如果基本单位总是一小时,你可以将我们的间隔乘以我们想要的数字,例如

interval '1' hour * 5

将返回5小时。 5可以是参数。所以你的查询应该是:

SELECT COUNT(*) 
   INTO tmp_counter
FROM visits 
WHERE stend < (timestamp '2017-11-29 15:00' - (interval '1' hour * index_hour)) 
  AND stend > (timestamp '2017-11-29 15:00' - (interval '1' hour * index_hour)) 
  AND location_id=6 
  AND duration > 0;

答案 1 :(得分:1)

您希望获得查询的语法(例如,index_hour = 8):

select count(*) 
from visits 
where 
    stend < (timestamp '2017-11-29 15:00' - interval '7 hour') and 
    stend > (timestamp '2017-11-29 15:00' - interval '8 hour') and
    location_id = 6 and 
    duration > 0;

注意引号所在的位置。这意味着您的变量必须在pl / pgsql中的引号内,这意味着它将被视为文字。

解决方案是:

execute 
    'select count(*) ' ||
    'from visits ' ||
    'where ' ||
        'stend < (timestamp ''2017-11-29 15:00'' - interval ''' || (index_hour - 1) || ' hour'') and ' ||
        'stend > (timestamp ''2017-11-29 15:00'' - interval ''' || index_hour || ' hour'') and ' ||
        'location_id = 6 and ' ||
        'duration > 0'

为了节省我设置数据,我使用我拥有的表(驱动程序)编写了一个更简单的示例,以便我可以测试。请注意,您必须使用2个单引号将一个引号引入字符串,这意味着要仔细计算引号。

create function a47768241() returns integer
as $body$
declare
    index_hour int;
    id integer;
begin
    index_hour = 8;
    execute
        'select id ' ||
        'from driver ' ||
        'where ' ||
        'from_date_time < (timestamp ''2013-04-22 16:00:00'' - interval  ''' || (index_hour - 1) || ' hour'') '
         into id;
    return id;
end;
$body$
language 'plpgsql';

简单测试:

# select a47768241();
 a47768241 
-----------
       158
(1 row)

使用结果值检查日期:

# select * from driver where id = a47768241();
 id  | vehicle_id | person_id |      from_date_time       |       to_date_time        |         created_at         | updated_at 
-----+------------+-----------+---------------------------+---------------------------+----------------------------+------------
 158 |       6784 |     15430 | 2012-09-13 17:00:41.39778 | 2012-09-14 01:54:46.39778 | 2016-06-03 16:43:11.456063 | 
(1 row)

答案 2 :(得分:0)

只是连接间隔值,如

interval concat(index_hour - 1 , ' hour')