SQLServer e formatação de campo data

Pessoal, estou apanhando pra formatar um campo data da forma como eu quero.

Preciso da data no formato MM/YYYY.

Sei que poderia usar DAY(data), MONTH(data) e YEAR(data) pra compor esse resultado final que desejo, porém não posso fazer isso pq uso i18n no meu sistema, onde um único sql retorna a data em diferentes formatos dependendo do que foi configurado na tabela de i18n.

Para os demais bancos que usamos (Oracle e MySQL) conseguimos fazer sem problemas. Mas no caso do SQLServer, não consigo encontrar uma forma dele aceitar máscaras que me retornem a data da forma que eu desejar.

Eu uso assim no momento:

select CONVERT(varchar, getdate(), 102) as data

Teria como no lugar desse “102” eu programar de forma que ele me retorne mm/yyyy ?!
Tem como eu combinar esses números (1, 0 e 2) pra formar o formato que eu quiser?

Eu olhei no help do SQLServer e tb no Google e não achei nada que atenda. Alguém já passou por isso?!

Grata

Você leu mesmo a documentação?

Procure no SQL Books Online por "CAST and CONVERT (Transact-SQL) ".

(Infelizmente, para achar coisas do Microsoft SQL Server, não é muito adequado procurar pelo Google, que você não acha direito. É melhor você ter uma cópia do SQL Books Online, que pode ser baixada da Microsoft, e ver pelo índice. )

O número 102 quer dizer “mostrar a data em formato ANSI”. Esse “102” quer dizer 100 + 2 (100 quer dizer incluir o século, e 2 o formato ANSI, que é ano.mês.dia.

Para fazer o que você quer, escolha um formato que tenha mês e ano colados (no seu caso o 103), e use substring. Não é fácil?

Não thingol…

Isso que vc falou eu sei e eu vi sim a explicação do CONVERT na documentação.

O problema é que como eu falei não posso usar substring, por causa da questão da i18n. Precisava de uma formatação de máscara sem usar substring.

Entendeu?!

Problemas de internacionalização?
Não entendi o que a internacionalização tem a ver com o seu problema.
Quando você usa CAST ou CONVERT, 102 sempre mostra no mesmo formato (ANSI, ou seja, ano.mês.dia); ele não faz nenhuma internacionalização.
No seu caso, talvez fosse melhor usar um PreparedStatement mesmo (retornando um java.sql.Timestamp), e a parte de apresentação dos dados é que faria a internacionalização correta (12/2007, 2007-12, etc.)

Ok, vou tentar explicar melhor.

Meu sistema usa i18n e além disso tb funciona com 3 diferentes BDs: MySQL, Oracle e SQLServer (este estamos terminando de implementar).

Então eu tenho uma tabela com os tags de i18n. Entre tantos tags, tenho esses:

mascaraDataMysql - %d/%m/%Y mascaraDataOracle - dd/mm/yyyy mascaraDataSqlserver - 103 mascaraDataSimplesMysql - %d/%m/%y mascaraDataSimplesOracle - dd/mm/yy mascaraDataSimplesSqlserver - <<esse eu não sei>> mascaraDiaMesMysql - %d/%m mascaraDiaMesOracle - dd/mm mascaraDiaMesSqlserver - <<esse eu não sei>>

Em meu sistema tenho uma interface, e através dela é instanciada a classe correspondente as instruções SQL de acordo com o BD que o usuário tiver configurado que deseja usar.

Vou usar como ex. um SQL simplificado de um relatório simples que tenho aqui.

No MySQL tenho ele assim:

sql = "select c.codigo, c.descricao, "+ " DATE_FORMAT(m.data,'" + meuResourceBundle.getString("mascaraDataMysql") + "') as data, "+ " m.loja, m.caixa, m.hora, IFNULL(m.valortot,0) as valor, "+ " m.cmc7 as obs "+ " from movcaixa m "+ "left join contas c on c.codigo = m.tipopgto "+ " where m.data >= '2007/01/01' "+ " and m.data <= '2007/12/31' "+ " and m.loja = 1 "+ " and m.cancelado <> 'S' "+ " and m.status = '60' "+ "order by 1,m.data,6";
No Oracle é assim:

sql = "select c.codigo, c.descricao, "+ " TO_CHAR(m.data,'" + meuResourceBundle.getString("mascaraDataOracle") + "') as data, "+ " m.loja, m.caixa, m.hora, NVL(m.valortot,0) as valor, "+ " m.cmc7 as obs "+ " from movcaixa m "+ "left join contas c on c.codigo = m.tipopgto "+ " where m.data >= TO_DATE('2007/01/01','yyyy/mm/dd') "+ " and m.data <= TO_DATE('2007/12/31','yyyy/mm/dd') "+ " and m.loja = 1 "+ " and m.cancelado <> 'S' "+ " and m.status = '60' "+ "order by 1,m.data,6";
No SqlServer é assim:

sql = "select c.codigo, c.descricao, "+ " CONVERT(varchar, m.data, " + meuResourceBundle.getString("mascaraDataSqlserver") + ") as data, "+ " m.loja, m.caixa, m.hora, ISNULL(m.valortot,0) as valor, "+ " m.cmc7 as obs "+ " from movcaixa m "+ "left join contas c on c.codigo = m.tipopgto "+ " where m.data >= '2007/01/01' "+ " and m.data <= '2007/09/30' "+ " and m.loja = 1 "+ " and m.cancelado <> 'S' "+ " and m.status = '60' "+ "order by 1,m.data,6";

Entendeu agora pq eu preciso entender se existe alguma forma de montar as máscaras de data como eu quiser?

No exemplo que eu dei, eu estou usando apenas a formatação dd/mm/yyyy, em outros SQLs uso dd/mm, ou mm/yyyy, dd/mm/yy, etc, etc… e claro, isso apenas falando do nosso padrão brasileiro. Quem configura aquelas tags de i18n são técnicos (não programadores, técnicos do suporte e instalação), a partir de regras que especificamos.

Ou seja, isso não é fixo dentro do sistema de forma que eu possa fazer um substring e montar o formato como eu quiser.

E contrário ao que vc disse, não posso fazer a formatação da data na apresentação dos dados como vc sugeriu, tenho outras coisas envolvidas que me impedem de fazer isso, as quais nem vou detalhar pra não me alongar muito no que não vai me ajudar.

Bom, agora acho que consegui me expressar melhor. :slight_smile:

Conto com a ajuda de vcs!

Poxa, ngn sabe oque devo preencher nos meus <<num sei>> ?!

olá,

Você não pode fazer a formatação via código?

Eu tb trabalho com SQL-SERVER e ORACLE e é um saco esses tipos de formatações, mas aqui eu faço sempre pelo JAVA e trago do banco apenas o Date.

acabei de ver aqui, para a: mascaraDataSimplesSqlserver, utilize 3 (dd/mm/yy)

linda
esta me devendo o seu msn
para enviar uma data para o banco sem problemas de formatacao vc deve usar o Timestamp passando um long

prepStatement.setTimestamp(1 , new Timestamp(dataDaLinda().getTime()));

Bom, não sei se você pode fazer isso, mas em sua consulta SQL-SERVER dá pra limitar a quantidade dos caracteres do VARCHAR, utilize isso:

CONVERT(VARCHAR(5), getdate(), 3)

é, mas se você fizer isso que eu acabei de falar aqui em cima, aí para os outros formatos não dá certo!!!
não dá pra você criar uma tabela i18n para os formatos também???

Obrigada pela ajuda, só falta um gente!

mascaraDataMysql - %d/%m/%Y mascaraDataOracle - dd/mm/yyyy mascaraDataSqlserver - 103 mascaraDataSimplesMysql - %d/%m/%y mascaraDataSimplesOracle - dd/mm/yy mascaraDataSimplesSqlserver - 3 mascaraDiaMesMysql - %d/%m mascaraDiaMesOracle - dd/mm mascaraDiaMesSqlserver - <<esse eu não sei>>

[quote=everson_z]Não entendi :?

Você tem um programa em java para N tipo de bancos??? Ou você quer apenas usar o SQLServer???

Se for para o java, use o long para não ter problemas com qual banco vai usar e na hs de mostrar para o usuário você informa o locale.[/quote]

Eu tenho um programa pra N tipos de bancos. Não posso usar o Long.

[quote=mateuscechito] olá,

Você não pode fazer a formatação via código?

Eu tb trabalho com SQL-SERVER e ORACLE e é um saco esses tipos de formatações, mas aqui eu faço sempre pelo JAVA e trago do banco apenas o Date.

acabei de ver aqui, para a: mascaraDataSimplesSqlserver, utilize 3 (dd/mm/yy)

Bom, não sei se você pode fazer isso, mas em sua consulta SQL-SERVER dá pra limitar a quantidade dos caracteres do VARCHAR, utilize isso:

CONVERT(VARCHAR(5), getdate(), 3)

é, mas se você fizer isso que eu acabei de falar aqui em cima, aí para os outros formatos não dá certo!!!
não dá pra você criar uma tabela i18n para os formatos também???[/quote]

Por outros motivos, eu não posso fazer a formatação via código. É uma pena msm… Ah, obrigada pelo 3! :wink:

O que vc quer dizer com uma tabela i18n?! Eu tenho uma tabela assim, é lá que estão as tags que eu mencionei no post anterior… Ou vc tá falando de outra coisa que eu não entendi.

[quote=jjose] linda
esta me devendo o seu msn
para enviar uma data para o banco sem problemas de formatacao vc deve usar o Timestamp passando um long [/quote]

Eu não to devendo nada pra ngn não!!! rs…
Ah, e eu não estou com problemas pra enviar uma data pro banco…

vc não fez essa tabela:

mascaraDataMysql - %d/%m/%Y mascaraDataOracle - dd/mm/yyyy mascaraDataSqlserver - 103 mascaraDataSimplesMysql - %d/%m/%y mascaraDataSimplesOracle - dd/mm/yy mascaraDataSimplesSqlserver - 3 mascaraDiaMesMysql - %d/%m mascaraDiaMesOracle - dd/mm mascaraDiaMesSqlserver - <<esse eu não sei>>
fez!!!
não poderia ter uma outra, tipo:

tipoDadoDataSimplesSqlserver - VARCHAR tipoDadoDiaMesSqlserver - VARCHAR(5)

daí vc usaria algo do tipo:

CONVERT(" + meuResourceBundle.getString("tipoDadoDiaMesSqlserver") + ", m.data, " + meuResourceBundle.getString("mascaraDiaMesSqlserver") + ") as data  

bom, só estou tendo uma idéia, nem sei se dá pra criar uma tabela i18n nesse formato!!!

tenta assim no sqlserver
Select FORMAT(SUADATA,‘m/yyyy’)

Não entendi :?

Você tem um programa em java para N tipo de bancos??? Ou você quer apenas usar o SQLServer???

Se for para o java, use o long para não ter problemas com qual banco vai usar e na hs de mostrar para o usuário você informa o locale.