'How to get list of table primary keys in snowflake?

I want to get all primary keys of a table in list in snowflake. I used

SHOW PRIMARY KEYS IN TABLE t1

but the output is a set of columns:

"created_on"    "database_name" "schema_name"   "table_name"    "column_name"   "key_sequence"  "constraint_name"   "comment"

and I need only the column_name column. I tried to do:

select a.* from (SHOW PRIMARY KEYS IN TABLE t1) a

but I got this error:

SQL Error [1003] [42000]: SQL compilation error:
syntax error line 1 at position 17 unexpected 'SHOW'.

if somebody has an idea, please help. thanks.



Solution 1:[1]

You can use RESULT_SCAN function to process the output of the SHOW command:

https://docs.snowflake.com/en/sql-reference/functions/result_scan.html

SHOW PRIMARY KEYS IN TABLE t1;

SELECT * FROM table(RESULT_SCAN( LAST_QUERY_ID() ));

Another sample:

SHOW PRIMARY KEYS IN TABLE test1;
select last_query_id();

This is the result:
-------------------
019c7ab2-3200-9e9b-0000-b4550014773e

Then I use it with RESULT_SCAN:

SELECT * FROM table(RESULT_SCAN( '019c7ab2-3200-9e9b-0000-b4550014773e'));

Please note that, last_query_id will always return last query in current session. It does not return the query IDs executed with other sessions.

Solution 2:[2]

A while back, I wrote a UDTF (User Defined Table Function) for a customer who needed a programmatic way to return the PK columns for a table as a table. This may be along the lines of what you're looking to do, though it may need a bit of adjustment if you want the return as a list rather than a table.

You can see a sample of how it works here https://snowflake.pavlik.us/index.php/2020/07/29/getting-snowflake-primary-key-columns-as-a-table/

/********************************************************************************************************
*                                                                                                       *
* User defined table function (UDTF) to get primary keys for a table.                                   *
*                                                                                                       *
* @param  {string}:  TABLE_DDL    The DDL for the table 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(TABLE_DDL string)
returns table (PK_COLUMN string)
language javascript
as
$$
{
    processRow: function get_params(row, rowWriter, context){
  
        var pkCols = getPKs(row.TABLE_DDL);
        for (i = 0; i < pkCols.length; i++) {
            rowWriter.writeRow({PK_COLUMN: pkCols[i]}); 
        }
          
        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
        }
    }
}
$$;

Solution 3:[3]

I did this using a very simple SQL based UDTF:

CREATE OR ALTER FUNCTION admin.get_primary_key(p_table_nm VARCHAR)
  RETURNS TABLE(column_name VARCHAR, ordinal_position int)
AS
  WITH t AS (select get_ddl('TABLE', p_table_nm) tbl_ddl)
     , t1 AS (
              SELECT POSITION('primary key (', tbl_ddl) + 13 pos
                   , SUBSTR(tbl_ddl, pos, POSITION(')', tbl_ddl, pos) - pos ) str
                FROM t
)
  SELECT x.value column_name
       , x.index ordinal_position
    FROM t1
       , LATERAL SPLIT_TO_TABLE(t1.str, ',') x
; 

You can then query this in a SQL statement:

select *
  FROM TABLE(admin.get_primary_key('<your table name>'));

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Mohit Agarwal