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 !