我在postgresql的規則內子查詢的執行順序內運行了一個奇怪的行爲(或者這是postgresql中的一個錯誤?)。考慮以下SQL:PostgreSQL子查詢在ON UPDATE規則內執行(可能是postgresql中的錯誤?)
BEGIN;
CREATE OR REPLACE FUNCTION debug(anyelement) RETURNS bool AS $$
pg_raise('notice', 'debug(): ' . json_encode($args[0]));
RETURN TRUE;
$$ LANGUAGE PLPHP IMMUTABLE STRICT;
CREATE TABLE foo_table (c1 text);
CREATE OR REPLACE RULE foo_update_rule AS ON UPDATE TO foo_table DO INSTEAD
(
WITH foobar_update AS
(
SELECT unnest('{a,b}'::text[]) AS _value, debug('update_inner'::text)
)
SELECT *, debug('update_outer_1'::text), debug('update_outer_2 -> '::text || _value::text) FROM foobar_update;
SELECT
(ROW(FALSE,FALSE) IN (SELECT
debug('update2_outer_1'::text), debug('update2_outer_2 -> '::text || _value::text)
FROM (SELECT unnest('{a,b}'::text[]) AS _value, debug('update_inner'::text)) AS foobar_update2 ))
);
-----------------------------------------------
WITH foobar_select AS
(
SELECT unnest('{a,b}'::text[]) AS _value, debug('select_inner'::text)
)
SELECT *, debug('select_outer_1'::text), debug('select_outer_2 -> '::text || _value::text), debug('select_outer_3'::text) FROM foobar_select;
UPDATE foo_table SET c1 = NULL where c1 = 'aaa';
ROLLBACK;
執行時上述代碼產生以下輸出:
NOTICE: plphp: debug(): "select_inner"
NOTICE: plphp: debug(): "select_outer_1"
NOTICE: plphp: debug(): "select_outer_3"
NOTICE: plphp: debug(): "select_outer_2 -> a"
NOTICE: plphp: debug(): "select_outer_2 -> b"
NOTICE: plphp: debug(): "update_inner"
NOTICE: plphp: debug(): "update_outer_1"
NOTICE: plphp: debug(): "update2_outer_1"
NOTICE: plphp: debug(): "update_inner"
從輸出中,它表明,這個問題是(又名「內部」)的之後執行的子查詢它在foo_update_rule的2個SELECT查詢中引用(又名'outer')查詢。其結果是,該_value柱(其子查詢中定義的)還沒有被當外部查詢求值定義,從而使調試(「update_outer_2 - >」 ::文本|| _value ::文本)默默地失效(和不打印通知)。
奇怪的是,ON INSERT規則中的同一個SQL會正常工作(打印出兩個'outer_2 - > ...'通知)。但由於某些原因,SQL在ON UPDATE規則中不起作用。
如何解決上述查詢問題,以便打印以下2個通知?
NOTICE: plphp: debug(): "update_outer_2 -> a"
NOTICE: plphp: debug(): "update_outer_2 -> b"
NOTICE: plphp: debug(): "update2_outer_2 -> a"
NOTICE: plphp: debug(): "update2_outer_2 -> b"
使用說明,看看其中的語句完成的順序。 –
爲了'mu太短',通知來自代碼塊頂部定義的debug()函數。在「update2_outer_2」是所謂的代碼塊開頭:ROW(FALSE,FALSE)IN(SELECT ...而且,是「調試(」 update_inner「::文本)」被稱爲在2個不同的地方,但就是意圖。 – archmeta
以「丹尼斯」,我不能夠使用規則內講解,爲pgsql的丟棄行。解釋上,它是在正確的順序執行的獨立選擇的節目。但原來的問題是,pgsql的正在執行不正確的順序規則中查詢,而在執行順序獨立的選擇是好的。 – archmeta