触发器替代中的动态SQL

时间:2012-11-28 17:17:36

标签: mysql sql triggers

我理解在触发器中不允许使用准备好的语句,但我看不出我能做到我想做的事情,所以任何替代方案/解决方法都会受到高度赞赏。

DELIMITER $$

CREATE TRIGGER trigger1 after INSERT on table1
FOR EACH ROW
begin
DECLARE a varchar(30);
DECLARE b varchar(30);
DECLARE c varchar(30);
DECLARE d varchar(30);
SET a = new.Col1;
SET b = new.Col2;
SET c = (select Col4 from table2 where Col3=new.Col3);
SET d = concat('select ',a,' from table3 where yq=',c,' and xz=',b);
insert into table4 values (d);
end
$$

DELIMITER;

所以发生了什么:插入一行,从该行{3},Col1Col2中取出3个值。 new.Col3用于从另一个表中获取一行,然后与new.Col3一起使用以搜索我需要的值的第三个表。 Col2是问题所在,因为它应该是Col1的动态生成列名,但这不起作用。 很明显,目前我所回复的是d中的一个select语句的字符串,这是我所期望的,但我不能执行该语句,因为这是不允许的。 那么如何才能将动态生成的列名称输入到select语句中?

表1

d

表2

Col1 | Col2 | Col3
c    | d    | x
a    | e    | y
b    | e    | z
b    | f    | x

表3

Col3 | Col4
x    | 1
y    | 2 
z    | 3

我想要的结果来自1a-9c。

我考虑过更改表模式,以便触发器中的列名可以修复,但这是最后的手段,因为它会导致其他代码位出现问题。

2 个答案:

答案 0 :(得分:3)

你必须完全放弃预准备语句和动态SQL的想法,并且只是痛苦地做一些IF..THEN语句:

DELIMITER $$

CREATE TRIGGER trigger1 after INSERT on table1
FOR EACH ROW
begin
DECLARE a varchar(30);
DECLARE b varchar(30);
DECLARE local_c varchar(30);
DECLARE d varchar(30);
SET a = new.Col1;
SET b = new.Col2;
SET local_c = (select Col4 from table2 where Col3=new.Col3);
IF local_c = 'a' THEN
    select a into d from table3 where yq=local_c and xz=b;
END IF;
IF local_c = 'b' THEN
    select b into d from table3 where yq=local_c and xz=b;
END IF;
IF local_c = 'c' THEN
    select c into d from table3 where yq=local_c and xz=b;
END IF;
IF ISNULL(d) = 0 THEN
    insert into table4 values (d);
END IF;
end
$$

DELIMITER;

答案 1 :(得分:-2)

尝试使用如下准备语句:

 PREPARE myStmt FROM 
 'concat( insert into table4 values (', 
          'select ',
          a,
          ' from table3 where yq=',
          c,
          ' and xz=',
          b, 
          '))';
 EXECUTE myStmt;