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

SQL Anywhere Sybase Discussion :

Conflit Trigger on Insert et Procédure


Sujet :

SQL Anywhere Sybase

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 083
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 083
    Par défaut Conflit Trigger on Insert et Procédure
    SQL AnyWhere 10
    J'ai besoin d'une SEQUENCE, semble que cela n'existe pas en version 10.
    J'ai donc fait une fonction qui va me trouver le Premier Numéro disponible (il y a une volonté de recycler les numéros supprimés), c'est un peu différent d'une SEQUENCE, je l'avoue !

    Code la fonction
    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
    DROP FUNCTION GetCensureNumberSequenceNextValue;
    CREATE FUNCTION GetCensureNumberSequenceNextValue (
      @TableName sysname,
      @SequenceFieldName sysname
    )
    RETURNS INTEGER
    NOT DETERMINISTIC
    BEGIN
      DECLARE @cpt INTEGER;
      DECLARE @found INTEGER;
      DECLARE @newid INTEGER;
      DECLARE @count INTEGER;
     
      SET @newid = 0;
      SET @found = 0;
      SET @cpt = 1;
     
      EXECUTE IMMEDIATE
        'SELECT COUNT(*) INTO @count FROM '||@TableName; 
     
      WHILE @cpt <= @count AND @newid = 0 LOOP
     
        SET @found = 0;
        EXECUTE IMMEDIATE
          'SELECT 1 INTO @found FROM '||@TableName||' WHERE '||@SequenceFieldName||' = @cpt';
     
        IF @found = 0 THEN
          SET @newid = @cpt
        ELSE
          SET @newid = 0
        END IF;   
     
        SET @cpt = @cpt + 1;
      END LOOP;
     
      IF @newid = 0 THEN
        SET @newid = @cpt;
      END IF;
     
      RETURN @newid;
    END;
    je l'ai testé via

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    INSERT INTO Machin(NumeroBidule, NomMachin)
    VALUES (GetCensureNumberSequenceNextValue ('Machin', 'NumeroBidule'), 'BOB')
    C'est parfait, j'ai bien un NumeroBidule avec les valeurs que j'attendais, cela bouche les trous puis cela incrémente naturellement par la suite !
    D'un point de vue performance, pas de soucis, la table restera très petite et des insertions très ponctuelles !

    A savoir qu'un code similaire existe dans l'application que je maintiens mais coder directement en C++ Builder (il y a autant de fois le code dupliqué qu'il doit exister de Séquence, oui c'est vilain), je voudrais uniformiser et l'intégrer directement à la Base de données
    au départ mon but était de l'intégrer à un Trigger comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DROP TRIGGER InsertMachinNumeroBidule; 
    CREATE TRIGGER InsertMachinNumeroBidule 
    AFTER INSERT ON Machin 
    REFERENCING NEW AS NewNumeroBidule 
    FOR EACH ROW 
    BEGIN 
      IF NewNumeroBidule.NumeroBidule IS NULL THEN 
        SELECT GetCensureNumberSequenceNextValue('Machin', 'NumeroBidule') INTO NewNumeroBidule.NumeroBidule
      END IF; 
    END;
    Mais c'est la que les choses se gatent !

    Erreur ! Impossible d'insérer la ligne.
    COMMIT/ROLLBACK n'est pas autorisé dans l'opération atomique
    [Sybase][ODBC Driver][SQL Anywhere]COMMIT/ROLLBACK n'est pas autorisé dans l'opération atomique
    SQLCODE: -267
    SQLSTATE: 42000
    Faut-il utiliser un CURSOR et mettre le code de la fonction directement dans le TRIGGER, du coup, je n'ai plus un code uniformiser et donc retour à un code dupliqué (autant le laisser en C++)

    Puis-je quand même utiliser une fonction et du SQL dynamique ?
    Je n'ai pas bien compris comment récupérer le CURSOR d'un EXECUTE, j'ai trouvé un code Sybase V15 ou SQL Server 2008 qui ne fonctionne pas sous la version AnyWhere 10 !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  2. #2
    Rédacteur/Modérateur

    Avatar de Fabien Celaia
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Octobre 2002
    Messages
    4 228
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : Suisse

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Service public

    Informations forums :
    Inscription : Octobre 2002
    Messages : 4 228
    Billets dans le blog
    25
    Par défaut
    Question stupide, mais pourquoi rechercher une séquence lorsque l'autincrément existe ? Quel est le gain de combler les trous ? C'est pas un peu dangereux en terme d'intégrité ?
    Sr DBA Oracle / MS-SQL / MySQL / Postgresql / SAP-Sybase / Informix / DB2

    N'oublie pas de consulter mes articles, mon blog, les cours et les FAQ SGBD

    Attention : pas de réponse technique par MP : pensez aux autres, passez par les forums !

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 083
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 083
    Par défaut
    Ne me pose pas la question, je reproduis le comportement actuel des 13 autres types d'objet qui utilise déjà ce système de numérotation recyclée !
    Le Développement du produit doit avoir environ 10 ans, j'y suis depuis 8 mois, j'ajoute des fonctionnalités et je respecte les conventions existantes !
    Moi je trouve cela assez moche, mais c'est vrai que pour l'utilisateur, semble que cela soit plus simple qu'il n'y ait pas de trou !

    Pire, les jointures sont faites sur cette numérotation, et parfois sur le PK Auto Inc ! Il semble que mes prédécesseurs n'étaient pas des habitués de la DB ... mais plutôt de l'ASM sur 68000 ou du C sur ARM3, en ce moment ma collègue compte ses µv consommés en trop pour prolonger le temps de vie sur le mode crise sur batterie, on est loin du SQL !

    Pour ma part, pour le nouveau 14eme type d'objet et le 13eme que j'ai réécrit, j'utilise uniquement la PK Auto Inc pour mes jointures, cette "séquence" n'est là qu'à titre informatif pour les utilisateurs habitués et quelques liens avec d'autres modules de l'appli qui ne savent causer qu'avec cette numérotation en séquence !

    Je me suis fait une couche OR, je n'utilise que cette couche pour mes MAJ DB qui pour ces deux classes gèrent ce mode "DeviceNumberSequence" !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre Expert Avatar de Yanika_bzh
    Homme Profil pro
    Responsable Applicatif et R&D
    Inscrit en
    Février 2006
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Responsable Applicatif et R&D
    Secteur : Finance

    Informations forums :
    Inscription : Février 2006
    Messages : 1 144
    Par défaut
    J'avais posté une réponse il y a quelques temps sur la recherche de rupture dans une séquence, cela pourra vous aider : ici

    Bon courage

  5. #5
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 083
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 083
    Par défaut
    hum, Yanika_bzh, j'ai tenté aussi de faire un seul SQL, je n'avais pas pensé à un troisième alias !
    Joli formulation !
    Cela donnerait

    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
    DROP FUNCTION GetCensureNumberSequenceNextValue;
    CREATE FUNCTION GetCensureNumberSequenceNextValue (
      @TableName sysname,
      @SequenceFieldName sysname
    )
    RETURNS INTEGER
    NOT DETERMINISTIC
    BEGIN
      DECLARE @newid INTEGER;
     
      EXECUTE IMMEDIATE
        ' SELECT ref.'||@SequenceFieldName||' + 1 INTO @newid ' ||
        ' FROM '||@TableName||' ref ' ||
        ' INNER JOIN '||@TableName||' cmpr ON (ref.'||@SequenceFieldName||' + 1 <> cmpr.'||@SequenceFieldName||') ' ||
        ' WHERE cmpr.'||@SequenceFieldName||' = (SELECT MIN(minbase.'||@SequenceFieldName||') ' ||
        '                                       FROM '||@TableName||' minbase ' ||
        '                                       WHERE minbase.'||@SequenceFieldName||' > ref.'||@SequenceFieldName||')';
     
      IF @newid is NULL THEN
        EXECUTE IMMEDIATE
          ' SELECT MAX('||@SequenceFieldName||') + 1 INTO @newid FROM '||@TableName;
     
        IF @newid is NULL THEN
          SET @newid = 1;
        END IF;    
      END IF;
     
      RETURN @newid;
    END;
    Il est vrai que cela génère moins de requête, bon, je crois pas dépassé 200 lignes dans ma table (cela voudrait sinon dire que l'on a eu un client très riche, car chaque ligne représente un matériel physique sur un site, à 200 à 500€ l'unité sans compteur concentrateur et connectique ... )

    je demanderais à mon responsable, quelle requête est lui semble préférable !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. Insert avec select sur table avec Trigger d'insertion
    Par bran_noz dans le forum Développement
    Réponses: 5
    Dernier message: 23/12/2005, 14h38
  2. Créer un trigger "before insert" avec SQL Server
    Par bubi dans le forum Développement
    Réponses: 2
    Dernier message: 14/11/2005, 10h12
  3. [trigger] update inserted?
    Par cosminutza dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 01/06/2005, 09h37
  4. Trigger et insert
    Par jf-nigou dans le forum Oracle
    Réponses: 5
    Dernier message: 16/02/2005, 16h45
  5. INSERT avec procédure stockée / Clef de type AutoInc
    Par bgdelphi dans le forum Bases de données
    Réponses: 5
    Dernier message: 18/10/2003, 18h30

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