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 paraEXECUTE
, 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 elUSING
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 enUSING
cláusula, no a los parámetros de la función. -
Mientras regresa
SELECT * FROM lookups.countries
, puede simplificar elRETURN
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
incluso si eso es tolerado (por ahora). Es un identificador.'plpgsql' -
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;