2012-03-29 16 views
13

के कारण म्यूटेटिंग टेबल हमने हाल ही में ओरेकल 10 से ओरेकल 11.2 तक अपग्रेड किया है। अपग्रेड करने के बाद, मैंने एक ट्रिगर की बजाय फ़ंक्शन के कारण एक उत्परिवर्तनीय तालिका त्रुटि को देखना शुरू कर दिया (जिसे मैंने पहले कभी नहीं देखा है)। यह पुराना कोड है जो ओरेकल के पूर्व संस्करणों में काम करता था।ओरेकल 11 में एक फ़ंक्शन

create table mutate (
    x NUMBER, 
    y NUMBER 
); 

insert into mutate (x, y) 
values (1,2); 

insert into mutate (x, y) 
values (3,4); 

मैं दो पंक्तियों बना लिया है:

यहाँ एक परिदृश्य है कि त्रुटि का कारण होगा। अब, मैं इस बयान को फोन करके मेरी पंक्तियों दोगुना कर देंगे:

insert into mutate (x, y) 
select x + 1, y + 1 
from mutate; 

यह नहीं सख्ती से त्रुटि डुप्लिकेट करने के लिए आवश्यक है, लेकिन बाद में मेरी प्रदर्शन के साथ मदद करता है। तो तालिका की सामग्री अब इस तरह दिखती है:

X,Y 
1,2 
3,4 
2,3 
4,5 

सब ठीक है। अब मजेदार भाग के लिए:

create or replace function mutate_count 
return PLS_INTEGER 
is 
    v_dummy PLS_INTEGER; 
begin 
    select count(*) 
    into v_dummy 
    from mutate; 

    return v_dummy; 
end mutate_count; 
/

मैंने अपनी तालिका पूछने और गिनती वापस करने के लिए एक फ़ंक्शन बनाया है। अब, मैं इसे एक INSERT कथन के साथ जोड़ दूंगा:

insert into mutate (x, y) 
select x + 2, y + 2 
from mutate 
where mutate_count() = 4; 

परिणाम? यह त्रुटि:

ORA-04091: table MUTATE is mutating, trigger/function may not see it 
ORA-06512: at "MUTATE_COUNT", line 6 

तो मैं क्या त्रुटि होती है पता है, लेकिन मैं क्यों जानने के लिए उत्सुक हूँ। ओरेकल चयन का प्रदर्शन नहीं कर रहा है, परिणाम सेट को पुनर्प्राप्त कर रहा है, और फिर उन परिणामों का एक बड़ा सम्मिलन कर रहा है? अगर क्वेरी समाप्त होने से पहले रिकॉर्ड पहले ही डाले जा रहे थे तो मैं केवल एक उत्परिवर्तनीय तालिका त्रुटि की अपेक्षा करता हूं। लेकिन अगर ओरेकल किया था, पहले बयान नहीं होगा कि:

insert into mutate (x, y) 
select x + 1, y + 1 
from mutate; 

अनंत लूप शुरू?

अद्यतन:

जेफरी का लिंक मैं the Oracle docs में यह पाया के माध्यम से:

By default, Oracle guarantees statement-level read consistency. The set of data returned by a single query is consistent with respect to a single point in time.

वहाँ भी his post में लेखक की ओर से एक टिप्पणी है:

One could argue why Oracle doesn't ensure this 'statement-level read consistency' for repeated function calls that appear inside a SQL statement. It could be considered a bug as far as I'm concerned. But this is the way it currently works.

हूँ मैं यह सोचते हैं कि इस में सही कर ओरेकल संस्करण 10 और 11 के बीच व्यवहार बदल गया है?

उत्तर

9

सबसे पहले,

insert into mutate (x, y) 
select x + 1, y + 1 
from mutate; 

अनंत लूप शुरू नहीं होता, क्योंकि क्वेरी डेटा कि डाला गया था नहीं देखेंगे - केवल डेटा है कि बयान की शुरुआत के रूप में मौजूद थे। नई पंक्तियां केवल बाद के बयान के लिए दिखाई देगी।

This काफी अच्छी तरह से यह बताते हैं:

When Oracle steps out of the SQL-engine that's currently executing the update statement, and invokes the function, then this function -- just like an after row update trigger would -- sees the intermediate states of EMP as they exist during execution of the update statement. This implies that the return value of our function invocations heavily depend on the order in which the rows happen to be updated.

+0

अच्छा लिंक, धन्यवाद! मैं अपने प्रश्न को अपडेट करने जा रहा हूं और यह देखने के लिए थोड़ा सा खुला हूं कि यह कोई अतिरिक्त चर्चा उत्पन्न करता है या नहीं। –

+0

+1 आपको यह पता चला कि यह क्यों होता है – zep

+0

इससे मदद मिली, लेकिन स्पष्टीकरण प्रश्न है ... क्या फ़ंक्शन एक पैकेज में मौजूद हो सकता है जिसे पहले अपडेट ट्रिगर से कहा जाता है? ओरेकल क्रैपी ट्रिगर्स के कारण मुझे कई अन्य लोगों की तरह दुःस्वप्न हो रहा है। –

8

वक्तव्य स्तरीय पढ़ें संगति और लेन-देन स्तरीय पढ़ें संगति "।

मैनुअल से:

"If a SELECT list contains a function, then the database applies statement-level read consistency at the statement level for SQL run within the PL/SQL function code, rather than at the parent SQL level. For example, a function could access a table whose data is changed and committed by another user. For each execution of the SELECT in the function, a new read consistent snapshot is established".

दोनों अवधारणाओं "Oracle® डाटाबेस अवधारणाओं" से वर्णन किया गया:

http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/consist.htm#sthref1955


- >>>अद्यतन

- >>> * धारा के बादओपी

नियम

तकनीकी नियम है, अच्छी तरह से श्री केम्प (@ जेफरी-केम्प) से जुड़े हुए बंद हो गया जोड़ा गया है और अच्छी तरह से तून Koppelaars द्वारा समझाया

When invoked from an INSERT, UPDATE, or DELETE statement, the function cannot query or modify any database tables modified by that statement.

If a function either queries or modifies a table, and a DML statement on that table invokes the function, then ORA-04091 (mutating-table error) occurs.

012: - here, में रिपोर्ट किया गया है "PL/SQL भाषा संदर्भ नियंत्रण साइड PL/SQL subprograms का प्रभाव" (अपने कार्य RNDS पढ़ता कोई डेटाबेस राज्य का उल्लंघन करती है)

PL/SQL Functions that SQL Statements Can Invoke

+0

जानना अच्छा है! यह निष्पादन विचार से परे जितना संभव हो सके SQL कथन के भीतर फ़ंक्शन कॉल से बचने के लिए एक और अच्छा कारण प्रतीत होता है - वे मूल एसक्यूएल स्तर स्नैपशॉट नियम का उल्लंघन करते हैं। –

+0

@ दान-ए। मैं उन्हें निर्धारक कार्यों में पंक्ति मानों पर जटिल गणना को सरल बनाने के लिए उपयोग करता हूं जहां वे WNDS और RNDS का उल्लंघन नहीं करते हैं (कोई डेटा स्थिति नहीं लिखते हैं और कोई डेटा स्थिति नहीं पढ़ते हैं)। – zep