使用 Snowflake Scripting 的 Snowflake 存储过程 - 遍历结果并使用结果更改用户

Snowflake stored procedure using Snowflake Scripting - Iterate through result and ALTER USER with result

我正在尝试创建一个 stored procedure with Snowflake Scripting 专门用于查询用户 table,然后遍历结果并更改这些用户。

这是我目前的情况:

create or replace procedure TEST_PROCEDURE()
  returns varchar
  language sql
  as
  $$
    declare
      c1 CURSOR for SELECT 'USERNAME@EMAIL.COM' AS NAME;
      user_name varchar;
    begin
      for record in c1 do
         user_name := record.name;
         ALTER USER user_name SET DEFAULT_ROLE = 'REPORTER', DEFAULT_WAREHOUSE = 'REPORTING_WH_L';
       end for;
      return user_name;
    end;
  $$
;

当我 运行 存储过程时,出现以下错误:

Uncaught exception of type 'STATEMENT_ERROR' on line 8 at position 9: SQL compilation error: User 'USER_NAME' does not exist or not authorized.

我更改了 USERNAME@EMAIL.COM 只是为了这个问题它正在查询 table 并返回有效的 Snowflake 用户名。

查询历史显示,在 ALTER USER 命令中,它没有用游标的结果替换 user_name。

关于如何解决这个问题有什么想法吗?

查看帮助的 using variables 部分,在使用循环变量的示例中,变量名称在 SQL

中大写
insert into names (v) values (:PV_NAME);

虽然“脚本”部分是小写,但它的前缀也是 :

create procedure duplicate_name(pv_name varchar)
returns varchar
language sql
as
$$
    begin
        declare
            pv_name varchar;
        begin
            pv_name := 'middle block variable';
            declare
                pv_name varchar;
            begin
                pv_name := 'innermost block variable';
                insert into names (v) values (:PV_NAME);
            end;
            -- Because the innermost and middle blocks have separate variables
            -- named "pv_name", the INSERT below inserts the value
            -- 'middle block variable'.
            insert into names (v) values (:PV_NAME);
        end;
        -- This inserts the value of the input parameter.
        insert into names (v) values (:PV_NAME);
        return 'Completed.';
    end;
$$
;

使用EXECUTE IMMEDIATE:

create or replace procedure TEST_PROCEDURE()
  returns varchar
  language sql
  as
  $$
  declare
      c1 CURSOR for SELECT '"USERNAME@EMAIL.COM"' AS NAME;
      SQL STRING;
    begin
      for record in c1 do
         SQL := 'ALTER USER '|| record.name ||  ' SET DEFAULT_ROLE = ''REPORTER'', DEFAULT_WAREHOUSE = ''REPORTING_WH_L''';
        
         EXECUTE IMMEDIATE :SQL;
       end for;
      return :SQL;
    end;
$$;

CALL TEST_PROCEDURE();
-- ALTER USER "USERNAME@EMAIL.COM" SET DEFAULT_ROLE = 'REPORTER', DEFAULT_WAREHOUSE = 'REPORTING_WH_L'

您需要使用 IDENTIFIER 并在 user_name 变量前添加冒号。

所以从

ALTER USER user_name 
  SET DEFAULT_ROLE = 'REPORTER', 
      DEFAULT_WAREHOUSE = 'REPORTING_WH_L';

ALTER USER IDENTIFIER(:user_name) 
  SET DEFAULT_ROLE = 'REPORTER', 
      DEFAULT_WAREHOUSE = 'REPORTING_WH_L';

我已经测试过了,它对我有用。