2012-07-24 18 views
5

मैं तालिका में होने वाले सभी परिवर्तनों का ट्रैक रखने के लिए एक ट्रिगर लिख रहा हूं। दुर्भाग्यवश तालिका में 150+ कॉलम हैं और मैं कोड में प्रत्येक कॉलम लिखने से बचाना चाहता था (उदा। New.col1, new.col2 ....) और इस प्रकार मैंने "ट्रिगर के बाद"mysql ट्रिगर, बदले गए कॉलम ढूंढें

INSERT INTO logs SELECT *, NOW() FROM abc WHERE abc.id = NEW.Id; 
में निम्न क्वेरी लिखी

यह विचार डेटा की नकल के कारण एकाधिक समस्या उत्पन्न कर रहा है जो अद्यतन क्वेरी में नहीं बदला गया है।

संक्षेप में मैं गतिशील रूप से यह जानना चाहता हूं कि कौन से कॉलम अपडेट क्वेरी का हिस्सा थे और यदि यह संभव नहीं है तो "नई" पंक्ति के सभी कॉलमों के माध्यम से पुनरावृत्ति करने का कोई तरीका है, इसलिए मैं गतिशील रूप से पुराने की तुलना कर सकता हूं। @ colName == नया। @ colName?

मैंने पहले ही Oracle PL/SQL: Loop Over Trigger Columns Dynamically, How to determine if anything changed in update trigger in t-sql और MySQL UPDATE trigger: INSERTing the values of the columns that actually changed देखा है।

अंतिम लिंक केवल एक अंतर के साथ मुझे जो चाहिए, उसे बंद कर देता है, मैं निम्नलिखित नियमों में कोड कोड नामों को कड़ी मेहनत नहीं करना चाहता क्योंकि मेरे पास सभी सारणी में 100 से अधिक कॉलम हैं जो मैं लिखने जा रहा हूं के लिए ट्रिगर !!

IF NEW.column1 <> OLD.column1 THEN INSERT INTO... END IF; IF NEW.column2 <> OLD.column2 THEN INSERT INTO... END IF 

उत्तर

2

मैं आज सुबह इस पर थोड़ा सा शोध कर रहा हूं और ऐसा लगता है कि मैं आपके जैसे ही खोज परिणामों में आया हूं। आखिरकार ऐसा लगता है कि सभी टेबल कॉलम पर लूप करने का कोई तरीका नहीं है और संबंधित पुराने/नए मानों का संदर्भ लें। मैं पर व्यवस्थित कर रहा हूँ स्पष्ट रूप से प्रत्येक स्तंभ की जाँच और फिर प्रवेश करने:

IF (NEW.fld1 <> OLD.fld1) OR (NEW.fld1 IS NOT NULL AND OLD.fld1 IS NULL) OR (NEW.fld1 IS NULL AND OLD.fld1 IS NOT NULL) THEN 
INSERT INTO `fld_audit` (`table`, `fldname`, `oldval`, `newval`) 
VALUES ("tblname", "fld1", OLD.fld1, NEW.fld1); 
END IF; 

IF (NEW.fld2 <> OLD.fld2) OR (NEW.fld2 IS NOT NULL AND OLD.fld2 IS NULL) OR (NEW.fld2 IS NULL AND OLD.fld2 IS NOT NULL) THEN 
INSERT INTO `fld_audit` (`table`, `fldname`, `oldval`, `newval`) 
VALUES ("tblname", "fld2", OLD.fld2, NEW.fld2); 
END IF; ... 

मैं एक और समाधान here के आभास मिल गया। सिद्धांत रूप में आपके पास 3 सीमांकित सूचियां हो सकती हैं, एक कॉलम नामों के लिए, एक पुराने vals के लिए और एक नए vals के लिए। आपको पुराने और नए vals को स्पष्ट रूप से संदर्भित करना होगा, लेकिन यह एक पंक्ति होगी (बनाए रखने में आसान या कॉपी/पेस्ट अन्य तालिकाओं पर लागू करने के लिए) और फिर आप पाश कर सकते हैं। तो छद्म कोड में यह कुछ ऐसा दिखाई देगा:

fields_array = concat_ws(",", "fld1", "fld2"); 
old_vals_array = concat_ws(",", OLD.fld1, OLD.fld2); 
new_vals_array = concat_ws(",", NEW.fld1, NEW.fld2); 

foreach fields_array as key => field_name 
    INSERT INTO `fld_audit` (`table`, `fldname`, `oldval`, `newval`) 
    VALUES ("tblname", field_name, old_vals_array[key], vew_vals_array[key]); 

मैंने इसे बहुत अधिक नहीं सोचा है। आपको चर सेट करने के बजाय संग्रहीत प्रक्रिया में कॉल करने की आवश्यकता हो सकती है। लेकिन यह देखने लायक हो सकता है। मैंने पहले से ही अपने ट्रिगर्स पर पर्याप्त समय बिताया है। यकीन नहीं है कि मैं एक और अधिक सुरुचिपूर्ण समाधान पर (मेरे बॉस) परीक्षण और त्रुटि समय को मान्य कर सकता हूं।

+0

मैं अब इस मुद्दे को एक नई तरह की सामना करना पड़ गया है ... यहां तक ​​कि अगर मैं अपने ट्रिगर्स में कठिन कोड करने के लिए तैयार सभी 150 कॉलम हूँ, मैं कर रहा हूँ "अपडेटेडबी" कॉलम का ट्रैक रखने में कठिन समय! मेरी मूल तालिका ऐप में लॉग इन लोगों के ट्रैक रखती है और जिन्होंने एप्लिकेशन के माध्यम से अंतिम परिवर्तन किया। दुर्भाग्यवश, हमारा समर्थन तकनीक "अपडेट किए गए" कॉलम को अपडेट किए बिना सीधे डाटाबेस से डेटा बदल सकता है और ऐसे मामले में मुझे यह जानने का कोई तरीका नहीं है कि "अपडेट किया गया" क्वेरी का हिस्सा था या नहीं और इस प्रकार मैं उस कॉलम को सेट नहीं कर सकता आवश्यकता होने पर शून्य करने के लिए! मुझे आशा है कि मैं यहां समझ रहा था :) – Sap

+0

समझ में आता है। हालांकि इसके बारे में कुछ भी नहीं कर सकता। यही एपीआई और "इंटरफेस" के लिए हैं। "समर्थन" लोगों/अन्य देवताओं को ऐसा करने के लिए मजबूर करने के लिए जो उन्हें करना है। – Jegsar

1

जैसे ही ingratiatednerd पहले से ही सुझाव दिया गया है, आप सभी आवश्यक मानों से तार बनाने और एक तुलनात्मक कथन बनाने के लिए CONCAT_WS का उपयोग कर सकते हैं।

शायद निम्नलिखित किसी के लिए उपयोगी है:

DECLARE old_concat, new_concat text; 
SET old_concat = CONCAT_WS(',', OLD.fld1, OLD.fld2, ...); 
SET new_concat = CONCAT_WS(',', NEW.fld1, NEW.fld2, ...); 

IF old_concat <> new_concat 
THEN 
    INSERT STATEMENT 
END IF; 
संबंधित मुद्दे