2009-09-29 10 views
112

Wie deklariere ich eine Variable für die Verwendung in einer PostgreSQL 8.3-Abfrage?So deklarieren Sie eine Variable in einer PostgreSQL-Abfrage

In MS SQL Server Ich kann dies tun:

DECLARE @myvar INT 
SET @myvar = 5 

SELECT * 
FROM somewhere 
WHERE something = @myvar 

Wie kann ich in PostgreSQL das gleiche tun? Gemäß der Dokumentation Variablen einfach als deklariert werden „name Typ;“, aber das gibt mir einen Syntaxfehler:

myvar INTEGER; 

Könnte mir jemand ein Beispiel für die korrekte Syntax geben?

+2

Es in nur PostgreSQL getan werden kann. Siehe die Antwort auf diese verwandte Frage: http://stackoverflow.com/questions/766657/how-do-you-use-variables-in-a-simple-postgresql-script#6990059 –

+2

Diese verwandte Antwort hat bessere Antworten: http://StackOverflow.com/Questions/13316773/is-there-a-way-to-define-a-named-constant-in-a-postgresql-query –

Antwort

52

Es gibt keine solche Funktion in PostgreSQL. Sie können es nur in pl/PgSQL (oder anderen pl/*), aber nicht in SQL.

+13

Jeder kümmert sich um zu erklären * warum * diese Antwort ist veraltet? – simonlchilds

+20

Okay, wie machst du es in pl/PgSQL ?! – stone

19

Mit einer Temp-Tabelle außerhalb von pl/PgSQL

Außerhalb der Verwendung von pl/pgsql oder anderen pl/* Sprache, wie vorgeschlagen, ist dies die einzige andere Möglichkeit, die ich denken konnte.

begin; 
select 5::int as var into temp table myvar; 
select * 
    from somewhere s, myvar v 
where s.something = v.var; 
commit; 
40

könnten Sie auch diese in plpgsql versuchen:

DO $$ 
DECLARE myvar integer; 
BEGIN 
    SELECT 5 INTO myvar; 

    DROP TABLE IF EXISTS tmp_table; 
    CREATE TABLE tmp_table AS 
    SELECT * FROM yourtable WHERE id = myvar; 
END $$; 

SELECT * FROM tmp_table; 

Die obige Postgres erfordert 9.0 oder höher.

+0

Die DO-Anweisung wurde in PostgreSQL 9.0 hinzugefügt und funktioniert nicht in 8.3. – Johny

+7

Verwenden Sie CREATE TEMPORARY TABLE oder CREATE TEMP TABLE, nicht CREATE TABLE. Aber ansonsten gut. –

32

Es hängt von Ihrem Kunden ab.

Wenn Sie jedoch die psql-Client verwenden, dann können Sie Folgendes verwenden:

my_db=> \set myvar 5 
my_db=> SELECT :myvar + 1 AS my_var_plus_1; 
my_var_plus_1 
--------------- 
      6 
+1

'\ set' muss klein geschrieben werden – deluan

115

ich das gleiche Ziel erreicht, indem ein WITH clause verwenden, ist es bei weitem nicht so elegant ist, aber kann das tun gleiche Sache. Obwohl es für dieses Beispiel wirklich übertrieben ist. Ich empfehle das auch nicht besonders.

WITH myconstants (var1, var2) as (
    values (5, 'foo') 
) 
SELECT * 
FROM somewhere, myconstants 
WHERE something = var1 
    OR something_else = var2; 
+2

Dies funktioniert gut für die meisten Fälle, wo Sie Variablen möchten. Wenn Sie jedoch eine Variable für LIMIT verwenden möchten (die keine Variablen enthalten kann), sollten Sie '\ set' verwenden, wie in der Antwort von Shahriar Aghajani vorgeschlagen. – cimmanon

+1

Dies ist ideal, wenn ich ein Migrationsskript habe, wo ich einige relationale Daten importieren möchte. Offensichtlich werde ich die Sequenz-ID, die die relationalen Daten geben, nicht kennen. – Relequestual

+2

Ich habe gerade diesen Ansatz versucht und einen vielleicht besseren Weg gefunden: 'VERBINDEN myconstants ON true' und dann ist es nicht nötig, die Sub-Auswahl zu machen. – vektor

6

Ich mag eine Verbesserung @DarioBarrionuevo's answer vorzuschlagen, es einfache Nutzung temporäre Tabellen zu machen.

DO $$ 
    DECLARE myvar integer = 5; 
BEGIN 
    CREATE TEMP TABLE tmp_table ON COMMIT DROP AS 
     -- put here your query with variables: 
     SELECT * 
     FROM yourtable 
     WHERE id = myvar; 
END $$; 

SELECT * FROM tmp_table; 
+0

nette Lösung zum Lösen von DO-Block kann Datensatz nicht zurückgeben! – CodeFarmer

26

Dynamische Config-Einstellungen

Sie können "missbrauchen" dynamische Konfigurationseinstellungen für diese:

-- choose some prefix that is unlikey to be used by postgres 
set session my.vars.id = '1'; 

select * 
from person 
where id = current_setting('my.vars.id')::int; 

Config-Einstellungen sind immer varchar Werte, so dass Sie sie in den richtigen Datentyp umwandeln müssen wenn Sie sie benutzen. Dies funktioniert mit jedem SQL-Client, während \set nur funktioniert in psql

Das obige erfordert Postgres 9.2 oder höher.

Für frühere Versionen musste die Variable vor der Verwendung in postgresql.conf deklariert werden, so dass ihre Verwendbarkeit etwas eingeschränkt wurde. Eigentlich nicht die Variable komplett, aber die Config "Klasse", die im Wesentlichen das Präfix ist.Aber sobald das Präfix definiert wurde, könnte eine beliebige Variable ohne Änderung verwendet werden. postgresql.conf

+0

kann dies 'set session my.vars.id' = '1'; sei durchschnittsspezifisch ??? –

+1

@BrijanElwadhi: Ja, das ist transaktional. –

+0

danke .. hat mir wirklich geholfen :) –

0

Hier ist ein Beispiel mit PREPARE statements. Sie können immer noch nicht ? verwenden, aber Sie $n Notation verwenden:

PREPARE foo(integer) AS 
    SELECT * 
    FROM somewhere 
    WHERE something = $1; 
EXECUTE foo(5); 
DEALLOCATE foo; 
Verwandte Themen