2009-09-29 11 views
112

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

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

DECLARE @myvar INT 
SET @myvar = 5 

SELECT * 
FROM somewhere 
WHERE something = @myvar 

Как сделать то же самое в PostgreSQL? Согласно документации, переменные объявляются просто как «типа имени;», но это дает мне ошибку синтаксиса:

myvar INTEGER; 

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

+2

Это может быть сделано всего PostgreSQL. См. Ответ на этот вопрос: http://stackoverflow.com/questions/766657/how-do-you-use-variables-in-a-simple-postgresql-script#6990059 –

+2

У этого ответного ответа есть лучшие ответы: http://stackoverflow.com/questions/13316773/is-there-a-way-to-define-a-named-constant-in-a-postgresql-query –

ответ

52

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

+13

Никто не хочет объяснять * почему * этот ответ устарел? – simonlchilds

+20

Итак, как вы это делаете в pl/PgSQL ?! – stone

19

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

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

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

Вы также можете попробовать это в 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 или более поздней версии.

+0

Оператор DO был добавлен в PostgreSQL 9.0 и не работает в формате 8.3. – Johny

+7

Используйте CREATE TEMPORARY TABLE или CREATE TEMP TABLE, а не CREATE TABLE. Но иначе отлично. –

32

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

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

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

'\ set' должен быть строчным. – deluan

115

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

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

Это отлично подходит для большинства случаев, когда вам нужны переменные. Однако, если вы хотите использовать переменную для LIMIT (которая не может содержать переменные), то вы хотите использовать '\ set', как это было предложено в ответе Шахриар Агаджани. – cimmanon

+1

Это идеальный вариант, когда у меня есть сценарий миграции, где я хочу импортировать некоторые реляционные данные. Очевидно, я не буду знать идентификатор последовательности, данные реляционных данных. – Relequestual

+2

Я просто пробовал этот подход и нашел, пожалуй, лучший способ: 'JOIN myconstants ON true ', а затем не нужно делать подвыбор. – vektor

6

Я хочу предложить усовершенствование к @DarioBarrionuevo's 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; 
+0

Хорошее решение для решения блока DO не может вернуть набор данных! – CodeFarmer

26

Dynamic Config

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

настройки
-- 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; 

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

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

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

+0

может это 'set session my.vars.id' = '1'; быть специфичным к трансекции ??? –

+1

@BrijanElwadhi: да, это транзакционно. –

+0

спасибо .. действительно помог мне :) –

0

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

PREPARE foo(integer) AS 
    SELECT * 
    FROM somewhere 
    WHERE something = $1; 
EXECUTE foo(5); 
DEALLOCATE foo; 
Смежные вопросы