postgresql

时间:2017-06-24 01:20:59

标签: postgresql loops variables for-loop nested-loops

我想知道postgresql中是否存在与变量和嵌套循环相关的内容,与其他语言的工作方式不同。

示例:

CREATE OR REPLACE FUNCTION public.generate_syllables()
  RETURNS integer AS
$BODY$

DECLARE
w RECORD;
s RECORD;
current_syllable integer := 1;
vowel_trigger integer := 0;
syllable_count integer := 1;

BEGIN

FOR w IN SELECT id FROM words LOOP
    FOR s IN SELECT sound, id FROM sounds WHERE id = w.id ORDER BY ordering LOOP
        IF (SELECT sr.vowel FROM sound_reference sr WHERE sr.sound = s.sound) = 1 AND vowel_trigger = 1 THEN
            syllable_count := syllable_count + 1;
            UPDATE sounds SET syllable = syllable_count WHERE id = s.id;
            vowel_trigger := 0;
        ELSIF (SELECT sr.vowel FROM sound_reference sr WHERE sr.sound = s.sound) = 1 THEN
            vowel_trigger := 1;
            UPDATE sounds SET syllable = syllable_count WHERE id = s.id;
        ELSE
            UPDATE sounds SET syllable = syllable_count WHERE id = s.id;
        END IF;
    END LOOP;
    UPDATE words SET syllables = syllable_count WHERE id = w.id;
    syllable_count := 1;
    vowel_trigger := 0;

END LOOP;

RETURN 1;

END;

$BODY$
  LANGUAGE plpgsql VOLATILE

当我按原样运行此函数时,该函数永远不会进入if语句中的第一个条件。我通过在第一个条件中添加一个return语句来测试它。起初我认为这肯定是一个逻辑错误,但我已经手工完成了从我的数据集生成的示例,它应该按照需要工作。更奇怪的是,当我在外部循环中注释掉行时,对于vowel_trigger:= 0,然后它输入第一个if语句。当然,逻辑也无法正常工作,从中我已经收集到syllable_count在嵌套循环完成循环之前被设置回0,这也解释了为什么永远不会输入第一个条件,因为设置了vowel_trigger在循环之前回到0使其恢复到第一个条件。

换句话说,在我看来,我的嵌套循环不像嵌套循环,而是嵌套循环在嵌套循环重新启动之前扩展到外部循环。我想我一定不能理解如何正确创建一个嵌套循环,或者也许他们只能在POSTGRESQL中以这种方式工作......任何建议都会非常感激。

1 个答案:

答案 0 :(得分:0)

您尚未提供表格结构,甚至更重要的数据。虽然您的函数的行为实际上取决于表wordssoundssound_reference中的数据。例如,如果sound_reference为空,vowel_trigger将永远不会是1,因此第一个IF变得无法实现。

这将有助于调试您的功能:

RAISE NOTICE 'printlining helps to debug! vowel_trigger=%, syllable_count=%',
  vowel_trigger, syllable_count;

作为旁注,我注意到UPDATE sounds SET syllable = syllable_count WHERE id = s.id;在所有if / else情况下都会重复,因此将它移到它们之外并放在内部END LOOP;之前可能是值得的。< / p>

另外:

  

...当我在外部循环中注释掉行,vowel_trigger:= 0时,它会输入第一个if语句。

它告诉我们内部循环的一个执行以vowel_trigger为1结束,它允许第一个IF触发,但是在内部循环之外你将它变为0,所以首先IF不起作用。