پوسٹگری ایس کیو ایل اینٹی پیٹرنز: ایس کیو ایل میں حالت کی تشخیص

SQL C++ نہیں ہے، اور نہ ہی یہ JavaScript ہے۔ لہذا، منطقی اظہار کی تشخیص مختلف ہے، اور یہ ایک ہی چیز نہیں ہے:

WHERE fncondX() AND fncondY()

= fncondX() && fncondY()

PostgreSQL استفسار کے عمل درآمد کے منصوبے کو بہتر بناتے ہوئے من مانی طور پر مساوی حالات کو "دوبارہ ترتیب" دے سکتا ہے۔انفرادی ریکارڈ کے لیے ان میں سے کسی کا حساب نہ لگائیں، اپلائیڈ انڈیکس کی حالت کا حوالہ دیں... مختصر میں، سب سے آسان طریقہ یہ ہے کہ آپ انتظام نہیں کر سکتے جس ترتیب میں وہ ہوں گے (اور کیا ان کا حساب کتاب کیا جائے گا) برابر شرائط

لہذا، اگر آپ اب بھی ترجیح کا انتظام کرنا چاہتے ہیں، تو آپ کو ساختی طور پر کرنے کی ضرورت ہے۔ ان شرائط کو غیر مساوی بنائیں مشروط کے ساتھ تاثرات и آپریٹرز.

پوسٹگری ایس کیو ایل اینٹی پیٹرنز: ایس کیو ایل میں حالت کی تشخیص
ڈیٹا اور ان کے ساتھ کام کرنا بنیاد ہے۔ ہمارے VLSI کمپلیکس کااس لیے ہمارے لیے یہ بہت اہم ہے کہ ان پر آپریشن نہ صرف درست طریقے سے کیے جائیں بلکہ موثر بھی ہوں۔ آئیے ٹھوس مثالوں کو دیکھتے ہیں جہاں اظہار کی تشخیص میں غلطیاں کی جا سکتی ہیں، اور کہاں یہ ان کی کارکردگی کو بہتر بنانے کے قابل ہے۔

#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-value، یعنی، اگر دونوں شرائط غلط ہیں۔ 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

نیا تبصرہ شامل کریں