Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Dynamiczne konstruowanie kodu MySQL do tworzenia wyzwalacza

Nie otrzymawszy żadnego konkretnego rozwiązania tego pytania, przystąpiłem do tworzenia opcji weryfikacji koncepcji (ponieważ MySQL natywnie nie pozwalał na uruchamianie kodu SQL, który tworzy wyzwalacz, za pomocą przygotowanych instrukcji). Prosimy o wszelkie pozytywne opinie.

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 ;  

W CELU UŻYCIA, wywołaj Procedurę:

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

Nowa baza danych jest tworzona przy użyciu nazwy bieżącej działającej bazy danych, z dołączonym do niej przyrostkiem „_history”. W nowej bazie danych tworzona jest tabela "nazwa_tabeli", identyczna z oryginalną tabelą.Pole "pri_key_fld" (które powinno być podstawowym/unikalnym kluczem tabeli "nazwa_tabeli") jest konwertowane na zwykły klucz "INDEX". Ma to na celu uniknięcie unikalnych naruszeń podczas rejestrowania kontrolnego wielu wierszy w przyszłości.

WTEDY uruchom plik utworzony przez procedurę:SOURCE 'path/to/file.sql'; (lub dowolna alternatywna składnia do uruchamiania SQL z tego pliku)

Kilka ostrzeżeń:W tej chwili możesz podać tylko jedno pole dla „pri_key_fld”. W idealnym przypadku chcielibyśmy dostarczyć „tablicę” zawierającą wszystkie unikatowe pola w tej tabeli. Obecnie, jeśli masz więcej niż jedno unikalne pole, unikatowe naruszenia uniemożliwiają rejestrowanie więcej niż jednego wiersza. A to nie jest miłe!

Ponownie, jest to oczywiście bardzo niezdarne i niewykonalne, aby przejść przez proces tworzenia pliku na dysku, tylko po to, aby odczytać SQL z tego samego pliku w następnym poleceniu. Jedną z alternatyw, które można zbadać w celu złagodzenia, jest to:Uruchom CALL createAuditTable fragment z wiersza poleceń, przechwyć dane wyjściowe jako tekst, a następnie uruchom to samo, co SQL w wierszu poleceń. Próbowałem tego w Windows PowerShell; ale dane wyjściowe były usiane dosłownymi ciągami "\r\n" (reprezentującymi podziały wierszy). Nie miałem czasu od razu zająć się czyszczeniem tego sznurka, więc jest teraz w lodówce!

Na koniec, o wy, ninja MySQL, proszę bądźcie mili. Naprawdę nie jestem zawodowcem. To tylko próba rozwiązania praktycznego problemu we własnym zakresie.

Dziękuję.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak sformatować czas na „2:34”, „0:34” itp. w MySQL

  2. kodowanie Pythona mysql :(

  3. Wstawianie elementów do bootstrap-dropdown z SQL Table

  4. MySQL od dziesiętnych (13.6) do waluty

  5. BLOB w widoku MySQL zamiast właściwych danych