MySql Trigger:在插入触发器后无法从NEW中检索一个特定列

时间:2014-06-24 14:46:50

标签: mysql triggers

我有3张桌子:

pp088_project_tasks

CREATE TABLE IF NOT EXISTS `pp088_project_tasks` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `task_list_id` int(10) unsigned DEFAULT NULL,
  `text` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
  `start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `due_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `assigned_to_company_id` int(10) DEFAULT NULL,
  `assigned_to_user_id` int(10) unsigned DEFAULT NULL,
  `completed_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `completed_by_id` int(10) unsigned DEFAULT NULL,
  `created_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `created_by_id` int(10) unsigned DEFAULT NULL,
  `updated_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_by_id` int(10) unsigned DEFAULT NULL,
  `order` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `task_list_id` (`task_list_id`),
  KEY `completed_on` (`completed_on`),
  KEY `created_on` (`created_on`),
  KEY `order` (`order`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=76 ;

pp088_project_task_lists

CREATE TABLE IF NOT EXISTS `pp088_project_task_lists` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `milestone_id` int(10) unsigned NOT NULL DEFAULT '0',
  `project_id` int(10) unsigned DEFAULT NULL,
  `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
  `priority` int(3) unsigned NOT NULL DEFAULT '0',
  `description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
  `start_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `due_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `score` int(3) unsigned NOT NULL DEFAULT '0',
  `is_private` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `completed_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `completed_by_id` int(10) unsigned DEFAULT NULL,
  `created_on` datetime DEFAULT NULL,
  `created_by_id` int(10) unsigned NOT NULL DEFAULT '0',
  `updated_on` datetime DEFAULT NULL,
  `updated_by_id` int(10) unsigned NOT NULL DEFAULT '0',
  `order` tinyint(3) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `milestone_id` (`milestone_id`),
  KEY `project_id` (`project_id`),
  KEY `completed_on` (`completed_on`),
  KEY `created_on` (`created_on`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

gantt_tasks

CREATE TABLE IF NOT EXISTS `gantt_tasks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `text` varchar(255) NOT NULL,
  `start_date` date NOT NULL,
  `duration` int(11) NOT NULL,
  `progress` float NOT NULL DEFAULT '1',
  `sortorder` int(11) NOT NULL,
  `parent` int(11) NOT NULL,
  `projectID` int(10) unsigned DEFAULT NULL,
  `tipo_evento` varchar(100) NOT NULL,
  `idPier` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=48 ;

我在'pp088_project_tasks'表上创建了一个AFTER INSERT触发器,以插入'gantt_tasks'

CREATE TRIGGER `insert_gantt_task` AFTER INSERT ON `pp088_project_tasks`
 FOR EACH ROW BEGIN

declare project_id int;
declare duracion int;

set project_id=(select project_id from pp088_project_task_lists where id=NEW.task_list_id);
set duracion=(select DATEDIFF(NEW.due_date,NEW.start_date));

insert into gantt_tasks (text,start_date,duration,projectID,idPier) values (NEW.text,NEW.start_date,duracion,project_id,NEW.id); 

END

但问题是设置了project_id变量,它将gantt_tasks字段projectID设置为NULL,因为该查询无法使用NEW.task_list_id检索该值,即使我直接在插入上使用该值只是为了检查值将gantt_tasks字段projectID设置为0 ......奇怪的是,如果我使用NEW的其他值它们都可以工作,那就是那个字段,插入对于gantt_tasks上的所有其他字段都是成功的。我检查过,类型是一样的,所以整理也是如此。 前两个表来自名为projectPier的项目管理器,而gantt_tasks表是我为甘特图创建的表(DHTMLX甘特图)。

1 个答案:

答案 0 :(得分:1)

  

...但问题在于设置了project_id变量,该变量将gantt_tasks字段projectID设置为NULL,因为该查询无法检索使用NEW.task_list_id的值,即使我直接在插入上使用该值,只是为了检查它将gantt_tasks字段projectID设置为0

原因非常可见

您有一个变量project_id,其名称与表中列的名称相匹配 当您使用没有表限定符的列名时,会出现名称冲突。并优先考虑列上的局部变量。

在您的情况下,由于声明

declare project_id int;

project_id的默认值为zero。因此,声明的输出

set project_id=(select project_id from pp088_project_task_lists 
                 where id=NEW.task_list_id);

将是zero。因此在insert语句中使用了相同的内容。

选项

  1. 将本地变量名称更改为相关内容。
  2. 使用表名来限定列名。
  3. 示例示例 :(使用选项1)

    对您的代码进行以下更改,它应该正常工作。

    delimiter //
    
    CREATE TRIGGER `insert_gantt_task` AFTER INSERT ON `pp088_project_tasks`
    FOR EACH ROW BEGIN
      declare _project_id int default 0;
      declare _duracion int default 0;
    
      select project_id into _project_id 
        from pp088_project_task_lists 
       where id = NEW.task_list_id;
    
      select DATEDIFF( NEW.due_date, NEW.start_date ) into _duracion;
    
      insert into gantt_tasks ( text, start_date, duration, projectID, idPier ) 
             values( NEW.text, NEW.start_date, _duracion, _project_id, NEW.id ); 
    END;
    
    //
    
    delimiter ;
    

    示例 :(使用选项2)

    对您的代码进行以下更改,它应该正常工作。

    delimiter //
    
    CREATE TRIGGER `insert_gantt_task` AFTER INSERT ON `pp088_project_tasks`
    FOR EACH ROW BEGIN
      declare project_id int default 0;
      declare duracion int default 0;
    
      set project_id := ( select tl.project_id 
                            from pp088_project_task_lists tl
                           where tl.id = NEW.task_list_id );
    
      set duracion := select DATEDIFF( NEW.due_date, NEW.start_date );
    
      insert into gantt_tasks ( text, start_date, duration, projectID, idPier ) 
             values( NEW.text, NEW.start_date, duracion, project_id, NEW.id ); 
    END;
    
    //
    
    delimiter ;