插入触发器之前将重复行插入另一个表

时间:2013-09-04 17:38:15

标签: mysql triggers

我有一个名为tblspmaster的表,其中sp列i具有唯一索引,因此不会插入重复项,但我想将重复的行插入tblspduplicate。所以我决定为此写出触发器。将使用tblspmaster

的加载文件插入IN主表,即mysql条记录
create trigger tblspmaster_noduplicate
before insert on tblspmaster
for each row
begin
  if ( select count(sp) from tblspmaster where sp=new.sp > 0 )then
    insert into tblspduplicate (sp,FileImported,AMZFileName)   values (NEW.sp,NEW.FileImported,NEW.AMZFileName)
  END
END

我有问题列表

  1. 这种方法是否可以阻止重复并插入另一个副本 表?

  2. 我的触发器没有执行,因为它显示了一些语法错误

  3. 错误回复是Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END END' at line 7

    ** * ** * ** * 的** * **** EDITED * ** * ** < em> * ** * ****

    这里是主表和重复表以及触发器和加载数据文件MySQL语句的表定义

    CREATE TABLE IF NOT EXISTS `tblspmaster` (
      `CSN` bigint(20) NOT NULL AUTO_INCREMENT,
      `SP` varchar(10) NOT NULL,
      `FileImportedDate` date NOT NULL,
      `AMZFileName` varchar(50) NOT NULL,
      `CasperBatch` varchar(50) NOT NULL,
      `BatchProcessedDate` date NOT NULL,
      `ExpiryDate` date NOT NULL,
      `Region` varchar(50) NOT NULL,
      `FCCity` varchar(50) NOT NULL,
      `VendorID` int(11) NOT NULL,
      `LocationID` int(11) NOT NULL,
      PRIMARY KEY (`CSN`),
      UNIQUE KEY `SP` (`SP`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=10000000000 ;
    
    
    
    
       CREATE TABLE IF NOT EXISTS `tblspduplicate` (
          `SP` varchar(50) NOT NULL,
          `FileImportedDate` date NOT NULL,
          `AMZFileName` varchar(50) NOT NULL
        ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    
    use casper;
    DELIMITER $$
    create trigger tblspmaster_noduplicate
    before insert on tblspmaster
    for each row
    begin
      if ( select count(sp) from tblspmaster where sp=new.sp > 0 ) then
        insert into tblspduplicate (sp,FileImportedDate,AMZFileName)   values (NEW.sp,NEW.FileImportedDate,NEW.AMZFileName);
      END IF;
    END$$
    
    DELIMITER ;
    
    
    
    
    
    
    LOAD DATA local INFILE 'E://31october//SP//sp_files_sample1//400k sp00 6-19 E.csv'
    INTO TABLE  tblspmaster
    FIELDS TERMINATED BY ','
    ENCLOSED BY '"'
    ESCAPED BY '\\'
    LINES TERMINATED BY '\n'
    IGNORE 1 LINES
    (sp);
    

    这是故事中的一个转折,我正在从c#控制台应用程序执行此MySql命令,但我认为它不会以任何方式影响我们的数据库相关结构或程序。 我还需要删除IGNORE 1 LINES语句,因为没有标题行。

1 个答案:

答案 0 :(得分:7)

就你引发的问题而言,有几个问题:

  1. 插入声明后没有;
  2. IF语句应以END IF和分号结尾,而不仅仅是END
  3. 您必须使用DELIMITER命令
  4. 更改分隔符
  5. 使用EXISTS()而不是COUNT()
  6. 据说你的触发器可能看起来像

    DELIMITER $$
    CREATE TRIGGER tblspmaster_noduplicate
    BEFORE INSERT ON tblspmaster
    FOR EACH ROW
    BEGIN
      IF (EXISTS(SELECT * FROM tblspmaster WHERE sp = NEW.sp)) THEN
        INSERT INTO tblspduplicate (sp,FileImported,AMZFileName)   
        VALUES (NEW.sp, NEW.FileImported, NEW.AMZFileName);
      END IF;
    END$$
    DELIMITER ;
    

    这是 SQLFiddle 演示

    IGNORE语句中使用LOAD DATA INFILE子句。 MySql会将错误(违反唯一约束)视为警告,有效地丢弃重复项。

      

    <强> LOAD DATA INFILE
      如果指定IGNORE,则会跳过复制唯一键值上现有行的输入行。

    LOAD DATA LOCAL INFILE 'E://31october//SP//sp_files_sample1//400k sp00 6-19 E.csv' 
    IGNORE  
    INTO TABLE tblspmaster 
    FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '\\' 
    LINES TERMINATED BY '\n' 
    -- IGNORE 1 LINES
    

    注意: FYI重复行的插入失败会在auto_increment SCN列的值中留下空白。


    您可能会考虑另一种可能更为优秀的方法:

    1. 创建没有约束且没有索引的临时登台表
    2. 使用LOAD DATA INFILE填充登台表
    3. 拥有tblspmaster和登台表并使用INSERT ... SELECT语法一次性插入tblspduplicate中的所有重复项
    4. 一次只将不存在的行从登台表插入tblspmaster
    5. TRUNCATEDROP临时表