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 :

[MSSQL 2000]Un petit trigger avec test de chevauchement de périodes


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 36
    Par défaut [MSSQL 2000]Un petit trigger avec test de chevauchement de périodes
    Bonjour à tous,

    Je galère depuis un petit moment sur un trigger qui devrait empêcher qu'un individu puisse exercer deux emplois en même temps. Ça se passe donc sur une table exercer_travail qui, sur un MCD, ferait association entre une table employeur et une table individu.

    Je vous montre où est-ce que j'ai commencé à m'embarquer. Ça ressemble à un trigger avec une petite tendance curseur. Je ne savais pas si on pouvais faire ce genre d'association, mais à priori rien ne s'y opposait. Après il y a le fait qu'il n'y ait pas d'OVERLAPS avec MSSQL2000 donc j'ai dû improviser (à partir de ce message très utile de SQLpro). Enfin, pour ce qui est des CONVERT j'ai de sérieux doutes sur leur bonne utilisation.
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    create trigger contrainte_pas_2_emplois_en_meme_temps
    on exercer_travail
    for insert
    BEGIN
    	declare @dateDbtIns int;
    	declare @dateFinIns int;
    	declare @curseur cursor;
    	declare @date_debut int;
    	declare @date_fin int;
    	declare @msg char(110);
    	declare @errno int;
     
    	BEGIN
    		select @dateDbtIns=CONVERT(INTEGER, inserted.code_date, 112) from inserted;
    		select @dateFinIns=CONVERT(INTEGER, inserted.date_fin, 112) from inserted;
     
    		set @curseur = cursor for (select CONVERT(INTEGER, exercer_travail.code_date, 112), CONVERT(INTEGER, exercer_travail.date_fin, 112) from exercer_travail, inserted where exercer_travail.code_individu = inserted.code_individu);
    		open @curseur
    		fetch next from @curseur into @date_debut, @date_fin
    		while @@FETCH_STATUS = 0
    		BEGIN
    			/*Un gros if bien lourd parce qu'apparemment OVERLAPS n'existe pas sur MSSQL 2000 */
    			if((@dateDbtIns > @date_debut AND (@dateDbtIns < @date_fin OR @dateFinIns < @date_fin))
    				OR (@date_debut > @dateDbtIns AND (@date_debut < @dateFinIns OR @date_fin < @dateFinIns))
    				OR (@dateDbtIns = @date_debut AND (@dateFinIns IS NOT NULL AND @date_fin IS NOT NULL)))
    			BEGIN
    				set @msg = 'Cette personne exerce déjà un emploi dans cette période. Une personne ne peut exercer 2 emplois en même temps.';
    				set @errno = 30003;
    				goto erreur;
    			END
    			else
    			BEGIN
    				commit
    			END
    			fetch next from @curseur into @date_debut, @date_fin
    		END
    		return
    		erreur:
    			raiserror @errno @msg;
    			rollback transaction;
    	END
    END
    En bref, je n'arrive à rien. Ça ne marche pas du tout. Je n'ai pas de message d'erreur à la création du trigger mais je n'en ai pas non plus lors des insertions avec des dates chevauchantes.

    Je m'en remet à vous pour savoir ce qui ne va pas.

  2. #2
    Membre très actif Avatar de hazamor
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2008
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2008
    Messages : 179
    Par défaut
    else
    BEGIN
    commit
    END
    D'abord cette commit est fausse, parceque il suffit que la première ligne testée pose le FAUX pour la condition (çàd ne chevauche pas avec les dates inseré) alors la ligne inserée sera commité et tu ne peut pas le retourner (Rollback).


    En suite, Essayons de citer les cas possibles de relations entre deux couples de dates, pour savoir s'il ya un erreur logique de teste:

    Soit A,B deux dates
    et C,D de même

    1) ABCD,CDAB: aucune relation

    2) ACBD : AB chevauche CD (Déjà fait)
    (@dateDbtIns > @date_debut AND (@dateDbtIns < @date_fin OR @dateFinIns < @date_fin)
    3) CADB: CD chevauche AB (Déjà fait)
    (@date_debut > @dateDbtIns AND (@date_debut < @dateFinIns OR @date_fin < @dateFinIns)
    4) CABD: CD contient AB (Déjà fait)
    (@date_debut > @dateDbtIns AND (@date_debut < @dateFinIns OR @date_fin < @dateFinIns)
    5) ACDB: AB contient CD (Déjà fait)
    (@dateDbtIns > @date_debut AND (@dateDbtIns < @date_fin OR @dateFinIns < @date_fin)

    6) ACD, CAD ??: ç'est à dire si B est null (dans notre exemple @dateFinIns est nulle)


    Encore, pourquoi tu converte les dates en entiers? L'operateur ">" fonctionne sur les dates!



  3. #3
    Membre très actif Avatar de hazamor
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2008
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2008
    Messages : 179
    Par défaut
    L'essentiel corriger le "COMMIT"
    mettre le dans la place qui convient ,çàd hors de la boucle.


  4. #4
    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,

    Il faut en tout premier lieu commencer par supprimer le curseur.
    Un curseur est itératif, donc lent dans une base de données, qui est conçue pour traiter des ensembles et pas pour effectuer des traitements ligne à ligne comment dans un langage par objet, par exemple.
    Pour vous en dégoûter, voici un bon article de SQLPro (encore ! ) à ce sujet (COMMANDEMENT N°4, mais les autres sont bons aussi )

    Votre trigger ne produit pas le traitement recherché parce que vous comparez le contenu de la table virtuelle INSERTED à elle-même, ce qui ne vous retourne donc aucune différence :
    - @dateDbtIns et @dateFinIns sont valuées à partir de INSERTED
    - @date_debut et @date_fin sont valuées par le FETCH du curseur sur la même INSERTED.

    Pour résumer, lors de l'exécution d'un déclencheur :

    - les tables virtuelles INSERTED et DELETED ont strictement la même structure de données que la table cible, à laquelle est attachée le déclencheur,
    - La table virtuelle INSERTED contient les nouvelles valeurs appliquées à la table cible lors d'un INSERT ou d'un UPDATE,
    - La table virtuelle DELETED contient les anciennes valeurs contenues dans la table cible lors d'un DELETE ou d'un UPDATE.

    Comme les tables virtuelles et la table cible ont la même structure, nous pouvons, pour effectuer la recherche de la requête, effectuer une auto-jointure sur la table exercer_travail.

    Comme vous ne fournissez pas le DDL (et un jeu d'essai aurait été encore mieux ! ), je me suis muni de ceux-ci :

    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
    CREATE TABLE exercer_travail
    (
    	IDEmploye INT,
    	code_date DATETIME,
    	date_fin DATETIME
    )
    GO
     
    INSERT INTO exercer_travail VALUES (1, '01/01/2009 08:00:00.000', '03/01/2009 08:00:00.000')
    INSERT INTO exercer_travail VALUES (1, '02/01/2009 08:00:00.000', '04/01/2009 08:00:00.000')
    INSERT INTO exercer_travail VALUES (1, '06/01/2009 08:00:00.000', '08/01/2009 08:00:00.000')
    INSERT INTO exercer_travail VALUES (1, '06/01/2009 08:00:00.000', '07/01/2009 08:00:00.000')
    INSERT INTO exercer_travail VALUES (2, '01/01/2009 08:00:00.000', '03/01/2009 08:00:00.000')
    INSERT INTO exercer_travail VALUES (2, '02/01/2009 08:00:00.000', '04/01/2009 08:00:00.000')
    INSERT INTO exercer_travail VALUES (2, '06/01/2009 08:00:00.000', '08/01/2009 08:00:00.000')
    INSERT INTO exercer_travail VALUES (2, '06/01/2009 08:00:00.000', '07/01/2009 08:00:00.000')
    Dans la requête suivante, je considère les tables dérivées PERIODE_1 et PERIODE_2, comme, respectivement, A et B d'une part, et exercer_travail et INSERTED d'autre part :

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    SELECT PERIODE_1.IDEmploye,
    		PERIODE_1.DateDeb,
    		PERIODE_1.DateFin,
    		PERIODE_2.DateDeb,
    		PERIODE_2.DateFin
    FROM (
    		SELECT A.IDEmploye,
    				A.code_date,
    				A.date_fin,
    				COUNT(*)
    		FROM dbo.exercer_travail A
    		JOIN dbo.exercer_travail B
    			ON A.IDEmploye = B.IDEmploye
    			AND A.code_date <= B.code_date
    			AND A.date_fin <= B.date_fin
    		GROUP BY A.IDEmploye,
    				A.code_date,
    				A.date_fin
    	) PERIODE_1 (IDEmploye, DateDeb, DateFin, Rang)
    JOIN(
    		SELECT A.IDEmploye,
    				A.code_date,
    				A.date_fin,
    				COUNT(*)
    		FROM dbo.exercer_travail A
    		JOIN dbo.exercer_travail B
    			ON A.IDEmploye = B.IDEmploye
    			AND A.code_date <= B.code_date
    			AND A.date_fin <= B.date_fin
    		GROUP BY A.IDEmploye,
    				A.code_date,
    				A.date_fin
    	) PERIODE_2 (IDEmploye, DateDeb, DateFin, Rang)
    ON PERIODE_1.IDEmploye = PERIODE_2.IDEmploye
    AND
    (
    	(
    		PERIODE_1.DateDeb > PERIODE_2.DateDeb
    		AND PERIODE_1.DateDeb < PERIODE_2.DateFin
    		AND PERIODE_2.DateFin > PERIODE_1.DateDeb
    		AND PERIODE_2.DateFin < PERIODE_1.DateFin
    	)
    	OR
    	(
    		PERIODE_2.DateDeb > PERIODE_1.DateDeb
    		AND PERIODE_2.DateDeb < PERIODE_1.DateFin
    		AND PERIODE_2.DateFin > PERIODE_1.DateFin
    	)
    	OR
    	(
    		PERIODE_2.DateDeb >= PERIODE_1.DateDeb
    		AND PERIODE_2.DateFin <= PERIODE_1.DateFin
    	)
    )
    AND PERIODE_1.Rang < PERIODE_2.Rang
    La même requête pourrait être simplifiée sous SQL Server 2005 en se servant de la fonction de fenêtrage ROW_NUMBER() OVER(), et d'une CTE:

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    WITH
    	CTE_PERIODE AS
    	(
    		SELECT IDEmploye,
    				code_date AS DateDeb,
    				date_fin AS DateFin,
    				ROW_NUMBER() OVER(PARTITION BY IDEmploye ORDER BY code_date) Rang
    		FROM dbo.exercer_travail
    	)
    SELECT PERIODE_1.IDEmploye,
    		PERIODE_1.DateDeb AS DateDeb1,
    		PERIODE_1.DateFin AS DateFin1,
    		PERIODE_2.DateDeb AS DateDeb2,
    		PERIODE_2.DateFin AS DateFin2
    FROM CTE_PERIODE AS PERIODE_1
    JOIN CTE_PERIODE AS PERIODE_2
    	ON PERIODE_1.IDEmploye = PERIODE_2.IDEmploye
    	AND
    	(
    		(
    			PERIODE_1.DateDeb > PERIODE_2.DateDeb
    			AND PERIODE_1.DateDeb < PERIODE_2.DateFin
    			AND PERIODE_2.DateFin > PERIODE_1.DateDeb
    			AND PERIODE_2.DateFin < PERIODE_1.DateFin
    		)
    		OR
    		(
    			PERIODE_2.DateDeb > PERIODE_1.DateDeb
    			AND PERIODE_2.DateDeb < PERIODE_1.DateFin
    			AND PERIODE_2.DateFin > PERIODE_1.DateFin
    		)
    		OR
    		(
    			PERIODE_2.DateDeb >= PERIODE_1.DateDeb
    			AND PERIODE_2.DateFin <= PERIODE_1.DateFin
    		)
    	)
    	AND PERIODE_1.Rang < PERIODE_2.Rang
    En remplaçant l'alias B de la table exercer_travail par la table virutelle INSERTED, le code de votre trigger devient :

    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    CREATE TRIGGER contrainte_pas_2_emplois_en_meme_temps
    ON exercer_travail
    FOR INSERT
    AS
    BEGIN
    	DECLARE @szErreur VARCHAR(256)
     
    	-- Collecte dans @szErreur de la liste des IDEmploye, séparés par
    	-- des virgules, qui ont des périodes de travail qui se chevauchent
    	SELECT @szErreur = ISNULL(@szErreur, '') + CAST(IDEmploye AS VARCHAR(10)) + ', '
    	FROM
    	(
    		SELECT PERIODE_1.IDEmploye,
    					PERIODE_1.DateDeb1,
    					PERIODE_1.DateFin1,
    					PERIODE_2.DateDeb2,
    					PERIODE_2.DateFin2
    		FROM (
    				SELECT A.IDEmploye,
    						A.code_date,
    						A.date_fin,
    						COUNT(*)
    				FROM dbo.exercer_travail A
    				JOIN INSERTED B
    					ON A.IDEmploye = B.IDEmploye
    					AND A.code_date <= B.code_date
    					AND A.date_fin <= B.date_fin
    				GROUP BY A.IDEmploye,
    						A.code_date,
    						A.date_fin
    			) PERIODE_1 (IDEmploye, DateDeb1, DateFin1, Rang)
    		JOIN(
    				SELECT A.IDEmploye,
    						A.code_date,
    						A.date_fin,
    						COUNT(*)
    				FROM dbo.exercer_travail A
    				JOIN INSERTED B
    					ON A.IDEmploye = B.IDEmploye
    					AND A.code_date <= B.code_date
    					AND A.date_fin <= B.date_fin
    				GROUP BY A.IDEmploye,
    						A.code_date,
    						A.date_fin
    			) PERIODE_2 (IDEmploye, DateDeb2, DateFin2, Rang)
    		ON PERIODE_1.IDEmploye = PERIODE_2.IDEmploye
    		AND
    		(
    			(
    				PERIODE_1.DateDeb1 > PERIODE_2.DateDeb2
    				AND PERIODE_1.DateDeb1 < PERIODE_2.DateFin2
    				AND PERIODE_2.DateFin2 > PERIODE_1.DateDeb1
    				AND PERIODE_2.DateFin2 < PERIODE_1.DateFin1
    			)
    			OR
    			(
    				PERIODE_2.DateDeb2 > PERIODE_1.DateDeb1
    				AND PERIODE_2.DateDeb2 < PERIODE_1.DateFin1
    				AND PERIODE_2.DateFin2 > PERIODE_1.DateFin1
    			)
    			OR
    			(
    				PERIODE_2.DateDeb2 >= PERIODE_1.DateDeb1
    				AND PERIODE_2.DateFin2 <= PERIODE_1.DateFin1
    			)
    		)
    		AND PERIODE_1.Rang < PERIODE_2.Rang
    	) TMP (IDEmploye, DateDeb1, DateFin1, DateDeb2, DateFin2)
     
    	-- Si la chaîne est valuée (<=> IS NOT NULL), alors on lève un exception
    	-- et on défait la transaction
    	IF @szErreur IS NOT NULL
    	BEGIN
    		SET @szErreur = 'Les employés d''identifiant %s ne peuvent avoir des périodes d''emploi se chevauchant.', 16, 1, @szErreur)
    		RAISERROR(@szErreur, 16, 1)
    		ROLLBACK TRANSACTION
    	END
    	-- Sinon, il n'y a pas d'employés pour lesquels on a tenté d'ajouter des emplois dont les périodes
    	-- chevauchent des périodes durant lesquelles l'employé est déjà affecté à une mission
    	-- La transaction sera donc validée automatiquement
    END
    @++

  5. #5
    Membre très actif Avatar de hazamor
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2008
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2008
    Messages : 179
    Par défaut
    Citation Envoyé par elsuket Voir le message
    Votre trigger ne produit pas le traitement recherché parce que vous comparez le contenu de la table virtuelle INSERTED à elle-même, ce qui ne vous retourne donc aucune différence :
    - @dateDbtIns et @dateFinIns sont valuées à partir de INSERTED
    - @date_debut et @date_fin sont valuées par le FETCH du curseur sur la même INSERTED.
    Effectivement, si vous voulez sauvegardeez le travaille avec le curseur commencez par supprimer la condition de WHERE:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SELECT @dateDbtIns=CONVERT(INTEGER, inserted.code_date, 112) FROM inserted;
    
    SELECT @dateFinIns=CONVERT(INTEGER, inserted.date_fin, 112) FROM inserted;
    
    SET @curseur = cursor FOR (SELECT CONVERT(INTEGER, exercer_travail.code_date, 112), CONVERT(INTEGER, exercer_travail.date_fin, 112) FROM exercer_travail, inserted

    Pour elsuket vous avez raison d'eviter de travailler avec le curseur, et de travailler avec des requetes.

  6. #6
    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, si vous voulez sauvegardeez le travaille avec le curseur commencez par supprimer la condition de WHERE
    Cela revient à effectuer le produit cartésien de la table cible et de la table INSERTED, ce qui n'a pas d'intérêt.
    D'autre part une jointure ne se spécifie pas par un WHERE mais par un JOIN.

    vous avez raison d'éviter de travailler avec le curseur, et de travailler avec des requetes.
    Les curseurs sont à bannir autant que cela est possible, et plus encore des triggers qui doivent s'exécuter le plus rapidement possible

    @++

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    36
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2009
    Messages : 36
    Par défaut
    Eh bien, merci à vous trois pour votre aide !

    elsuket, je crois avoir à peu près compris l'idée de départ. Mais je dois dire que je me suis noyé dans tout ce code tellement il y a de jointures et de requêtes.

    Apparemment, la solution la plus optimisée est celle que vous proposez SQLpro. Je n'avais jamais vu ça auparavant, mais je pense comprendre. Et la méthode me plait beaucoup.

    Après, étant donné que je risque de devoir expliquer ça devant un jury, il vaut mieux que je comprenne à 100% ce qui est fait. Donc, dans un premier temps je vais essayer de bien décortiquer le code, le tester, peut-être en parler avec mon prof d'info. Et, si au final ça ne le fait pas, je me rabattrai sur mon trigger avec curseur minable.

    Mais, à première vue, ça n'a pas l'air bien sorcier.

    Je teste, je décrypte et si besoin est, je repasserai.


  8. #8
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 002
    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 : 22 002
    Billets dans le blog
    6
    Par défaut
    Mais non, parles de tes échecs, de tes expériences et de l'aide que tu as eu.
    Teste donc toutes ces solutions et essaye par toi même de montrer celle qui est la plus intéressante.
    Internet est fait pour cela et on ne t'en voudra pas d'avoir intelligemment essayer de trouver la meilleurs solution sur le web, en doutant de celle que tu avait commencer à élaborer !
    Le jury saura aprécier.

    (et c'est un vis de juriste... si tu lis ma signature !)

    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/ * * * * *

Discussions similaires

  1. [MySQL-5.6] TRIGGER avec test sur les minute d'une date
    Par Squale76 dans le forum Requêtes
    Réponses: 1
    Dernier message: 28/01/2015, 16h41
  2. [MSSQL 2000] Construire un fichier XML AUTO avec une valeur
    Par carjo dans le forum Développement
    Réponses: 7
    Dernier message: 22/06/2010, 17h33
  3. Réponses: 1
    Dernier message: 09/11/2007, 09h37
  4. [Débutant][|MSSQL 2000] problème avec Overlaps
    Par Spoutnik dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 14/11/2006, 10h33
  5. [debutant] pour debbuger un petit prog avec menu
    Par niluge01 dans le forum Windows
    Réponses: 3
    Dernier message: 22/11/2003, 14h03

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