如何将select语句输出存储到变量thro PSQL(postgresql)

时间:2014-01-31 20:34:42

标签: sql postgresql date amazon-redshift

我正在亚马逊云环境(Redshift)上探索postgresql数据库。我想使用\set命令将值存储到变量中,如下所示。但我无法做到这一点。

我想将“current_date + 90”的输出存储到一个变量中,并在创建用户帐户时将其设置为USER:

postgres=# select current_date;
    date
------------
 2014-01-31
(1 row)

postgres=#
postgres=# select current_date+90;
  ?column?
------------
 2014-05-01
(1 row)

我想在上面的日期休息如下:

alter user <user_name> with password <new_passowrd> VALID UNTIL 'current_date+90';

---下面是我对回复我的人的回复(他已经让我使用DO $$ ..)

嗨,

感谢您的时间并回复我的帖子。

我在psql提示符中调用.sql文件,如下所示:

psql -h <host_name> -U <user_name> -d <db_name> -p <port> -a -f c:\redshift\scripts\psql-alter-user.sql --log-file c:\testlogs\alter-user.log -v v_username=test_user3 -v v_password='Today123#'

(ii)下面是脚本内容(psql-alter-user.sql)

\echo :v_username
\echo :v_password

\set v_date 'select current_timestamp+90;'
:v_date

alter user :v_username with password :v_password valid until ':v_date';

\q

(iii)执行此脚本后,下面是我的日志文件:

********* QUERY **********
select current_timestamp+90;
**************************

           ?column?            
-------------------------------
 2014-05-01 23:40:47.856804+00
(1 row)

********* QUERY **********
alter user test_user3 with password 'Today123#' valid until ':v_date';
**************************

我无法将实际值(2014-05-01 23:40:47.856804 + 00)作为:ALTER USER语法中的v_date。请你帮助我好吗。这对我目前的项目有很大帮助。

谢谢 Keavan

3 个答案:

答案 0 :(得分:1)

你不能完全在Redshift中这样做,因为在PostgreSQL中实现它的唯一方法是在EXECUTE函数或PL/PgSQL块中使用动态SQL - DO。你没有在Redshift中使用PL / pgSQL。

您必须做的是让客户端脚本读取current_timestamp+90的值,将其存储在变量中,并从结果生成它发送给服务器的ALTER语句。 / p>

如果您要这样做,为什么不让客户端生成到期时间,而不是询问服务器?如果您使用的是shell脚本,例如:

password="fr'ed"
expires=`date -I -d '+ 90 days'`
psql -c "alter user test_user3 with password '${password//\'/''}' valid until '${expires} 00:00:00';"

请注意$password中单引号加倍。

答案 1 :(得分:1)

可能有一个丑陋的技巧(可从PostgreSQL 9.3获得干净的解决方案)

postgres=# \set myvar `psql -At postgres -c "select current_date+90;"`
postgres=# \set user tom
postgres=# \set password somepassword

postgres=# create role tom login;
CREATE ROLE
Time: 45.915 ms
postgres=# alter user :user with password :'password' valid until :'myvar';
ALTER ROLE
Time: 8.599 ms

postgres=# \du tom
                            List of roles
 Role name │                 Attributes                  │ Member of 
───────────┼─────────────────────────────────────────────┼───────────
 tom       │ Password valid until 2014-05-02 00:00:00+02 │ {}

现在我不确定,如果Redshift中有安全转义的psql变量,因为它是Postgres的相对较旧的分支。克雷格林格解决方案可能只有一个并且是正确的。

答案 2 :(得分:0)

PSQL的最新版本具有/gset元命令,可以很好地处理此问题。

Postgres current version psql documentation

\set :v_username tom
\echo :v_username
-- tom

-- notice the lack of a ';'
select current_date + 90 v_date  \gset 

\echo :v_date
-- 2019-05-22

alter user :user valid until :'v_date';

我发现这对于将轻量级过程作为变量存储在我的.psqlrc文件中非常方便。

请注意,尽管在alter user语句中使用日期作为字符串,但是在具有日期函数的更通用查询中的用法通常需要显式转换为:: date,例如:

select date_trunc('year',:v_date);
-- ERROR:  function date_trunc("unknown", integer) does not exist

select date_trunc('year',:'v_date'::date);
┌─────────────────────┐
│     date_trunc      │
├─────────────────────┤
│ 2019-01-01 00:00:00 │
└─────────────────────┘