Tengo un procedimiento que toma como entrada un sufijo del nombre de una tabla. Luego, usando el formato de ejecución (), paso este parámetro para ejecutar la consulta dinámica. El problema es que este parámetro es el mismo en todo momento, no quiero pasarlo x veces como tal:

execute format('SELECT table_%s.field1, table_%s.field2,table_%s.field3
FROM table_%s', inTableSuffix, inTableSuffix, inTableSuffix, inTableSuffix, ...) 

Me gustaría un formato similar al siguiente:

execute format('SELECT table_%s.field1, table_%s.field2,table_%s.field3
FROM table_%s', inTableSuffix) 

Entiendo que puedo resolver este problema usando un alias para el nombre de la tabla, pero ¿hay otra alternativa?

1
Zeruno 14 ene. 2017 a las 18:03
Entonces, ¿tienes tu respuesta?
 – 
Erwin Brandstetter
18 ene. 2017 a las 23:22

2 respuestas

@wildplasser ya proporcionó la sintaxis sobre cómo hacer referencia al mismo parámetro repetidamente en format(). Sin embargo, el código sigue siendo peligroso. Necesitas escapar de los identificadores creados a partir de la entrada del usuario:

EXECUTE format('SELECT field1, field2, field3 FROM %I', 'table_' || inTableSuffix);

Para el ejemplo dado, solo necesita el parámetro una vez de todos modos. El alcance de las consultas dinámicas ejecutadas con EXECUTE en plpgsql se limita a la consulta en sí. Otras variables o parámetros de la función no son visibles dentro de EXECUTE. Por lo tanto, no es necesario calificar columnas de tabla en una consulta dinámica con una sola tabla en la cláusula FROM.

Pero lo que es más importante, %I es usado en format() para identificadores para evitar errores de sintaxis, minúsculas equivocadas o, peor aún, inyección SQL. Incluye comillas dobles (¡solo!) De lo contrario identificadores ilegales, como lo haría quote_ident().

Detalles:

1
Community 23 may. 2017 a las 14:46
@wildplasser: Parece que te estás perdiendo que ya lo hago. No necesita una variable (más cara), puede pasar la expresión concatenada como parámetro. Aparte: es quote_ident(), no quote_identifier().
 – 
Erwin Brandstetter
14 ene. 2017 a las 19:37
Vaya, no vi eso.
 – 
wildplasser
14 ene. 2017 a las 19:39

Puede repetidamente abordar los argumentos posicionales de esta manera:


execute format('SELECT table_%1$s.field1
   , table_%1$s.field2,table_%1$s.field3
FROM table_%1$s;', inTableSuffix); 

Nota: en este caso particular, puede evitar repetirse usando un alias:


execute format('SELECT tx.field1
   , tx.field2, tx.field3
FROM table_%s tx;', inTableSuffix); 
3
wildplasser 14 ene. 2017 a las 18:55
Además, no es necesario usar el nombre de la tabla para cada columna si no hay una combinación, pero incluso si hay una combinación, puede usar un alias para la tabla, por lo que no es necesario concatizar varias veces el nombre completo de la tabla.
 – 
llouk
14 ene. 2017 a las 18:54