2013-08-25 5 views
1

MySQL 5.2, CentOS 6.4.MySQL SELECT *는 PREPARE가 생성 한 임시 테이블에서 첫 번째 전달 후 동적 열과 테이블 이름을 사용하여 실패합니다.

MySQL SELECT *는 첫 번째 단계에서 동적 이름과 테이블 이름을 사용하여 PREPARE에 의해 생성 된 임시 테이블에서 열 이름과 테이블 이름이 첫 번째 단계에서 다른 값으로 변경되는 경우 실패합니다.

해결 방법은 통과에서 통과까지 동일하게 유지되는 열 별칭을 사용하는 것입니다.

DROP PROCEDURE IF EXISTS test1; 
DELIMITER $$ 
CREATE PROCEDURE test1(column_name VARCHAR(20), table_name VARCHAR(20)) 
BEGIN 
    SET @prepared_stmt_arg = 'prepared_stmt_arg_value'; 

    DROP TABLE IF EXISTS tmp1; 
    CREATE TEMPORARY TABLE tmp1 
     SELECT 1 AS col_tmp1; 

    DROP TABLE IF EXISTS tmp2; 
    CREATE TEMPORARY TABLE tmp2 
     SELECT 2 AS col_tmp2; 

    # drop tmp table if it exists 
    DROP TABLE IF EXISTS tmp_test1; 

    # prepared statement 
    SET @prepared_stmt = 
     CONCAT(" 
      CREATE TEMPORARY TABLE tmp_test1 
       SELECT ? AS prepared_stmt_arg, ", column_name, " # AS constant_col_alias 
        FROM ", table_name, " 
      "); # END statement 

    # display prepared statement before executing it 
    SELECT @prepared_stmt; 

    # prepare the statement 
    PREPARE ps FROM @prepared_stmt; 

    # execute 
    EXECUTE ps USING @prepared_stmt_arg; 

    # deallocate 
    DEALLOCATE PREPARE ps; 

    # display 
    SELECT * FROM tmp_test1; 

END $$ 
DELIMITER ; 

절차의 끝에있는 SELECT 문이 실패합니다. (당신은 오류 메시지를 보려면 아래로 스크롤해야 할 수도 있습니다.)

mysql> CALL test1('col_tmp1', 'tmp1'); 
+---------------------------------------------------------------------------------------------------------------------------------+ 
| @prepared_stmt                             | 
+---------------------------------------------------------------------------------------------------------------------------------+ 
| 
           CREATE TEMPORARY TABLE tmp_test1 
             SELECT ? AS prepared_stmt_arg, col_tmp1 # AS constant_col_alias 
               FROM tmp1 
           | 
+---------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

+-------------------------+----------+ 
| prepared_stmt_arg  | col_tmp1 | 
+-------------------------+----------+ 
| prepared_stmt_arg_value |  1 | 
+-------------------------+----------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

mysql> CALL test1('col_tmp2', 'tmp2'); 
+---------------------------------------------------------------------------------------------------------------------------------+ 
| @prepared_stmt                             | 
+---------------------------------------------------------------------------------------------------------------------------------+ 
| 
           CREATE TEMPORARY TABLE tmp_test1 
             SELECT ? AS prepared_stmt_arg, col_tmp2 # AS constant_col_alias 
               FROM tmp2 
           | 
+---------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

ERROR 1054 (42S22): Unknown column 'dev.tmp_test1.col_tmp1' in 'field list' 

그러나, 당신은 열 별칭의 주석 (단지 AS constant_col_alias 전에 # 제거)하는 경우, 모두 잘 작동합니다. 쿼리를 확인하려면 아래로 스크롤해야 할 수 있습니다.

mysql> CALL test1('col_tmp1', 'tmp1'); 
+-------------------------------------------------------------------------------------------------------------------------------+ 
| @prepared_stmt                            | 
+-------------------------------------------------------------------------------------------------------------------------------+ 
| 
           CREATE TEMPORARY TABLE tmp_test1 
             SELECT ? AS prepared_stmt_arg, col_tmp1 AS constant_col_alias 
               FROM tmp1 
           | 
+-------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

+-------------------------+--------------------+ 
| prepared_stmt_arg  | constant_col_alias | 
+-------------------------+--------------------+ 
| prepared_stmt_arg_value |     1 | 
+-------------------------+--------------------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

mysql> CALL test1('col_tmp2', 'tmp2'); 
+-------------------------------------------------------------------------------------------------------------------------------+ 
| @prepared_stmt                            | 
+-------------------------------------------------------------------------------------------------------------------------------+ 
| 
           CREATE TEMPORARY TABLE tmp_test1 
             SELECT ? AS prepared_stmt_arg, col_tmp2 AS constant_col_alias 
               FROM tmp2 
           | 
+-------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

+-------------------------+--------------------+ 
| prepared_stmt_arg  | constant_col_alias | 
+-------------------------+--------------------+ 
| prepared_stmt_arg_value |     2 | 
+-------------------------+--------------------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 
+0

  • 업그레이드는 정말'이름의 열이 의미합니까? '또는 자리 표시자를 수를 의미? – peterm

  • +0

    그냥 자리 표시 자입니다. 준비된 진술 그 자체가 제대로 작동하고있는 것처럼 보일 수 있도록 설명을하기 위해 그것을 거기에 놓습니다. 나는 그것이 문제와 관련이 없으므로 그것을 제거 할 것이다. – Michael

    답변

    1

    글쎄, 버그 또는 기능 (원하는 경우) 버전 5.6까지입니다.

    Bug #32868 Stored routines do not detect changes in meta-data.

    해결 방법을 참조하십시오 :이 작업을 수행하여 저장된 루틴 캐시를 플러시 :
    만들거나 VIEW tmpview AS SELECT 1 교체;

    여기 SQLFiddle 데모 mysql을하여 5.1.x
    당신이 당신이 당신의 오류가 발생합니다 CREATE OR REPLACE VIEW tmpview AS SELECT 1을 주석 경우 여기 SQLFiddle 데모 mysql을 5.5.X

    입니다.

    1. SELECT * 사용을 명시 적으로 열 이름을 사용하지 않는 : 여기

      SQLFiddle 데모 MySQL을 5.6.X이 문제


      당신이 갈 적어도 이러한 옵션이 이제 더 이상 있다고 보여줍니다이다 대신.
    2. 사용 제안 된 해결 방법 5.6.X
    +0

    정말 고마워요 - 챔피언처럼! – Michael

    +0

    @Michael 대단히 환영합니다. 내가 도울 수있어서 기뻐. :) – peterm