【发布时间】:2017-08-01 12:53:06
【问题描述】:
我从堆栈溢出中找到了这个过程。我想从所有具有特定列的表中获取特定值的行。 所以:
- 获取包含该列的所有表
-
从表中获取列值为 x 的所有行
@DELIMITER $$ CREATE PROCEDURE db.selectStuff () BEGIN DECLARE a varchar(100); DECLARE i CURSOR FOR SELECT DISTINCT TABLE_NAME from INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME="my_column_name"; OPEN i; read_loop: LOOP FETCH i INTO crt_table; SELECT * FROM crt_table WHERE my_column_name=some_id; END LOOP read_loop; CLOSE i; END$$ @DELIMITER; call selectStuff();
我收到了
[Code: 1064, SQL State: 42000] 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 'DECLARE i CURSOR FOR SELECT DISTINCT TABLE_NAME from INFORMATION_SCHEMA.COLUMNS ' at line 1 从 DBVisualizer Pro 9.5.7
选择有效。
更新: 从下面的 cmets 中,我将代码更改为:
@DELIMITER $$
CREATE PROCEDURE selectStuff ()
BEGIN
DECLARE s VARCHAR(300);
DECLARE i CURSOR FOR SELECT CONCAT('SELECT * FROM ',c.TABLE_NAME,' where `my_column_name`=1') as s from INFORMATION_SCHEMA.COLUMNS c WHERE c.COLUMN_NAME="my_column_name";
OPEN i;
do_stuff: LOOP
FETCH i INTO s;
PREPARE run FROM s;
EXECUTE run;
DEALLOCATE PREPARE run;
END LOOP do_stuff;
CLOSE i;
END$$
@DELIMITER;
call selectStuff();
我遇到了同样的错误。
注意:跑步
SELECT CONCAT('SELECT * FROM ',c.TABLE_NAME,' where `my_column_name`=1') as s from INFORMATION_SCHEMA.COLUMNS c WHERE c.COLUMN_NAME="my_column_name"
确实提供了正确的 SQL 语句,可以得到我想要的。
更新: 在 dbForge Studio Express 中运行它:
DELIMITER $
CREATE PROCEDURE selectStuff()
BEGIN
DECLARE done TINYINT DEFAULT 0;
DECLARE s VARCHAR (3000);
DECLARE i CURSOR FOR SELECT CONCAT("SELECT * FROM ", c.TABLE_NAME, " where my_column_name=1") as QUERY from INFORMATION_SCHEMA.COLUMNS c WHERE c.COLUMN_NAME="my_column_name";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN i;
do_stuff: LOOP
FETCH i INTO s;
IF done = 1 THEN LEAVE do_stuff;
END IF;
PREPARE stmt FROM s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP do_stuff;
CLOSE i;
END$
DELIMITER;
#call selectStuff();
我遇到了一些其他错误,但光标部分通过了。
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 's;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP do_stuff;
【问题讨论】:
-
更改:
@DELIMITER $$byDELIMITER $$和@DELIMITER;byDELIMITER ;。避免像你的表那样命名变量(crt_table)并声明该变量。 -
如果这是您的错误消息,则您的分隔符不起作用。另外:您需要使用动态sql。
SELECT * FROM crt_table将尝试查找表crt_table,而不是具有该变量值的表。参见例如this question 基本上和你想做的一样,只是做一个update。或者here 为所有表中的每一列提供一个(虽然有点太复杂了)。 -
@solarflare 你能看一下更新吗?如果我运行单行,我会得到正确的查询,但声明仍然有该错误。我正在使用 DBVisualizer。我认为@DELIMITER 是必要的。
-
显然对于 dbvisualizer,您必须使用
@DELIMITER $$;包括;(和@DELIMITER ;$$来结束它)。对于您在编辑中的新错误:您需要将@variable用于准备好的语句,因此请使用例如set @dsql = s; PREPARE stmt FROM @dsql;。乍一看,您还应该在查询中包含一个模式(或者在来自 information_schema 的那个中,或者在您的动态 sql 中,添加使用表所在的模式)。最后一个DELIMITER;必须包含一个空格 (DELIMITER ;) -
谢谢,@Solarflare,我已根据您的帮助和关于 stackoverflow 的另一个问题发布了答案。