sql >> Base de Datos >  >> RDS >> Mysql

Consulta de selección de MySQL con nombre de columna variable

La solución más simple es usar dos consultas separadas.

Usamos el resultado de la primera consulta para generar dinámicamente el texto SQL para la segunda consulta.

mysql> SET @colname := '' ; 
mysql> SELECT t.rslt FROM table1 t WHERE t.id = 1 ORDER BY t.rslt LIMIT 1 INTO @colname ;

mysql> SET @sql := CONCAT('SELECT `',@colname,'` FROM table2 ORDER BY 1') ;
mysql> PREPARE stmt FROM @sql ; 
mysql> EXECUTE stmt ;

mysql> DEALLOCATE PREPARE stmt ;

nótese bien incluyendo @colname como parte del texto SQL, SQL preparado dinámicamente, es una vulnerabilidad potencial de inyección SQL.

Si el requisito es hacer algo similar en el contexto de un single instrucción SQL, la instrucción debe anticipar los valores posibles que se devolverán para la consulta de la tabla 1 e incluir referencias explícitas a las columnas posibles de la tabla 2. Por ejemplo, algo como esto:

  SELECT CASE ( SELECT t.rslt FROM table1 t WHERE t.id = 1 LIMIT 1 )
           WHEN 'r1' THEN r.r1 
           WHEN 'r2' THEN r.r2 
           WHEN 'r3' THEN r.r3 
           ELSE NULL
         END AS c2
    FROM table2 r
   ORDER BY ...

Esta no es necesariamente la forma más eficiente de escribir la consulta, pero demuestra el patrón.

Dentro de una instrucción SQL, los identificadores (nombres de tablas, nombres de columnas, nombres de funciones) deben especificarse explícitamente; estos no se pueden derivar dinámicamente en tiempo de ejecución. Esto se debe a cómo se procesan las declaraciones SQL... analizando el texto SQL en busca de sintaxis, luego analizando la semántica (referencias y privilegios válidos), evaluando el costo relativo para las rutas de acceso disponibles, seleccionando un plan de ejecución y luego ejecutando ese plan.

Es decir, el comportamiento observado con este SQL es el esperado:

 SELECT (SELECT rslt FROM table1 WHERE id = 1) FROM table2

Se prepara el texto SQL, y en tiempo de ejecución, para cada fila de la tabla2, la subconsulta en el SELECT se ejecuta la lista. Si la subconsulta devuelve un valor escalar, el valor escalar se devuelve como una columna de la consulta externa. El valor devuelto por la subconsulta es un valor , no es (y no puede ser) evaluado como un nombre de columna.