Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Ist es möglich zu sehen, welche Daten durch eine Abfrage geändert wurden?

OK. Meine Lösung ist eine Kombination aus PHP und MySQL, damit dies so "transparent" wie möglich funktioniert.

Diese Methoden existieren in einem Data Wrapper-Klasse, die PDO und vorbereitete Anweisungen verwendet.

Einige Erläuterungen zu anderen verwendeten Methoden:

  • Data::prepareAndExecute ($query, $tokens); ist eine Shortcut-Methode, die eine Abfrage vorbereitet, ausführt und, falls es Ergebnisse gibt, ein assoziatives Array dieser Ergebnisse zurückgibt.
  • Data::isSafeDatabaseEntity ($table) prüft einfach, ob der Tabellenname zu einem preg_match ("/^([a-zA-Z0-9_]+)$/", $check); passt Befehl, um SQL-Injection zu verhindern. Dies liegt daran, dass ich keine vorbereiteten Anweisungen für Feld- und Tabellennamen verwenden kann.
  • Data::tableInfo ($table); gibt ein assoziatives Array der Spalten in einer Tabelle basierend auf den von PDOStatement::getColumnMeta (); empfangenen Informationen zurück .
  • Data::getTablePrimaryKey ($table); verwendet die Ergebnisse eines SHOW INDEX FROM... Anfrage. Es sollte gesagt werden, dass dies nur für die Arbeit mit Einzelfeld-PKs ausgelegt ist.

Auszüge aus meinen Data Klasse:

public static function addTableLogging ($table, $ignorecolumns = array ())
{
    if (Data::isSafeDatabaseEntity ($table))
    {
        $update_trigger = "CREATE TRIGGER `{$table}_after_update` AFTER UPDATE ON `{$table}` FOR EACH ROW BEGIN\n";
        $insert_trigger = "CREATE TRIGGER `{$table}_after_insert` AFTER INSERT ON `{$table}` FOR EACH ROW BEGIN\n";
        $columns = Data::tableInfo ($table);
        $pk = Data::getTablePrimaryKey ($table);
        foreach ($columns as $column)
        {
            if (!in_array ($column ['name'], $ignorecolumns))
            {
                $update_trigger .= "   IF (NEW.{$column ['name']} != OLD.{$column ['name']}) THEN
     CALL changelog_store ('{$table}', OLD.{$pk}, '{$column ['name']}', OLD.{$column ['name']}, NEW.{$column ['name']});
  END IF;\n";
                $insert_trigger .= "   CALL changelog_store ('{$table}', NEW.{$pk}, '{$column ['name']}', '', NEW.{$column ['name']});\n";
            }
        }
        $update_trigger .= "END";
        $insert_trigger .= "END";

        self::removeTableLogging ($table);
        self::prepareAndExecute ($update_trigger);
        self::prepareAndExecute ($insert_trigger);
    }
}

public static function removeTableLogging ($table)
{
    if (self::isSafeDatabaseEntity ($table))
    {
        Data::prepareAndExecute ("DROP TRIGGER IF EXISTS `{$table}_after_update`;");
        Data::prepareAndExecute ("DROP TRIGGER IF EXISTS `{$table}_after_insert`;");
    }
}

public static function refreshLoggingProcedure ()
{
    /* -- for logging into MySQL Table:
      CREATE TABLE `changelog` (
        `change_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        `change_table` VARCHAR(50) NULL DEFAULT NULL,
        `change_table_id` VARCHAR(25) NULL DEFAULT NULL,
        `change_field` VARCHAR(50) NULL DEFAULT NULL,
        `change_old` VARCHAR(255) NULL DEFAULT NULL,
        `change_new` VARCHAR(255) NULL DEFAULT NULL,
        `change_user` INT(10) UNSIGNED NOT NULL DEFAULT '0',
        `change_date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
        PRIMARY KEY (`change_id`),
        INDEX `change_table_id` (`change_table_id`),
        INDEX `change_table` (`change_table`, `change_field`)
      );
    */
    $logquery = "CREATE PROCEDURE `changelog_store`(IN `tab` VARCHAR(50), IN `pkval` INT, IN `fieldn` VARCHAR(50), IN `oldv` TEXT, IN `newv` TEXT)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
    IF ISNULL(@STAFFID) THEN
        SET @STAFFID = 0;
    END IF;
    INSERT INTO `changelog` (change_table, change_table_id, change_field, change_old, change_new, change_date, change_user)
        VALUES (tab, pkval, fieldn, oldv, newv, NOW(), @STAFFID);
END";
    Data::prepareAndExecute ("DROP PROCEDURE IF EXISTS `changelog_store`;");
    Data::prepareAndExecute ($logquery);
}