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

Bases de données Delphi Discussion :

Encombrement requêtes SQL


Sujet :

Bases de données Delphi

  1. #1
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 53
    Points
    53
    Par défaut Encombrement requêtes SQL
    Bonjour, je développe Delphi/ Sql Server

    j'ai des rquêtes du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    insert into table1 (champ1,champ2....) values (value1,value2,...)
    qui s'exécutent en cliquant sur un bouton "valider".

    il y a une référence automatique qui se crée par programme (la clé unique)


    Dès qu'un utilisateur du poste A clique sur valider (la requête bien sur s'exécute).
    si un autre utilisateur du poste B clique sur le bouton valider , j'ai ajouté une procédure de contrôle si la référence existe (déja posté par l'utilisateur A), il regénère une autre clé et exécute la requête.

    pour cela ça va ça marche.

    Le problème est le suivant:
    "Quand ces deux utilisateurs cliquent en même temps sur le même bouton , j'ai un message d'erreur de violation de clé"

    y a t il une solution plus efficace pour remédier à ce type de problèmes (gérer les priorités d'exécution de requêtes sur le serveur)???

    meilleures salutations

  2. #2
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Il y a plusieurs solutions :
    - Tu peux utiliser des champs autoincrémentés pour générer les clés primaires (champ IDENTITY dans SQL Server).
    - Si la clé doit être calculée par l'application, le mieux c'est de la faire calculer par la requête d'insertion, dans la même transaction. De cette façon, il n'y a pas de risques de générer de doublons.

  3. #3
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 53
    Points
    53
    Par défaut
    Franck SORIANO a dit:
    - Tu peux utiliser des champs autoincrémentés pour générer les clés primaires (champ IDENTITY dans SQL Server).
    pour ça ça m'intéresse pas car mes clés sont du genre: FAC/08/0015, donc un num autoincrement n'est pas utile.

    Franck SORIANO a dit:
    - Si la clé doit être calculée par l'application, le mieux c'est de la faire calculer par la requête d'insertion, dans la même transaction.

    j'ai pas compris ce que vous voulez dire par " le mieux c'est de la faire calculer par la requête d'insertion, dans la même transaction."
    comment faire exactement??

  4. #4
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 235
    Points : 8 504
    Points
    8 504
    Par défaut
    Citation Envoyé par BYALI Voir le message
    j'ai pas compris ce que vous voulez dire par " le mieux c'est de la faire calculer par la requête d'insertion, dans la même transaction."
    comment faire exactement??
    Lire ceci sur les transactions
    Modérateur Delphi

    Le guide du bon forumeur :
    __________
    Rayek World : Youtube Facebook

  5. #5
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Citation Envoyé par BYALI Voir le message
    j'ai pas compris ce que vous voulez dire par " le mieux c'est de la faire calculer par la requête d'insertion, dans la même transaction."
    comment faire exactement??
    Admettons que tu ais une table CPTFAC de compteurs qui te serve à générer les numéros de facture et une table FACTURE dans laquelle tu veux faire l'insertion :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    create table CPTFAC
     (
      idCPT varchar(3),
      valeur int
     )
    GO
    create table FACTURE
      (
    	numFacture varchar(20),
        dateFacture datetime
      )
    GO
    insert into CPTFAC(idCpt, valeur) values ('FAC', 0)   
    GO

    Tu fais l'insertion avec un truc du genre :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    BEGIN TRAN
     
    update CPTFAC
    set valeur = valeur +1
    where idCpt = 'FAC'
     
    insert into FACTURE(numFacture, dateFacture)
    select 
      numFacture = 'FAC/' + right(cast(year(getdate()) as varchar(4)), 2) + '/' + right('0000' + cast(valeur as varchar(4)), 4),
      dateFacture = GetDate()
    from CPTFAC
    where idCpt = 'FAC'
     
    COMMIT TRAN

    Tu peux éventuellement mettre ça dans une procédure stockée, ou faire exécuter le batch avec un ADOCommand (ou ce que tu veux).

  6. #6
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 53
    Points
    53
    Par défaut
    sur la base du code source que Franck SORIANO m'a transmis, j'ai essayé d'exécuter à la même milliseconde, et bien ça marche comme sur des roulettes

    la question , c'est admettons que quelqu'un quelque part exécute cette requête dans une transaction, et une autre personne a une table1 dont table name est facture.

    il a cliqué sur un bouton qui le met en mode insertion "table1.insert", le num est généré automatiquement......... il saisit toutes ses données et ensuite il clique sur le bouton qui lance "table1.post".

    est ce que dans ce cas j'utilise une transaction ou bien la transaction de l'autre utilisateur c'est elle qui gère les priorités????

  7. #7
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Lorsque tu fais l'insertion tel que je l'ai indiqué, on commence par faire un UPDATE sur la table des compteurs CPTFAC.
    Cette opération pose un verrou sur la table qui interdit aux autres utilisateurs d'accéder à la même ligne (ou la page, voir la table selon ta config) tant que la transaction en cours n'a pas été validée (COMMIT TRAN) ou annulée (ROLLBACK TRAN).
    De fait, si un autre utilisateur essaie de faire la même opération, il sera bloqué au moment de lire CPTFAC jusqu'à ce que la première transaction soit terminée.

    il a cliqué sur un bouton qui le met en mode insertion "table1.insert", le num est généré automatiquement.........
    Le problème si tu procèdes comme ça, c'est que la génération du numéro et la validation de l'insertion ne s'effectuent pas dans la même transaction. Donc tu peux générer un numéro au moment du Table1.Insert, puis l'utilisateur annule sa création (donc la facture ne sera jamais générée) et tu te retrouve avec un trou dans la numérotation car ton compteur a progressé d'une valeur.

    Si tu ouvres une transaction au moment pour l'utilisateur fait son insert, pour ne la valider que plus tard au moment du post, ta transaction va resté ouverte beaucoup trop longtemps. Tous les autres utilisateurs seront bloqués à cause des verrous sur la table des compteurs jusqu'à ce que la transaction soit validée... Par contre, tu peux ouvrir la transaction dans le BeforePost, générer le numéro de facture, laisser le Post s'effectuer et valider la transaction dans l'AfterPost. Ce n'est pas ma façon préféré de travailler mais c'est faisable.

    S'il y a une règle à retenir, c'est qu'il ne doit jamais y avoir de traitement interactif au milieu d'une transaction de base de données. Ton programme doit être capable d'enchaîner tous les traitements nécessaires sans attente, sinon tu risques de bloquer tous les autres utilisateurs.

    Pour un programme de facturation, tes numéros de factures doivent obligatoirement être continus (il ne doit pas y avoir de trou dans la numérotation) et ils doivent suivre l'ordre des dates de facturation. C'est la dessus que les contrôleurs du fiscs se baserons pour voir si tu n'essaies pas de dissimuler une partie de ton activitée (genre facture émise, réglée en liquide puis effacée de la base pour ne pas la déclarer dans la déclaration de TVA...). J'ai eu un client qui numérotait ces factures de 10 en 10 (enfin c'était le résultat dans sa base, les factures entre disparaissaient par l'opération du saint-esprit). Un jour il a eu un contrôle fiscale... qui a donné lieu à un redressement de plus de 200 millions de francs...

    C'est pourquoi je préfère générer les numéros de factures au moment de l'édition définitive de la facture.
    Tu prends un identifiant interne pour la clé primaire et tu ne donnes le numéro de facture final qu'à l'édition de la facture.
    Autrement dit, tu met le code de génération du numéro de facture dans une procédure stockée qui fait la facturation.
    Evidemment, une fois la facture émise, tu interdis sa suppression dans l'application.

  8. #8
    Membre du Club
    Inscrit en
    Février 2007
    Messages
    119
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 119
    Points : 53
    Points
    53
    Par défaut
    merci FRANCK SORIANO pour vos lumières.

    je prendrais en considérations ce que vous m'avez conseillé.

    bonne continuation

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

Discussions similaires

  1. [ DB2 ] [ AS400] requête sql
    Par zinaif dans le forum DB2
    Réponses: 6
    Dernier message: 23/08/2008, 19h42
  2. Utilisation de MAX dans une requête SQL
    Par Evil onE dans le forum Langage SQL
    Réponses: 7
    Dernier message: 15/06/2004, 18h38
  3. A propos d'une requête SQL sur plusieurs tables...
    Par ylebihan dans le forum Langage SQL
    Réponses: 2
    Dernier message: 14/09/2003, 16h26
  4. PB requète SQL avec Interbase
    Par missllyss dans le forum InterBase
    Réponses: 2
    Dernier message: 15/07/2003, 11h37
  5. Requête SQL
    Par Leludo dans le forum Langage SQL
    Réponses: 2
    Dernier message: 17/02/2003, 16h44

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