sql >> Base de Datos >  >> RDS >> PostgreSQL

PostgreSQL:escribir sql dinámico en un procedimiento almacenado que devuelve un conjunto de resultados

Hay espacio para mejoras:

CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
                                                   , ends_with   text = NULL)
  RETURNS SETOF lookups.countries AS
$func$
DECLARE
   sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
   IF ends_with IS NOT NULL THEN
      sql := sql || ' AND country_name <= $2';
   END IF;

   RETURN QUERY EXECUTE sql
   USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;
-- the rest is default settings

Puntos principales

  • PostgreSQL 8.4 introdujo el USING cláusula para EXECUTE , que es útil por varias razones. Resumen en el manual:

    La cadena de comando puede usar valores de parámetros, a los que se hace referencia en el comando como $1, $2 , etc. Estos símbolos se refieren a los valores proporcionados en el USING cláusula. Este método a menudo es preferible a la inserción de valores de datos en la cadena de comando como texto:evita la sobrecarga en tiempo de ejecución de convertir los valores a texto y viceversa, y es mucho menos propenso a los ataques de inyección de SQL ya que no hay necesidad de citar o escapar. /P>

    IOW, es más seguro y rápido que crear una cadena de consulta con representación de texto de parámetros, incluso cuando se desinfecta con quote_literal() .
    Tenga en cuenta que $1, $2 en la cadena de consulta, consulte los valores proporcionados en USING cláusula, no a los parámetros de la función.

  • Mientras regresa SELECT * FROM lookups.countries , puede simplificar el RETURN declaración como se demuestra:

    RETURNS SETOF lookups.countries
    

    En PostgreSQL hay un tipo compuesto definido para cada tabla automáticamente. úsalo El efecto es que la función depende del tipo y obtiene un mensaje de error si intenta modificar la tabla. Soltar y volver a crear la función en tal caso.

    Esto puede o no ser deseable, ¡generalmente lo es! Quiere estar al tanto de los efectos secundarios si modifica las tablas. De la forma en que lo tiene, su función se rompería en silencio y generaría una excepción en su próxima llamada.

  • Si proporciona un predeterminado explícito para el segundo parámetro en la declaración como se muestra, puede (pero no tiene que hacerlo) simplificar la llamada en caso de que no quiera establecer un límite superior con ends_with .

    SELECT * FROM report_get_countries_new('Zaire');
    

    en lugar de:

    SELECT * FROM report_get_countries_new('Zaire', NULL);
    

    Tenga cuidado con la sobrecarga de funciones en este contexto.

  • No cite el nombre del idioma 'plpgsql' incluso si eso es tolerado (por ahora). Es un identificador.

  • Puede asignar una variable en el momento de la declaración. Ahorra un paso extra.

  • Los parámetros se nombran en el encabezado. Suelta las líneas sin sentido:

     starts_with ALIAS FOR $1;
     ends_with ALIAS FOR $2;