Skip to main content

Formatted SQL

Formatted SQL uses string interpolation to build SQL statements from SQL fragments and parameter values.

Formatted SQL is most commonly used when calling the CommandFormat method on a connector, passing an interpolated string with parameter values. CommandFormat is actually a convenience method that is equivalent to calling Sql.Format and passing the returned SqlSource to the Command method.

A SqlSource represents a SQL fragment and any attached parameter values. The Sql static class contains many methods that create SqlSource objects.

Text

Sql.Format is the most useful method for building SQL fragments. An unnamed parameter is substituted for each interpolated expression, unless the expression is a SqlSource, in which case the corresponding SQL fragment is substituted.

Sql.Raw creates a SQL fragment from a raw SQL string with no parameter values.

Sql.Empty contains an empty SQL fragment, equivalent to Sql.Raw("").

Sql.Name surrounds the specified string with delimiters that prevent it from being interpreted as a SQL keyword. ANSI SQL uses double quotes for this, but some databases have their own syntax, so be sure to use the right MuchAdo package or SqlSyntax.

Concatenation

SqlSource instances can be concatenated with the + operator, but there are usually better ways to build SQL from fragments, as documented below.

As mentioned previously, Sql.Format can be used to build a SqlSource from other instances.

Like the + operator, Sql.Concat concatenates any number of SQL fragments.

Sql.Join works like string.Join; it interleaves SQL fragments with the specified raw SQL separator. Empty fragments are ignored, rather than doubling up the separator.

Sql.Clauses is shorthand for calling Sql.Join with a newline.

Sql.List is shorthand for calling Sql.Join with a comma.

Sql.Tuple is shorthand for a comma-separated list surrounded by parentheses, equivalent to Sql.Format($"({Sql.List(...)})".

Keywords

There are a few methods that generate keywords. The advantage of these methods over typing the keyword directly is that the keyword is omitted if the arguments are missing or all empty.

Sql.Where and Sql.Having generate a WHERE or HAVING keyword followed by the specified argument.

Sql.OrderBy and Sql.GroupBy generate ORDER BY or GROUP BY keywords followed by the arguments separated by commas.

Sql.And and Sql.Or separate any non-empty arguments with AND or OR keywords. The entire expression is surrounded with parentheses, in case there is nesting. If there is only one non-empty argument, it is used as-is.

Parameters

Classes that represent one or more parameters are derived from SqlParamSource. When a parameter source is used in formatted SQL, parameter placeholders are generated that reference parameters with the corresponding values, comma-separated if there are more than one. Depending on the database, unnamed parameters use named placeholders like @ado1, numbered placeholders like $1, or positional placeholders like ?. See Parameters for more information about SqlParamSource.

Sql.Param creates an unnamed parameter with the specified value. The returned object has a Value property that can be set, if you want to reuse the object for multiple commands to save the allocation.

Sql.RepeatParam creates an unnamed parameter designed to be used more than once in a single command. For databases that use named or numbered placeholders, the same placeholder is used each time the same object from Sql.RepeatParam is used, which could save bandwidth, depending on your database.

Sql.Params generates unnamed parameters from a collection. The collection is not copied; parameters will be generated from the items just in time. If the collection is empty, empty SQL will be produced, which could result in invalid SQL. Generally, you should check for an empty collection and bypass the command or add a conditional to generate valid SQL for that case.

Named Parameters

Unnamed parameters are usually simpler and sometimes more efficient, but you can also create named parameters. Be sure to avoid specifying two different parameters with the same name.

Sql.NamedParam creates a parameter with the specified name and value. Named parameters use the corresponding named placeholder, e.g. @height.

Sql.NamedParams creates multiple parameters with the specified names and values, either from a collection of tuple pairs where the first value is the parameter name, or from a collection of key/value pairs where the key is the parameter name. As with Sql.Params, you should usually avoid empty collections.

DTOs

Sql.DtoColumnNames is useful when selecting fields to map to a DTO.

Use From when you're using an explicit table name or alias.

Sql.DtoParams generates unnamed parameters for the value of each property of a DTO. It is often used with Sql.DtoColumnNames when inserting database records.

In both cases, you can use Where to filter properties by name.

If you prefer named parameters, you can use Sql.DtoNamedParams.

To add a prefix or suffix to help ensure that the parameter name is unique, use Renamed.

If you want to manually generate parameter placeholders for a DTO, use Sql.DtoParamNames.