Skip to main content

Generating SELECT Statements Using GetColumnList

Why This Pattern Matters​

Once a Biml project can generate SQL from metadata, the next step is shaping the column lists that feed into SELECT, INSERT, JOIN, and MERGE statements. The 'GetColumnList' method on a table node returns a comma separated list of columns ready to drop into a T-SQL statement, and a few optional parameters cover the cases where the default output is not enough.

What GetColumnList Returns​

By default, 'GetColumnList' returns every column on a table, square bracket delimited and comma separated:

[CustomerID], [FirstName], [LastName]

That string can be customized by passing in a table alias, a predicate to filter the columns, or replacement delimiters. With those parameters, the same call can produce something like this instead:

c.FirstName, c.LastName

The sections below show the six common variations.

Generating a SELECT for Every Source Table​

A connection node and an import call set up the metadata, and a foreach loop emits one SELECT per table:

<#
var srcConn = SchemaManager.CreateConnectionNode("Sales", @"Data Source=...;");
var srcSchema = srcConn.GetDatabaseSchema();
#>

<# foreach (var srcTable in srcSchema.TableNodes) { #>
SELECT <#=srcTable.GetColumnList()#>
FROM <#=srcTable.SchemaQualifiedName#>;
<# } #>

The output is a series of statements that look like this:

SELECT [RegionID], [RegionName], [CountryID], [PostalCode] ...
FROM [sales].[Regions];

SELECT [CountryID], [CountryName], [IsoCode], [Currency] ...
FROM [sales].[Countries];

The result is a plain text script. It can be pasted into a query editor for ad hoc use, or wrapped in further Biml to drive an OleDbSource transformation inside an SSIS package.

Customizing the Output With Parameters​

'GetColumnList' accepts up to four parameters. Three are simple strings: 'tableAlias', 'beginningDelimiter', and 'endingDelimiter'. The fourth is a 'predicate', supplied as a lambda expression. The available combinations are:

MethodExample Output
GetColumnList()[CustomerID], [FirstName], [LastName]
GetColumnList("c")[c].[CustomerID], [c].[FirstName], [c].[LastName]
GetColumnList(col => col.IsUsedInPrimaryKey)[CustomerID]
GetColumnList(col => col.IsUsedInPrimaryKey, "c")[c].[CustomerID]
GetColumnList("c", "", "")c.CustomerID, c.FirstName, c.LastName
GetColumnList(col => col.IsUsedInPrimaryKey, "c", "", "")c.CustomerID

What the Predicate Parameter Does​

The predicate is a C# lambda expression. The arrow '=>' separates the input parameter on the left from the boolean expression on the right:

column => column.Name == "CustomerID"

When 'GetColumnList' is called with a predicate, every column on the table is evaluated against the expression. Columns that return true are kept, columns that return false are dropped. The input parameter can be named anything, so a shorter form is common:

col => col.Name == "CustomerID"

The predicate can inspect any property exposed by a column node, which means filters can be expressed against name, data type, nullability, or key membership:

col => col.Name == "CustomerID"
col => col.DataType != System.Data.DbType.Guid
col => col.IsNullable
col => !col.IsUsedInKey

Example: SELECT With a Table Alias​

Passing the alias parameter prefixes every column with the alias, and the same alias is used in the FROM clause:

SELECT <#=srcTable.GetColumnList("src")#>
FROM <#=srcTable.SchemaQualifiedName#> AS src;

The output looks like this:

SELECT [src].[RegionID], [src].[RegionName], [src].[CountryID], [src].[PostalCode] ...
FROM [sales].[Regions] AS src;

Example: SELECT Only Specific Columns​

Passing a predicate restricts the output to columns that match. The example below returns only the primary key columns:

SELECT <#=srcTable.GetColumnList(col => col.IsUsedInPrimaryKey)#>
FROM <#=srcTable.SchemaQualifiedName#>;

The output looks like this:

SELECT [RegionID]
FROM [sales].[Regions];

If a table does not have a primary key, the column list will be empty for that table.

Example: Predicate, Alias, and Custom Delimiters​

The fullest form of the call combines a predicate, an alias, and a pair of replacement delimiters. Passing two empty strings as the delimiters strips the square brackets:

SELECT <#=srcTable.GetColumnList(col => !col.IsUsedInPrimaryKey, "src", "", "")#>
FROM <#=srcTable.SchemaQualifiedName#>;

The output looks like this:

SELECT src.RegionName, src.CountryID, src.PostalCode ...
FROM sales.Regions AS src;

Summary​

'GetColumnList' produces customizable column lists from table metadata. The four parameters cover aliasing, filtering by predicate, and overriding the default square bracket delimiters, which is enough to assemble most repetitive T-SQL patterns from the same source metadata that drives package generation.