How the FORMAT() Function Works in SQL Server (T-SQL)

In SQL Server, you can use the T-SQL FORMAT() function to return values such as numbers and dates as formatted strings.

You provide the value to be formatted, and you specify the format to use. The function accepts an optional argument that allows you to specify a culture to use when formatting the value.

Syntax

The syntax goes like this:

FORMAT ( value, format [, culture ] )

Where value is the value you want formatted, and format is a valid format string that specifies the desired format.

The optional culture argument can be used to specify a culture. If omitted, the language of the current session is used.

The FORMAT function is nondeterministic.

Example 1 – Format a Number

Here’s an example of formatting a number:

SELECT FORMAT(1, 'N') AS Result;

Result:

+----------+
| Result   |
|----------|
| 1.00     |
+----------+

In this case, I used N as the format string. This is a standard numeric format specifier for outputting the value as a number. This particular format specifier results in the output being formatted with integral and decimal digits, group separators, and a decimal separator with optional negative sign. This format specifier is case-insensitive, so either N or n is fine.

Example 2 – Format to a Currency

Here’s an example of formatting a number as a currency:

SELECT FORMAT(1, 'C') AS Result;

Result:

+----------+
| Result   |
|----------|
| $1.00    |
+----------+

More Numeric Formats

There are many more format strings that can be used with the FORMAT() function. For example, there are format strings for percentages, fixed-point, exponential (scientific), hexadecimal, and more.

The numeric format strings are separated into standard and custom.

The following two articles list all of the numeric format strings, including examples:

Also see How to Format Numbers in SQL Server for more examples of formatting numbers.

Example 3 – Format a Date

Here’s an example of formatting a date:

SELECT 
  GETDATE() AS 'Unformatted Date',
  FORMAT( GETDATE(), 'D') AS 'Formatted Date';

Result:

+-------------------------+------------------------+
| Unformatted Date        | Formatted Date         |
|-------------------------+------------------------|
| 2019-05-08 06:16:55.613 | Wednesday, May 8, 2019 |
+-------------------------+------------------------+

In this case, I used D which specifies a long date pattern.

More Date Formats

There are many more format strings that can be used for formatting dates. As with the numeric format strings, date and time format strings are separated into standard and custom, so you can build your own custom formats, or you can rely on a standard one.

The following two articles list all of the date and time format strings, including examples:

Also see How to Format the Date & Time in SQL Server for more examples.

Example 4 – The Optional culture Argument

Here’s an example of using the culture argument to return a value in various currencies:

SELECT 
    FORMAT(1, 'C', 'fr-FR') AS 'France', 
    FORMAT(1, 'C', 'th-TH') AS 'Thailand', 
    FORMAT(1, 'C', 'ja-JP') AS 'Japan';

Result:

+----------+------------+---------+
| France   | Thailand   | Japan   |
|----------+------------+---------|
| 1,00 €   | ฿1.00      | ¥1      |
+----------+------------+---------+

The FORMAT() function accepts any culture supported by the .NET Framework as an argument; it is not limited to the languages explicitly supported by SQL Server.

If you don’t provide this argument, the language of the current session is used.

For more examples, see How Language Settings can Affect your FORMAT() Results.

Example 5 – Invalid culture Argument

If you provide an invalid culture, you’ll get an error:

SELECT FORMAT(1, 'C', 'oop-SS!') AS 'Oops!';

Result:

The culture parameter 'oop-SS!' provided in the function call is not supported.

Example 6 – Invalid Format Value

However, for other errors, the function returns NULL. For example, here’s what happens if I provide an invalid value to be formatted:

SELECT FORMAT(GETDATE(), 'C') AS 'Result';

Result:

+----------+
| Result   |
|----------|
| NULL     |
+----------+

In this case, I was trying to format a date into a currency, and therefore the result was NULL.

Valid Data Types

FORMAT() relies on the presence of the .NET Framework Common Language Runtime (CLR), and uses the CLR formatting rules.

The following data types can be formatted with the FORMAT() function. This list contains the acceptable data types for the input string together with their .NET Framework mapping equivalent types.

Category Type .NET type
Numeric bigint Int64
Numeric int Int32
Numeric smallint Int16
Numeric tinyint Byte
Numeric decimal SqlDecimal
Numeric numeric SqlDecimal
Numeric float Double
Numeric real Single
Numeric smallmoney Decimal
Numeric money Decimal
Date and Time date DateTime
Date and Time time TimeSpan
Date and Time datetime DateTime
Date and Time smalldatetime DateTime
Date and Time datetime2 DateTime
Date and Time datetimeoffset DateTimeOffset

Escaping Colons and Periods for the ‘time’ Data Type

When using FORMAT, colons and periods must be escaped (this adheres to the the CLR formatting rules). Therefore, when the format string (second parameter) contains a colon or period, the colon or period must be escaped with a backslash when an input value (first parameter) is of the time data type.

Example:

SELECT 
  CAST('12:15' AS time) AS 'Unformatted Data',
  FORMAT(CAST('12:15' AS time), N'hh.mm') AS 'Unescaped',
  FORMAT(CAST('12:15' AS time), N'hh\.mm') AS 'Escaped';

Result:

+--------------------+-------------+-----------+
| Unformatted Data   | Unescaped   | Escaped   |
|--------------------+-------------+-----------|
| 12:15:00           | NULL        | 12.15     |
+--------------------+-------------+-----------+

So as expected, the unescaped string returns NULL.

As mentioned, this only applies to the time data type. If we change the input value to a different data type, we don’t need to escape it:

SELECT 
  CAST('12:15' AS datetime) AS 'Unformatted Data',
  FORMAT(CAST('12:15' AS datetime), N'hh.mm') AS 'Unescaped',
  FORMAT(CAST('12:15' AS datetime), N'hh.mm') AS 'Escaped';

Result:

+-------------------------+-------------+-----------+
| Unformatted Data        | Unescaped   | Escaped   |
|-------------------------+-------------+-----------|
| 1900-01-01 12:15:00.000 | 12.15       | 12.15     |
+-------------------------+-------------+-----------+

In this case, the input value is datetime, and therefore, the result is fine without escaping it.

You can also use the backslash to escape any other character you want included in the result string, that would otherwise be interpreted as a format specifier. Preceding a character with a backslash signifies that the following character is a character literal that should be included in the result string unchanged.

In a custom date and time format string, the d, f, F, g, h, H, K, m, M, s, t, y, z, :, or / characters are interpreted as custom format specifiers rather than as literal characters.

In a custom numeric format string, the #, 0, ., ,, %, and symbols are interpreted as format specifiers rather than as literal characters. The uppercase and lowercase E as well as the + and - symbols may also be interpreted as format specifiers, depending on their position within the format string.

If you need to include a backslash in the result string, escape it with another backslash.

Remoting

The FORMAT() function cannot be remoted since it depends on the presence of the CLR. Remoting a function that requires the CLR, could cause an error on the remote server.

When to Use the FORMAT() Function

Microsoft recommends that the FORMAT() function is used for locale-aware formatting of date/time and number values as strings, and that for general data type conversions, either the CAST() function or the CONVERT() function should be used instead.