Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

Tự động xây dựng Mã MySQL để tạo trình kích hoạt

Không nhận được bất kỳ giải pháp xác định nào cho câu hỏi này, tôi đã tiến hành tạo ra một tùy chọn bằng chứng về khái niệm (vì MySQL nguyên bản sẽ không cho phép bạn chạy mã SQL tạo ra một trình kích hoạt, bằng cách sử dụng Câu lệnh chuẩn bị). Vui lòng đưa ra bất kỳ ý kiến ​​tích cực nào.

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 ;  

ĐỂ SỬ DỤNG, hãy gọi Thủ tục:

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

Một cơ sở dữ liệu mới được tạo bằng cách sử dụng tên của DB đang hoạt động hiện tại của bạn, với một hậu tố là "_history" được thêm vào nó. Bảng "name_of_table" được tạo trong DB mới này, giống với bảng gốc Trường "pri_key_fld" (phải là khóa chính / duy nhất của bảng "name_of_table") được chuyển đổi thành khóa "INDEX" thông thường. Mục đích của việc này là ngăn chặn các vi phạm duy nhất trong quá trình ghi nhật ký kiểm tra của nhiều hàng trong tương lai.

SAU ĐÓ Chạy tệp được tạo bởi thủ tục:SOURCE 'path/to/file.sql'; (hoặc bất kỳ cú pháp thay thế nào để chạy SQL từ tệp đó)

Một số lưu ý:Hiện tại, bạn chỉ có thể cung cấp một trường cho "pri_key_fld". Lý tưởng nhất là chúng ta muốn cung cấp một "mảng" chứa tất cả các trường duy nhất trong bảng đó. Hiện tại, nếu bạn có nhiều trường duy nhất, các vi phạm duy nhất sẽ ngăn bạn ghi nhật ký nhiều hơn một hàng. Và điều đó thật không hay!

Một lần nữa, rõ ràng là rất vụng về và không hiệu quả khi thực hiện quá trình tạo tệp trên đĩa, chỉ để đọc SQL từ cùng tệp trong lệnh tiếp theo. Một thay thế mà người ta có thể khám phá để cải thiện là:Chạy CALL createAuditTable từ dòng lệnh, bắt đầu ra dưới dạng văn bản, sau đó Chạy tương tự như SQL ngay tại đó trên dòng lệnh. Tôi đã thử điều đó trên Windows PowerShell; nhưng đầu ra có các chuỗi "\ r \ n" theo nghĩa đen (đại diện cho các ngắt dòng). Tôi không có thời gian ngay lập tức để làm sạch chuỗi này, vì vậy nó đang ở trong tủ lạnh!

Cuối cùng, hỡi các ninja trong MySQL, hãy tử tế. Tôi thực sự không chuyên nghiệp. Đây chỉ là một nỗ lực của riêng bạn để giải quyết một vấn đề thực tế.

Xin cảm ơ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. Có cách nào trong MySQL để tạo ngầm một khóa chính cho một bảng không?

  2. Các câu lệnh SELECT đã sử dụng có một số cột khác nhau

  3. Tính thứ hạng trong PHP / MySQL

  4. ĐƯỢC XÁC NHẬN BẰNG 'mật khẩu' trong MySQL

  5. Làm cách nào tôi có thể thực hiện truy vấn cột json trong laravel?