SQL نه C++ دی او نه دا جاواسکریپټ دی. له همدې امله، د منطقي څرګندونو ارزونه توپیر لري، او دا په اصل کې ورته شی نه دی:
WHERE fncondX() AND fncondY()
= fncondX() && fncondY()
پداسې حال کې چې د PostgreSQL پوښتنې د اجرا کولو پلان اصلاح کول
له همدې امله، که تاسو اوس هم غواړئ لومړیتوب اداره کړئ، تاسو اړتیا لرئ چې جوړښتي بڼه ولرئ دا شرایط غیر مساوي کړئ په مشروط ډول
ډاټا او د دوی سره کار کول اساس دی
#0: RTFM
پیل کول
کله چې د ارزونې ترتیب مهم وي، دا د ساختمان سره تنظیم کیدی شي
CASE
. د مثال په توګه، دا لاره په یوه جمله کې د صفر لخوا ویشلو څخه مخنیوی کويWHERE
بې اعتباره:SELECT ... WHERE x > 0 AND y/x > 1.5;
خوندي انتخاب:
SELECT ... WHERE CASE WHEN x > 0 THEN y/x > 1.5 ELSE false END;
ساختمان کارول شوی
CASE
بیان د اصلاح کولو څخه ساتي، نو دا باید یوازې د اړتیا په وخت کې وکارول شي.
#1: د محرک حالت
BEGIN
IF cond(NEW.fld) AND EXISTS(SELECT ...) THEN
...
END IF;
RETURN NEW;
END;
هرڅه ښه ښکاري، مګر ... هیڅوک ژمنه نه کوي چې پانګه اچونه یې کړې SELECT
نه به اجرا شي که لومړی شرط غلط وي. سره سم کړئ ځالې IF
:
BEGIN
IF cond(NEW.fld) THEN
IF EXISTS(SELECT ...) THEN
...
END IF;
END IF;
RETURN NEW;
END;
اوس راځئ چې په دقت سره وګورو - د ټریګر فنکشن ټول بدن "لپټ" شو IF
. او دا پدې مانا ده چې هیڅ شی موږ ته د دې حالت د کارولو له پروسې څخه د لرې کولو مخه نه نیسي WHEN
- شرایط
BEGIN
IF EXISTS(SELECT ...) THEN
...
END IF;
RETURN NEW;
END;
...
CREATE TRIGGER ...
WHEN cond(NEW.fld);
دا طریقه تاسو ته اجازه درکوي د تضمین سره د سرور سرچینې خوندي کړئ که حالت غلط وي.
#2: یا/او سلسله
SELECT ... WHERE EXISTS(... A) OR EXISTS(... B)
که نه نو، دا ترلاسه کیدی شي چې دواړه EXISTS
ریښتیا به وي، مګر دواړه به اعدام شي.
مګر که موږ په یقین سره پوهیږو چې یو له دوی څخه "ریښتیا" دی ډیر ځله (یا "غلط" - لپاره AND
زنځیرونه) - ایا دا امکان لري چې په یو ډول "خپل لومړیتوب ډیر کړي" ترڅو دوهم یو ځل بیا اعدام نشي؟
دا معلومه شوه چې دا ممکنه ده - د الګوریتمیک طریقه د مقالې موضوع ته نږدې ده
راځئ چې یوازې دا دواړه شرایط "د قضیې لاندې وغورځوو":
SELECT ...
WHERE
CASE
WHEN EXISTS(... A) THEN TRUE
WHEN EXISTS(... B) THEN TRUE
END
په دې حالت کې، موږ تعریف نه شو ELSE
- ارزښت، دا دی، که دواړه شرایط غلط وي CASE
بیرته به راشي NULL
، کوم چې په توګه تشریح کیږي FALSE
в WHERE
- شرایط.
دا مثال په بل ډول سره یوځای کیدی شي - د خوند او رنګ لپاره:
SELECT ...
WHERE
CASE
WHEN NOT EXISTS(... A) THEN EXISTS(... B)
ELSE TRUE
END
#3: د شرایطو لیکلو څرنګوالی
موږ دوه ورځې د دې محرک د "عجیب" محرک لاملونو تحلیل کولو کې تیرې کړې - راځئ چې وګورو ولې.
سرچینه:
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 ...
ستونزه #1: نابرابري د NULL لپاره حساب نه کوي
راځئ چې دا هر څه فرض کړو OLD
- ساحې مهمې دي NULL
. څه به وشي؟
SELECT NULL <> 1 OR NULL <> 2;
-- NULL
او د شرایطو څخه د کار کولو له نظره NULL
برابر FALSE
لکه څنګه چې پورته یادونه وشوه.
پریکړه: چلونکی وکاروئ IS DISTINCT FROM
ROW
- آپریټر، په یوځل کې ټول ریکارډونه پرتله کول:
SELECT (NULL, NULL) IS DISTINCT FROM (1, 2);
-- TRUE
ستونزه 2: د ورته فعالیت مختلف پلي کول
پرتله کول:
NEW."Документ_" = (select '"Комплект"'::regclass::oid)
NEW."Документ_" = (select to_regclass('"ДокументПоЗарплате"')::oid)
ولې اضافي پانګونې شتون لري SELECT
؟ یو فعالیت to_regclass
؟ ولې توپیر لري ...
راځئ چې اصلاح کړو:
NEW."Документ_" = '"Комплект"'::regclass::oid
NEW."Документ_" = '"ДокументПоЗарплате"'::regclass::oid
ستونزه #3: د بول لومړیتوب
راځئ چې سرچینه فارمیټ کړو:
{... IS NULL} OR
{... Комплект} OR
{... ДокументПоЗарплате} AND
( {... неравенства} )
او په حقیقت کې، دا معلومه شوه چې د لومړیو دوو حالتونو څخه د حقیقت په صورت کې، ټول حالت بدلیږي. TRUE
د نابرابریو په پام کې نیولو سره. او دا هغه څه ندي چې موږ یې غوښتل.
راځئ چې اصلاح کړو:
(
{... IS NULL} OR
{... Комплект} OR
{... ДокументПоЗарплате}
) AND
( {... неравенства} )
ستونزه #4 (کوچنۍ): د یوې ساحې لپاره پیچلې یا حالت
په حقیقت کې موږ په دریم نمبر کې ستونزې درلودې ځکه چې درې شرایط شتون درلود. مګر د دوی پرځای ، تاسو کولی شئ د میکانیزم په کارولو سره د یو سره ترلاسه کړئ coalesce ... IN
:
coalesce(NEW."Документ_"::text, '') IN ('', '"Комплект"', '"ДокументПоЗарплате"')
همداسې موږ یو NULL
"کیچ"، او پیچلي OR
تاسو اړتیا نلرئ د قوسونو سره ګډوډي وکړئ.
ټول
راځئ چې هغه څه سم کړو چې موږ ترلاسه کړل:
IF (
coalesce(NEW."Документ_"::text, '') IN ('', '"Комплект"', '"ДокументПоЗарплате"') AND
(
OLD."ДокументНашаОрганизация"
, OLD."Удален"
, OLD."Дата"
, OLD."Время"
, OLD."ЛицоСоздал"
) IS DISTINCT FROM (
NEW."ДокументНашаОрганизация"
, NEW."Удален"
, NEW."Дата"
, NEW."Время"
, NEW."ЛицоСоздал"
)
) THEN ...
او ورکړل شوی چې دا محرک فنکشن یوازې په کې کارول کیدی شي UPDATE
د شتون له امله محرک OLD/NEW
د پورتنۍ کچې حالت کې، نو دا حالت په عمومي توګه بهر اخیستل کیدی شي WHEN
- حالت لکه څنګه چې په # 1 کې ښودل شوی ...
سرچینه: www.habr.com