لماذا يفشل مسار الكيان الذي يحسب حقل المخزن تلقائيًا باستخدام case when داخل sql؟

Viewed 1

حاولت إنشاء مسار كيان لحساب حقل المخزن details.specificDimensions.warehouse تلقائيًا اعتمادًا على قسم الصنف، باستخدام الجملة التالية:

details.specificDimensions.warehouse=sql(select case when {details.item.item.section.code} = '1' then 'W-MG' else warehouse_id end from SrvJOrderMaterialLine where SrvCJobOrder_id = {ref1.$toReal.id} and {details.item.item.id} = material_id)

لكن المسار لا يعمل، ولا يُعيَّن أي مخزن في كثير من السطور. ما هي المشاكل الموجودة في هذه الجملة، وما هي الصياغة الصحيحة التي تضمن أن الاستعلام يعيد دائمًا قيمة منطقية يمكن لـ SQL Server التعامل معها؟

1 Answers

في الجملة الأصلية توجد مشكلتان:

  1. نوع القيمة غير واضح في case when: أحد الفروع يُرجع نصًا ثابتًا ('W-MG')، والفرع الآخر يُرجع حقل warehouse_id مباشرة. هذا الخلط يجعل من الصعب على SQL Server تحديد نوع القيمة المطلوبة (هل هو نص أم معرف؟)، مما قد يؤدي إلى فشل التنفيذ أو نتائج غير متوقعة.
  2. غياب نتائج من الجدول: في حالة عدم وجود أي سطر في SrvJOrderMaterialLine يُحقق شروط الفلترة، فإن الاستعلام بأكمله لن يُعيد أي قيمة، وبالتالي لن يتم تعيين أي مخزن للسطر إطلاقًا.

الحل

استخدم صيغة sub-query بشكل صحيح داخل فرع else في case when، لضمان أن الاستعلام دائمًا يُرجع قيمة (حتى لو كانت null) بدلًا من ألا يُرجع شيئًا على الإطلاق. كذلك استخدم معرّف المخزن مباشرة (binary id) في الفرع الأول بدل النص حتى يتطابق نوع القيمة بين الفرعين.

الصيغة المصححة:

details.specificDimensions.warehouse=mlsql(
  select case 
    when {details.item.item.section.code} = '1' 
    then 0xffff00019247e58188000000ff09aee9 
    else (select warehouse_id from SrvJOrderMaterialLine where SrvCJobOrder_id = {ref1.$toReal.id} and {details.item.item.id} = material_id) 
  end
)endmlsql

بهذا الشكل يتم ضمان أن الجملة تُعيد دائمًا قيمة واحدة منطقية يمكن لـ SQL Server التعامل معها، كما أن الاستعلام لن يفشل في حالة عدم وجود سطور مطابقة في الجدول.