Question
· Feb 12, 2016

Get columns dynamically?

In MSSQL I think you can do something like this:

select *
from HS_IHE_ATNA_Repository.COLUMNS
where TABLE_NAME='Aggregation'

 

How can I do this in Cache SQL?

[%msg: < Table 'HS_IHE_ATNA_REPOSITORY.COLUMNS' not found>]

Discussion (11)1
Log in or sign up to continue

This has been bothering me a little bit; %Dictionary.* should really be a last-resort option, in my opinion, and it isn't easy to use it to get the full picture from an SQL perspective.

Here are some alternative/possibly-better solutions, using %SQL.StatementMetadata and INFORMATION_SCHEMA. It looks like INFORMATION_SCHEMA is more exactly what you were looking for, if you're running on a recent enough Caché version (2015.1+). I haven't been able to find documentation on it other than the class reference, though.

/// NOTE: It could be good to validate pTableName to avoid SQL injection. (Outside the scope of this demo.)
/// This works pre-2015.1 (since %SQL.Statement was introduced - maybe 2012.2+?)
ClassMethod GetTableColumns(pTableName As %String) As %List
{
    #dim tResult As %SQL.StatementResult
    #dim tMetadata As %SQL.StatementMetadata
    Set tStmt = ##class(%SQL.Statement).%New()
    $$$ThrowOnError(tStmt.%Prepare("select top 0 * from "_pTableName))
    Set tResult = tStmt.%Execute(), tMetadata = tResult.%GetMetadata()
    Set tCols = ""
    For i=1:1:tMetadata.columnCount {
        Set tCols = tCols_$ListBuild(tMetadata.columns.GetAt(i).colName)
    }
    Quit tCols
}

/// This will only work on 2015.1+; INFORMATION_SCHEMA is a new feature. For more information, see the class reference for it in the documentation.
ClassMethod GetTableColumnsNew(pTableName As %String) As %List
{
    #dim tResult As %SQL.StatementResult
    Set tStmt = ##class(%SQL.Statement).%New()
    Set tSchema = $Piece(pTableName,".")
    Set tTableName = $Piece(pTableName,".",2)
    $$$ThrowOnError(tStmt.%Prepare("select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_SCHEMA = ? and TABLE_NAME = ?"))
    Set tResult = tStmt.%Execute(tSchema,tTableName)
    Set tCols = ""
    While tResult.%Next(.tSC) {
        Set tCols = tCols_$ListBuild(tResult.%Get("COLUMN_NAME"))
    }
    $$$ThrowOnError(tSC)
    Quit tCols
}

Using this:

SAMPLES>set cols = ##class(Demo.TableColumns).GetTableColumns("Sample.Person")
SAMPLES>w $lts(cols)
ID,Age,DOB,FavoriteColors,Name,SSN,Spouse,Home_City,Home_State,Home_Street,Home_Zip,Office_City,Office_State,Office_Street,Office_Zip
SAMPLES>set cols = ##class(Demo.TableColumns).GetTableColumnsNew("Sample.Person")
SAMPLES>w $lts(cols)                                                            ID,Age,DOB,FavoriteColors,Name,SSN,Spouse,Home_City,Home_State,Home_Street,Home_Zip,Office_City,Office_State,Office_Street,Office_Zip