16/08/2026
استخدام Global Temporary Table بدل Collection في APEX
١. إنشاء الجدول (مرة واحدة بس، في الـ schema)
CREATE GLOBAL TEMPORARY TABLE gtt_invoice_lines (
invoice_no VARCHAR2(20),
item_code VARCHAR2(50),
qty NUMBER,
price NUMBER,
line_total NUMBER GENERATED ALWAYS AS (qty * price),
session_id NUMBER DEFAULT SYS_CONTEXT('USERENV','SESSIONID')
)
ON COMMIT PRESERVE ROWS;
CREATE INDEX idx_gtt_item ON gtt_invoice_lines(item_code);
موجودة طول الـ session (زي الـ Collection بالظبط)، لو استخدمت ON COMMIT DELETE ROWS هتتمسح مع كل commit.
• كل session بتشوف بياناتها هي بس تلقائيًا، Oracle بتعزل البيانات per-session على مستوى الـ storage segment، فمش محتاج تفلتر بـ session_id يدويًا زي ما بتعمل مع الـ Collection (لكن ينفع تضيفه كـ safety net).
٢. الإدراج بدل APEX_COLLECTION.ADD_MEMBER
INSERT INTO gtt_invoice_lines (invoice_no, item_code, qty, price)
VALUES (:P1_INVOICE_NO, l_item_code, l_qty, l_price);
بدل
APEX_COLLECTION.ADD_MEMBER(
p_collection_name => 'INVOICE_LINES',
p_c001 => l_item_code,
p_n001 => l_qty
);
٣. العرض في الصفحة (Interactive Report / Grid)
استخدم الجدول مباشرة كمصدر للـ Region بدل APEX_COLLECTIONS:
مش محتاج WHERE collection_name = 'INVOICE_LINES' ولا seq_id.
٤. التحقق (Validation) على مستوى الجدول
ALTER TABLE gtt_invoice_lines
ADD CONSTRAINT chk_qty_positive CHECK (qty > 0);
٥. الترحيل ثم التنظيف
INSERT INTO real_invoice_lines (invoice_no, item_code, qty, price)
SELECT invoice_no, item_code, qty, price FROM gtt_invoice_lines
WHERE invoice_no = :P1_INVOICE_NO;
DELETE FROM gtt_invoice_lines WHERE invoice_no = :P1_INVOICE_NO;
COMMIT;
نقطة مهمة في APEX تحديدًا: الـ GTT بياناتها بترتبط بالـ database session، والـ APEX session مش دايمًا نفس الـ DB session بين الصفحات (يعتمد على connection pooling). عمليًا في معظم إعدادات APEX العادية (mod_plsql / ORDS مع session state protection) البيانات بتفضل متسقة، بس لو شغال على بنية فيها connection pooling عدواني، اختبر السيناريو ده كويس قبل ما تعتمد عليه بالكامل — دي أكبر ميزة كانت الـ Collection بتحلها تلقائيًا وهنا لازم تتأكد بنفس