私は 隣接リスト 2つのテーブルで構成されています:
CREATE TABLE permission (id SMALLINT AUTO_INCREMENT(-32768, 1) PRIMARY KEY);
CREATE TABLE permission_graph (parent_id SMALLINT NOT NULL, child_id SMALLINT NOT NULL,
UNIQUE KEY (parent_id, child_id),
FOREIGN KEY (parent_id) REFERENCES permission(id) ON DELETE CASCADE,
FOREIGN KEY (child_id) REFERENCES permission(id) ON DELETE CASCADE);
次を実行すると [〜#〜] cte [〜#〜] 空のセットが得られます:
WITH RECURSIVE cte (parent_id, child_id)
AS
(
(
SELECT anchor.parent_id, anchor.child_id
FROM permission_graph anchor
WHERE anchor.child_id = -32763
)
UNION ALL
(
SELECT recursive.parent_id, recursive.child_id
FROM cte, permission_graph recursive
WHERE recursive.child_id = cte.child_id
)
)
SELECT cte.parent_id, cte.child_id
FROM cte
しかし、アンカー条件を実行すると、次のようになります。
SELECT anchor.parent_id, anchor.child_id
FROM permission_graph anchor
WHERE anchor.child_id = -32763
私は得る:
[parent_id = -32767, child_id = -32763]
[parent_id = -32768, child_id = -32763]
アンカー結果が空でないのにCTEが空のセットを返すのはなぜですか?CTE結果にアンカー結果を含めるべきではありませんか?
私はそれを考え出した。 (私を助けようとしたあなた方に謝罪します。これを理解する方法はありませんでした。)
多くの実験の後、動的クエリ(Connection.createStatement()
)は結果を返していましたが、パラメータ化されたクエリ(Connection.prepareStatement()
)は空のセットを返していました。私の質問がクエリを次のように誤ってリストしたため、これを知る方法がありませんでした。
chunk.child_id = -32763
実際にはそれはPreparedStatement
でした
アンカー.child_id =?
値が-32763
。
H2の奥深く リリースノート 私はこの素晴らしい文章に出くわしました:
パラメータは、最後のSELECTステートメント内でのみサポートされます(回避策は、テーブル式内で@startなどのセッション変数を使用することです)。
要するに、これはH2の制限/バグのように見えます。空のセットを返すのではなく、H2が例外をスローすることを本当に望んでいました。
https://groups.google.com/d/msg/h2-database/OJfqNF_Iqyo/Z748UP7W3NAJ この問題を確認します(nullではなく空のセットを取得していますが、それ以外は問題の説明は同じです) 。
助けてくれた皆さん、ありがとう!