2013-10-03 14 views
10

मुझे पंक्ति में बदलकर सभी मूल्यों को प्राप्त करने और अन्य 'ऑडिट' तालिका में संशोधन पोस्ट करने की आवश्यकता है। क्या मैं इसे पंक्ति से प्रत्येक तत्व के लिए शर्तों को लिखने के बिना पूरा कर सकता हूं? मैं http://www.firebirdfaq.org/faq133/ से एसक्यूएल जो आप सत्यापन के लिए सभी शर्तों देता है पता है:फायरबर्ड - एक ट्रिगर के अंदर सभी संशोधित फ़ील्ड प्राप्त करें

select 'if (new.' || rdb$field_name || ' is null and old.' || 
rdb$field_name || ' is not null or new.' || rdb$field_name || 
'is not null and old.' || rdb$field_name || ' is null or new.' || 
rdb$field_name || ' <> old.' || rdb$field_name || ') then' 
from rdb$relation_fields 
where rdb$relation_name = 'EMPLOYEE'; 

लेकिन यह ट्रिगर में लिखा जाना चाहिए। इसलिए, यदि मैं एक टेबल बदलता हूं तो मुझे ट्रिगर को संशोधित करने की आवश्यकता है।

इस तथ्य के कारण कि फायरबर्ड एक वर्चुअल वैरिएबल के आकार को गतिशील रूप से बढ़ाने की अनुमति नहीं देता है, मैं एक टेक्स्ट वर्ब में इसे डालने से पहले, सभी मूल्यों को एक बड़े वर्चर वेरिएबल को कास्टिंग और संयोजित करने की सोच रहा था।

क्या GTTs का उपयोग किए बिना इसे पूरा करने की कोई संभावना है?

http://www.upscene.com/products.audit.iblm_main.php

अन्यथा आप new./old उपयोग नहीं कर सकते:

उत्तर

4

आपको कुछ मेटा प्रोग्रामिंग की आवश्यकता है, लेकिन सिस्टम टेबल पर ट्रिगर्स के साथ कोई समस्या नहीं है।

यह समाधान काम करता है, भले ही आपके पास बहुत सारे कॉलम हों।

set term^; 

create or alter procedure create_audit_update_trigger (tablename char(31)) as 
    declare sql blob sub_type 1; 
    declare fn char(31); 
    declare skip decimal(1); 
begin 
    -- TODO add/remove fields to/from audit table 

    sql = 'create or alter trigger ' || trim(tablename) || '_audit_upd for ' || trim(tablename) || ' after update as begin if ('; 

    skip = 1; 
    for select rdb$field_name from rdb$relation_fields where rdb$relation_name = :tablename into :fn do 
    begin 
     if (skip = 0) then sql = sql || ' or '; 
     sql = sql || '(old.' || trim(:fn) || ' is distinct from new.' || trim(:fn) || ')'; 
     skip = 0; 
    end 
    sql = sql || ') then insert into ' || trim(tablename) || '_audit ('; 

    skip = 1; 
    for select rdb$field_name from rdb$relation_fields where rdb$relation_name = :tablename into :fn do 
    begin 
     if (skip = 0) then sql = sql || ','; 
     sql = sql || trim(:fn); 
     skip = 0; 
    end 
    sql = sql || ') values ('; 

    skip = 1; 
    for select rdb$field_name from rdb$relation_fields where rdb$relation_name = :tablename into :fn do 
    begin 
     if (skip = 0) then sql = sql || ','; 
     sql = sql || 'new.' || trim(:fn); 
     skip = 0; 
    end 
    sql = sql || '); end'; 

    execute statement :sql; 
end^

create or alter trigger field_audit for rdb$relation_fields after insert or update or delete as 
begin 
    -- TODO filter table name, don't include system or audit tables 
    -- TODO add insert trigger 
    execute procedure create_audit_update_trigger(new.rdb$relation_name); 
end^

set term ;^
+4

+1 ... लेकिन क्या यह काम करता है? [यह मेलिंग सूची थ्रेड] (http://groups.yahoo.com/neo/groups/firebird-support/conversations/topics/100294) सुझाव देता है कि table सिस्टम तालिका ट्रिगर्स गायब हो जाती है जब कुछ तालिका ड्रॉप होती है, और ② यह दृष्टिकोण कम से कम दुर्घटनाग्रस्त होने के लिए प्रयोग किया जाता है। – pilcrow

4

यह उपकरण आपकी समस्या के लिए फायरबर्ड्स समाधान है। गतिशील रूप से चर।

मैंने निष्पादित कथन आधारित समाधान की जांच की, लेकिन यह भी एक मृत अंत है।

, एक संदर्भ चर (नई या पुरानी) होगा कभी काम नहीं के साथ बयान निष्पादित कि (निष्पादित वक्तव्य) ट्रिगर के अंदर निष्पादित नहीं कर रहा है एक ट्रिगर के अंदर ही उपलब्ध है, एक नया बयान में नहीं पैदा कर का उपयोग करना, हालांकि यह एक ही कनेक्शन और लेनदेन का उपयोग करता है।

+0

मैं किसी अन्य उपकरण का उपयोग नहीं कर सकता। इसे 'इन-हाउस' बनाने की जरूरत है। धन्यवाद। – RBA

+1

इस मामले में, मुझे लगता है कि ट्रिगर्स को पुन: उत्पन्न करने के लिए कुछ संग्रहीत प्रक्रियाओं को बनाने का सबसे अच्छा तरीका है, और उन्हें दैनिक आधार पर चलाने के लिए शेड्यूल करें (या जब आप अपने डेटाबेस पर डीडीएल-एस चलाते हैं)। आविष्कार के लिए –

संबंधित मुद्दे