如何在psql中使用脚本变量?

时间:2020-03-05 18:45:41  来源:igfitidea点击:

在MS SQL Server中,我创建了脚本以使用可自定义的变量:

DECLARE @somevariable int  
SELECT @somevariable = -1

INSERT INTO foo VALUES ( @somevariable )

然后,我将在运行时更改@somevariable的值,具体取决于我在特定情况下所需的值。由于它位于脚本的顶部,因此很容易看到和记住。

我如何对PostgreSQL客户端psql做同样的事情?

解决方案

回答

FWIW,真正的问题是我在\ set命令的末尾添加了分号:

\set owner_password 'thepassword';

分号被解释为变量中的实际字符:

\echo :owner_password
  thepassword;

因此,当我尝试使用它时:

CREATE ROLE myrole LOGIN UNENCRYPTED PASSWORD :owner_password NOINHERIT CREATEDB CREATEROLE VALID UNTIL 'infinity';

...我懂了:

CREATE ROLE myrole LOGIN UNENCRYPTED PASSWORD thepassword; NOINHERIT CREATEDB CREATEROLE VALID UNTIL 'infinity';

这不仅无法在文字周围设置引号,而且将命令分为两部分(第二部分无效,因为它以" NOINHERIT"开头)。

这个故事的寓意:PostgreSQL"变量"实际上是文本扩展中使用的宏,而不是真正的值。我敢肯定这会派上用场,但起初是很棘手的。

回答

关于PSQL变量的最后一句话:

  • 如果将它们用SQL语句括在单引号中,则它们不会扩展。因此,这是行不通的:
SELECT * FROM foo WHERE bar = ':myvariable'
  • 要在SQL语句中扩展为字符串文字,我们必须在变量集中包括引号。但是,变量值已经必须用引号引起来,这意味着我们需要第二组引号,并且必须对内部引号进行转义。因此,我们需要:
\set myvariable '\'somestring\''  
SELECT * FROM foo WHERE bar = :myvariable

编辑:从PostgreSQL 9.1开始,我们可以改写:

\set myvariable somestring
SELECT * FROM foo WHERE bar = :'myvariable'

回答

我们需要使用一种过程语言,例如PL / pgSQL,而不是SQL proc语言。
在PL / pgSQL中,我们可以在SQL语句中直接使用vars。
对于单引号,可以使用引号文字函数。

回答

Postgres变量是通过\ set命令创建的,例如...

\set myvariable value

...,然后可以替换为...

SELECT * FROM :myvariable.table1;

... 或者 ...

SELECT * FROM table1 WHERE :myvariable IS NULL;

...,但是,如果我们要将变量用作条件字符串查询中的值,例如...

SELECT * FROM table1 WHERE column1 = ':myvariable';

...则我们需要在变量本身中包含引号,因为上述内容将无法正常工作。而是这样定义变量...

\set myvariable 'value'

但是,如果像我一样,我们遇到了要从现有变量中创建字符串的情况,我发现诀窍是...

\set quoted_myvariable '\'' :myvariable '\''

现在,我们同时具有相同字符串的带引号和不带引号的变量!而且你可以做这样的事情....

INSERT INTO :myvariable.table1 SELECT * FROM table2 WHERE column1 = :quoted_myvariable;