Conversão não determinística de cadeias de caracteres literais de data em valores de DATA

Aplica-se a:SQL ServerBanco de Dados SQL do AzureInstância Gerenciada de SQL do AzureAzure Synapse AnalyticsPDW (Analytics Platform System)

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.

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.

Veja também