Test für die null in der Funktion mit unterschiedlichen Parametern
Ich habe eine Postgres-Funktion:
create function myfunction(integer, text, text, text, text, text, text) RETURNS
table(id int, match text, score int, nr int, nr_extra character varying, info character varying, postcode character varying,
street character varying, place character varying, country character varying, the_geom geometry)
AS $$
BEGIN
return query (select a.id, 'address' as match, 1 as score, a.ad_nr, a.ad_nr_extra,a.ad_info,a.ad_postcode, s.name as street, p.name place , c.name country, a.wkb_geometry as wkb_geometry from "Addresses" a
left join "Streets" s on a.street_id = s.id
left join "Places" p on s.place_id = p.id
left join "Countries" c on p.country_id = c.id
where c.name = $7
and p.name = $6
and s.name = $5
and a.ad_nr = $1
and a.ad_nr_extra = $2
and a.ad_info = $3
and ad_postcode = $4);
END;
$$
LANGUAGE plpgsql;
Diese Funktion kann nicht für das richtige Ergebnis, wenn eine oder mehrere der Variablen eingegeben sind NULL, weil ad_postcode = NULL
fehl.
Was kann ich tun, um auf NULL zu testen innerhalb der Abfrage?
Sie können der Funktion Argumente, Namen anstelle von
Und Lesen Sie einige Artikel über SQL-Abfrage zu formatieren. Derzeit ist es schrecklich. Oder zumindest, verwenden Sie eine automatische Abfrage-verschönerer.
Danke für hinting mir Argumentnamen verwenden, sehr geschätzt.
$1
..$9
. So etwas wie myfunction(v_ad_nr integer, v_ad_nr_extra text, ...
und ... a.ad_nr = v_ad_nr ...
. Es macht den code sehr viel besser lesbar und einfacher zu ändern.Und Lesen Sie einige Artikel über SQL-Abfrage zu formatieren. Derzeit ist es schrecklich. Oder zumindest, verwenden Sie eine automatische Abfrage-verschönerer.
Danke für hinting mir Argumentnamen verwenden, sehr geschätzt.
InformationsquelleAutor milovanderlinden | 2013-06-27
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bin nicht einverstanden mit einigen der Beratung in anderen Antworten. Diese kann getan werden, mit plpgsql und ich denke, es ist meist weit überlegen Montage-Abfragen in einer client-Anwendung. Es ist schneller und sauberer, und die app sendet nur das absolute minimum über dem Draht auf Anfragen. SQL-Anweisungen gespeichert sind, die innerhalb der Datenbank, der es einfacher macht zu halten - es sei denn, Sie möchten sammeln Sie alle business-Logik im client-Anwendung, dies hängt von der Allgemeinen Architektur.
Allgemeine Hinweise
Brauchen Sie nicht, Sie Klammern, um die
SELECT
mitRETURN QUERY
Nie Verwendung
name
undid
als Spaltennamen. Sie sind nicht aussagekräftig und wenn Sie an einen Haufen von Tabellen (wie Siea lot
in einer relationalen Datenbank), die Sie am Ende mit mehreren Spalten, die alle den Namenname
oderid
. Duh.Bitte formatieren Sie Ihre SQL-richtig-zumindest bei Fragen, Fragen der öffentlichkeit. Aber tun Sie es auch privat, für Ihre eigenen gut.
PL/pgSQL-Funktion
Nennen:
Da ich default-Werte für alle Parameter der Funktion, die Sie verwenden können, positions - notation, namens notation oder gemischt Schreibweise im Aufruf der Funktion. Mehr in diesem Zusammenhang zu beantworten:
Funktionen mit einer Variablen Anzahl von input-Parametern
Weitere Erklärung auf die Grundlagen der dynamischen SQL finden Sie in diesem Zusammenhang beantworten:
Umgestalten einer PL/pgSQL-Funktion zum zurückgeben der Ausgabe an verschiedene SELECT-Abfragen
Den
concat()
Funktion ist maßgeblich für den Aufbau der saite. Es war eingeführt mit Postgres 9.1.Den
ELSE
Zweig derCASE
- Anweisung standardmäßig aufNULL
wenn nicht vorhanden. Vereinfacht den code.Den
Klausel für
EXECUTE
macht SQL-injection unmöglich und erlaubt es, parameter, Werte direkt, genau wie prepared statements.NULL
Werte werden verwendet, um Parameter ignorieren hier. Sie sind eigentlich nicht verwendet, zu suchen.Einfache SQL-Funktion
Du könnte tun Sie es mit einem einfachen SQL-Funktion, und vermeiden Sie dynamische SQL. Bei einigen Fällen kann dies schneller sein. Aber ich würde nicht erwarten, dass es in diesem Fall. Re-Planung die Abfrage mit oder ohne joins und where-Bedingungen ist der überlegene Ansatz. Es wird Ihnen optimierte Abfragepläne. Planung der Kosten für eine einfache Abfrage, wie ist dies praktisch zu vernachlässigen.
Identischen Anruf.
Effektiv ignorieren Parameter mit
NULL
Werte:Wenn Sie wirklich wollen, zu verwenden NULL-Werte als Parameter, verwenden Sie dieses Konstrukt statt:
Dies ermöglicht auch Indizes verwendet werden.
Auch ersetzen Sie alle Instanzen von
LEFT JOIN
mitJOIN
.SQL Fiddle mit vereinfachten demo für alle Varianten.
"$3 "null" ist mir "Query failed: ERROR: 42P08: konnte nicht bestimmen, Datentyp der parameter $3". $3 ist ein string mit 4 Zeichen.
Der Datentyp der Parameter sind abgeleitet aus dem Kontext, also ($1 NULL IST UND eine.ad_nr IST NULL ODER eine.ad_nr = $1) funktionieren nicht mit mir (Postgresql weiß nicht, der Typ von $1 vorher), aber (ein.ad_nr = $1 ODER $1 NULL IST UND eine.ad_nr NULL IST) funktioniert.
Welche Funktion hast du test? Ich kann nicht nachvollziehen, was Sie kommentiert. Der Datentyp aller Parameter vorgegeben ist. Was ist Ihre version auf Postgres? Was ist Ihre genaue Aufruf? Getestet habe ich diese, bevor ich gepostet mit Postgres 9.1. Gerade getestet alle Varianten wieder mit pg 9.3 und 9.4 zu finden Sie wie beworben. Ich habe ein fiddle-demo, um meine Antwort: sqlfiddle.com/#!15/58e6c/2
"Die Daten geben Sie alle Parameter vordefiniert ist", eigentlich sind Sie ja nicht sein (in 9.4 oder 9.3). Sieht aus wie wenn wir anfangen zu vergleichen, die 1 $mit NULL, SQL haben keinen Kontext zu lernen. Aber wenn wir beginnen den Vergleich einer bekannten Spalte mit $1, dann "lernt" der Typ von $1. Der Vorteil, dass Sie nicht die Angabe des Datentypen ist nur einen kleinen Gewinn in der Geschwindigkeit der Umsetzung. Bisher scheint es zu funktionieren.
InformationsquelleAutor Erwin Brandstetter
Können Sie
Zurück
true
wennc.name
und$7
sind gleich oder beide sindnull
.Oder verwenden Sie
Zurück
true
wennc.name
und$7
gleich sind oder$7
null ist.InformationsquelleAutor Igor Romanchenko
Wenn Sie können die Abfrage ändern, Sie konnte etwas tun, wie
InformationsquelleAutor bma
Mehrere Dinge...
Zunächst als Anmerkung: die Semantik Ihrer Abfrage möglicherweise benötigen besuchen. Einige der Sachen in Ihrem
where
Klauseln könnten, gehören eigentlich in Ihremjoin
Klauseln, wie:Wenn Sie nicht, Sie sollten die meisten wahrscheinlich einen
inner join
eher als eineleft join
.Zweiten, es ist ein
is not distinct from
Betreiber, die können gelegentlich nützlich sein, statt=
.a is not distinct from b
ist im Grunde gleichwertig zuma = b or a is null and b is null
.Beachten Sie jedoch, dass
is not distinct from
hat NICHT einen index verwenden, in der Erwägung, dass=
undis null
tatsächlich tun. Könnten Sie(field = $i or $i is null)
statt in Ihrem speziellen Fall, und es wird der Ertrag der optimalen plan, wenn Sie mit der neuesten version von Postgres:https://gist.github.com/ddebernardy/5884267
Wow, Postgres einige gravierende Verbesserungen an dieser front seit ich das Letzte mal gebraucht. Ich fügte hinzu, eine Zusammenfassung mit einem Beispiel aus der gleichen vorbereitete Anweisung mit zwei verschiedenen Parametern. 9.2 scheint, bereiten Sie mehrere Pläne auf welches Prädikat gelten. Coole Sachen.
Das war ein großes update in 9.2. Einige details in den release notes. BTW, ich bin nicht über Ihre Antwort, wenn Sie nicht @-reply, da wir kommentieren Ihr Antwort. Dies sah zufällig.
Danke für die Antworten und Kommentare. Die Hinweise auf eine bessere Organisation meines Codes sind geschätzt.
InformationsquelleAutor Denis de Bernardy