الانتقال إلى المحتوى
View in the app

A better way to browse. Learn more.

مجموعة مستخدمي أوراكل العربية

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

دالة تاريخ

Featured Replies

بتاريخ:

لو سمحتم انا عايز فانكشن او بروسيدشر لحساب الفرق بين تاريخين بدون الجمعة او السبت لو وقع احدهما بين التاريخين

بتاريخ:

الأخ الكريم ، قبل أي شيء يجب عليك معرفة محتويات التاريخين ... يعني بيتكون من أي شهور ( من البداية الي النهاية ) ... وتدرج كل هذه الشهور في جدول مستقل كما يلي :

CREATE TABLE TMP_MONTHS
(
 DAT  DATE;
)
/

DECLARE
  ID_START_DATE  CONSTANT DATE := TO_DATE('24/9/1981','DD/MM/YYYY');
  ID_END_DATE	 CONSTANT DATE := TO_DATE('24/9/2008','DD/MM/YYYY');
  ID_DATE   DATE;
BEGIN
  ID_DATE := ID_START_DATE;
  WHILE ID_DATE <= ID_END_DATE
  LOOP
 ID_DATE := ID_DATE + 30.4375;
 INSERT INTO TMP_MONTHS VALUES(TO_DATE(TO_CHAR(ID_DATE,'YYYY/MM') || '1' ,'YYYY/MM/DD'));
  END LOOP;
END;



الآن أنت لديك جدول TEMP يحتوي علي كافة الشهور التي يحتوي عليها ما بين تاريخين ... يجب عليك الآن أن تمتلك جدول آخر أو عارض ليتضمن كافة أيام الشهر الممكنة كما يلي :

CREATE TABLE DAYS
(
 D  VARCHAR2(2);
)
/
DECLARE
 X  NUMBER;
BEGIN
 FOR X IN 1 .. 31
 LOOP
INSERT INTO DAYS VALUES(X);
 END LOOP;
END;
/



السؤال ، لماذا لم يتم إدراج الأيام في جدول TMP_MONTHS علي الفور ... السبب لأن في هذه الحالة لو كان عدد السنوات 10 أو 20 أو 30 أو .... الي آخرة هيكون عملية الـ LOOP بطيئة بالزات أن كل سنة هتكون مكونة من 365 أو 366 يوم ... ولكن فكرة أنك تقم بإدراج جدول وسيط يدعي DAYS تدرج فية كل أيام الشهر دة في حد ذاتة هيخلي عملية الـ LOOP أقل وسرعة عالية نظراً لأن السنة في هذه الحالة ستحتوي علي 12 شهر يعني إجراء دوارة LOOP بمقدار 12 مرة وليس 365 أو 366 لكل سنة.

المهم

طريقة الدمج بين الشهر واليوم :

1- إنشاء FUNCTION يدعي IS_DATE لهدف أنه ليس من الشرط أن يكون كل شهر يحتوي علي 31 يوم :



 
CREATE OR REPLACE FUNCTION IS_DATE(IN_TEXT VARCHAR2) RETURN NUMBER
AS
 ID_DATE DATE;
BEGIN
 ID_DATE := TO_DATE(IN_TEXT,'YYYY/MM/DD');
 RETURN 1;
EXCEPTION
 WHEN OTHERS THEN
RETURN 0;
END;
/




بعد ذلك تنشأ VIEW لجلب كل أيام الشهور بل السنوات كما يلي :

CREATE OR REPLACE LIST_ALL_DAYS
AS
(
 SELECT TO_DATE(TO_CHAR(TMP_MONTHS.DAT,'YYYY/MM/DD') || DAYS.D,'YYYY/MM/DD') AS DAY
 FROM TMP_MONTHS, DAYS
 WHERE IS_DATE(TO_DATE(TO_CHAR(TMP_MONTHS.DAT,'YYYY/MM/DD') || DAYS.D,'YYYY/MM/DD')) = 1
)
/



بكدة هيكون لديك جدول كامل يحتوي علي كل الأيام المطلوبة للسنوات ... ولكن أنتبه يجب عليك إجراء تحديث دوري علي جدول TMP_MONTHS نظراً لتغير القيمة المدخلة كل مرة .



الآن إليك إجابة سؤالك الخاص ، كيف يمكننا إيجاد عدد أيام بين تاريخين دون إحتساب يومي الجمعة أو السبت ... أنظر الكود :

CREATE OR REPLACE FUNCTION GET_COUNT_DAYS(IN_START DATE, IN_END DATE,) RETURN NUMBER
AS
 ID_DATE DATE;
 ID_RETURN NUMBER;
BEGIN
 --1: تحديث جدول الشهور أولاً.
 ID_DATE := ID_START_DATE;
 WHILE ID_DATE <= ID_END_DATE
 LOOP
ID_DATE := ID_DATE + 30.4375;
INSERT INTO TMP_MONTHS VALUES(TO_DATE(TO_CHAR(ID_DATE,'YYYY/MM') 
		 || '1' ,'YYYY/MM/DD'));
 END LOOP;

 --2: إيجاد عدد الأيام المناسبة دون يومي السبت والجمعة.
 SELECT COUNT(*)
 INTO ID_RETURN
 FROM LIST_ALL_DAYS
 WHERE LIST_ALL_DAYS.DAY BETWEEN IN_START AND IN_END AND TO_CHAR
		(LIST_ALL_DAYS.DAY,'D') IN NOT (1,7)

 REUTN ID_RETURN;
END;
/






بالتوفيق

بتاريخ:

ودي طريقه تانيه لعمل ما تريد

من هنا

بتاريخ:

الأخ الكريم ( أحمد يحيي ) أشكرك كل الشكر علي هذا الـ Function الأكثر من روعة ...

بس أسمح لي بأن أوضح بعض الأمور

قاعدة البيانات عاملة زي معالج الحاسب Processor ... وكما تعلم أن المعالج لا يفهم سوي الإشارات الرقمية الثنائية ( لغة آلة ) ... فكلما أقتربت من لغة الآلة كلما كانت العملية أسرع بكثير ... بس هيبقي فية صعوبة التصميم والبرمجة ... لكن لو أبتعدت عن لغة الآلة يعني مثلاً أستخدمت لغة برمجة مثل الفيجوال 6.0 أو الدوت نيت فهتكون العملية سهلة جداً بس هيكون أبطأ نسبياً .


تخيل حضرتك أنك ستصنع Function يعمل Loop علي أساس 25 سنة حضور وإنصارف لموظف محدد ... وكل سنة 365.25 يوم يعني ( 365.25 × 12 = 4383 ) ... في كل مرة سيقوم بإجراء الـ Loop ويؤدي الي توقف مؤقت فترة ( وذلك يرجع الي عدد العمليات المدرجة داخل جملة الـ Loop ) ... أنظر الي العملية البسيطة التالية :

Set ServerOutput On
Declare
 X  Number;
 Y  Number;
Begin
 DBMS_Output.Put_Line(To_Char(SysDate,'HH24:MI:SS'));
 For X In 1 .. 4383
 Loop
Select Count(*) Into Y From Tab;
 End Loop;
 DBMS_Output.Put_Line(To_Char(SysDate,'HH24:MI:SS'));
End;
/



رغم أنها عملية بسيطة ولكنها أخذت مني علي سرعة معالج 256 ورامات 512 بمقدار 12 ثواني ... ولكن ماذا لو كان العميل لدية حاسب أضعف ... عموماً الثانية لو كانت أقل من الملي ثانية بالطبع هيكون أفضل بكثير .

لكن لو صنعنا Loop بسيط وبعد ذلك إستخدمنا جمل الـ SQL هيكون أسرع


لذلك أقول أن كلما أقتربنا من الـ SQL هيكون العملية أسرع بكثير من الـ PL خصوصاً لو كانت العملية تتطلب الي عرض أكثر من سجل ... وكل سجل يحتوي علي 3 أو 4 أو 5 أو -------------- ؟ حقول ... وكل حقل يتضمن Function يأخز وقت ثقيل بسبب جملة Loop .

أنا لا أقول أن الـ PL/SQL ضعيف ... ولا أقل أن الـ Loop غير مطلوب ... ولكنني أقول بأن كل صح له الأصح منه

علي فكرة أخي أنا والله جربت هذه الفكرة من قبل ... بس عجبتني الفكرة التي أدرجتها لأنها فعلاً بسيطة وواضحة وفي نفس الوقت أسرع بكثير ... مجرد تنفذ مرة واحدة وبعد كدة تجلب الي أنت عايزة .






شكراً ، وبالتوفيق للجميع ،

بتاريخ:

كلامك صحيح يا أخ مصطفى وأنا معاك. عشان كده إحنا ممكن نعمل حاجه ظريفه زياده على الفانكشن دي:

نستخدم تقنية ال forall ونعمل temp table ثم نقوم بعملية إدخال للأيام غير الجمعه والسبت وبعد كده نعمل count للسجلات وتقريباًَ ده هايكون كويس جداً لعملية ال performance .

طبعاً لابد وأن نضع في الحسبان الآداء .

انضم إلى المناقشة

يمكنك المشاركة الآن والتسجيل لاحقاً. إذا كان لديك حساب, سجل دخولك الآن لتقوم بالمشاركة من خلال حسابك.

زائر
أضف رد على هذا الموضوع...

برجاء الإنتباه

بإستخدامك للموقع فأنت تتعهد بالموافقة على هذه البنود: سياسة الخصوصية

Account

Navigation

البحث

إعداد إشعارات المتصفح الفورية

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.