سؤال

دعونا نقول لدي استدعاء دالة على حدد أو حيث شرط في أوراكل مثل هذا:

select a, b, c, dbms_crypto.hash(utl_raw.cast_to_raw('HELLO'),3)
  from my_table

مثال مشابه يمكن بناؤها MS SQLServer.

ما هو السلوك المتوقع في كل حالة ؟

هو تجزئة الوظيفة ستكون دعا مرة واحدة لكل صف في الجدول ، أو DBMS سوف تكون ذكية بما فيه الكفاية إلى استدعاء الدالة مرة واحدة فقط, منذ انها وظيفة ثابتة مع المعلمات و لا الآثار الجانبية?

شكرا جزيلا.

هل كانت مفيدة؟

المحلول

الجواب Oracle هو ذلك يعتمد.وظيفة سيتم استدعاء كل صف المحدد إلا وظيفة يتم وضع علامة 'الحتمية' في هذه الحالة سيكون فقط اتصل مرة واحدة.

CREATE OR REPLACE PACKAGE TestCallCount AS
    FUNCTION StringLen(SrcStr VARCHAR) RETURN INTEGER;
    FUNCTION StringLen2(SrcStr VARCHAR) RETURN INTEGER DETERMINISTIC;
    FUNCTION GetCallCount RETURN INTEGER;
    FUNCTION GetCallCount2 RETURN INTEGER;
END TestCallCount;

CREATE OR REPLACE PACKAGE BODY TestCallCount AS
    TotalFunctionCalls INTEGER := 0;
    TotalFunctionCalls2 INTEGER := 0;

    FUNCTION StringLen(SrcStr VARCHAR) RETURN INTEGER AS
    BEGIN
        TotalFunctionCalls := TotalFunctionCalls + 1;
        RETURN Length(SrcStr);
    END;
    FUNCTION GetCallCount RETURN INTEGER AS
    BEGIN
        RETURN TotalFunctionCalls;
    END;

    FUNCTION StringLen2(SrcStr VARCHAR) RETURN INTEGER DETERMINISTIC AS
    BEGIN
        TotalFunctionCalls2 := TotalFunctionCalls2 + 1;
        RETURN Length(SrcStr);
    END;
    FUNCTION GetCallCount2 RETURN INTEGER AS
    BEGIN
        RETURN TotalFunctionCalls2;
    END;

END TestCallCount;




SELECT a,TestCallCount.StringLen('foo') FROM(
    SELECT 0 as a FROM dual
    UNION
    SELECT 1 as a FROM dual
    UNION
    SELECT 2 as a FROM dual
);

SELECT TestCallCount.GetCallCount() AS TotalFunctionCalls FROM dual;

الإخراج:

A                      TESTCALLCOUNT.STRINGLEN('FOO') 
---------------------- ------------------------------ 
0                      3                              
1                      3                              
2                      3                              

3 rows selected


TOTALFUNCTIONCALLS     
---------------------- 
3                      

1 rows selected

حتى StringLen() وظيفة كانت تسمى ثلاث مرات في الحالة الأولى.الآن عند تنفيذ مع StringLen2() التي تدل القطعية:

SELECT a,TestCallCount.StringLen2('foo') from(
    select 0 as a from dual
    union
    select 1 as a from dual
    union
    select 2 as a from dual
);

SELECT TestCallCount.GetCallCount2() AS TotalFunctionCalls FROM dual;

النتائج:

A                      TESTCALLCOUNT.STRINGLEN2('FOO') 
---------------------- ------------------------------- 
0                      3                               
1                      3                               
2                      3                               

3 rows selected

TOTALFUNCTIONCALLS     
---------------------- 
1                      

1 rows selected

حتى StringLen2() وظيفة إلا مرة واحدة منذ أن تم وضع علامة القطعية.

على وظيفة لم يتم وضع علامة القطعية ، يمكنك الحصول على حول هذا عن طريق تعديل الاستعلام الخاص بك على هذا النحو:

select a, b, c, hashed
  from my_table
cross join (
  select dbms_crypto.hash(utl_raw.cast_to_raw('HELLO'),3) as hashed from dual
);

نصائح أخرى

ل SQL server ، سيتم تقييم كل صف واحد.

سوف تكون أفضل حالا بكثير من تشغيل الدالة مرة واحدة و تعيين إلى متغير باستخدام متغير في الاستعلام.

الجواب القصير....ذلك يعتمد.

إذا كانت وظيفة هو الوصول إلى البيانات "أوراكل" لا أعرف ما إذا كان سيكون نفس لكل صف ، وبالتالي ، فإنه يحتاج إلى الاستعلام عن بعضها.مثلا: إذا كانت وظيفة الخاص بك هو مجرد المنسق أن يعود دائما نفس القيمة ثم يمكنك تشغيل التخزين المؤقت (وسم على أنها حتمية) والتي قد تسمح لك أن تفعل سوى استدعاء الدالة مرة واحدة.

شيء قد ترغب في النظر في أوراكل مع استعلام فرعي:

مع query_name بند يتيح لك تعيين اسم فرعي كتلة.لك ثم يمكن الإشارة الاستعلام الفرعي كتلة أماكن متعددة في الاستعلام من قبل تحديد اسم الاستعلام.أوراكل يحسن الاستعلام عن طريق علاج اسم الاستعلام إما مضمن أو كما جدول مؤقت

لدي النص المقتبس من هنا, والذي يحتوي على العديد من الأمثلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top