【问题标题】:Use of table name variable in Mysql triggerMysql触发器中表名变量的使用
【发布时间】:2022-06-11 02:23:57
【问题描述】:

当我有一个名为 buffer 的主表和 > 100 个具有相似名称的表时,我被这个可怕的解决方案所困扰 'ftm'、'ada'、... 等等,我需要在主表上设置一个触发器根据destination_table字段中的表名将数据插入这些辅助表中:

CREATE TRIGGER distribute AFTER INSERT ON buffer
  FOR EACH ROW BEGIN
    CASE 
      WHEN NEW.destination_table = 'ftm' THEN INSERT INTO ftm (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed);
      WHEN NEW.destination_table = 'sol' THEN INSERT INTO sol (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed);
      WHEN NEW.destination_table = 'ada' THEN INSERT INTO ada (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed);
      WHEN NEW.destination_table = 'ltc' THEN INSERT INTO ltc (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed);
      WHEN NEW.destination_table = 'mkr' THEN INSERT INTO mkr (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed);
      WHEN ... > 100 similar conditions ...
    END CASE;
  END;

我尝试了几种方法来克服这个问题:

DECLARE x VARCHAR(255);
SET x = NEW.destination_table;
INSERT INTO x (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed);

DECLARE x VARCHAR(255);
SET x = (SELECT destination_table FROM collection_1m LIMIT 1);
INSERT INTO x (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed);

但它所做的只是抛出一个错误,例如 THE TABLE 'schema.x' does not exist... 也就是说,它不想读取存储在那个 'x' 变量中的值(如果有任何东西存储在那里)。

有什么建议可以让这段代码更智能吗?感谢任何帮助!

--------更新--------- 我试过这样做:

DELIMITER //
            
CREATE TABLE dist ( id SMALLINT NOT NULL AUTO_INCREMENT,
  dest_table varchar(32) NOT NULL,
  param1 BIGINT NOT NULL,
  param2 FLOAT NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;
            
CREATE TABLE aaa ( id SMALLINT NOT NULL AUTO_INCREMENT,
  param1 BIGINT NOT NULL,
  param2 FLOAT NOT NULL,
  PRIMARY KEY(`id`)
) ENGINE=InnoDB;
            
CREATE PROCEDURE dispatch (IN dest_table CHAR(32), IN val_a BIGINT, IN val_b FLOAT)
  BEGIN
    SET @table = dest_table;
    SET @param1 = val_a;
    SET @param2 = val_b;
    SET @s = CONCAT('INSERT INTO ', @table, '( param1, param2) VALUES (',@param1,',',@param2,')');
                
    PREPARE stmt3 FROM @s;
    EXECUTE stmt3;
                        
  END;

CREATE TRIGGER distr AFTER INSERT ON dist 
  FOR EACH ROW
    BEGIN                
      CALL dispatch( NEW.dest_table, NEW.param1, NEW.param2 );
    END;            
  END; //
  DELIMITER ;

但现在是 ERROR 1336 (0A000): Dynamic SQL is not allowed in stored function or trigger

【问题讨论】:

    标签: mysql sql triggers case plpgsql


    【解决方案1】:

    CREATE TRIGGER 在 INSERT ON 缓冲区后分发 每一行开始

      IF NEW.destination_table = 'ftm' THEN INSERT INTO ftm (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed); END IF;
    
      IF NEW.destination_table = 'sol' THEN INSERT INTO sol (opened, open, high, low, close, volume, closed) VALUES (NEW.opened, NEW.open, NEW.high, NEW.low, NEW.close, NEW.volume, NEW.closed); END IF;
    

    100 条类似的 IF 语句

    结束;

    【讨论】:

    • 感谢 Moshe 的建议,但这基本上是具有 100 多行代码的相同解决方案。我只是想知道是否有一个简单而优雅的解决方案......
    • 对不起,我认为您的问题是您的代码无法正常工作。如果您想要更优雅的解决方案,请使用准备好的语句。创建一个存储过程,它采用所需的参数,包括表名。从触发器调用存储过程。在存储过程中使用准备好的语句来动态创建您的插入子句。 dev.mysql.com/doc/refman/5.7/en/sql-prepared-statements.html。见示例 3
    猜你喜欢
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-29
    • 2021-03-13
    相关资源
    最近更新 更多