【问题标题】:Is there a simpler way to get the argument type list for a snowflake procedure?有没有更简单的方法来获取雪花过程的参数类型列表?
【发布时间】:2022-11-19 13:07:13
【问题描述】:

我需要将克隆后雪花程序的所有权转移到新角色。

为此,我使用了一个处理 database.information_schema.xxxx 视图中所有对象的过程。

虽然过程有问题,SHOW PROCEDURE 有一列将过程签名显示为参数类型,但 information_schema.procedures 视图显示实际参数名称及其参数类型,如果传递给 GRANT 命令则不起作用- 授予仅需要参数类型签名,而不是参数名称:/

显示过程参数 => PROCEDURE_NAME(VARCHAR) 返回 VARCHAR INFORMATION_SCHEMA.PROCEDURES.ARGUMENT_SIGNATURE => PROCEDURE_NAME(P_PARAM1 VARCHAR)

我最终想出了这个很有趣,但感觉相当复杂的问题是 - 我错过了一个更简单的方法吗?

SELECT procedure_name
     , concat('(',listagg(argtype, '') within group (order by argindex)) cleanArgTypes
  FROM (SELECT procedure_name
             , argument_signature
             , lf.index argindex
             , lf.value argtype
          FROM rock_dev_test_1.information_schema.procedures
             , lateral flatten(input=>split(decode(argument_signature
                                                  ,'()','( )'
                                                       ,argument_signature
                                                  ),' ')
                              ,outer=>true) lf
          WHERE lf.index/2 != round(lf.index/2)
        )
GROUP BY procedure_name
         , argument_signature
ORDER by 1,2;

cleanArgTypes => (VARCHAR)

这将过度特定的 argument_signature 使用空格作为分隔符将其拆分为一个数组,然后将返回集横向展平为行,丢弃参数名称(始终在偶数索引处),然后按参数名称和签名分组并使用 ListAgg 放置参数参数类型变回字符串。

那个()中的小皱纹不起作用,所以必须转移到()

虽然我喜欢涉足 Snowflakes 的一些半结构化功能,如果有更简单的方法,我宁愿使用它!

【问题讨论】:

  • 抱歉,我没有足够的声誉来支持答案,希望另一位读者会……感谢您的输入,总是很高兴看到替代方法,特别是如果它提供更紧凑、更整洁或更高效的代码。一位同事使用带有 RegExp 的 UDF 来解决这个问题,并且由于我需要将它重用于函数,这就是 atm 采用的方法。

标签: stored-procedures snowflake-cloud-data-platform


【解决方案1】:

大部分代码相同,但不需要嵌套,我从 arg_sig(输入)交换为使用拆分的 SEQ,但大部分仍然相同:

SELECT p.procedure_name
    ,'( '|| listagg(split_part(trim(t.value),' ',2), ', ') within group (order by t.index) || ')' as out
FROM information_schema.procedures as p
    ,table(split_to_table(substring(p.argument_signature, 2,length(p.argument_signature)-2), ',')) t
group by 1, t.seq;

对于我的堆栈溢出模式中的玩具程序,我得到:

PROCEDURE_NAME OUT
DATE_HANDLER ( DATE)
TODAYS_DELIVERY_AMOUNT ( VARCHAR)
ABC ( TIMESTAMP_NTZ, TIMESTAMP_NTZ, VARCHAR)
ABC_DAILY ( )
STRING_HANDLER ( VARCHAR)

【讨论】:

  • 不确定您的方法是否可以处理重载过程,但我确实更喜欢您处理输入字符串的方式,感觉更清晰,更有效地分解为“name argtype”然后获取 argtype。我错过了一些东西,我认为将数组转换为行并连接到自身需要横向展平,但看起来并非如此。?
  • @MattPrince 简单的方法就是测试。但确实是因为 t.seq 是展平的行输入。因此,每个 inout 行都是分开的。
  • 啊,我明白了,split_to_table 是做横向展平的表函数,seq 是输入行,索引序列内生成的顺序或行。我现在明白了,在那种情况下,如果我能赞成这个答案,我会的,它是一个更清洁、更严格的实施。
【解决方案2】:

我认为没有内置的方法可以做到这一点。这是另一种方法:

with A as
(
select PROCEDURE_NAME, split(replace(trim(ARGUMENT_SIGNATURE, '()'), ','), ' ') ARGS
      ,ARGUMENT_SIGNATURE
from   test.information_schema.procedures P
)
select PROCEDURE_NAME
       ,listagg(VALUE::string, ',') as ARGS
from A, table(flatten(ARGS))
where index % 2 = 1
group by PROCEDURE_NAME
;

您还可以在 show 命令之后使用结果扫描来获取单个字符串中的过程名称和参数签名:

show procedures;
select split("arguments", ')')[0] || ')' as SIGNATURE from table(result_scan(last_query_id()));

【讨论】:

  • 我认为您也丢失了重载过程,但除此之外,我认为第一个是有效的替代方法,第二个是更好的替代方法。最初我回避使用 show,/result scan 但后来不得不使用它来转移似乎没有匹配信息模式视图的任务的所有权。
【解决方案3】:

我写这篇文章是为了从信息模式中提取具有正确格式参数签名的过程列表,结合使用 SPLIT 拆分字符串,使用 LATERAL FLATTEN 将每个值放在单独的行中,过滤以仅获取使用的数据类型INDEX,然后用 LISTAGG 重新分组。也不需要子查询。

SELECT PROCEDURE_SCHEMA || '.' || PROCEDURE_NAME || '(' ||
REPLACE(LISTAGG(C.Value,' ') WITHIN GROUP (ORDER BY C.INDEX),'(','') AS "Procedure"
FROM INFORMATION_SCHEMA.PROCEDURES,
LATERAL FLATTEN (INPUT => SPLIT(ARGUMENT_SIGNATURE,' ')) C
WHERE INDEX % 2 = 1 OR ARGUMENT_SIGNATURE = '()'
GROUP BY PROCEDURE_SCHEMA, PROCEDURE_NAME, ARGUMENT_SIGNATURE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 2020-02-15
    • 1970-01-01
    • 2011-05-21
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 2019-06-11
    相关资源
    最近更新 更多