web-dev-qa-db-fra.com

Comment déclarer une variable dans une requête PostgreSQL

Comment déclarer une variable à utiliser dans une requête PostgreSQL 8.3?

Dans MS SQL Server, je peux le faire:

DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

Comment faire la même chose dans PostgreSQL? Selon la documentation, les variables sont simplement déclarées comme "type de nom;", mais cela me donne une erreur de syntaxe:

myvar INTEGER;

Quelqu'un pourrait-il me donner un exemple de la syntaxe correcte?

188
EMP

Il n’existe pas de telle fonctionnalité dans PostgreSQL. Vous pouvez le faire uniquement dans pl/PgSQL (ou autre pl/*), mais pas en langage SQL simple.

Une exception est la requête WITH () qui peut fonctionner en tant que variable, ou même Tuple de variables. Il vous permet de renvoyer une table de valeurs temporaires.

WITH master_user AS (
    SELECT
      login,
      registration_date
    FROM users
    WHERE ...
)

SELECT *
FROM users
WHERE master_login = (SELECT login
                      FROM master_user)
      AND (SELECT registration_date
           FROM master_user) > ...;
89
user80168

J'ai atteint le même objectif en utilisant une clause _ (WITH) , c'est loin d'être aussi élégant, mais je peux faire la même chose. Bien que pour cet exemple, c'est vraiment exagéré. Je ne recommande pas particulièrement cela.

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

Vous pouvez également essayer ceci dans PLPGSQL:

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;

Ceci nécessite Postgres 9.0 ou une version ultérieure.

68
Dario Barrionuevo

Cela dépend de votre client.

Toutefois, si vous utilisez le client psql, vous pouvez utiliser les éléments suivants:

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

Si vous utilisez des variables de texte, vous devez citer.

\set myvar 'sometextvalue'
select * from sometable where name = :'myvar';
45
Shahriar Aghajani

Paramètres de configuration dynamiques

vous pouvez "abuser" des paramètres de configuration dynamiques pour cela:

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

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

Les paramètres de configuration sont toujours des valeurs varchar. Vous devez donc les attribuer au type de données approprié lors de leur utilisation. Cela fonctionne avec n'importe quel client SQL alors que \set ne fonctionne que dans psql

Ceci nécessite Postgres 9.2 ou une version ultérieure.

Pour les versions précédentes, la variable devait être déclarée dans postgresql.conf avant d'être utilisée, ce qui limitait quelque peu sa convivialité. En fait, pas complètement la variable, mais la "classe" de configuration qui est essentiellement le préfixe. Mais une fois le préfixe défini, toute variable pouvait être utilisée sans modifier postgresql.conf

41

Utiliser une table temporaire en dehors de pl/PgSQL

En dehors de l'utilisation de pl/pgsql ou d'un autre langage pl/* comme suggéré, c'est la seule autre possibilité à laquelle je pouvais penser.

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

Je souhaite proposer une amélioration à réponse de @ DarioBarrionuevo , afin de simplifier l'utilisation des tables temporaires.

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;
10
bluish

Cette solution est basée sur celle proposée par fei0x mais présente les avantages qu’il n’est pas nécessaire de joindre la liste de valeurs des constantes dans la requête et que les constantes peuvent facilement être listées au début de la requête. Cela fonctionne aussi dans les requêtes récursives.

Fondamentalement, chaque constante est une table à valeur unique déclarée dans une clause WITH qui peut ensuite être appelée n'importe où dans la partie restante de la requête.

  • Exemple de base avec deux constantes:
WITH
    constant_1_str AS (VALUES ('Hello World')),
    constant_2_int AS (VALUES (100))
SELECT *
FROM some_table
WHERE table_column = (table constant_1_str)
LIMIT (table constant_2_int)

Vous pouvez également utiliser SELECT * FROM constant_name au lieu de TABLE constant_name, qui peut ne pas être valide pour d'autres langages de requête différents de postgresql.

5
Jorge Luis

Voici un exemple d'utilisation de instructions PREPARE . Vous ne pouvez toujours pas utiliser ?, mais vous pouvez utiliser la notation $n:

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

Certes, il n’existe pas de moyen clair et sans équivoque de déclarer une variable à valeur unique, vous pouvez faire ce qui suit:

with myVar as (select "any value really")

puis, pour avoir accès à la valeur stockée dans cette construction, vous devez

(select * from myVar)

par exemple

with var as (select 123)    
... where id = (select * from var)
4