2013-07-17 26 views
1

我有包含“columnname”字段的表“mytable”,这是mytable2中列的名称。Mysql触发器,声明一个变量并将其用作列名称

我用这一个选择:

SET @DptScn = (SELECT columnname FROM mytable WHERE tablename = 'CustomTableName' AND fieldlabel = 'CustomField'); 
SET @identifiedid=144; 

,但是,当我尝试:

SELECT @DptScn FROM mytable2 WHERE identifiedid = @identifiedid; 

这给我场的不是内容而是containted到变量@DptScn名称。 ..

有什么建议吗? 我不能使用预处理语句,因为我在一个触发器是...

UPDATE:

正如spencer7593我创建一个程序提示:

DROP PROCEDURE IF EXISTS p_t; 
DELIMITER $$ 
CREATE PROCEDURE p_t (IN DptTcn VARCHAR(255), IN tid INT, OUT tT INT) 
BEGIN 
    SET @DptTcn = DptTcn; 
    SET @tid = tid; 
    SET @sql = CONCAT('SELECT @DptTcn FROM mytable3 WHERE tid = @tid'); 
    PREPARE stmt FROM @sql; 
    EXECUTE stmt; 
END$$ 
DELIMITER ; 

那我试试吧:

SET @DptTcn = (SELECT columnname mytable WHERE tablename = 'CustomTableName' AND fieldlabel = 'CustomField'); 
SET @identifiedid=145; 
CALL proc_ticket(@DptTcn, @identifiedid, @DptT); 

但是我收到一个:

#2014 - Commands out of sync; you can't run this command now 
+0

没有。没有准备好的陈述没办法。 – fancyPants

+1

'SET @sql = CONCAT('SELECT',@ DptTcn,'FROM mytable3 WHERE tid =',@ tid);'这就是您需要构建SQL语句的方式;您的过程中的SQL文本无效;使用MySQL用户变量代替标识符是无效的。列名称)在SQL语句中。 – spencer7593

+0

我改变了,但问题仍然存在(命令不同步) – MiPnamic

回答

1

要考虑的一个选项是创建一个使用预准备语句的PROCEDURE,然后从触发器中调用存储过程。

为了从特定列中获取值而执行的SQL语句必须具有在SQL文本中指定的column_name;这不能在执行语句时“动态”派生。

要实现这样的事情,您需要运行两个单独的语句;一个获取column_name;第二个到“SELECT column_name FROM”。 MySQL提供的执行第二个查询的机制是一个准备好的语句。


跟进

下面是一个例子。我试图用SQLFiddle来构建它,但是无法使它工作(它只是挂起来了,所以,这里是mysql命令行客户端的输出)

(以下所有的语句都使用相同的分隔符//,因为我们不能使用分号作为存储过程的分隔符。在SQLFiddle中,我们必须在所有语句中使用相同的分隔符,并且//恰好是SQLFiddle中的一个选项。)

mysql> DELIMITER // 

mysql> CREATE PROCEDURE foo(IN colname VARCHAR(255), IN id INT, OUT val VARCHAR(255)) 
    -> BEGIN 
    -> -- handler for "Unknown column" and "No data" exceptions 
    -> DECLARE EXIT HANDLER FOR 1054, 1329 BEGIN SET val = NULL; END; 
    -> SET @sql = CONCAT('SELECT ',colname,' INTO @val FROM t WHERE id = ',id,' LIMIT 1'); 
    -> PREPARE stmt FROM @sql; 
    -> EXECUTE stmt; 
    -> SET val = @val; 
    -> END// 
Query OK, 0 rows affected (0.00 sec) 

mysql> CREATE TABLE t (id INT, attr VARCHAR(4), ball VARCHAR(4))// 
Query OK, 0 rows affected (0.11 sec) 

mysql> INSERT INTO t VALUES (1, 'abcd','efgh'),(2,'ijkl','mnop')// 
Query OK, 2 rows affected (0.00 sec) 
Records: 2 Duplicates: 0 Warnings: 0 

mysql> CALL foo('attr',1,@attr_1)// 
Query OK, 0 rows affected (0.00 sec) 

mysql> CALL foo('attr',2,@attr_2)// 
Query OK, 0 rows affected (0.00 sec) 

mysql> CALL foo('ball',1,@ball_1)// 
Query OK, 0 rows affected (0.00 sec) 

mysql> CALL foo('ball',2,@ball_2)// 
Query OK, 0 rows affected (0.00 sec) 

mysql> CALL foo('attr',777,@err_bad_id)// 
Query OK, 0 rows affected (0.00 sec) 

mysql> CALL foo('badcol',1,@err_badcol)// 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT @attr_1 
    ->  , @attr_2 
    ->  , @ball_1 
    ->  , @ball_2 
    ->  , @err_bad_id 
    ->  , @err_badcol// 
+---------+---------+---------+---------+-------------+-------------+ 
| @attr_1 | @attr_2 | @ball_1 | @ball_2 | @err_bad_id | @err_badcol | 
+---------+---------+---------+---------+-------------+-------------+ 
| abcd | ijkl | efgh | mnop | NULL  | NULL  | 
+---------+---------+---------+---------+-------------+-------------+ 
1 row in set (0.00 sec) 

mysql> DELIMITER ; 
+0

我更新了你的建议之后的答案...但有些东西我不明白... – MiPnamic

+0

@MiPnamic:我无法得到这个在SQL小提琴(它只是挂起,说“建设”),所以我在这里把mysql命令行客户端的输出粘贴到这里,注意SQL语句是以字符串的形式表示的;被执行的字符串只有一个用户变量,这是SQL语句赋值的地方。还包含“无数据”异常(在查询未返回行时引发)的异常处理程序以及“未知列”异常(当表中不存在指定的列时引发)。处理exce一种不同的方式。 – spencer7593

+0

它完全可以工作! – MiPnamic

0

你应该创建一个SP并给出列名。

create proc dbo.TestGetData(@DptScn nvarchar(256)) 
as 
    begin 
    set nocount on 
    DECLARE @SQL NVARCHAR(MAX) 
    SET @SQL = 'SELECT @DptScn FROM mytable2 WHERE identifiedid = 144' 
    exec sp_executesql @SQL, N'@DptScn nvarchar(256)', @DptScn [email protected] 
end 

Then

exec dbo.TestGetData 'Column1' 
+0

我可以在我的触发器中“exec dbo.TestGetData @DptScn”吗? – MiPnamic

+0

此语法适用于Microsoft SQL Server,不适用于MySQL。 – spencer7593