Équivalent PostgreSQL des variables de requête MySQL?

9

Existe-t-il un moyen simple d'adapter ces types de requêtes MySQL à PostgreSQL:

  1. définir des variables dans MySQL comme

    set @aintconst = -333
    set @arealconst = -9.999

    Il semble que non .

  2. Assigner des variables à partir de requêtes SELECT et utiliser ces variables par la suite dans mon SQL comme:

     select @pfID := id from platform where bios like '%INTEL%'
     select @clientID := id from client where platformID = @pfID

Je serais très reconnaissant aux pointeurs, en particulier sur (2).

Daniel
la source
Vous trouverez peut-être que les variables PSQL sont ce que vous recherchez. dba.stackexchange.com/a/213009/2639
Evan Carroll

Réponses:

13

C'est facile à faire dans une fonction PL / pgSQL (ou un bloc DO ):

create function myfunc() returns void language plpgsql as $$
  declare
    aintconst constant int = -333;
    arealconst constant real = -9.99;
    pfid int;
    clientid int;
  begin

    select id from platform where bios like '%INTEL%' into pfid;

    select id from client where platformID = pfid into clientid;

  end $$;

Vous pouvez également utiliser des variables GUC :

--set a session variable
set mycustom.var = 'value';

--use it
select * from mytable where some_column = current_setting('mycustom.var');

Ou vous pouvez utiliser un CTE avec une jointure:

with myvars as (
  select
    -333::int as aint,
    -9.99::real as areal
)

select 
  a.*
from mytable a
join myvars on true
where
  a.thing = aint
Neil McGuigan
la source
Si vous utilisez la méthode GUC, comment configurez-vous une variable avec une liste énumérée de nombres?
user952342
9

J'utilise des instructions WITH:

WITH vars as (SELECT -333::double precision as aintconst,-9.999::double precision as arealconst)
UPDATE table SET col1 = (SELECT aintconst FROM vars)

et:

WITH platformx AS (SELECT id FROM platform WHERE bios like '%INTEL%')
SELECT id FROM client WHERE platformID = (SELECT id FROM platformx)
user2641043
la source
3

Vous avez déjà répondu vous-même à cette question: non, il n'y en a pas en SQL simple. Vous pouvez utiliser PL / PgSQL si vous voulez des variables, dans une fonction ou un DObloc.

La plupart des utilisations des variables de requête dans MySQL sont satisfaites par les CTE ( WITHrequêtes), les fonctions de fenêtre, etc. dans PostgreSQL.


Eh bien, en fait, il existe, mais ils ne conviennent pas à une utilisation générale dans les requêtes. Vous accédez généralement aux GUC personnalisés avec SETet SHOW, mais vous pouvez utiliser à la place:

regress=> select set_config('a.b', 'c', false);
 set_config 
------------
 c
(1 row)

regress=> select current_setting('a.b');
 current_setting 
-----------------
 c
(1 row)

Les GUC sont chers et c'est une mauvaise idée de l'utiliser pour des requêtes à usage général, mais il y a très occasionnellement une utilisation valide. Vous pouvez uniquement utiliser des paramètres tels que myapp.variable.

Craig Ringer
la source
2

Variables PSQL

Depuis au moins la version 7.1, le client PostgreSQL a fourni cette fonctionnalité avec des psqlvariables

\set aintconst  -333
\set arealconst -9.999

SELECT :aintconst AS aintconst, :arealconst AS realconst;
 aintconst | realconst 
-----------+-----------
      -333 |    -9.999
(1 row)

Essentiellement, ce que vous voulez, c'est la possibilité de script SQL. PSQL a des conditions et des variables, et la possibilité de réinjecter du SQL généré dynamiquement, ce qui facilite ce travail. Ce n'est pas une fonctionnalité côté serveur dans le monde PostgreSQL, et généralement je le ferais dans un langage client (comme Node.js ou Perl plutôt qu'en psql).

Evan Carroll
la source
besoin de mises à jour. car le dernier Postgresql permet:SET LOCAL variable value
Eugen Konkov
1
Ce sont pour les paramètres de configuration - c'est une chose totalement différente @EugenKonkov
Evan Carroll
1

Pour le deuxième exemple, vous n'avez pas besoin d'une variable (ni dans MySQL ni dans Postgres):

select id 
from client 
where platformID in (select id 
                     from platform 
                     where bios like '%INTEL%');

N'ayez pas peur des sous-requêtes, l'optimiseur de requêtes de Postgres est beaucoup plus intelligent que MySQL.

Si ce qui précède est trop lent, sa réécriture dans une existsrequête est parfois plus rapide:

select c.id 
from client c
where exists  (select 1
               from platform p
               where c.platformID = p.id
                 and bios like '%INTEL%');
un cheval sans nom
la source