Подтвердить что ты не робот

Как объявить переменную в запросе PostgreSQL

Как объявить переменную для использования в запросе PostgreSQL 8.3?

В MS SQL Server я могу это сделать:

DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

Как мне сделать то же самое в PostgreSQL? В соответствии с документацией переменные объявляются просто как "name type;", но это дает мне синтаксическую ошибку:

myvar INTEGER;

Может ли кто-нибудь дать мне пример правильного синтаксиса?

4b9b3361

Ответ 1

В PostgreSQL такой функции нет. Вы можете сделать это только в pl/PgSQL (или другом pl/*), но не в простом SQL.

Исключением является запрос WITH() который может работать как переменная или даже как tuple переменных. Это позволяет вам возвращать таблицу временных значений.

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) > ...;

Ответ 2

Я достиг той же цели, используя предложение WITH, оно далеко не так элегантно, но может сделать то же самое. Хотя для этого примера это действительно перебор. Я также не особо рекомендую это.

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

Ответ 3

Вы также можете попробовать это в 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;

Для этого требуется Postgres 9.0 или новее.

Ответ 4

Это зависит от вашего клиента.

Однако, если вы используете клиент PSQL, то вы можете использовать следующее:

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

Если вы используете текстовые переменные, вам нужно заключить в кавычки.

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

Ответ 5

Настройки динамической конфигурации

Вы можете "злоупотребить" настройками динамической конфигурации для этого:

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

Настройки конфигурации всегда являются значениями varchar, поэтому вам нужно привести их к правильному типу данных при их использовании. Это работает с любым клиентом SQL, тогда как \set работает только в psql

Выше требуется Postgres 9.2 или более поздняя версия.

Для предыдущих версий переменная должна была быть объявлена в postgresql.conf перед использованием, поэтому она несколько ограничивала ее удобство использования. На самом деле не переменная полностью, а конфиг "класс", который по сути является префиксом. Но как только префикс был определен, любая переменная могла использоваться без изменения postgresql.conf

Ответ 6

Использование таблицы Temp вне pl/PgSQL

Вне использования pl/pgsql или другого языка pl/*, как это было предложено, это единственная возможность, о которой я мог подумать.

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

Ответ 7

Я хочу предложить улучшение @DarioBarrionuevo answer, чтобы упростить использование временных таблиц.

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;

Ответ 8

Это решение основано на предложении fei0x, но имеет те преимущества, что нет необходимости присоединять список значений констант в запросе, и константы могут быть легко перечислены в начале запроса. Это также работает в рекурсивных запросах.

По сути, каждая константа - это таблица с одним значением, объявленная в предложении WITH, которая затем может быть вызвана в любой части оставшейся части запроса.

  • Базовый пример с двумя константами:
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)

В качестве альтернативы вы можете использовать SELECT * FROM constant_name вместо TABLE constant_name что может быть недопустимо для других языков запросов, отличных от postgresql.

Ответ 9

Вот пример использования операторов PREPARE. Вы все еще не можете использовать ? , но вы можете использовать обозначение $n:

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

Ответ 10

Правда, не существует яркого и однозначного способа объявить переменную с одним значением, что вы можете сделать, это

with myVar as (select "any value really")

затем, чтобы получить доступ к значению, хранящемуся в этой конструкции, вы делаете

(select * from myVar)

например

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