Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server > Développement
Développement Forum d'entraide sur le Transact-SQL, le CLR, les procédures stockées, les triggers, les requêtes SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 29/06/2011, 09h15   #1
Invité régulier
 
Inscription : novembre 2010
Messages : 34
Détails du profil
Informations forums :
Inscription : novembre 2010
Messages : 34
Points : 7
Points : 7
Par défaut Trigger calcul date

Bonjour,
J'essaye de faire un trigger pour calculer une durée entre une date de début et une date de fin:
Code :
1
2
3
4
5
6
7
 
CREATE TRIGGER [dbo].[Duree] 
   ON  [MaTable]
   AFTER INSERT,DELETE,UPDATE
   AS UPDATE MaTable
 
SET DureeTravail = DateFin-DateDebut
Mais je reçois ce genre de résultat:
1900-01-02 15:33:00.000
J'aimerais avoir une durée avec Xjours ou Xheures.

Je pense qu'il faut utiliser un DATEDIFF mais je ne m'en sors pas trop avec la syntaxe DECLARE SET...

Merci d'avance
chadoum est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/06/2011, 12h27   #2
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 954
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 954
Points : 17 774
Points : 17 774
Utilisez un
DATEDIFF(HOUR, DateDebut, DateFin) / 24.0 => ceci vous donnera un nombre de jour décimal (par exemple 2,5 jours, soit 2 jours 12 h).

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/06/2011, 12h48   #3
Invité régulier
 
Inscription : novembre 2010
Messages : 34
Détails du profil
Informations forums :
Inscription : novembre 2010
Messages : 34
Points : 7
Points : 7
Merci
chadoum est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/06/2011, 14h17   #4
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
Bonjour

Cela dit, si j'ai bien compris, votre table contient :
- une colonne DateDebut
- une colonne DateFin
- une colonne Duree

Il serait sans doute préférable de définir cette dernière colonne comme colonne calculée, éventuellement persistante. Vous pouvez ainsi vous passer de votre trigger qui, soit dit en passant, recalcule la durée pour toutes les lignes de votre table à chaque insertion.
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 29/06/2011, 14h56   #5
Invité régulier
 
Inscription : novembre 2010
Messages : 34
Détails du profil
Informations forums :
Inscription : novembre 2010
Messages : 34
Points : 7
Points : 7
Oui c'est juste. Mais comment définit-on une colonne calculée?
chadoum est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/06/2011, 15h05   #6
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
Dans votre cas, se serait :

Code SQL :
1
2
3
4
5
6
 
CREATE TABLE MaTable(
    DateDebut DATETIME,
    DateFin DATETIME,
    Duree AS (DATEDIFF(HOUR, DateDebut, DateFin) / 24.0) PERSISTED
)

Le PERSISTED est optionel. S'il est spécifié, le résultat du calcul est stocké au même titre qu'une autre colonne au lieu d’être calculé à la volée lors des requêtes. Cela permet de créer des index portant sur cette colonne.
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 29/06/2011, 15h14   #7
Invité régulier
 
Inscription : novembre 2010
Messages : 34
Détails du profil
Informations forums :
Inscription : novembre 2010
Messages : 34
Points : 7
Points : 7
Merci pour l'info!
chadoum est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/06/2011, 15h15   #8
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 669
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2005
Messages : 4 669
Points : 8 729
Points : 8 729
Bonjour,

Effectivement plusieurs erreurs dans ce trigger, notamment celles qu'a relevé aieeeuuuuu.

En outre recalculer la durée de travail lors d'une suppression de ligne n'a plus d'intérêt puisque la ligne n'est plus là.
Cela donnerait dont le trigger suivant :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
CREATE TRIGGER TR_A_IU_MaTable
	ON dbo.MaTable
	AFTER INSERT, UPDATE
AS 
BEGIN
	SET NOCOUNT ON
 
	IF 
	(
		UPDATE(DateDebut) 
		OR UPDATE(DateFin)
	)
	BEGIN
		UPDATE		dbo.MaTable
		SET		DureeTravail = DATEDIFF(hour, I.DateDebut, I.DateFin) / 24.0
		FROM		dbo.MaTable AS T
		INNER JOIN	inserted AS I ON T.primary_key = I.primary_key
	END
END
Un trigger DML (sur INSERT/UPDATE/DELETE) expose 2 tables virtuelles : inserted et deleted, qui ont strictement la même structure que la table à laquelle est attachée le trigger, et qui, dans le cas :

- d'un INSERT, n'est accessible que la table virtuelle inserted qui expose les valeurs des lignes qui viennent d'être ajoutées
- d'un UPDATE, sont accessibles les deux tables virtuelles inserted et deleted, qui respectivement exposent les anciennes et nouvelles valeurs pour toutes les lignes affectées par l'UPDATE
- d'un DELETE, n'est accessible que la table virtuelle deleted qui expose les valeurs des lignes qui viennent d'être supprimées.

La fonction UPDATE() permet de vérifier si une colonne a été mise à jour.
Dans le cas d'un UPDATE d'autres colonnes de la table MaTable que DateDebut et DateFin, il n'y a pas besoin de recalculer l'intervalle.

Mais comme l'a suggéré aieeeuuuuu, le mieux est d'utiliser une colonne calculée, ou encore de faire une vue.
Tout dépend si vous avez des requêtes qui vont filtrer sur la colonne DureeTravail.

Si c'est le cas, le mieux est de faire une colonne calculée :

Code :
1
2
3
4
5
6
ALTER TABLE dbo.MaTable
DROP COLUMN DureeTravail
GO
 
ALTER TABLE dbo.MaTable
ADD DureeTravail AS (DATEDIFF(hour, DateDebut, DateFin) / 24.0)
Puis de créer un index dessus pour faciliter les recherches (il n'y a pas besoin de la persister si vous ne la rendez pas visible à l'utilisateur)

Code :
1
2
CREATE INDEX IXNCMaTable
ON dbo.MaTable(DureeTravail)
Si vous la rendez pas visible à l'utilisateur, il suffit de la persister :

Code :
1
2
ALTER TABLE dbo.MaTable
ADD DureeTravail AS (DATEDIFF(hour, DateDebut, DateFin) / 24.0) PERSISTED
L'ordre de création de l'index est le même.

Maintenant s'il s'agit simplement d'afficher la durée de travail, et que vous ne filtrez pas dessus :

- soit vous faites la colonne calculée (1er script), et vous interrogez la table
- soit vous implémentez la vue suivante, qui s'interroge comme une table :

Code :
1
2
3
4
5
CREATE VIEW VDureeTravail
AS
	SELECT	desColonnes
		, DATEDIFF(hour, DateDebut, DateFin) / 24.0 AS DureeTravail
	FROM	dbo.MaTable
Puis :

Code :
1
2
3
SELECT	desColonnes
FROM	dbo.VDureeTravail
WHERE	[... ] -- Mais pas WHERE DureeTravail ...
@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 30/06/2011, 09h18   #9
Invité régulier
 
Inscription : novembre 2010
Messages : 34
Détails du profil
Informations forums :
Inscription : novembre 2010
Messages : 34
Points : 7
Points : 7
Merci beaucoup pour les conseils elsuket
chadoum est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 02h29.


 
 
 
 
Partenaires

Hébergement Web