Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

ट्रिगर बनाने के लिए गतिशील रूप से MySQL कोड का निर्माण

इस प्रश्न के लिए कोई निश्चित समाधान प्राप्त नहीं होने के कारण, मैंने अवधारणा विकल्प का प्रमाण तैयार करना शुरू कर दिया है (चूंकि MySQL मूल रूप से आपको SQL कोड चलाने नहीं देगा जो एक ट्रिगर बनाता है, तैयार विवरण का उपयोग करके)। कृपया कोई भी सकारात्मक इनपुट देने के लिए स्वतंत्र महसूस करें।

DELIMITER //
DROP PROCEDURE IF EXISTS createAuditTable//
CREATE PROCEDURE createAuditTable(tblname CHAR(30), sufftxt CHAR(10), pri CHAR(20), filename CHAR(255) )
BEGIN
    SELECT DATABASE() INTO @dbname;
    SET @srctbl = CONCAT(@dbname, ".", tblname);
    SET @destdb = CONCAT(@dbname, "_", sufftxt);
    SET @desttbl = CONCAT(@destdb, ".", tblname);

    SET @str1 = CONCAT( "CREATE DATABASE IF NOT EXISTS ", @destdb);
    PREPARE stmt1 FROM @str1;
    EXECUTE stmt1;
    DEALLOCATE PREPARE stmt1;

    SET @str2 = "SET FOREIGN_KEY_CHECKS=0";
    PREPARE stmt2 FROM @str2;
    EXECUTE stmt2;
    DEALLOCATE PREPARE stmt2;

    SELECT COUNT(*) FROM information_schema.tables WHERE table_name = tblname AND table_schema = @destdb INTO @tblcount;
    IF (@tblcount = 0) THEN 
        SET @str3 = CONCAT("CREATE TABLE ", @desttbl, " LIKE ", @srctbl);
        PREPARE stmt3 FROM @str3;
        EXECUTE stmt3;
        DEALLOCATE PREPARE stmt3;
    END IF;

    SELECT COUNT(*) FROM information_schema.columns WHERE table_name = tblname AND table_schema = @destdb AND column_key = 'PRI' INTO @keycount;

    IF (@keycount <> 0) THEN 
        SET @str4 = CONCAT("ALTER TABLE ", @desttbl, " DROP PRIMARY KEY, ADD INDEX ", pri, " (", pri, ")" );
        PREPARE stmt4 FROM @str4;
        EXECUTE stmt4;
        DEALLOCATE PREPARE stmt4;
    END IF;

SELECT CONCAT( "DELIMITER $$
DROP TRIGGER IF EXISTS ", tblname, "_history_BU$$
CREATE TRIGGER ", tblname, "_history_BU
BEFORE UPDATE ON ", tblname, "
FOR EACH ROW
BEGIN
    INSERT INTO ", @desttbl, " (",
(SELECT GROUP_CONCAT(column_name) FROM information_schema.columns WHERE table_schema = @dbname AND table_name = tblname), ") ",
    "
    VALUES(", 
(SELECT GROUP_CONCAT('OLD.', column_name) FROM information_schema.columns WHERE table_schema = @dbname AND table_name = tblname),
 ");
END$$
DELIMITER ;"
 ) AS qstr FROM DUAL INTO @triggertxt;

SET @savestr = CONCAT('SELECT ', '"', @triggertxt, '"', " INTO DUMPFILE ", '"', filename, '"');
PREPARE stmt5 FROM @savestr;
EXECUTE stmt5;
DEALLOCATE PREPARE stmt5;


END//
DELIMITER ;  

उपयोग करने के लिए, प्रक्रिया को कॉल करें:

CALL createAuditTable('name_of_table', 'history', 'pri_key_fld', 'path/to/file.sql');

आपके वर्तमान कार्यशील DB के नाम का उपयोग करके एक नया डेटाबेस बनाया गया है, जिसमें "_history" का प्रत्यय जोड़ा गया है। तालिका "name_of_table" इस नए डीबी में बनाई गई है, मूल तालिका के समान फ़ील्ड "pri_key_fld" (जो तालिका "name_of_table" की प्राथमिक/अद्वितीय कुंजी होनी चाहिए) को सामान्य "INDEX" कुंजी में परिवर्तित कर दिया गया है। इसका उद्देश्य भविष्य में कई पंक्तियों के ऑडिट लॉगिंग के दौरान अद्वितीय उल्लंघनों को रोकना है।

फिर प्रक्रिया द्वारा बनाई गई फ़ाइल चलाएँ:SOURCE 'path/to/file.sql'; (या उस फ़ाइल से SQL चलाने के लिए कोई वैकल्पिक सिंटैक्स)

कुछ चेतावनी:अभी, आप "pri_key_fld" के लिए केवल एक फ़ील्ड प्रदान कर सकते हैं। आदर्श रूप से, हम उस तालिका में सभी अद्वितीय फ़ील्ड वाले "सरणी" की आपूर्ति करना चाहते हैं। वर्तमान में, यदि आपके पास एक से अधिक अद्वितीय फ़ील्ड हैं, तो अद्वितीय उल्लंघन आपको एक से अधिक पंक्तियों में प्रवेश करने से रोकेंगे। और यह अच्छा नहीं है!

फिर, डिस्क पर फ़ाइल बनाने की प्रक्रिया के माध्यम से जाने के लिए यह स्पष्ट रूप से बहुत ही बेकार और गैर-निष्पादक है, केवल अगले आदेश में उसी फ़ाइल से SQL को पढ़ने के लिए। इसे बेहतर बनाने के लिए एक विकल्प तलाशा जा सकता है:CALL createAuditTable चलाएँ कमांड लाइन से भाग, आउटपुट को टेक्स्ट के रूप में पकड़ें, फिर कमांड लाइन पर वहीं SQL के समान चलाएँ। मैंने कोशिश की कि विंडोज पावरशेल पर; लेकिन आउटपुट शाब्दिक "\r\n" स्ट्रिंग्स (लाइन ब्रेक का प्रतिनिधित्व) के साथ भरा हुआ था। मेरे पास इस तार को साफ करने के लिए तुरंत काम करने का समय नहीं था, इसलिए यह अब फ्रिज में है!

अंत में, हे मायएसक्यूएल निन्जा, कृपया अच्छा बनें। मैं कोई समर्थक नहीं हूँ, वास्तव में। यह एक व्यावहारिक समस्या को हल करने के लिए केवल एक ग्रो-योर-खुद-किराने का प्रयास है।

धन्यवाद।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. उबंटू पर luaSQL स्थापित करें

  2. Laravel 5 PDOException ड्राइवर नहीं ढूँढ सका

  3. MySQL के पुराने संस्करणों में TO_SECONDS() का अनुकरण करना (<5.5.0)

  4. mySQL डेटाबेस:AutoIncrement फ़ील्ड रीसेट करें

  5. तारीखों को खोए बिना एक varchar कॉलम प्रकार को दिनांक प्रकार में कैसे बदलें