AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Code-Bibliothek Neuen Beitrag zur Code-Library hinzufügen Firebird-Script zur Erzeugung von AutoInc (inc. max Value)
Thema durchsuchen
Ansicht
Themen-Optionen

Firebird-Script zur Erzeugung von AutoInc (inc. max Value)

Ein Thema von Elvis · begonnen am 13. Aug 2008
Antwort Antwort
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#1

Firebird-Script zur Erzeugung von AutoInc (inc. max Value)

  Alt 13. Aug 2008, 15:30
Hier ist ein kleines Script, welches ich gerade brauchte um bei ein paar zu Firebird migrierten Datenbanken die Primärschlüssel autom. hochzählen zu lassen.

Ich habe es so geändert, dass man es auch mit ISQL oder jedem anderen Tool laufen lassen kann, welches ISQL syntax unterstützt.
Außerdem hatte ich hier den Sequences den Suffix "_BI" gegeben. Manche Copy&Waste-Fehler sieht man einfach nicht...

Was zu beachten ist:
  • Es werden alle Tabellen hergenommen, die PKs mit nur einem Feld haben.
    Dieses Feld muss außerdem numerisch sein und darf auch keine Nachkommastellen haben.
  • Die Sequence wird auf den größten Wert des PKs + 1 initialisiert.
  • Wenn der Tabellenname zu groß wird, nimmt er die RelationID aus Rdb$Relations um die Generatoren/Trigger zu benennen und wiederzufinden.
  • rejectInputIDs:
    • 1 -> es werden keinerlei übergebenen Werte vom Insert an den PK angenommen, sondern immer die Sequence befragt.
    • -1 -> ein PK mit null oder 0 sorgt dafür, dass ein neuer Wert aus der Sequence geholt wird.
    • alles andere -> nur ein leerer PK sorgt dafür, dass ein neuer Wert aus der Sequence geholt wird.
  • overwriteTriggers:
    • 1 -> Es werden auch bereits bestehende Trigger überschrieben.
    • alles anddere -> Bestehende PK Trigger mit gleichem Namen werden nicht angefasst.
Viel Spaß damit:
SQL-Code:
set term ^;
execute block
AS
  declare tableName varchar(50);
  declare tableID integer;
  declare fieldName varchar(50);

  declare recordCount integer;
  declare maxPK bigint;

  declare generatorRoot varchar(30);

  -- Pseudo parameters:
  declare rejectInputIDs smallint;
  -- * -1 -> if new.ID null or -1 -> get sequence value
  -- * 1 -> *always* get sequence value, no matter what the input for "ID" was
  -- * otherwise -> if new.ID is null -> get sequence value

  declare overwriteTriggers smallint;
  -- * 1 -> equally named triggers will be re-created
  -- * null or <>1 -> equally named triggers won't be touched
begin
  rejectInputIDs = 0;
  overwriteTriggers = 0;
  
  for SELECT
        trim(r.Rdb$Relation_Name) TableName,
        r.Rdb$Relation_ID TableID,
        min(trim(idxFields.Rdb$Field_Name)) FieldName
      FROM
        Rdb$Indices i
        INNER JOIN Rdb$Relations r
          on i.Rdb$Relation_Name = r.Rdb$Relation_Name
        INNER JOIN Rdb$Index_Segments idxFields
          on i.Rdb$Index_Name = idxFields.Rdb$Index_Name
        INNER JOIN Rdb$Relation_Constraints rc
          on rc.Rdb$Relation_Name = r.Rdb$Relation_Name
             and rc.Rdb$Index_Name = i.Rdb$Index_Name
        INNER JOIN Rdb$Relation_Fields fld
          on fld.Rdb$Relation_Name = r.Rdb$Relation_Name
             and fld.Rdb$Field_Name = idxFields.Rdb$Field_Name
        INNER JOIN Rdb$Fields fldTypes
          on fldTypes.Rdb$Field_Name = fld.Rdb$Field_Source
      WHERE
        rc.Rdb$Constraint_Type = 'PRIMARY KEY
        and fldTypes.Rdb$FIELD_Type IN (7, 8, 16)
        and fldTypes.Rdb$Field_Scale > -1
      GROUP BY r.Rdb$Relation_Name,
               r.Rdb$Relation_ID
      HAVING COUNT(*) = 1
      INTO :tableName,
           :tableID,
           :fieldName do
  begin
    generatorRoot = :tableName;

    if (CHAR_LENGTH(generatorRoot) > 24) then
      generatorRoot = 'TableID ' || tableID;

    SELECT count(*)
    FROM Rdb$Generators
    WHERE trim(Rdb$Generator_Name) = 'GEN_' || :generatorRoot || '_ID
    INTO recordCount;
      
    if (recordCount = 0) then
       execute statement 'create sequence "GEN_' || generatorRoot || '_ID"';
        
    execute statement 'select max("' || fieldName || '") from "' || tableName || '"
       into maxPK;

    if ((maxPK is not null)
    and (maxPK > 0)) then
      execute statement 'alter sequence "GEN_' || generatorRoot || '_ID" restart with ' || (maxPK + 1);
  
    if (overwriteTriggers = 1) then
      recordCount = 0;
    else
      SELECT count(*)
      FROM Rdb$Triggers
      WHERE trim(Rdb$Trigger_Name) = :generatorRoot || '_BI
      INTO recordCount;

    if (recordCount = 0) then
    begin
      if (rejectInputIDs = 1) then
        execute statement
          'recreate trigger "'|| generatorRoot||'_BI"' || ascii_char(10) ||
          ' for "'||tableName||'"' || ascii_char(10) ||
          ' active before insert position 0' || ascii_char(10) ||
          'as' || ascii_char(10) ||
          'begin' || ascii_char(10) ||
          ' new."'||fieldName||'" = gen_id("GEN_'|| generatorRoot ||'_ID",1);' || ascii_char(10) ||
          'end';
      else if (rejectInputIDs = -1) then
        execute statement
          'recreate trigger "'|| generatorRoot||'_BI"' || ascii_char(10) ||
          ' for "'||tableName||'"' || ascii_char(10) ||
          ' active before insert position 0' || ascii_char(10) ||
          'as' || ascii_char(10) ||
          'begin' || ascii_char(10) ||
          ' if (new."'||fieldName||'" is null or new."'||fieldName||'" = 0) then' || ascii_char(10) ||
          ' new."'||fieldName||'" = gen_id("GEN_'|| generatorRoot ||'_ID",1);' || ascii_char(10) ||
          'end';
      else execute statement
          'recreate trigger "'|| generatorRoot ||'_BI"' || ascii_char(10) ||
          ' for "'||tableName||'"' || ascii_char(10) ||
          ' active before insert position 0' || ascii_char(10) ||
          'as' || ascii_char(10) ||
          'begin' || ascii_char(10) ||
          ' if (new."'||fieldName||'" is null) then' || ascii_char(10) ||
          ' new."'||fieldName||'" = gen_id("GEN_'|| generatorRoot ||'_ID",1);' || ascii_char(10) ||
          'end';
    end
  end
end^
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz