SQL se pa C++, epi li pa JavaScript. Se poutèt sa, kalkil la nan ekspresyon lojik rive yon fason diferan, epi sa a se pa nan tout menm bagay la:
WHERE fncondX() AND fncondY()
= fncondX() && fncondY()
Nan pwosesis pou optimize plan ekzekisyon rechèch PostgreSQL la
Se poutèt sa, si ou toujou vle jere priyorite, ou bezwen estrikti li fè kondisyon sa yo inegal itilize kondisyonèl
Done ak travay avèk yo se baz la
#0: RTFM
Kòmanse
Lè lòd evalyasyon an enpòtan, li ka kaptire lè l sèvi avèk konstriksyon an
CASE
. Pou egzanp, sa a se yon fason pou evite divizyon pa zewo nan yon frazWHERE
enfidèl:SELECT ... WHERE x > 0 AND y/x > 1.5;
Opsyon san danje:
SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;
Konsepsyon yo itilize nan fason sa a
CASE
pwoteje ekspresyon an soti nan optimize, kidonk li ta dwe itilize sèlman lè sa nesesè.
#1: kondisyon deklanche
BEGIN
IF cond(NEW.fld) AND EXISTS(SELECT ...) THEN
...
END IF;
RETURN NEW;
END;
Tout sanble gade byen, men... Pa gen moun ki pwomèt ke envestisman an SELECT
pa pral egzekite si premye kondisyon an se fo. Ann ranje li ak enbrike IF
:
BEGIN
IF cond(NEW.fld) THEN
IF EXISTS(SELECT ...) THEN
...
END IF;
END IF;
RETURN NEW;
END;
Koulye a, ann gade ak anpil atansyon - tout kò a nan fonksyon an deklanche se "vlope" nan IF
. Sa vle di ke pa gen anyen ki anpeche nou retire kondisyon sa a nan pwosedi a lè l sèvi avèk WHEN
-kondisyon
BEGIN
IF EXISTS(SELECT ...) THEN
...
END IF;
RETURN NEW;
END;
...
CREATE TRIGGER ...
WHEN cond(NEW.fld);
Apwòch sa a garanti pou konsève pou resous sèvè lè kondisyon an fo.
#2: OSWA/AK chèn
SELECT ... WHERE EXISTS(... A) OR EXISTS(... B)
Sinon, ou ka fini ak tou de EXISTS
pral "vre", men tou de pral rive vre.
Men, si nou konnen pou asire w ke youn nan yo se "vre" pi souvan (oswa "fo" - pou AND
-chèn) - èske li posib pou yon jan kanmenm "ogmante priyorite li" pou dezyèm lan pa egzekite yon lòt fwa ankò?
Li sanble ke li posib - apwòch la algoritm se tou pre sijè a nan atik la
Ann jis "pouse" tou de kondisyon sa yo nan CASE:
SELECT ...
WHERE
CASE
WHEN EXISTS(... A) THEN TRUE
WHEN EXISTS(... B) THEN TRUE
END
Nan ka sa a nou pa t defini ELSE
-valè, se sa ki, si tou de kondisyon yo fo CASE
pral retounen NULL
, ki entèprete kòm FALSE
в WHERE
-kondisyon.
Egzanp sa a ka konbine nan lòt fason - depann sou gou ak koulè:
SELECT ...
WHERE
CASE
WHEN NOT EXISTS(... A) THEN EXISTS(... B)
ELSE TRUE
END
#3: ki jan [pa] ekri kondisyon yo
Nou te pase de jou analize rezon pou operasyon "etranj" deklanche sa a - ann wè poukisa.
Sous:
IF( NEW."Документ_" is null or NEW."Документ_" = (select '"Комплект"'::regclass::oid) or NEW."Документ_" = (select to_regclass('"ДокументПоЗарплате"')::oid)
AND ( OLD."ДокументНашаОрганизация" <> NEW."ДокументНашаОрганизация"
OR OLD."Удален" <> NEW."Удален"
OR OLD."Дата" <> NEW."Дата"
OR OLD."Время" <> NEW."Время"
OR OLD."ЛицоСоздал" <> NEW."ЛицоСоздал" ) ) THEN ...
Pwoblèm #1: inegalite pa respekte NULL
Ann imajine ke tout bagay OLD
-fields te gen siyifikasyon NULL
. Kisa ki pral rive?
SELECT NULL <> 1 OR NULL <> 2;
-- NULL
Ak nan pwen de vi nan travay deyò kondisyon yo NULL
ekivalan FALSE
, jan mansyone pi wo a.
desizyon: sèvi ak operatè IS DISTINCT FROM
ROW
-operatè, konpare tout dosye nan yon fwa:
SELECT (NULL, NULL) IS DISTINCT FROM (1, 2);
-- TRUE
Pwoblèm #2: aplikasyon diferan nan menm fonksyonalite a
Ann konpare:
NEW."Документ_" = (select '"Комплект"'::regclass::oid)
NEW."Документ_" = (select to_regclass('"ДокументПоЗарплате"')::oid)
Poukisa gen plis envestisman isit la? SELECT
? Yon fonksyon to_regclass
? Poukisa li diferan? ..
Ann ranje:
NEW."Документ_" = '"Комплект"'::regclass::oid
NEW."Документ_" = '"ДокументПоЗарплате"'::regclass::oid
Pwoblèm #3: priyorite nan operasyon bool
Ann fòma sous la:
{... IS NULL} OR
{... Комплект} OR
{... ДокументПоЗарплате} AND
( {... неравенства} )
Oops... An reyalite, li te tounen soti ke si nenpòt nan de premye kondisyon yo se vre, kondisyon an antye vire nan TRUE
, san yo pa pran an kont inegalite. Ak sa a se pa nan tout sa nou te vle.
Ann ranje:
(
{... IS NULL} OR
{... Комплект} OR
{... ДокументПоЗарплате}
) AND
( {... неравенства} )
Pwoblèm #4 (ti): konplèks OSWA kondisyon pou yon jaden
Aktyèlman, nou te gen pwoblèm nan nimewo 3 jisteman paske te gen twa kondisyon. Men, olye pou yo yo ou ka jwenn pa ak yon sèl, lè l sèvi avèk mekanis la coalesce ... IN
:
coalesce(NEW."Документ_"::text, '') IN ('', '"Комплект"', '"ДокументПоЗарплате"')
Se konsa, nou NULL
"nou pral trape", ak difisil OR
Pa gen okenn nesesite kloti ak parantèz.
Nan total
Ann anrejistre sa nou jwenn:
IF (
coalesce(NEW."Документ_"::text, '') IN ('', '"Комплект"', '"ДокументПоЗарплате"') AND
(
OLD."ДокументНашаОрганизация"
, OLD."Удален"
, OLD."Дата"
, OLD."Время"
, OLD."ЛицоСоздал"
) IS DISTINCT FROM (
NEW."ДокументНашаОрганизация"
, NEW."Удален"
, NEW."Дата"
, NEW."Время"
, NEW."ЛицоСоздал"
)
) THEN ...
Men, si ou konsidere ke fonksyon deklanche sa a ka sèlman itilize nan UPDATE
-deklanche akòz disponiblite OLD/NEW
nan kondisyon an nivo siperyè, Lè sa a, kondisyon sa a ka jeneralman mete nan WHEN
-kondisyon, jan yo montre nan #1...
Sous: www.habr.com