Conversão não determinística de cadeias de caracteres literais de data em valores de DATA
Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure PDW (Sistema de Plataforma de Análise) do Azure Synapse Analytics
Tenha cuidado ao permitir que a conversão de suas cadeias de CARACTERES em tipos de dados de DATA. O motivo é que essas conversões frequentemente não são determinísticas.
Você controla essas conversões não determinísticas considerado as configurações SET LANGUAGE e SET DATEFORMAT.
Exemplo de SET LANGUAGE: nome do mês em polonês
SET LANGUAGE Polish;
Uma cadeia de caracteres pode ser o nome de um mês. Mas é o nome está inglês, polonês, croata ou em outro idioma? A sessão do usuário será definida como o idioma correspondente correto?
Por exemplo, considere a palavra listopad, que é o nome de um mês. Mas qual mês depende do idioma que o sistema SQL acredita que está sendo usado:
- Se for polonês, então listopad será traduzido como o mês 11 (novembro em português).
- Se croata, então listopad será traduzido como o mês 10 (outubro em português).
Exemplo de código de SET LANGUAGE
--SELECT alias FROM sys.syslanguages ORDER BY alias;
DECLARE @yourInputDate NVARCHAR(32) = '28 listopad 2018';
SET LANGUAGE Polish;
SELECT CONVERT(DATE, @yourInputDate) AS [SL_Polish];
SET LANGUAGE Croatian;
SELECT CONVERT(DATE, @yourInputDate) AS [SL_Croatian];
SET LANGUAGE English;
/*** Actual output: For the two months, note the 11 versus the 10.
SL_Polish
2018-11-28
SL_Croatian
2018-10-28
***/
Exemplo de SET DATEFORMAT
SET DATEFORMAT dmy;
O formato dma anterior diz que uma cadeia de caracteres de data de exemplo de '01-03-2018' deve ser interpretada como o primeiro dia de março do ano de 2018.
Em vez disso, mda fosse especificado, a mesma cadeia de caracteres '01-03-2018' significaria o terceiro dia de janeiro de 2018.
E se amd tivesse sido especificado, não haveria nenhuma garantia de qual seria a saída. O valor numérico de '2018' é muito grande para ser um dia.
Países/regiões específicos
No Japão e na China, DATEFORMAT de amd é usado. As partes do formato estão em uma sequência lógica da maior unidade para a menor. Assim, esse formato é bem classificado. Esse formato é considerado o formato internacional. É internacional porque os quatro dígitos do ano são não ambíguos e nenhum país/região na Terra usa o formato arcaico do ydm.
Em outros países/regiões, como Alemanha e França, DATEFORMAT é dma, que significa 'dd-mm-aaaa'. O formato dma não é bem classificado, mas é uma sequência lógica da menor unidade para a maior.
Os Estados Unidos e os Estados Federados da Micronésia, são os únicos países/regiões que usam mda, que não é classificado. A sequência mista de formato corresponde ao padrão de discurso verbal em datas faladas.
Exemplo de código de SET DATEFORMAT: mda versus dma
O exemplo de código Transact-SQL a seguir usa a mesma cadeia de caracteres de data com três configurações diferentes de DATEFORMAT. Uma execução do código produz a saída mostrada no comentário:
DECLARE @yourDateString NVARCHAR(10) = '12-09-2018';
PRINT @yourDateString + ' = the input.';
SET DATEFORMAT dmy;
SELECT CONVERT(DATE, @yourDateString) AS [DMY-Interpretation-of-input-format];
SET DATEFORMAT mdy;
SELECT CONVERT(DATE, @yourDateString) AS [MDY-Interpretation-of-input-format];
SET DATEFORMAT ymd;
SELECT CONVERT(DATE, @yourDateString) AS [YMD-Interpretation--?--NotGuaranteed];
/*** Actual output:
12-09-2018 = the input.
DMY-Interpretation-of-input-format
2018-09-12
MDY-Interpretation-of-input-format
2018-12-09
YMD-Interpretation--?--NotGuaranteed
2018-12-09
***/
No exemplo de código anterior, o exemplo final tem uma incompatibilidade entre o formato amd versus a cadeia de caracteres de entrada. O terceiro nó da cadeia de caracteres de entrada representa um valor numérico muito grande para ser um dia. A Microsoft não garante o valor de saída dessas incompatibilidades.
CONVERT oferece códigos explícitos para controle determinístico dos formatos de data
Nosso artigo de documentação CAST e CONVERT lista códigos explícitos que você pode usar com a função CONVERT para controlar de modo determinístico conversões de data. A cada mês, o artigo tem uma de nossas contagens de exibições de página mais altas.
- CAST e CONVERT (Transact-SQL): estilos de data e hora
- CAST e CONVERT (Transact-SQL): algumas conversões de datetime não são determinísticas
Nível de compatibilidade 90 e superior
No SQL Server 2000, o nível de compatibilidade era 80. Para configurações de nível 80 ou inferior, as conversões de data implícita eram determinísticas.
Começando com o SQL Server 2005 e seu nível de compatibilidade 90, conversões de data implícita passaram a não ser determinísticas. Conversões de data tornaram-se dependentes de SET LANGUAGE e SET DATEFORMAT do nível 90 em diante.
Unicode
Conversão de dados de caractere não Unicode entre ordenações também é considerada não determinística.