In this post today I would like to show you the T-SQL FORMAT function, available since SQL Server 2012, and which to this day few people use on a daily basis to format dates and numbers.
When I analyze queries, functions and Stored Procedures, I see that even today, many developers insist on using CAST, CONVERT and concatenations to format dates and numbers, even with a function specifically for that. After reading this post, I hope you understand how to use this function and start simplifying your T-SQL codes with it.
Who has never needed to fill in a number with 0 on the left to generate a layout? Format a date? Extract only the time from a date? There are numerous situations in which the FORMAT function is useful.
Formatting numeric data
Pre-defined formatting
Simpler use, the pre-defined functions allow the formatting of values using masks already defined by default in SQL Server, such as “C” for currency.
Most used formats
SELECT
FORMAT(123456.99, 'C'), -- Formato de moeda padrão
FORMAT(-123456.987654321, 'C4'), -- Formato de moeda com 4 casas decimais
FORMAT(123456.987654321, 'C2', 'pt-br') -- Formato de moeda forçando a localidade pra Brasil e 2 casas decimais
SELECT
FORMAT(123456.99, 'D'), -- Formato de número inteiro com valores numeric (NULL)
FORMAT(123456, 'D'), -- Formato de número inteiro
FORMAT(-123456, 'D4'), -- Formato de número inteiro com valores negativos
FORMAT(123456, 'D10', 'pt-br'), -- formato de número inteiro com tamanho fixo em 10 caracteres
FORMAT(-123456, 'D10', 'pt-br') -- formato de número inteiro com tamanho fixo em 10 caracteres
SELECT
FORMAT(123456.99, 'E'), -- Formato de notação científica
FORMAT(123456.99, 'E4') -- Formato de notação científica e 4 casas decimais de precisão
SELECT
FORMAT(1, 'P'), -- Formato de porcentagem
FORMAT(1, 'P2'), -- Formato de porcentagem com 2 casas decimais
FORMAT(0.91, 'P'), -- Formato de porcentagem
FORMAT(0.005, 'P4') -- Formato de porcentagem com 4 casas decimais
SELECT
FORMAT(255, 'X'), -- Formato hexadecimal
FORMAT(512, 'X8') -- Formato hexadecimal fixando o retorno em 8 caracteres
Examples
Other formats
SELECT
FORMAT(123456.99, 'F'), -- Formato de número
FORMAT(123456.99, 'F4') -- Formato de número com 4 casas decimais
SELECT
FORMAT(123456.99, 'G'), -- Formato de número compacto
FORMAT(123456.99, 'G4'), -- Formato de número (tenta forçar o número com 4 caracteres)
FORMAT(123456.99, 'G20') -- Formato de número com tamanho máximo de 10 caracteres
SELECT
FORMAT(123456.99, 'N'), -- Formato de número genérico
FORMAT(123456.99, 'N4') -- Formato de número genérico fixando 4 casas decimais
Examples
Custom Formatting
Filling a number with a leading zero
Formatting a number for Brazilian currency
Function used in this example:
CREATE FUNCTION fncConverte_Moeda_Real (
@Numero VARCHAR(40)
)
RETURNS VARCHAR(40)
AS
BEGIN
DECLARE @Contador INT
DECLARE @Pontos INT
DECLARE @CasasVirgula INT
DECLARE @Parte1 VARCHAR(40)
DECLARE @Parte2 VARCHAR(40)
SET @CasasVirgula = (LEN(SUBSTRING(@Numero, CHARINDEX('.', @Numero) + 1, LEN(@Numero))))
IF @CasasVirgula > 2
SET @Numero = (SUBSTRING(@Numero, 1, (CHARINDEX('.', @Numero)) + 2))
IF CHARINDEX('.', @Numero) <> 0 BEGIN
SET @Numero = REPLACE(@Numero, '.', ',')
IF LEN(SUBSTRING(@Numero, CHARINDEX(',', @Numero) + 1, 2)) = 1
SET @Numero = @Numero + '0'
END
ELSE
SET @Numero = @Numero + ',00'
SET @Contador = (CHARINDEX(',', @Numero) - 1)
SET @Pontos = @Contador / 3
WHILE @Pontos <> 0 BEGIN
SET @Contador = @Contador - 3
SET @Parte2 = (SUBSTRING(@Numero, @Contador + 1, LEN(@Numero)))
SET @Parte1 = (SUBSTRING(@Numero, 1, (CHARINDEX(@Parte2, @Numero) - 1)))
SET @Numero = @Parte1 + '.' + @Parte2
SET @Pontos = @Pontos - 1
END
IF (SUBSTRING(@Numero, 1, 1)) = '.'
SET @Numero = (SUBSTRING(@Numero, 2, LEN(@Numero)))
SET @Numero = 'R$ ' + @Numero
RETURN @Numero
END
Other examples:
SELECT
-- Formato de moeda brasileira (manualmente)
FORMAT(123456789.9, 'R$ ###,###,###,###.00'),
-- Utilizando sessão (;) para formatar valores positivos e negativos
FORMAT(123456789.9, 'R$ ###,###,###,###.00;-R$ ###,###,###,###.00'),
-- Utilizando sessão (;) para formatar valores positivos e negativos
FORMAT(-123456789.9, 'R$ ###,###,###,###.00;-R$ ###,###,###,###.00'),
-- Utilizando sessão (;) para formatar valores positivos e negativos
FORMAT(-123456789.9, 'R$ ###,###,###,###.00;(R$ ###,###,###,###.00)'),
-- Formatando porcentagem com 2 casas decimais
FORMAT(0.9975, '#.00%'),
-- Formatando porcentagem com 4 casas decimais
FORMAT(0.997521654, '#.0000%'),
-- Formatando porcentagem com 4 casas decimais
FORMAT(123456789.997521654, '#.0000%'),
-- Formatando porcentagem com 2 casas decimais e utilizando sessão (;)
FORMAT(0.123456789, '#.00%;-#.00%'),
-- Formatando porcentagem com 2 casas decimais e utilizando sessão (;)
FORMAT(-0.123456789, '#.00%;-#.00%'),
-- Formatando porcentagem com 2 casas decimais e utilizando sessão (;)
FORMAT(-0.123456789, '#.00%;(#.00%)')
Result:
Formatting dates
Pre-defined formatting
Most common formats
SET LANGUAGE 'English'
SELECT
FORMAT(GETDATE(), 'd'), -- Padrão de data abreviada.
FORMAT(GETDATE(), 'D'), -- Padrão de data completa.
FORMAT(GETDATE(), 'R'), -- Padrão RFC1123
FORMAT(GETDATE(), 't'), -- Padrão de hora abreviada.
FORMAT(GETDATE(), 'T') -- Padrão de hora completa.
SET LANGUAGE 'Brazilian'
SELECT
FORMAT(GETDATE(), 'd'), -- Padrão de data abreviada.
FORMAT(GETDATE(), 'D'), -- Padrão de data completa.
FORMAT(GETDATE(), 'R'), -- Padrão RFC1123
FORMAT(GETDATE(), 't'), -- Padrão de hora abreviada.
FORMAT(GETDATE(), 'T') -- Padrão de hora completa.
SELECT
-- Formato de data típico do Brasil
FORMAT(GETDATE(), 'dd/MM/yyyy'),
-- Formato de data/hora típico dos EUA
FORMAT(GETDATE(), 'yyyy-MM-dd HH:mm:ss.fff'),
-- Exibindo a data por extenso
FORMAT(GETDATE(), 'dddd, dd \d\e MMMM \d\e yyyy'),
-- Exibindo a data por extenso (forçando o idioma pra PT-BR)
FORMAT(GETDATE(), 'dddd, dd \d\e MMMM \d\e yyyy', 'pt-br'),
-- Exibindo a data/hora, mas zerando os minutos e segundos
FORMAT(GETDATE(), 'dd/MM/yyyy HH:00:00', 'pt-br')
Formatting numbers and dates before SQL Server 2012
Now that you've seen how simple and quick it is to format numbers and dates using the native FORMAT function, it's even difficult to want to format these types of data manually again, right?
Unfortunately, the FORMAT function was introduced in SQL Server 2012, that is, in versions 2005 and 2008, you will still have to use the traditional (expensive and laborious) ways of formatting dates and numbers. Or not.
For those who have a database project in their instance (also known as SQLCLR), you can easily implement 2 functions very similar (practically the same) to the FORMAT function, allowing you to easily format data using these functions, even in versions 2005 and 2008 of SQL Server.
See how the usage is practically the same as the FORMAT function (I did not implement the third parameter – culture):
Note that both pre-defined formats and custom formats remain unchanged using the CLR function. This happens because the FORMAT function internally uses the same C# function that I used in these SQLCLR functions.
fncFormata_Datetime source code
using System.Data.SqlTypes;
using System.Globalization;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString fncFormata_Datetime(SqlDateTime Dt_Referencia, SqlString Ds_Mascara)
{
return Dt_Referencia.IsNull ? SqlString.Null : Dt_Referencia.Value.ToString(Ds_Mascara.Value, new CultureInfo("pt-BR"));
}
};
How to format numbers with the CLR
Examples with standard formats
Examples with custom formats
fncFormata_Numero source code
using System.Data.SqlTypes;
using System.Globalization;
public partial class UserDefinedFunctions
{
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString fncFormata_Numero(SqlDouble Ds_String, SqlString Ds_Formato)
{
if (Ds_String.IsNull)
return SqlString.Null;
return Ds_Formato.IsNull ? Ds_String.Value.ToString(CultureInfo.InvariantCulture) : Ds_String.Value.ToString(Ds_Formato.Value, CultureInfo.CreateSpecificCulture("pt-br"));
}
}
That's it, folks!
I hope you start using the FORMAT function more in your daily life (when necessary) and if you are using the 2005 or 2008 versions of SQL Server, know that it is possible to simulate the behavior of this function using SQLCLR.
Comentários (0)
Carregando comentários…