EMP*_*EMP 205 sql postgresql postgresql-8.3
如何声明变量以用于PostgreSQL 8.3查询?
在MS SQL Server中,我可以这样做:
DECLARE @myvar INT
SET @myvar = 5
SELECT *
FROM somewhere
WHERE something = @myvar
Run Code Online (Sandbox Code Playgroud)
我如何在PostgreSQL中做同样的事情?根据文档变量被简单地声明为"名称类型;",但这给了我一个语法错误:
myvar INTEGER;
Run Code Online (Sandbox Code Playgroud)
有人能给我一个正确语法的例子吗?
fei*_*i0x 196
我通过使用一个WITH条款完成了同样的目标,它没有那么优雅,但可以做同样的事情.虽然这个例子真的有点过分.我也不特别推荐这个.
WITH myconstants (var1, var2) as (
values (5, 'foo')
)
SELECT *
FROM somewhere, myconstants
WHERE something = var1
OR something_else = var2;
Run Code Online (Sandbox Code Playgroud)
小智 94
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) > ...;
Run Code Online (Sandbox Code Playgroud)
Dar*_*evo 74
你也可以在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;
Run Code Online (Sandbox Code Playgroud)
以上要求Postgres 9.0或更高版本.
a_h*_*ame 49
你可以"滥用"动态配置设置:
-- 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;
Run Code Online (Sandbox Code Playgroud)
配置设置始终是varchar值,因此在使用它们时需要将它们转换为正确的数据类型.这适用于任何SQL客户端,而\set只适用于psql
以上要求Postgres 9.2或更高版本.
对于以前的版本,变量必须在使用postgresql.conf之前声明,因此它在某种程度上限制了它的可用性.实际上不是变量完全,但配置"类"本质上是前缀.但是一旦定义了前缀,就可以使用任何变量而无需更改postgresql.conf
小智 47
这取决于您的客户.
但是,如果您使用的是psql客户端,则可以使用以下命令:
my_db=> \set myvar 5
my_db=> SELECT :myvar + 1 AS my_var_plus_1;
my_var_plus_1
---------------
6
Run Code Online (Sandbox Code Playgroud)
Man*_*ngo 21
正如您从其他答案中了解到的那样,PostgreSQL 在直接 SQL 中没有这种机制,尽管您现在可以使用匿名块。但是,您可以使用公用表表达式 (CTE) 执行类似的操作:
\nWITH vars AS (\n SELECT 5 AS myvar\n)\nSELECT *\nFROM somewhere,vars\nWHERE something = vars.myvar;\nRun Code Online (Sandbox Code Playgroud)\n当然,您可以拥有任意多个变量,并且它们也可以导出。例如:
\nWITH vars AS (\n SELECT\n \'1980-01-01\'::date AS start,\n \'1999-12-31\'::date AS end,\n (SELECT avg(height) FROM customers) AS avg_height\n)\nSELECT *\nFROM customers,vars\nWHERE (dob BETWEEN vars.start AND vars.end) AND height<vars.avg_height;\nRun Code Online (Sandbox Code Playgroud)\n其过程是:
\nSELECT(在 Oracle 中,您需要包含FROM DUAL)。CROSS JOIN语法,但较旧的逗号语法可读性稍好一些。SELECT条款中可能出现的问题。我使用了 PostgreSQL\xe2\x80\x99s 较短的语法,但您可以使用更正式的CAST(\'1980-01-01\' AS date)跨方言兼容性。通常,您希望避免交叉联接,但由于您\xe2\x80\x99 仅交叉联接单个行,因此这会产生简单地使用可变数据扩大表的效果。
\nvars.在许多情况下,如果名称与其他表中的名称不冲突,则不需要包含前缀。我把它放在这里是为了明确这一点。
此外,您还可以继续添加更多 CTE。
\n这也适用于支持变量的所有当前版本的 MSSQL 和 MySQL,以及不支持变量的 SQLite,以及支持变量和不支持变量的 Oracle。
\n小智 20
除了建议使用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;
Run Code Online (Sandbox Code Playgroud)
blu*_*ish 11
我想提议对@ DarioBarrionuevo的答案进行改进,以便更简单地利用临时表.
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;
Run Code Online (Sandbox Code Playgroud)
The*_*der 10
在 DBeaver 中,您可以像在代码中一样在查询中使用参数,因此这将起作用:
SELECT *
FROM somewhere
WHERE something = :myvar
Run Code Online (Sandbox Code Playgroud)
当您运行查询时,DBeaver 将询问您 :myvar 的值并运行查询。
此解决方案基于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)
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用SELECT * FROM constant_name代替TABLE constant_name对其他不同于postgresql的查询语言无效的语言。
这是使用PREPARE语句的示例。您仍然不能使用?,但是可以使用$n符号:
PREPARE foo(integer) AS
SELECT *
FROM somewhere
WHERE something = $1;
EXECUTE foo(5);
DEALLOCATE foo;
Run Code Online (Sandbox Code Playgroud)
小智 5
的确,没有一种生动明确的方法来声明单值变量,您可以做的是
with myVar as (select "any value really")
Run Code Online (Sandbox Code Playgroud)
然后,要访问此构造中存储的值,您需要
(select * from myVar)
Run Code Online (Sandbox Code Playgroud)
例如
with var as (select 123)
... where id = (select * from var)
Run Code Online (Sandbox Code Playgroud)
您可以求助于工具的特殊功能。就像 DBeaver 自己的专有语法:
@set name = 'me'
SELECT :name;
SELECT ${name};
DELETE FROM book b
WHERE b.author_id IN (SELECT a.id FROM author AS a WHERE a.name = :name);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
307171 次 |
| 最近记录: |