2012-04-27 47 views
0

在思考SO上另一个问题的潜在解决方案时,我开始考虑在一个过程中使用准备好的语句(在函数中没有动态SQL让我感到难过)。在该过程中执行PREPARE的幼稚方法似乎效率低下,因为只需在会话期间首次调用该过程时才需要准备该语句。只有在MySQL不存在的情况下,MySQL才有可能编写一份声明?有没有办法检查预先准备的陈述的存在?如果可能的话,我们如何避免重新准备纯SQL语句?

下面是供人们玩的示例程序。它会创建一个声明,SELECT是给定表中给定类型的所有列。

DROP PROCEDURE IF EXISTS select_columns_of_type_statement; 
delimiter // 
CREATE PROCEDURE select_columns_of_type_statement(IN db VARCHAR(255), IN tbl VARCHAR(255), IN type VARCHAR(255), OUT result VARCHAR(4095)) 
    READS SQL DATA 
    NOT DETERMINISTIC -- as tables can be ALTERed 
BEGIN 
    SET @scots_db=db, @scots_tbl=tbl, @scots_type=type; 
    PREPARE generate_scots FROM "SELECT CONCAT(
      'SELECT ', 
      GROUP_CONCAT(COLUMN_NAME SEPARATOR ', '), 
      ' FROM `', ?, '`.`', ?, '` ' 
     ) 
     FROM INFORMATION_SCHEMA.COLUMNS 
     WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND data_type=? 
     INTO @scots_stmt"; 
    EXECUTE generate_scots USING @scots_db, @scots_tbl, @scots_db, @scots_tbl, @scots_type; 
    SET result = @scots_stmt; 
END // 
delimiter ; 

用法示例:

CALL select_columns_of_type_statement('mysql', 'user', 'int', @stmt); 
SELECT @stmt; 
-- or even: 
SET @stmt=CONCAT(@stmt, 'LIMIT 3'); 
PREPARE user_int_cols FROM @stmt; 
EXECUTE user_int_cols; 

必须使用的用户变量这么多也让我伤心。

回答

0

检查存在可能不可行,但try-and-handle-failure模式将起作用。 DECLARE定义了&的错误处理程序执行准备好的语句,并在处理程序之外执行准备好的语句。如果语句不存在,错误处理程序将运行。这并不漂亮,但它的工作原理。

DROP PROCEDURE IF EXISTS select_columns_of_type_statement; 
delimiter // 
CREATE PROCEDURE select_columns_of_type_statement(IN db VARCHAR(255), IN tbl VARCHAR(255), IN type VARCHAR(255), OUT result VARCHAR(4095)) 
    READS SQL DATA 
    NOT DETERMINISTIC -- as tables can be ALTERed 
BEGIN 
    DECLARE CONTINUE HANDLER 
     FOR 1243 
     BEGIN 
     PREPARE generate_scots FROM "SELECT CONCAT(
       'SELECT ', 
       GROUP_CONCAT(COLUMN_NAME SEPARATOR ', '), 
       ' FROM `', ?, '`.`', ?, '` ' 
      ) 
      FROM INFORMATION_SCHEMA.COLUMNS 
      WHERE TABLE_SCHEMA=? AND TABLE_NAME=? AND data_type=? 
      INTO @scots_stmt"; 
     EXECUTE generate_scots USING @scots_db, @scots_tbl, @scots_db, @scots_tbl, @scots_type; 
     END; 
    SET @scots_db=db, @scots_tbl=tbl, @scots_type=type; 
    EXECUTE generate_scots USING @scots_db, @scots_tbl, @scots_db, @scots_tbl, @scots_type; 
    SET result = @scots_stmt; 
END // 
delimiter ;