我正在尝试在 AWS 中自动创建用户。但是,如果我只编写用户创建脚本,如果重新运行并且用户已经存在,它们将会失败。
我在 AWS Redshift 工作。
我很想能够做类似的事情
CREATE USER IF NOT EXISTS usr_name
password '<random_secure_password>'
NOCREATEDB
NOCREATEUSER
;
然而这似乎不可能。
然后我找到了 CASE 语句,但 CASE 语句似乎也不适合我。
即
CASE WHEN
SELECT count(*) FROM pg_user WHERE usename = 'usr_name' = 0
THEN
CREATE USER usr_name
password '<random_secure_password>'
NOCREATEDB
NOCREATEUSER
END
这行得通吗? (不是超级用户,所以我无法自己测试)
如果没有,有什么想法吗?任何帮助,提前致谢。
如果您使用 psql,您可以使用
\gexec
元命令:
\t on
BEGIN;
SELECT CASE WHEN (SELECT count(*) FROM pg_user WHERE usename = 'nonesuch') = 0
THEN 'CREATE USER nonesuch PASSWORD DISABLE'
END
\gexec
SELECT CASE WHEN (SELECT count(*) FROM pg_user WHERE usename = 'nonesuch') = 0
THEN 'CREATE USER nonesuch PASSWORD DISABLE'
ELSE 'SELECT \'user already exists, doing nothing\''
END
\gexec
ROLLBACK;
结果:
BEGIN
CREATE USER
user already exists, doing nothing
ROLLBACK
https://www.postgresql.org/docs/9.6/app-psql.html(请注意,您不能像示例中那样使用
format()
,因为它未在 Redshift 中实现)
据我所知,Redshift(目前)没有任何机制可以做到这一点,并且向更多云模型的转变让我合作过的许多公司都感到困惑。 许多本地数据库都希望有自己的操作世界,所有事情都必须通过 SQL 在数据库内部完成,无论这些是否是数据操作。 我称之为“通用数据库”模型。 Redshift 是 AWS 云解决方案更大生态系统的一部分,其中许多管理/管理/灵活性操作最好在云层完成,而不是在数据库中完成。 “数据的数据库”模型。
您没有解释为什么需要测试用户是否存在并在用户不存在时创建它们,或者为什么要在 SQL 中完成此决定。 我确实预计会有一定程度的“我们过去就是这样做的”。 您想要做的可以是 Lambda(带或不带)Step Function,很可能可以在您的 ETL 解决方案中完成,甚至可以编写为 bash 脚本。 您想要做的事情实际上很简单,我建议您考虑将其作为解决方案级别架构的一部分 - 而不是作为点数据库操作。
现在您可能会问“如果这很容易,为什么 Redshift 做不到?” 公平的一点,我已经被问过很多次了。 一个答案是 Redshift 是一个基于云的大数据分析仓库,因此它被设计为在这种环境下运行。 另一个答案是,如果足够多的大客户表现出需求并要求该功能,那么就会添加该功能(AWS 确实会做出反应以满足一般需求)。 请记住,有数千个地方可以添加新的 SQL 命令选项,但所有这些选项都不会添加到 Redshift - 事实上,几乎每个数据库都会经常发出这种类型的增强请求。
我的建议是退后一步,看看您的用户和用户权限管理应如何适用于您的解决方案,而不仅仅是数据库。 然后转移到在解决方案的适当层(无论您决定是什么)管理这些权限的体系结构。 Redshift用户可以与IAM集成,IAM可用于控制对其他系统和其他数据库的访问。 我知道这种变化需要工作和时间才能完成(并且可能会影响组织角色),因此在此之前我会查看您现有的数据库控制系统(ETL、真空/分析启动器、指标收集器等),看看哪些可以满足您的近期需求。
创建一个以用户名作为参数的存储过程,并在其中进行检查。您可以在部署步骤中调用此存储过程。 仅数据库创建不能在块内完成。可以在存储过程中创建用户。
CREATE OR REPLACE PROCEDURE sp_create_user(i_username varchar)
AS $$
DECLARE
t_user_count BIGINT;
BEGIN
SELECT count(1)
INTO t_user_count
FROM pg_user WHERE LOWER(usename) = 'username';
IF t_user_count>0 THEN
RAISE INFO 'User already exists';
ELSE
CREATE USER username WITH PASSWORD 'password' NOCREATEDB NOCREATEUSER;
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE EXCEPTION '[Error while creating user: username] Exception: %', SQLERRM;
END;
$$
LANGUAGE plpgsql;
我非常喜欢@andrea-reina的回答。不幸的是,我在部署期间运行 Redshift 语句的便捷工具是 Redshift Data API,它不接受
\gexec
。 (更准确地说,我正在使用 Terraform 的 aws_redshiftdata_statement。)
对我有用的,作为 Redshift Data API 的单个“语句”是这样的:
DROP USER IF EXISTS my_user;
CREATE USER my_user WITH PASSWORD DISABLE IN GROUP fancy_group
这只适用于我,因为我的用户没有获得任何授予,并且不(也不会)拥有任何对象。