web-dev-qa-db-fra.com

Formatage date/heure personnalisé dans SQL Server

J'essaie d'écrire une procédure stockée qui sélectionne les colonnes d'une table et ajoute 2 colonnes supplémentaires au ResultSet. Ces 2 colonnes supplémentaires sont le résultat de conversions sur un champ de la table qui est un champ de date/heure.

Le champ Format de date/heure a le format suivant 'AAAA-MM-JJ HH: MM: SS.S'

Les 2 champs supplémentaires qui doivent être au format suivant:

  1. DDMMM
  2. HHMMT, où T est 'A' pour un matin et 'P' pour un soir.

Exemple: Si les données dans le champ étaient '2008-10-12 13: 19: 12.0', les champs extraits devraient contenir:

  1. 12OCT
  2. 0119P

J'ai essayé d'utiliser les formats de chaîne CONVERT, mais aucun des formats ne correspond à la sortie que je souhaite obtenir. Je songe à extraire les données de terrain via CONVERT, puis à utiliser REPLACE, mais j’ai certainement besoin d’aide ici, car je n’en suis pas sûr.

Est-ce que quelqu'un qui connaît bien les procédures stockées peut m'aider ici? Merci!

11
Pascal

Si dt ​​est votre colonne datetime, alors 

Pour 1:

SUBSTRING(CONVERT(varchar, dt, 13), 1, 2)
    + UPPER(SUBSTRING(CONVERT(varchar, dt, 13), 4, 3))

Pour 2:

SUBSTRING(CONVERT(varchar, dt, 100), 13, 2)
    + SUBSTRING(CONVERT(varchar, dt, 100), 16, 3)
5
Cade Roux

Utiliser DATENAME et envelopper la logique dans une fonction et non dans un processus stocké

declare @myTime as DateTime

set @myTime = GETDATE()

select @myTime

select DATENAME(day, @myTime) + SUBSTRING(UPPER(DATENAME(month, @myTime)), 0,4)

Retourne "14OCT"

Essayez de ne pas utiliser d'opérations basées sur des caractères/chaînes, si possible, lorsque vous travaillez avec des dates. Ils sont numériques (un flottant) et les performances vont pâtir de ces conversions de types de données. 

Creusez ces conversions pratiques que j'ai compilées au fil des ans ...

/* Common date functions */
--//This contains common date functions for MSSQL server

/*Getting Parts of a DateTime*/
    --//gets the date only, 20x faster than using Convert/Cast to varchar
    --//this has been especially useful for JOINS
    SELECT (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime))

    --//gets the time only (date portion is '1900-01-01' and is considered the "0 time" of dates in MSSQL, even with the datatype min value of 01/01/1753. 
    SELECT (GETDATE() - (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime)))


/*Relative Dates*/
--//These are all functions that will calculate a date relative to the current date and time
    /*Current Day*/
    --//now
    SELECT (GETDATE())

    --//midnight of today
    SELECT (DATEADD(ms,-4,(DATEADD(dd,DATEDIFF(dd,0,GETDATE()) + 1,0))))

    --//Current Hour
    SELECT DATEADD(hh,DATEPART(hh,GETDATE()),CAST(FLOOR(CAST(GETDATE() AS FLOAT)) as DateTime))

    --//Current Half-Hour - if its 9:36, this will show 9:30
    SELECT DATEADD(mi,((DATEDIFF(mi,(CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)), GETDATE())) / 30) * 30,(CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)))

    /*Yearly*/
    --//first datetime of the current year
    SELECT (DATEADD(yy,DATEDIFF(yy,0,GETDATE()),0))

    --//last datetime of the current year
    SELECT (DATEADD(ms,-4,(DATEADD(yy,DATEDIFF(yy,0,GETDATE()) + 1,0))))

    /*Monthly*/
    --//first datetime of current month
    SELECT (DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))

    --//last datetime of the current month
    SELECT (DATEADD(ms,-4,DATEADD(mm,1,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))))

    --//first datetime of the previous month
    SELECT (DATEADD(mm,DATEDIFF(mm,0,GETDATE()) -1,0))

    --//last datetime of the previous month
    SELECT (DATEADD(ms, -4,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0)))

    /*Weekly*/
    --//previous monday at 12AM
    SELECT (DATEADD(wk,DATEDIFF(wk,0,GETDATE()) -1 ,0))

    --//previous friday at 11:59:59 PM
    SELECT (DATEADD(ms,-4,DATEADD(dd,5,DATEADD(wk,DATEDIFF(wk,0,GETDATE()) -1 ,0))))

    /*Quarterly*/
    --//first datetime of current quarter
    SELECT (DATEADD(qq,DATEDIFF(qq,0,GETDATE()),0))

    --//last datetime of current quarter
    SELECT (DATEADD(ms,-4,DATEADD(qq,DATEDIFF(qq,0,GETDATE()) + 1,0)))
24
StingyJack

Vous pouvez utiliser la commande suivante dans SQL Server pour le créer:

select FORMAT(getdate(), N'yyyy-MM-ddThh:mm:ss')
6
Mehdi

Ne répondez pas à votre question de manière spécifique, mais n'est-ce pas quelque chose qui devrait être traité par la couche de présentation de votre application. En procédant comme vous le décrivez, vous créez un traitement supplémentaire du côté de la base de données et vous ajoutez du trafic réseau supplémentaire (en supposant que la base de données existe sur un ordinateur différent de celui de l'application), ce qui peut facilement être calculé du côté de l'application, avec une date plus riche traitement des bibliothèques, ainsi que plus agnostique de la langue, en particulier dans le cas de votre premier exemple qui contient le nom abrégé du mois. Quoi qu'il en soit, les réponses que les autres vous donnent devraient vous indiquer la bonne direction si vous décidez quand même de suivre cette voie.

6
Kibbee

Le champ Format de date/heure a le format suivant 'AAAA-MM-JJ HH: MM: SS.S'

Cette déclaration est fausse. C’est exactement comme cela que Enterprise Manager ou SQL Server choisit de show la date. En interne, il s'agit d'une valeur binaire de 8 octets. C'est pourquoi certaines des fonctions publiées par Andrew fonctionnent si bien.

Kibbee fait également valoir un argument valable et, dans un monde parfait, je serais d'accord avec lui. Cependant, vous souhaitez parfois lier les résultats de la requête directement pour afficher le contrôle ou les widgets et vous ne pouvez vraiment pas formater. Et parfois, la couche de présentation réside sur un serveur Web encore plus occupé que la base de données. En gardant cela à l'esprit, ce n'est pas forcément une mauvaise chose de savoir comment faire cela en SQL.

4
Joel Coehoorn

Yes Depart est une solution pour ça mais je pense que ce genre de méthodes sont des longs trajets!

SERVEUR SQL:

SELECT CAST(DATEPART(DD,GETDATE()) AS VARCHAR)+'/'
+CAST(DATEPART(MM,GETDATE()) AS VARCHAR)
+'/'+CAST(DATEPART(YYYY,GETDATE()) AS VARCHAR)
+' '+CAST(DATEPART(HH,GETDATE()) AS VARCHAR)
+':'+CAST(DATEPART(MI,GETDATE()) AS VARCHAR)

Oracle:

Select to_char(sysdate,'DD/MM/YYYY HH24:MI') from dual

Vous pouvez écrire votre propre fonction de cette façon, vous pouvez vous en débarrasser.

http://sql.dzone.com/news/custom-date-formatting-sql-ser

select myshortfun(getdate(),myformat)
GO
1
Davut Gürbüz

J'ajoute cette réponse (pour moi-même) comme étant pertinente pour la mise en forme personnalisée. 

Pour souligner yyyy_MM_dd 

REPLACE(SUBSTRING(CONVERT(VARCHAR, @dt, 120), 1, 10),'-','_')
0
Pawel Cioch

Vous allez avoir besoin de DATEPART ici. Vous pouvez concaténer les résultats des appels DATEPART.

Pour obtenir les abréviations du mois, vous pourrez peut-être utiliser DATENAME; Si cela ne fonctionne pas pour vous, vous pouvez utiliser une instruction CASE sur DATEPART.

DATEPART fonctionne également pour le champ Heure.

Je peux penser à deux façons d’obtenir l’indicateur AM/PM, notamment en comparant les nouvelles dates construites avec DATEPART ou en calculant le nombre total de secondes écoulées dans la journée, et en comparant cela aux seuils AM/PM connus.

0
Paul Williams

S'il s'agit de quelque chose de plus spécifique, comme DateKey (yyyymmdd), dont vous avez besoin pour les modèles dimensionnels, je suggère quelque chose sans conversion ni conversion:

DECLARE @DateKeyToday int = (SELECT 10000 * DATEPART(yy,GETDATE()) + 100 * DATEPART(mm,GETDATE()) + DATEPART(dd,GETDATE()));
PRINT @DateKeyToday
0
Mark

dans MS SQL Server, vous pouvez faire:

SET DATEFORMAT ymd

année mois jour,

0
ch2o