Postgresql

在 FOR 循環中分配多個變數的結果令人驚訝

  • March 1, 2019
CREATE OR REPLACE FUNCTION my_function(input jsonb)
 RETURNS jsonb
 LANGUAGE plpgsql AS  -- language declaration required
$func$
DECLARE
  _key   text;
  _value text;
BEGIN
   FOR _key, _value IN
     SELECT jsonb_each_text($1)
   LOOP
       -- do some math operation on its corresponding value
       RAISE NOTICE '%: %', _key, _value;
   END LOOP;

   RETURN input;
END
$func$;

對於函式,如果我呼叫:

my_function('{"a":1, "b":2}');

它將在消息框中發出類似於 (a, 1), (b, 2) 的通知。

但是,如果我更改程式碼:

       RAISE NOTICE '%: %', _key, _value;

進入:

       RAISE NOTICE '%', _key;

會彈出相同的結果。

雖然程式碼:

       RAISE NOTICE '%', _value;

什麼都不會彈出。那是怎麼發生的?

我想我應該為這種混亂負責。

程式碼範例來自我對您之前的問題的回答,其中有一個微妙的錯誤(現已修復)。

出了什麼問題?

jsonb_each_text()是一個集合返回函式,它返回一組。呼叫時:

SELECT * FROM jsonb_each_text('{"a":1, "b":2}')

它返回:

關鍵 | 價值
-----+-------
一個 | 1
乙 | 2

但是當像上面這樣呼叫時:

SELECT jsonb_each_text('{"a":1, "b":2}')

它返回:

jsonb_each_text
-----------------
(a,1)
(b,2)

每行都返回一個,即行值,其文本表示形式與顯示的一樣。

現在,分配:

 FOR _key, _value IN SELECT jsonb_each_text($1) ...

將每行的第一個值分配給提供的第一個變數,_key在範例中。行值text在賦值中被強制轉換。由於沒有第二個值,_value因此設置為NULL。所以,後者:

RAISE NOTICE '%: %', _key, _value;

輸出消息:

注意:(a,1): <NULL>
注意:(b,2):<NULL>

這可能會產生誤導。(但請注意懸空: <NULL>!)

改成:

FOR _key, _value IN SELECT * FROM jsonb_each_text($1)

.. 迷霧應該會散去。

引用自:https://dba.stackexchange.com/questions/231068