Cómo declarar una variable en una consulta PostgreSQL
¿Cómo declaro una variable para su uso en una consulta PostgreSQL 8.3?
En MS SQL Server puedo hacer esto:
DECLARE @myvar INT
SET @myvar = 5
SELECT *
FROM somewhere
WHERE something = @myvar
¿Cómo hago lo mismo en PostgreSQL? De acuerdo con la documentación, las variables se declaran simplemente como " name type;", pero esto me da un error de sintaxis:
myvar INTEGER;
Podría alguien darme un ejemplo de la sintaxis correcta?
8 answers
No existe tal característica en PostgreSQL. Solo puede hacerlo en pl / PgSQL (u otro pl/*), pero no en SQL simple.
Una excepción es la consulta WITH ()
que puede funcionar como una variable, o incluso tuple
de variables. Permite devolver una tabla de valores temporales.
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) > ...;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-09 12:39:18
Logré el mismo objetivo usando un WITH
clause, no es ni de lejos tan elegante pero puede hacer lo mismo. Aunque para este ejemplo es realmente exagerado. Tampoco recomiendo particularmente esto.
WITH myconstants (var1, var2) as (
values (5, 'foo')
)
SELECT *
FROM somewhere, myconstants
WHERE something = var1
OR something_else = var2;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 18:51:29
También puedes probar esto en 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;
Lo anterior requiere Postgres 9.0 o posterior.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-15 15:38:31
Depende de su cliente.
Sin embargo, si estás usando el cliente psql, entonces puedes usar lo siguiente:
my_db=> \set myvar 5
my_db=> SELECT :myvar + 1 AS my_var_plus_1;
my_var_plus_1
---------------
6
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-29 02:44:58
Configuración dinámica
Puede "abusar" de la configuración dinámica para esto:
-- 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;
Los ajustes de configuración son siempre valores varchar, por lo que debe enviarlos al tipo de datos correcto cuando los use. Esto funciona con cualquier cliente SQL mientras que \set
solo funciona en psql
Lo anterior requiere Postgres 9.2 o posterior.
Para versiones anteriores, la variable tenía que ser declarada en postgresql.conf
antes de ser utilizada, por lo que limitaba un poco su usabilidad. En realidad no la variable completamente, pero la "clase" de configuración que es esencialmente el prefijo. Pero una vez definido el prefijo, cualquier variable podría ser utilizada sin cambiar postgresql.conf
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-11 09:50:48
Usando una tabla Temporal fuera de pl / PgSQL
Fuera del uso de pl/pgsql u otro lenguaje pl/* como se sugiere, esta es la única otra posibilidad que se me ocurrió.
begin;
select 5::int as var into temp table myvar;
select *
from somewhere s, myvar v
where s.something = v.var;
commit;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-01 18:16:19
Quiero proponer una mejora a la respuesta de @DarioBarrionuevo, para hacerlo más simple aprovechando las tablas temporales.
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;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:34
Aquí hay un ejemplo usando PREPARE declaraciones. Todavía no puedes usar ?
, pero puedes usar $n
notación:
PREPARE foo(integer) AS
SELECT *
FROM somewhere
WHERE something = $1;
EXECUTE foo(5);
DEALLOCATE foo;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-30 16:54:03