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 :

[SQL serveur 2000] if NOT EXISTS


Sujet :

Développement SQL Server

  1. #1
    Membre éclairé Avatar de s.lennon
    Inscrit en
    Juin 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Juin 2009
    Messages : 66
    Par défaut [SQL serveur 2000] if NOT EXISTS
    Bonjour.

    Je suppose que la solution est toute bête, mais après une journée sur cette procédure, je n'y vois plus très clair... Je débute en T-SQL et je voudrais insérer un résultat dans une table s'il n'existe pas déjà.

    J'ai une table SUP_PARCELLE avec deux champs : noeud et niveau. J'ai quelques valeurs :

    noeud niveau
    ------------------
    1 NULL
    NULL 1
    NULL 2

    Je voudrais insérer de nouvelles valeurs "niveau" à condition qu'elles ne figurent pas déjà dans la table.

    J'ai essayé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    -- insertion dans SUP_PARCELLE
    IF NOT EXISTS (SELECT niveau FROM sup_parcelle WHERE niveau = @id_niveau)
      INSERT INTO sup_parcelle(niveau) VALUES (@id_niveau)
    mais ça ne fonctionne pas, et j'ignore pourquoi... Une idée ?

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

    Avec quelles valeurs de @id_niveau testez-vous ?
    Donnez nous le DDL de votre table (CREATE TABLE ...)
    Quel est le libellé exact de l'erreur que vous obtenez ?

    @++

  3. #3
    Membre éclairé Avatar de s.lennon
    Inscrit en
    Juin 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Juin 2009
    Messages : 66
    Par défaut
    Hum, je sens que j'ai fait une boulette là... Y'a pas de clé primaire en fait, vu que c'est une table qui me sert juste le temps de quelques manip', je pensais que ce n'était pas nécessaire ...

    Je n'ai pas de message d'erreurs.

    Ce morceau de code est dans une boucle. Dans mes tests, la première valeur existe déjà et ne doit pas être insérée... Mais au final, aucune valeur n'est insérée !

    Pour l'instant, j'ai trouvé un truc un peu "bidouillé" mais qui marche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    IF EXISTS (SELECT niveau FROM sup_parcelle WHERE niveau = @id_niveau)
    	PRINT 'pas insertion'
    ELSE
    	INSERT INTO sup_parcelle(niveau) VALUES (@id_niveau)
    Je ne sais pas si mettre l'ensemble de la procédure peut être utile ?


    EDIT :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE TABLE sup_parcelle(noeud INT, niveau INT)

  4. #4
    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
    Une table sans clef ne permet pas de repérer un ligne précise et de plus s'avère lente pour les performances....
    http://blog.developpez.com/sqlpro/p7...d-index-ni-de/

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

  5. #5
    Membre éclairé Avatar de s.lennon
    Inscrit en
    Juin 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Juin 2009
    Messages : 66
    Par défaut
    La seule exception à cette règle est pour les petites tables, par exemple celles pour lesquelles le volume des données ne représente pas plus d'une page. Mais même dans ce dernier cas, la présence d'index ou non ne permettra pas de voir la différence, et surtout petite table peut devenir grosse !
    Loin de moi l'idée d'insister, je veux juste essayer de bien comprendre :
    dans mon cas, il s'agit d'une "table" qui me permet de stocker quelques valeurs le temps de ma procédure (je la vide à la fin), simplement parce que je ne sais pas stocker plusieurs valeurs autrement...

    Le but de ma procédure est de récupérer plusieurs valeurs pour ensuite supprimer toutes les données associées. Je n'ai pas réussi à faire une sorte de valeur "globale" qui ne serait pas remise à zéro à chaque tour de boucle ; du coup j'ai créer une table avec une colonne pour stocker ces valeurs.

    D'où deux questions :
    - cette table ne deviendra jamais "grosse", elle n'est pas liée (et ne le sera jamais) à d'autres tables, une clé primaire est-elle vraiment nécessaire ?
    - existe-t-il une autre façon de stocker ces valeurs ?

  6. #6
    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
    Citation Envoyé par s.lennon Voir le message
    - cette table ne deviendra jamais "grosse", elle n'est pas liée (et ne le sera jamais) à d'autres tables, une clé primaire est-elle vraiment nécessaire ?
    En principe toute table doit avoir une clef. C'est obligatoire dans la théorie relationnelle, mais SQL permet de ne pas en mettre pour des raisons de facilité qui peuvent se retourner contre vous.


    Citation Envoyé par s.lennon Voir le message
    - existe-t-il une autre façon de stocker ces valeurs ?
    Il n'est sans doute pas besoin de les stocker puisqu'à l'évidence vous les avez déjà !

    Postez TOUT le code de votre traitement avec le DDL de vos tables et nous vous aiderons.

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

  7. #7
    Membre éclairé Avatar de s.lennon
    Inscrit en
    Juin 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Juin 2009
    Messages : 66
    Par défaut
    Les tables dont j'ai besoin :
    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
    CREATE TABLE PARCELLE (
      id_parcelle INTEGER NOT NULL IDENTITY,
      parcelle_mere INTEGER,
      denomination_parcelle VARCHAR(30) NOT NULL,
      densite_parcelle NUMERIC NULL,
      surface_parcelle NUMERIC NULL,
      PRIMARY KEY(id_parcelle)
    );
     
    CREATE TABLE NOEUD (
      id_noeud INTEGER NOT NULL IDENTITY,
      parcelle_parent INTEGER,
      niveau_parent INTEGER,
      lib_noeud VARCHAR(50) NOT NULL,
      description_noeud VARCHAR(100) NULL,
      PRIMARY KEY(id_noeud)
    );
     
    CREATE TABLE NIVEAU (
      id_niveau INTEGER NOT NULL IDENTITY,
      lien_noeud INTEGER NOT NULL,
      lib_niveau VARCHAR(50) NOT NULL,
      PRIMARY KEY(id_niveau),
      FOREIGN KEY(lien_noeud)
        REFERENCES NOEUD(id_noeud) 
    );
    Je joins le modèle avec un schéma d'explication.

    Ma procédure doit me permettre de récupérer à partir de l'ID d'une parcelle tous les niveaux qui en découlent. Pour cela j'ai créer deux tables que j'utilise uniquement dans cette procédure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE x_supparcelle (
    	niveau INTEGER
    );
     
    CREATE TABLE recherche_niveaux (
    	item VARCHAR(20),
    	lvl INTEGER
    );
    J'ai ensuite créer deux procédures, la première à partir d'un tutoriel (recherche_niveauxfils), la seconde appelant la première (delete_parcelle).

    recherche_niveauxfils :
    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
    CREATE PROCEDURE recherche_niveauxfils
    	@id_niveau INT
    AS
    	SET NOCOUNT ON
    	DECLARE @lvl int,
    	@line char(20)
     
    	INSERT INTO recherche_niveaux VALUES (@id_niveau, 1)
     
    	SELECT @lvl = 1
    	WHILE @lvl > 0
    		BEGIN
    			IF EXISTS (SELECT * FROM recherche_niveaux WHERE lvl = @lvl)
    				BEGIN
    					-- find the 1st node
    					SELECT @id_niveau = item
    					FROM recherche_niveaux
    					WHERE lvl = @lvl		
     
    					-- (@lvl – 1) spaces before the node name
    					SELECT @line = space(@lvl - 1) + @id_niveau
    					PRINT @line
     
    					-- remove the current node from the stack
    					DELETE FROM recherche_niveaux
    					WHERE lvl = @lvl
    					AND item = @id_niveau
     
    					-- insert the childnodes into the stack
    					INSERT recherche_niveaux
    					SELECT id_niveau, @lvl + 1
    					FROM niveau
    					JOIN noeud ON id_noeud = lien_noeud
    					WHERE niveau_parent = @id_niveau
     
    					-- insertion dans x_supparcelle
    					INSERT INTO x_supparcelle(niveau) VALUES (@id_niveau)					
     
    					-- if it exists, go down for its 1st child ???
    					IF @@ROWCOUNT > 0
    						SELECT @lvl = @lvl + 1
    					END				
     
    			ELSE
    				-- back to the level immediately above
    				SELECT @lvl = @lvl - 1
     
    		END
    delete_parcelle :
    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
    CREATE PROCEDURE delete_parcelle
    	@id_parcelle INT –- parcelle à supprimer
    AS
     
    IF EXISTS (SELECT id_noeud FROM noeud WHERE parcelle_parent = @id_parcelle)
    	BEGIN
    		-- récupération de l'id_noeud
    		DECLARE @id_noeud int;
    		SELECT @id_noeud = id_noeud FROM noeud WHERE parcelle_parent = @id_parcelle
     
    		-- recuperation des id des niveaux-fils de la parcelle
    		DECLARE @id_niveau INT;
    		SET @id_niveau = -1;
     
    		WHILE EXISTS (SELECT MIN(id_niveau) FROM niveau WHERE lien_noeud = 15 AND id_niveau > @id_niveau HAVING MIN(id_niveau) IS NOT null)
    			BEGIN
    				SELECT @id_niveau = MIN(id_niveau) FROM niveau WHERE lien_noeud = 15 AND id_niveau > @id_niveau
     
    				-- insertion dans x_supparcelle
    				IF EXISTS (SELECT niveau FROM x_supparcelle WHERE niveau = @id_niveau)
    					PRINT 'pas insertion'
    				ELSE
    					INSERT INTO x_supparcelle(niveau) VALUES (@id_niveau)
    			END
     
    		-- test des fils de ces niveaux : procedure de recherche
    		DECLARE @niveau_fils INT
    		SET @niveau_fils = -1
     
    		WHILE (@niveau_fils < (SELECT MAX(niveau) FROM x_supparcelle WHERE niveau IS NOT null))
    			BEGIN
    				SELECT @niveau_fils = MIN(niveau) FROM x_supparcelle WHERE niveau > @niveau_fils
    				execute recherche_niveauxfils @niveau_fils
    			END
     
    		-- on supprime dans l'ordre les niveaux puis les noeuds
    		-- JE VIENS DE VOIR UNE ERREUR A MODIFIER ICI, PUISQUE JE RECUPERE LES ID_NOEUD APRES SUPPRESSION DES NIVEAUX, CE QUI VA POSER PROBLEME
    		DELETE FROM niveau WHERE id_niveau IN (SELECT niveau FROM x_supparcelle)
    		DELETE FROM noeud WHERE id_noeud IN (SELECT DISTINCT lien_noeud FROM niveau WHERE id_niveau IN (SELECT niveau FROM x_supparcelle))
    	END
     
    -- on supprime la parcelle
    DELETE FROM parcelle WHERE id_parcelle = @id_parcelle
     
    -- on vide la table intermédiaire
    DELETE FROM x_supparcelle
    Je débute en Transact-SQL, donc tout conseil d'amélioration est le bienvenu J'espère n'avoir rien oublié pour comprendre tout ça...

  8. #8
    Membre éclairé Avatar de s.lennon
    Inscrit en
    Juin 2009
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Juin 2009
    Messages : 66
    Par défaut
    Bonjour.

    Bon bah finalement, en reprenant tout ça à tête reposée, j'ai trouvé comment faire une liste de valeurs plutôt que d'utiliser une table (on ne prônera jamais assez les vertus d'une bonne nuit de sommeil ^^).

    Mon erreur était assez bête : je ne savais pas que VARCHAR était équivalent à VARCHAR(1), d'où des soucis pour ajouter des valeurs au fur et à mesure.

    Merci tout de même pour votre aide.
    Bonne journée.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Sql serveur 2000 Changer null/not null et valeur par defaut
    Par mictif dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 07/03/2006, 07h55
  2. [MS SQL Serveur 2000] Problème sauvegarde restauration
    Par m-mas dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 30/11/2005, 12h25
  3. [debutant]Plan de maintenance sous sql serveur 2000
    Par christophebmx dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/05/2005, 12h18
  4. Taille Maxi pour un SQL SERVEUR 2000
    Par WOLO Laurent dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 21/07/2003, 09h37
  5. Supprimer une colonne sous SQL Serveur 2000
    Par WOLO Laurent dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 14/07/2003, 12h24

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