FirebirdSQL logo

Curseur inopiné

La clause facultative AS CURSOR crée un curseur nommé qui peut être référencé (en utilisant la clause WHERE CURRENT OF) dans l’instruction composée qui suit la clause DO afin de supprimer ou de modifier la ligne courante.

Il est permis d’utiliser le nom du curseur comme une variable de type enregistrement (similaire à OLD et NEW dans les triggers) qui permet d’accéder aux colonnes du jeu résultant (i.e. cursor_name . columnname). L’utilisation de la clause AS CURSOR rend la clause INTO facultative.

Règles pour les variables de curseur :
  • Pour résoudre l’ambiguïté lors de l’accès à une variable curseur, un préfixe deux-points est requis avant le nom du curseur ;

  • La variable curseur peut être accédée sans le préfixe deux-points, mais dans ce cas, selon la portée des contextes existants dans la requête, le nom peut être résolu comme un contexte de requête au lieu du curseur ;

  • Les variables du curseur sont en lecture seule ;

  • Dans une instruction FOR SELECT sans la clause AS CURSOR, la clause INTO doit être utilisée. Si la clause AS CURSOR est spécifiée, la clause INTO n’est pas requise mais autorisée ;

  • La lecture d’une variable curseur renvoie les valeurs actuelles des champs. Cela signifie que l’Instruction UPDATE (avec la clause WHERE CURRENT OF) mettra également à jour les valeurs des champs dans la variable curseur pour les lectures suivantes. L’exécution de l’instruction DELETE (avec la suggestion WHERE CURRENT OF) mettra NULL pour les valeurs des champs de la variable curseur pour les lectures suivantes.

Note
  • Les Instructions OPEN, FETCH et CLOSE ne peuvent pas être exécutés sur un curseur déclaré avec une clause AS CURSOR ;

  • Assurez-vous que le nom du curseur défini ici n’est pas le même qu’un nom précédemment créé par l’instruction DECLARE VARIABLE ;

  • La clause FOR UPDATE autorisée à être utilisée dans l’instruction SELECT n’est pas nécessaire pour une mise à jour ou une suppression positionnelle réussie.

Exemples en utilisant FOR SELECT

Example 1. Utilisation de l’Instruction FOR SELECT
CREATE PROCEDURE SHOWNUMS
RETURNS (
  AA INTEGER,
  BB INTEGER,
  SM INTEGER,
  DF INTEGER)
AS
BEGIN
  FOR SELECT DISTINCT A, B
      FROM NUMBERS
    ORDER BY A, B
    INTO AA, BB
  DO
  BEGIN
    SM = AA + BB;
    DF = AA - BB;
    SUSPEND;
  END
END
Example 2. Ci-joint FOR SELECT
CREATE PROCEDURE RELFIELDS
RETURNS (
  RELATION CHAR(32),
  POS INTEGER,
  FIELD CHAR(32))
AS
BEGIN
  FOR SELECT RDB$RELATION_NAME
      FROM RDB$RELATIONS
      ORDER BY 1
      INTO :RELATION
  DO
  BEGIN
    FOR SELECT
          RDB$FIELD_POSITION + 1,
          RDB$FIELD_NAME
        FROM RDB$RELATION_FIELDS
        WHERE
          RDB$RELATION_NAME = :RELATION
        ORDER BY RDB$FIELD_POSITION
        INTO :POS, :FIELD
    DO
    BEGIN
      IF (POS = 2) THEN
        RELATION = ' "';
      -- Pour éviter la répétition des noms de tables et de vues
      SUSPEND;
    END
  END
END
Example 3. Utilisation de la clause `AS CURSOR' pour la suppression d’un enregistrement positionnel
CREATE PROCEDURE DELTOWN (
  TOWNTODELETE VARCHAR(24))
RETURNS (
  TOWN VARCHAR(24),
  POP INTEGER)
AS
BEGIN
  FOR SELECT TOWN, POP
      FROM TOWNS
      INTO :TOWN, :POP
      AS CURSOR TCUR
  DO
  BEGIN
    IF (:TOWN = :TOWNTODELETE) THEN
      -- Suppression de position d'un enregistrement
      DELETE FROM TOWNS
      WHERE CURRENT OF TCUR;
    ELSE
      SUSPEND;
  END
END
Example 4. Utilisation d’un curseur déclaré implicitement comme variable de curseur
EXECUTE BLOCK
RETURNS (
    o CHAR(63))
AS
BEGIN
  FOR
      SELECT
          rdb$relation_name AS name
      FROM
          rdb$relations AS CURSOR c
  DO
  BEGIN
    o = c.name;
    SUSPEND;
  END
END
Example 5. Résolution des ambiguïtés des variables de curseur dans les requêtes
EXECUTE BLOCK
RETURNS (
    o1 CHAR(63),
    o2 CHAR(63))
AS
BEGIN
  FOR
      SELECT
          rdb$relation_name
      FROM
          rdb$relations
      WHERE
          rdb$relation_name = 'RDB$RELATIONS' AS CURSOR c
  DO
  BEGIN
    FOR
        SELECT
            -- avec un préfixe est autorisé comme curseur
            :c.rdb$relation_name x1,
            -- sans préfixe comme alias de la table rdb$relations
            c.rdb$relation_name x2
        FROM
            rdb$relations c
        WHERE
            rdb$relation_name = 'RDB$DATABASE' AS CURSOR d
    DO
    BEGIN
      o1 = d.x1;
      o2 = d.x2;
      SUSPEND;
    END
  END
END