如何在 PostgreSQL 查询中声明变量

新手上路,请多包涵

如何声明用于 PostgreSQL 8.3 查询的变量?

在 MS SQL Server 中,我可以这样做:

 DECLARE @myvar INT
SET @myvar = 5

SELECT *
FROM somewhere
WHERE something = @myvar

我如何在 PostgreSQL 中做同样的事情?根据文档,变量被简单地声明为“名称类型;”,但这给了我一个语法错误:

 myvar INTEGER;

有人可以给我一个正确语法的例子吗?

原文由 EMP 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.8k
2 个回答

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

原文由 user80168 发布,翻译遵循 CC BY-SA 4.0 许可协议

正如您将从其他答案中收集到的那样,PostgreSQL 在直接 SQL 中没有这种机制,尽管您现在可以使用 匿名块。但是,您可以使用公用表表达式 (CTE) 执行类似的操作:

 WITH vars AS (
    SELECT 5 AS myvar
)
SELECT *
FROM somewhere,vars
WHERE something = vars.myvar;

当然,您可以拥有任意数量的变量,也可以导出它们。例如:

 WITH vars AS (
    SELECT
        '1980-01-01'::date AS start,
        '1999-12-31'::date AS end,
        (SELECT avg(height) FROM customers) AS avg_height
)
SELECT *
FROM customers,vars
WHERE (dob BETWEEN vars.start AND vars.end) AND height<vars.avg_height;

过程是:

  • 在没有表的情况下使用 SELECT 生成单行 cte(在 Oracle 中,您需要包括 FROM DUAL )。
  • 将 cte 与另一个表交叉连接。虽然有 CROSS JOIN 语法,但旧的逗号语法更易读。
  • 请注意,我已经确定了日期以避免 SELECT 子句中可能出现的问题。我使用了 PostgreSQL 的较短语法,但您可以使用更正式的 CAST('1980-01-01' AS date) 来实现跨方言兼容性。

通常,您希望避免交叉连接,但由于您只交叉连接单行,这具有简单地用可变数据扩大表的效果。

在许多情况下,如果名称与其他表中的名称不冲突,则不需要包含 vars. 前缀。我把它包括在这里是为了说明这一点。

此外,您可以继续添加更多 CTE。

这也适用于所有当前版本的 MSSQL 和 MySQL,它们支持变量,以及不支持变量的 SQLite,以及支持和不支持的 Oracle。

原文由 Manngo 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进