【问题标题】:Issue with nested loops in postgresqlpostgresql 中的嵌套循环问题
【发布时间】:2017-06-24 01:20:58
【问题描述】:

我想知道 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 中以这种方式工作......任何建议将不胜感激。

【问题讨论】:

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


    【解决方案1】:

    您还没有提供表结构和 - 更重要的是 - 数据。虽然您的函数的行为实际上取决于表 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; 之前。

    加法:

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

    它告诉我们内部循环的一个执行以 vowel_trigger 为 1 结束,它会允许第一个 IF 触发,但在内部循环外部你将它设为 0,所以第一个 IF那就不行了。

    【讨论】:

      猜你喜欢
      • 2021-05-17
      • 2016-06-23
      • 2017-09-20
      • 1970-01-01
      • 1970-01-01
      • 2012-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多