SQL dudu C++, uga JavaScript. Mulane, evaluasi ekspresi logis beda, lan iki ora padha:
WHERE fncondX() AND fncondY()
= fncondX() && fncondY()
Nalika ngoptimalake rencana eksekusi pitakon PostgreSQL
Mulane, yen sampeyan isih pengin ngatur prioritas, sampeyan kudu struktural nggawe kahanan iki ora padha kanthi kondisional
Data lan nggarap wong-wong mau minangka basis
#0: RTFM
miwiti
Nalika urutan evaluasi penting, bisa diatasi kanthi konstruksi
CASE
. Contone, cara iki kanggo ngindhari divisi kanthi nol ing ukaraWHERE
ora bisa dipercaya:SELECT ... WHERE x > 0 AND y/x > 1.5;
Pilihan aman:
SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;
Konstruksi sing digunakake
CASE
nglindhungi expression saka Optimization, supaya mung kudu digunakake yen perlu.
# 1: kondisi pemicu
BEGIN
IF cond(NEW.fld) AND EXISTS(SELECT ...) THEN
...
END IF;
RETURN NEW;
END;
Kabeh katon apik, nanging ... Ora ana sing janji yen nandur modal SELECT
ora bakal dieksekusi yen kondisi pisanan salah. Ndandani karo bersarang IF
:
BEGIN
IF cond(NEW.fld) THEN
IF EXISTS(SELECT ...) THEN
...
END IF;
END IF;
RETURN NEW;
END;
Saiki ayo dideleng kanthi teliti - kabeh awak fungsi pemicu dadi "dibungkus". IF
. Lan iki tegese ora ana sing ngalangi kita mbusak kondisi iki saka prosedur nggunakake WHEN
- syarat
BEGIN
IF EXISTS(SELECT ...) THEN
...
END IF;
RETURN NEW;
END;
...
CREATE TRIGGER ...
WHEN cond(NEW.fld);
Pendekatan iki ngidini sampeyan nyimpen sumber daya server kanthi jaminan yen kondisi kasebut salah.
# 2: UTAWA / LAN chain
SELECT ... WHERE EXISTS(... A) OR EXISTS(... B)
Yen ora, bisa dipikolehi sing loro EXISTS
bakal bener, nanging loro bakal kaleksanan.
Nanging yen kita ngerti manawa salah sijine "bener" luwih asring (utawa "palsu" - kanggo AND
-chains) - apa bisa "nambah prioritas" supaya sing nomer loro ora dieksekusi maneh?
Pranyata iku bisa - pendekatan algorithmically cedhak topik artikel
Ayo mung "shove ing CASE" loro kondisi iki:
SELECT ...
WHERE
CASE
WHEN EXISTS(... A) THEN TRUE
WHEN EXISTS(... B) THEN TRUE
END
Ing kasus iki, kita ora nemtokake ELSE
-nilai, sing, yen loro kondisi iku palsu CASE
bakal bali NULL
, sing ditegesi minangka FALSE
Π² WHERE
- syarat.
Conto iki bisa digabungake kanthi cara liya - kanggo rasa lan werna:
SELECT ...
WHERE
CASE
WHEN NOT EXISTS(... A) THEN EXISTS(... B)
ELSE TRUE
END
#3: carane [ora] nulis kahanan
Kita ngenteni rong dina kanggo nganalisa sebab-sebab pemicu "aneh" pemicu iki - ayo goleki kenapa.
Sumber:
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 ...
Masalah #1: Ketimpangan ora nyatakake NULL
Ayo nganggep kabeh OLD
- lapangan penting NULL
. Apa sing bakal kelakon?
SELECT NULL <> 1 OR NULL <> 2;
-- NULL
Lan saka sudut pandang nggarap kahanan NULL
padha karo FALSE
, kaya kasebut ing ndhuwur.
kaputusan: gunakake operator IS DISTINCT FROM
ROW
-operator, mbandhingake kabeh rekaman bebarengan:
SELECT (NULL, NULL) IS DISTINCT FROM (1, 2);
-- TRUE
Masalah nomer 2: implementasine beda saka fungsi sing padha
Banding:
NEW."ΠΠΎΠΊΡΠΌΠ΅Π½Ρ_" = (select '"ΠΠΎΠΌΠΏΠ»Π΅ΠΊΡ"'::regclass::oid)
NEW."ΠΠΎΠΊΡΠΌΠ΅Π½Ρ_" = (select to_regclass('"ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠΎΠΠ°ΡΠΏΠ»Π°ΡΠ΅"')::oid)
Apa ana investasi ekstra SELECT
? A fungsi to_regclass
? Kok beda...
Ayo ndandani:
NEW."ΠΠΎΠΊΡΠΌΠ΅Π½Ρ_" = '"ΠΠΎΠΌΠΏΠ»Π΅ΠΊΡ"'::regclass::oid
NEW."ΠΠΎΠΊΡΠΌΠ΅Π½Ρ_" = '"ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠΎΠΠ°ΡΠΏΠ»Π°ΡΠ΅"'::regclass::oid
Masalah #3: precedence bool
Ayo format sumber:
{... IS NULL} OR
{... ΠΠΎΠΌΠΏΠ»Π΅ΠΊΡ} OR
{... ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠΎΠΠ°ΡΠΏΠ»Π°ΡΠ΅} AND
( {... Π½Π΅ΡΠ°Π²Π΅Π½ΡΡΠ²Π°} )
Adhuh ... Nyatane, ing kasus bebener salah siji saka rong kondisi pisanan, kabeh kondisi dadi. TRUE
, ora nggatekake ketimpangan. Lan iki ora kabeh sing dikarepake.
Ayo ndandani:
(
{... IS NULL} OR
{... ΠΠΎΠΌΠΏΠ»Π΅ΠΊΡ} OR
{... ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠΎΠΠ°ΡΠΏΠ»Π°ΡΠ΅}
) AND
( {... Π½Π΅ΡΠ°Π²Π΅Π½ΡΡΠ²Π°} )
Masalah # 4 (cilik): Komplek UTAWA kondisi kanggo siji lapangan
Bener, kita duwe masalah ing nomer 3 amarga ana telung kahanan. Nanging tinimbang wong-wong mau, sampeyan bisa njaluk karo siji, nggunakake mekanisme coalesce ... IN
:
coalesce(NEW."ΠΠΎΠΊΡΠΌΠ΅Π½Ρ_"::text, '') IN ('', '"ΠΠΎΠΌΠΏΠ»Π΅ΠΊΡ"', '"ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠΎΠΠ°ΡΠΏΠ»Π°ΡΠ΅"')
Semono uga kita NULL
"nyekel", lan kompleks OR
Sampeyan ora kudu repot karo kurung.
Total
Ayo ndandani apa sing entuk:
IF (
coalesce(NEW."ΠΠΎΠΊΡΠΌΠ΅Π½Ρ_"::text, '') IN ('', '"ΠΠΎΠΌΠΏΠ»Π΅ΠΊΡ"', '"ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠΎΠΠ°ΡΠΏΠ»Π°ΡΠ΅"') AND
(
OLD."ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠ°ΡΠ°ΠΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡ"
, OLD."Π£Π΄Π°Π»Π΅Π½"
, OLD."ΠΠ°ΡΠ°"
, OLD."ΠΡΠ΅ΠΌΡ"
, OLD."ΠΠΈΡΠΎΠ‘ΠΎΠ·Π΄Π°Π»"
) IS DISTINCT FROM (
NEW."ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠΠ°ΡΠ°ΠΡΠ³Π°Π½ΠΈΠ·Π°ΡΠΈΡ"
, NEW."Π£Π΄Π°Π»Π΅Π½"
, NEW."ΠΠ°ΡΠ°"
, NEW."ΠΡΠ΅ΠΌΡ"
, NEW."ΠΠΈΡΠΎΠ‘ΠΎΠ·Π΄Π°Π»"
)
) THEN ...
Lan diwenehi fungsi pemicu iki mung bisa digunakake ing UPDATE
pemicu amarga saka ngarsane OLD/NEW
ing kondisi tingkat ndhuwur, banjur kondisi iki umume bisa dijupuk metu ing WHEN
- kondisi kaya sing ditampilake ing nomer 1 ...
Source: www.habr.com