Jaka jest różnica między operatorem INi ANYw PostgreSQL?
Mechanizm działania obu wydaje się być taki sam. Czy ktoś może to wyjaśnić na przykładzie?
Jaka jest różnica między operatorem INi ANYw PostgreSQL?
Mechanizm działania obu wydaje się być taki sam. Czy ktoś może to wyjaśnić na przykładzie?
Odpowiedzi:
(Ani „operator”, INani ANY„ nie jest”. „Konstrukcja” lub „element składni”).
Logicznie , cytując instrukcję :
INjest równoważne= ANY.
Ale istnieją dwa warianty składniowe z INi dwa warianty ANY. Detale:
IN zabranie zestawu jest równoznaczne z = ANYwzięciem zestawu , jak pokazano tutaj:
Ale drugi wariant każdego z nich nie jest równoważny z drugim. Drugi wariant ANYkonstrukcji przyjmuje tablicę (musi być rzeczywistym typem tablicy), podczas gdy drugi wariant INprzyjmuje listę wartości oddzielonych przecinkami . Prowadzi to do różnych ograniczeń w przekazywaniu wartości i może również prowadzić do różnych planów zapytań w szczególnych przypadkach:
=any()ale używany zinANY jest bardziej wszechstronnyANYKonstrukcja jest bardziej uniwersalny, ponieważ mogą one być połączone z różnymi operatorami, nie tylko =. Przykład:
SELECT 'foo' LIKE ANY('{FOO,bar,%oo%}');
W przypadku dużej liczby wartości zapewnienie zestawu skal dla każdej z nich jest lepsze:
Związane z:
„Znajdź wiersze, w których idznajduje się podana tablica”:
SELECT * FROM tbl WHERE id = ANY (ARRAY[1, 2]);
Inwersja: „Znajdź wiersze, których nieid ma w tablicy”:
SELECT * FROM tbl WHERE id <> ALL (ARRAY[1, 2]);
SELECT * FROM tbl WHERE id <> ALL ('{1, 2}'); -- equivalent array literal
SELECT * FROM tbl WHERE NOT (id = ANY ('{1, 2}'));
Wszystkie trzy równoważne. Pierwsza z konstruktorem tablicy , pozostałe dwie z literałem tablicowym . Typ danych można jednoznacznie wyprowadzić z kontekstu. W przeciwnym razie może być wymagana wyraźna obsada, na przykład '{1,2}'::int[].
Wiersze z id IS NULLnie przechodzą żadnego z tych wyrażeń. Aby NULLdodatkowo uwzględnić wartości:
SELECT * FROM tbl WHERE (id = ANY ('{1, 2}')) IS NOT TRUE;
SELECT * from mytable where id in (1, 2, 3)zawsze będą powodować te same wiersze, co SELECT * from mytable where id = ANY('{1, 2, 3}'), nawet jeśli potencjalnie mogą mieć różne plany zapytań.
ANY nie można łączyć z !=operatorem. Myślę, że nie jest to udokumentowane, ale select * from foo where id != ANY (ARRAY[1, 2])to nie to samo, co select * from foo where id NOT IN (1, 2). Z drugiej strony select * from foo where NOT (id = ANY (ARRAY[1, 2]))działa zgodnie z oczekiwaniami.
ANYmożna łączyć z !=operatorem. Ale to nie wszystko. Dodałem rozdział powyżej. (Zauważ, że <>jest to operator w standardowym SQL - choć !=jest również akceptowany w Postgres.)
NULLwartości? Działałby WHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;równie dobrze?
(id = ...) IS NOT TRUEdziała, ponieważ wartościowane są id = ...tylko TRUEwtedy, gdy istnieje rzeczywiste dopasowanie. Wyniki FALSElub NULLzdaj nasz test. Zobacz: stackoverflow.com/a/23767625/939860 . Twoje dodane wyrażenie sprawdza coś innego. To byłoby równoważneWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Istnieją dwa oczywiste punkty, a także punkty w drugiej odpowiedzi:
Są dokładnie równoważne podczas korzystania z zapytań podrzędnych:
SELECT * FROM table
WHERE column IN(subquery);
SELECT * FROM table
WHERE column = ANY(subquery);Z drugiej strony:
Tylko INoperator umożliwia prostą listę:
SELECT * FROM table
WHERE column IN(… , … , …);Zakładanie, że są dokładnie takie same, przyłapało mnie kilka razy, kiedy zapominałem, że ANYto nie działa w przypadku list.