Postgres在FOR循环中访问行值

时间:2018-08-06 22:02:03

标签: postgresql loops rows variable-assignment plpgsql

我是Postgres的新手。这是我的job_defn 的结构和一些示例数据:

CREATE TABLE job_defn (
        job_id INTEGER NOT NULL,
        job_name CHARACTER VARYING(255) NOT NULL,
        system CHARACTER VARYING(50) NOT NULL,
        frequency CHARACTER VARYING(10) NOT NULL,
        run_day_id INTEGER NOT NULL,
        run_day_of_month INTEGER NOT NULL,
        eff_start_date DATE NOT NULL,
        eff_end_date DATE NOT NULL
    );

样本数据:

---------------------------
job_id         frequency
---------------------------
1001           DAILY 
1002           WEEKLY
---------------------------

运行以下函数时,我期望l_freq变量包含表中的frequency列值。但是,即使表行包含一个值,它也始终显示NULL:

CREATE OR REPLACE FUNCTION testing()
   RETURNS void AS $$
   DECLARE

       l_job_id INTEGER;
       l_job_defn_record job_defn%ROWTYPE;
       l_freq CHARACTER VARYING(10);
   BEGIN
       FOR l_job_defn_record IN 
               SELECT job_id, frequency FROM job_defn ORDER BY job_id ASC
       LOOP
               l_job_id := l_job_defn_record.job_id;
               l_freq := l_job_defn_record.frequency;
               raise info'job id: %,  frq: %', l_job_id, l_freq;
               raise info'row==>%', l_job_defn_record;

       END LOOP;
   END;
   $$ LANGUAGE plpgsql VOLATILE;

日志:

17:50:52  [CREATE - 0 row(s), 0.036 secs]  Command processed. No rows were affected
Code: 0 SQL State: 00000 --- job id: 10001,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10001,DAILY,,,,,,,,,,)
Code: 0 SQL State: 00000 --- job id: 10001,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10001,DAILY,,,,,,,,,,)
Code: 0 SQL State: 00000 --- job id: 10001,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10001,DAILY,,,,,,,,,,)
Code: 0 SQL State: 00000 --- job id: 10001,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10001,DAILY,,,,,,,,,,)
Code: 0 SQL State: 00000 --- job id: 10001,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10001,DAILY,,,,,,,,,,)
Code: 0 SQL State: 00000 --- job id: 10001,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10001,DAILY,,,,,,,,,,)
Code: 0 SQL State: 00000 --- job id: 10001,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10001,DAILY,,,,,,,,,,)
Code: 0 SQL State: 00000 --- job id: 10002,  frq: <NULL>
Code: 0 SQL State: 00000 --- row==>(10002,WEEKLY,,,,,,,,,,)
... 1 statement(s) executed, 0 row(s) affected, exec/fetch time: 0.036/0.000 sec  [0 successful, 1 warnings, 0 errors]

2 个答案:

答案 0 :(得分:1)

您将记录变量l_job_defn_record声明为类型job_defn%ROWTYPE。正如您稍后所阐明的,表job_defn实际上不仅包含您最初公开的两列。 FOR循环中的分配仅分配记录变量的 前两个字段

...
   FOR l_job_defn_record IN 
      SELECT job_id, frequency FROM ...  -- wrong!
...

通过这种方式,来自SELECT查询(job_defn.frequency)的第二列被分配给记录变量(l_job_defn_record.job_name)的第二个字段-显然不是预期的。由于frequency的类型也是varchar,因此它可以工作。记录的尾部字段未分配,默认为NULL

这将解决该问题:

...
   FOR l_job_defn_record IN 
      SELECT * FROM job_defn ORDER BY job_id
...

SELECT *通常是可疑的编码,但是在这种情况下,这是正确的方法,因为根据定义,l_job_defn_record具有与表job_defn相同的行类型。

答案 1 :(得分:1)

Erwin在回答中清楚地说明了错误的原因。我建议对变量使用the RECORD type而不是ROWTYPE

    l_job_defn_record RECORD;

此类变量的实际结构是在为其分配值时动态定义的。因此,变量和赋值之间不存在不兼容的可能性。