IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Trigger calcul date


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2010
    Messages : 127
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 999
    Billets dans le blog
    6
    Par défaut
    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
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre éprouvé
    Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2010
    Messages : 127
    Par défaut
    Merci

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    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.

  5. #5
    Membre éprouvé
    Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2010
    Messages : 127
    Par défaut
    Oui c'est juste. Mais comment définit-on une colonne calculée?

  6. #6
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Dans votre cas, se serait :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  7. #7
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Haute Garonne (Midi Pyrénées)

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

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CREATE INDEX IXNCMaTable
    ON dbo.MaTable(DureeTravail)
    Si vous la rendez pas visible à l'utilisateur, il suffit de la persister :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE VIEW VDureeTravail
    AS
    	SELECT	desColonnes
    		, DATEDIFF(hour, DateDebut, DateFin) / 24.0 AS DureeTravail
    	FROM	dbo.MaTable
    Puis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT	desColonnes
    FROM	dbo.VDureeTravail
    WHERE	[... ] -- Mais pas WHERE DureeTravail ...
    @++

  8. #8
    Membre éprouvé
    Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2010
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Conseil

    Informations forums :
    Inscription : Novembre 2010
    Messages : 127
    Par défaut
    Merci beaucoup pour les conseils elsuket

Discussions similaires

  1. Calcul date veille
    Par njogou dans le forum Linux
    Réponses: 2
    Dernier message: 10/11/2006, 13h00
  2. parcour d'une table et calcul date?
    Par dj_techno dans le forum Bases de données
    Réponses: 4
    Dernier message: 25/08/2006, 09h02
  3. [Pl/Sql] Trigger et date, heure system
    Par brigadier dans le forum Oracle
    Réponses: 7
    Dernier message: 03/08/2006, 12h34
  4. [WB9] Calcul Date de Naissance
    Par Angeldu74 dans le forum WebDev
    Réponses: 1
    Dernier message: 02/06/2006, 10h46
  5. Réponses: 5
    Dernier message: 21/03/2006, 21h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo