438 votes

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 déclarées simplement comme "nom type ;", mais cela me donne une erreur de syntaxe :

myvar INTEGER;

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

3 votes

Cela peut se faire uniquement avec PostgreSQL. Voir la réponse à cette question connexe : stackoverflow.com/questions/766657/

4 votes

Cette réponse connexe contient de meilleures réponses : stackoverflow.com/questions/13316773/

387voto

fei0x Points 251

J'ai atteint le même objectif en utilisant un WITH clause Il est loin d'être aussi élégant mais peut faire la même chose. Bien que pour cet exemple, c'est vraiment exagéré. Je ne le recommande pas non plus particulièrement.

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

5 votes

Cela fonctionne très bien dans la plupart des cas où vous voulez des variables. Toutefois, si vous souhaitez utiliser une variable pour LIMIT (qui ne peut pas contenir de variables), vous devez utiliser la méthode suivante \set comme suggéré dans la réponse de Shahriar Aghajani.

2 votes

C'est idéal lorsque j'ai une migration script où je veux importer des données relationnelles. Évidemment, je ne connaîtrai pas l'id de séquence que les données relationnelles reçoivent.

4 votes

Je viens d'essayer cette approche, et j'ai trouvé une méthode peut-être meilleure : JOIN myconstants ON true et il n'est donc pas nécessaire d'effectuer la sous-sélection.

206voto

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

Une exception est WITH () qui peut fonctionner comme une variable, ou encore tuple de variables. Il permet de renvoyer un tableau 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) > ...;

3 votes

J'ai essayé cette méthode d'utilisation des CTE comme variables. Mais j'ai rapidement rencontré un problème où les différentes requêtes de modification des données dans les CTE ne sont pas garanties de voir les effets des autres. J'ai dû utiliser plusieurs CTE car j'avais besoin d'utiliser cette variable dans plusieurs requêtes.

142voto

Dario Barrionuevo Points 455

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;

Ce qui précède nécessite Postgres 9.0 ou une version ultérieure.

3 votes

L'instruction DO a été ajoutée dans PostgreSQL 9.0 et ne fonctionne pas dans 8.3.

29 votes

Utilisez CREATE TEMPORARY TABLE ou CREATE TEMP TABLE, et non CREATE TABLE. Mais sinon, tout va bien.

105voto

a_horse_with_no_name Points 100769

Paramètres de configuration dynamique

vous pouvez "abuser" des paramètres de configuration dynamique 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 convertir en un type de données correct lorsque vous les utilisez. Cela fonctionne avec tout client SQL alors que \set ne fonctionne que dans psql

Ce qui précède nécessite Postgres 9.2 ou une version ultérieure.

Pour les versions précédentes, la variable devait être déclarée dans le fichier postgresql.conf avant d'être utilisé, ce qui en limitait quelque peu l'utilité. En fait, il ne s'agit pas de la variable elle-même, mais de la "classe" de configuration qui est essentiellement le préfixe. Mais une fois le préfixe défini, n'importe quelle variable pouvait être utilisée sans modifier postgresql.conf

4 votes

@BrijanElwadhi : oui, c'est transactionnel.

2 votes

A titre d'information : certains mots sont réservés, par exemple : changer set session my.vars.id = '1'; à set session my.user.id = '1'; donnera ERROR: syntax error at or near "user"

3 votes

@BrijanElwadhi : Pour rendre la transaction variable spécifique, vous devez utiliser : SET LOCAL ... . Le site session sera en vigueur aussi longtemps que votre connexion le sera. Le site local s'applique à la transaction.

79voto

Shahriar Aghajani Points 101

Cela dépend de votre client.

Cependant, si vous utilisez le psql vous pouvez alors utiliser ce qui suit :

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 les citer.

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

1 votes

\set doit être minuscule

0 votes

Db=# \set profile_id 102 db=# :profile_id ; ERROR : erreur de syntaxe à ou près de "102" LINE 1 : 102 ; ^.

1 votes

@AlxVallejo vous devez l'utiliser dans une déclaration et psql console. db=> \set someid 8292 db=> SELECT * FROM sometable WHERE id = :someid;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X