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 (ಸಣ್ಣ): ಒಂದು ಕ್ಷೇತ್ರಕ್ಕೆ ಸಂಕೀರ್ಣ ಅಥವಾ ಸ್ಥಿತಿ
ವಾಸ್ತವವಾಗಿ, ನಾವು ಸಂಖ್ಯೆ 3 ರಲ್ಲಿ ಸಮಸ್ಯೆಗಳನ್ನು ಹೊಂದಿದ್ದೇವೆ ಏಕೆಂದರೆ ನಿಖರವಾಗಿ ಮೂರು ಷರತ್ತುಗಳಿವೆ. ಆದರೆ ಅವುಗಳ ಬದಲಿಗೆ, ನೀವು ಯಾಂತ್ರಿಕ ವ್ಯವಸ್ಥೆಯನ್ನು ಬಳಸಿಕೊಂಡು ಒಂದನ್ನು ಪಡೆಯಬಹುದು 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