有哪些选项可用于获取 Snowflake 中的主键列名称?

Posted

技术标签:

【中文标题】有哪些选项可用于获取 Snowflake 中的主键列名称?【英文标题】:What are the options available to get Primary Key Column Names in Snowflake? 【发布时间】:2021-07-15 13:41:32 【问题描述】:

我需要同时获取所有主键、它们的父表名、列名和模式名。 我正在使用 INFORMATION_SCHEMA 获取所有元数据,SHOW PRIMARY KEYS/DESCRIBE TABLE 可以完成这项工作,但这里不是一个选项。

需要类似于 SELECT *FROM DB.INFORMATION_SCHEMA.XXX 的内容。 我们有哪些选择?

*我正在使用 JDBC

【问题讨论】:

How to get list of table primary keys in snowflake? 使用 JDBC 这会很困难,我们需要一个查询来获得它。 一个选项总是用存储过程包装代码并使用CALL get_pk_keys(schema/table)? 【参考方案1】:

您可以考虑使用:getPrimaryKeys(String, String, String)

详情:https://docs.snowflake.com/en/user-guide/jdbc-api.html#object-databasemetadata

【讨论】:

听起来不错,让我试试这个,谢谢【参考方案2】:

不久前,我编写了一个用户定义的表函数 (UDTF) 来获取单个表的 PK 列,PK 中的每一列作为返回中的单行。我将其扩展为返回一个包含整个数据库中 PK 中所有列的表。

创建 UDTF 后,您可以像这样获取数据库的所有 PK:

select * from table(get_pk_columns(get_ddl('database', 'MY_DB_NAME')));

它将返回一个包含模式名称、表名称和列名称列的表。请注意,如果有复合 PK,它会在表中显示为每列一行。您当然可以使用诸如 listagg() 之类的聚合函数将其更改为单行,其中复合 PK 的列名称用逗号分隔。

如果您的数据库中有大量的表/列,则 GET_DDL() 函数的返回可能会太大而无法满足 16mb 的限制。如果它确实合适,这应该会很快返回结果。

/********************************************************************************************************
*                                                                                                       *
* User defined table function (UDTF) to get all primary keys for a database.                            *
*                                                                                                       *
* @param  string:  DATABASE_DDL The DDL for the database to get the PKs. Usually use GET_DDL()       *
* @return table:                A table with the columns comprising the table's primary key           *
*                                                                                                       *
********************************************************************************************************/
create or replace function GET_PK_COLUMNS(DATABASE_DDL string)
returns table ("SCHEMA_NAME" string, "TABLE_NAME" string, PK_COLUMN string)
language javascript
as
$$

    processRow: function get_params(row, rowWriter, context)
    
        var startTableLine = -1;
        var endTableLine = -1;
    
        var dbDDL = row.DATABASE_DDL.replace(/'[\s\S]*'/gm, '')
    
        var lines = dbDDL.split("\n");
        var currentSchema = "";
        var currentTable = "";
    
        var ln = 0;
        var tableDDL = "";
        var pkCols = null;
        var c = 0;

        for (var i=0; i < lines.length; i++) 
        
            if (lines[i].match(/^create .* schema /)) 
                currentSchema = lines[i].split("schema")[1].replace(/;/, '');
                //rowWriter.writeRow(PK_COLUMN: "currentSchema = " + currentSchema);
            
        
        
            if (lines[i].match(/^create or replace TABLE /)) 
                startTableLine = i;
            
            
            if (startTableLine != -1 && lines[i] == ");") 
                endTableLine = i;
            
            
            if (startTableLine != -1 && endTableLine != -1) 
                // We found a table. Now, join it and send it for parsing
                tableDDL = "";
                for (ln = startTableLine; ln <= endTableLine; ln++) 
                    if (ln > 0) tableDDL += "\n";
                    tableDDL += lines[ln];
                
                startTableLine = -1;
                endTableLine = -1;
                currentTable = getTableName(tableDDL);
                pkCols = getPKs(tableDDL);

                for (c = 0; c < pkCols.length; c++) 
                    rowWriter.writeRow(PK_COLUMN: pkCols[c], SCHEMA_NAME: currentSchema, TABLE_NAME: currentTable);
                
            
        

        function getTableName(tableDDL) 
            var lines = tableDDL.split("\n");
            var s = lines[1];
            s = s.substring(s.indexOf(" TABLE ") + " TABLE ".length);
            s = s.split(" (")[0];
            return s;
        

        function getPKs(tableDDL) 
            var c;
            var keyword = "primary key";
            var ins = -1;
            var s = tableDDL.split("\n");
            for (var i = 0; i < s.length; i++)   
                ins = s[i].indexOf(keyword);
                if (ins != -1) 
                    var colList = s[i].substring(ins + keyword.length);
                    colList = colList.replace("(", "");
                    colList = colList.replace(")", "");
                    var colArray = colList.split(",");
                    for (pkc = 0; c < colArray.length; pkc++) 
                        colArray[pkc] = colArray[pkc].trim();
                    
                    return colArray;
                
            
            return [];  // No PK
        
    

$$;

【讨论】:

以上是关于有哪些选项可用于获取 Snowflake 中的主键列名称?的主要内容,如果未能解决你的问题,请参考以下文章

有哪些选项可用于获取 cron 的结果以及如何设置它们?

需要 Debezium 连接器中用于 postgres 插入事件的主键信息

雪花算法(SnowFlake)

Alteryx“更新选项所需的主键”中的雪花插入/更新错误

如何在 C# 中获取 DataGridView 中的主键?

小白知识:数据库表主键ID生成策略及snowflake雪花算法的由来