Jest miejsce na ulepszenia:
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
Główne punkty
-
PostgreSQL 8.4 wprowadził
USING
klauzulaEXECUTE
, co jest przydatne z kilku powodów. Podsumuj w instrukcji:Ciąg polecenia może używać wartości parametrów, do których odwołuje się w poleceniu jako
$1, $2
itp. Te symbole odnoszą się do wartości podanych wUSING
klauzula. Ta metoda jest często preferowana niż wstawianie wartości danych do ciągu poleceń jako tekstu:pozwala uniknąć narzutów w czasie wykonywania związanych z konwersją wartości na tekst iz powrotem i jest znacznie mniej podatna na ataki polegające na wstrzykiwaniu SQL, ponieważ nie ma potrzeby cytowania ani ucieczki.IOW, jest bezpieczniejsze i szybsze niż tworzenie ciągu zapytania z tekstową reprezentacją parametrów, nawet po oczyszczeniu za pomocą
quote_literal()
.
Pamiętaj, że$1, $2
w ciągu zapytania odwołaj się do podanych wartości wUSING
klauzula, nie do parametrów funkcji. -
Podczas zwracania
SELECT * FROM lookups.countries
, możesz uprościćRETURN
deklaracja jak zademonstrowana:RETURNS SETOF lookups.countries
W PostgreSQL istnieje typ kompozytowy definiowany automatycznie dla każdej tabeli. Użyj tego. Efekt jest taki, że funkcja zależy od typu i jeśli spróbujesz zmienić tabelę, pojawi się komunikat o błędzie. W takim przypadku upuść i odtwórz funkcję.
To może być lub nie być pożądane - generalnie tak jest! Chcesz być świadomy skutków ubocznych zmiany tabel. Tak jak to zrobiłeś, twoja funkcja po cichu się zepsuje i zgłosi wyjątek przy następnym wywołaniu.
-
Jeśli podasz wyraźną wartość domyślną dla drugiego parametru w deklaracji, jak pokazano, możesz (ale nie musisz) uprościć wywołanie w przypadku, gdy nie chcesz ustawiać górnej granicy za pomocą
ends_with
.SELECT * FROM report_get_countries_new('Zaire');
zamiast:
SELECT * FROM report_get_countries_new('Zaire', NULL);
Należy pamiętać o przeciążaniu funkcji w tym kontekście.
-
Nie cytuj nazwy języka
nawet jeśli jest to tolerowane (na razie). To identyfikator.'plpgsql' -
Możesz przypisać zmienną w czasie deklaracji. Oszczędza dodatkowy krok.
-
Parametry są nazwane w nagłówku. Porzuć bezsensowne linie:
starts_with ALIAS FOR $1; ends_with ALIAS FOR $2;