AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Autowerte bei Firebird setzen

Autowerte bei Firebird setzen

Ein Thema von FBrust · begonnen am 10. Jun 2005 · letzter Beitrag vom 14. Jun 2005
Antwort Antwort
Seite 3 von 4     123 4   
Benutzerbild von alcaeus
alcaeus

Registriert seit: 11. Aug 2003
Ort: München
6.536 Beiträge
 
#21

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 01:40
Hallo ihr,

ich will euch mal bitten, sachlich zu bleiben. So eine "Diskussion" bringt wirklich keinem was. Auch wenn ich die Materie nicht wirklich verstehe ( ich bin eben kein Datenbankmensch), aber ich denke der Vorschlag von Robert hat durchaus was sinnvolles, was nicht durch irgendwelche Kommentare "dummgeredet" werden muss.

@Hansa: tut mir Leid wenn ich dich direkt anspreche, aber du bist nicht der, der versucht hat das Problem zu loesen. Ich bitte dich also, die unnuetzen Kommentare fuer dich zu behalten, oder diesen Disput mit Robert per PN auszutragen. Das was hier abgeht hilft dem Threadersteller beim besten Willen nicht, und auch wenn es fuer den einen nur "Woerter, die verwirren" sind, fuer den anderen kann so ein Loesungsweg durchaus Sinn ergeben. Und um auf den Kommentar des "Oberschlaumeiers" einzugehn: nur weil jemand versucht zu helfen, und dabei auch ziemlich komplizierte Loesungsvorschlaege kommen, muss man jemanden nicht beleidigen, nur weil man diese nicht versteht, sich nie damit befasst hat oder weil sie einen ganz einfach nicht interessieren. Das ist meine Meinung.

Und nun, back to topic please. Falls jemand von euch noch etwas dazu zu sagen hat, kann er dies gerne per PN tun, aber weitere offtopic-Postings werde ich nicht dulden.

Greetz
alcaeus
Andreas B.
Die Mutter der Dummen ist immer schwanger.
Ein Portal für Informatik-Studenten: www.infler.de
  Mit Zitat antworten Zitat
Benutzerbild von Marcel Gascoyne
Marcel Gascoyne

Registriert seit: 18. Nov 2003
Ort: Uetersen
271 Beiträge
 
Delphi 2005 Architect
 
#22

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 07:25
Von automatisch generieren PK's halte ich auch nicht sehr viel. Eine einfache Möglichkeit ist die Verwendung einer GUID als PK, die kann man ganz einfach mit Delphi und auch aus anderen Anwendungen erzeugen:

Delphi-Quellcode:
var
  MyGuid: TGUID;
  MyPK: string;
begin
  CreateGUID(MyGuid);
  MyPK := StringReplace(Copy(GuidToString(MyGuid),2,36),'-','',[rfReplaceAll]);
end;
Der PK ist dann vom Typ varchar(32) in der Firebird Datenbank.

Gruß,
Marcel
Marcel Gascoyne
Der Fehler sitzt immer vor der Tastatur
  Mit Zitat antworten Zitat
Benutzerbild von mschaefer
mschaefer

Registriert seit: 4. Feb 2003
Ort: Hannover
2.026 Beiträge
 
Delphi XE3 Enterprise
 
#23

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 07:55
Moin zusammen,

das Thema wird gerade richtig interessant!

Marcel hat gerade Hansa´s Ansatz es vom Programm aus zu steuern mit einem praktischen Beispiel belegt. Für eine SingleUser-Anwendung ist das vom Aufwand her der ergonomischste Weg. Im kleinen Netz kann ich auch die IP´s zur Guid einbeziehen und dann ist es auch hier Rechnereindeutig.


Wie das aber im Internet mit dynamischer Adressvergabe dann laufen soll ist mir allerdings nicht ganz klar. Also wie kann ich die Eindeutigkei in einem Mehrbenutzersystem wirklich garantieren. Selbst neige ich daher zu Roberts-Ansatz (ja wir sind tatsächlich mal einer Meinung!):
Zitat:
Eine *piep*-normale string Property, die den Namen des Generators enthält.
Im OnBeforeXXX wird sich dann der neue Wert aus diesem Generator geholt, falls ein Name eingetragen wurde.
Wir verfolgen den Primärschlüssel über den getriggerten Generator zu vergeben und das Dataset-Object (TZQuery) die Fähigkeit anzugedeihen sich vor einem Insert den aktuellen Generator-Wert zu holen um sprünge in der Griddarstellung zu vermeiden. Die Datenbankvariante hat zuden den Vorteil, das auch bei Store-Procedures für den PID-Wert ein AutoInc ausgeführt wird.


So jetzt komme ich zu meinem aktuellen Problem dazu: Mir ist es n i c h t gelungen nur mit dem Generatornamen als String den aktuellen Generatorwert abzufragen o h n e eine Stored-Procedure zu bemühen. Kennt hier jemand ein eLösung ???

Grüße // Martin
Martin Schaefer
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
3.898 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#24

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 08:41
Hallo zusammen,

sehr interessant, was hier diskutiert wird.
Darüber hab ich mir schon des öfteren mal Gedanken gemacht.

Aber, was ihr in diesem Kontext leider vergessen habt ist folgendes:
Die Zeos sind nicht nur für Firebird / Interbase !!!

In MySQL gibts z.B. keine Generatoren, in Oracle sind es Sequenzen usw ...

Das heißt, es muss ein gemeinsamer Nenner gefunden werden, um das Problem der servergenerierten Felder zu behandeln.
(worüber ich mich auch schon derbe bei den Zeos-Kompos aufgeregt hab! *g*)

Was es zudem in Zeos (noch) nicht gibt, ist die Möglichkeit, einen einzelnen Datensatz zu refreshen,
was auch in diesen Bereich fällt. Also hab ich mir folgendes überlegt:

- die TSQLUpdate-Kompo muss um einen 4. SQL erweitert werden: RefreshSQL
- es muss die Möglichkeit geben, Generator/Sequence/was-auch-immer-Felder
nach einem Insert zurückzubekommen --> evtl eigene Komponente?

Würd mich freuen, wenn ihr dazu mal eure Meinung äußern würdet.

MfG
Stevie

P.S.: Den Weg, ein ID-Feld in der DB zu füllen, halte ich für den saubersten,
auch wenn es im Moment etwas schwierig ist. (zumindest mit Zeos)
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#25

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 09:01
Hallo Martin,

Zitat von mschaefer:
Mir ist es n i c h t gelungen nur mit dem Generatornamen als String den aktuellen Generatorwert abzufragen o h n e eine Stored-Procedure zu bemühen. Kennt hier jemand eine Lösung ???
meinst du das hier:

SELECT GEN_ID(DeinGeneratorName, 0) FROM RDB$DATABASE Grüße vom marabu

Nachtrag:

Relational gespeichert wird in der Datenbank nur ein Zugriffsschlüssel für den Generator. Damit wird die Forderung erfüllt, dass der Generator außerhalb der Transaktionsverwaltung geführt werden muss. Die Werte können also nicht als Spaltenwerte einer Systemtabelle abgefragt werden.
  Mit Zitat antworten Zitat
Benutzerbild von mschaefer
mschaefer

Registriert seit: 4. Feb 2003
Ort: Hannover
2.026 Beiträge
 
Delphi XE3 Enterprise
 
#26

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 09:18
Moin, Jihu!

Marabu, genau der Schritt hat mir gefehlt. Klasse !

Jetzt holen wir Stevie ins Boot und bauen Roberts 'abgedrehtes' Zeug in eine abgeleitete TZQuery-Komponente ein
und am Ende fällt dann auch für Hansa was praktisches an. Denn eine solche Query verliert nicht nach einem Post
ihren aktuellen Datensatz sondern bleibt auf ihm stehen.

Mit etwas zeitlicher Verzögerung, da noch aktuelle Aufgaben anstehen, kommt nachher mein Komponentenprototyp!

Grüße // Martin
Martin Schaefer
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
3.898 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#27

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 09:22
Zitat von mschaefer:
Jetzt holen wir Stevie ins Boot ...
Wenn, dann hol ich euch ins (Zeos-)Boot!

Aber Scherz beiseite, bin mal gespannt, was da nachher kommt.

P.S. Für MySQL und SQLite funktioniert das mit dem AutoInc-Werte holen.
Bei MySQL wird das folgendermaßen gemacht (ZDbcMySqlResultSet.pas):
Delphi-Quellcode:
{**
  Posts updates to database.
  @param Sender a cached result set object.
  @param UpdateType a type of updates.
  @param OldRowAccessor an accessor object to old column values.
  @param NewRowAccessor an accessor object to new column values.
}

procedure TZMySQLCachedResolver.PostUpdates(Sender: IZCachedResultSet;
  UpdateType: TZRowUpdateType; OldRowAccessor, NewRowAccessor: TZRowAccessor);
var
  Statement: IZStatement;
  ResultSet: IZResultSet;
begin
  inherited PostUpdates(Sender, UpdateType, OldRowAccessor, NewRowAccessor);

  if (UpdateType = utInserted) and (FAutoColumnIndex > 0)
    and OldRowAccessor.IsNull(FAutoColumnIndex) then
  begin
    Statement := Connection.CreateStatement;
    ResultSet := Statement.ExecuteQuery('SELECT LAST_INSERT_ID()');
    try
      if ResultSet.Next then
        NewRowAccessor.SetLong(FAutoColumnIndex, ResultSet.GetLong(1));
    finally
      ResultSet.Close;
      Statement.Close;
    end;
  end;
end;
Ich denke, an dieser Stelle sollte man bei den anderen Protokollen auch ansetzen.
Und da dann mit der angesprochenen Eigenschaft Sequenz/Generator-Name.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Benutzerbild von mschaefer
mschaefer

Registriert seit: 4. Feb 2003
Ort: Hannover
2.026 Beiträge
 
Delphi XE3 Enterprise
 
#28

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 10:54
Moin,

also das jetzt gleich in Zeos einzuordnen dürfte aufgrund meines etwas veralteten Standes so wohl nich sinnig sein. Aber so kommt zunächst meine angeflanschte Minikomponente:

Delphi-Quellcode:
unit UNIT_TzEnhDataset;
{                                                                              }
{                                                                              }
interface uses
 ZIbSqlQuery, dialogs, Classes, SysUtils, DB, DBCommon;
type
{                                                                              }
{                                                                              }
  TzEnhDataset = class( TZCustomIbSqlDataset )
  private {                                                             }
                  FGeneratorName : String;
                  function Get_New_PID : string;
  public {                                                             }
                  constructor Create
                  ( AOwner : TComponent); override;
                  destructor Destroy; override;
                  procedure DoBeforeInsert; override;
  published {                                                             }
                 property GeneratorName : String
                                                      read FGeneratorName
                                                      write FGeneratorName;
  end;
{                                                                              }

  TEnh_TZQuery = class(TzEnhDataset)
  public {                                                             }
                   property MacroCount;
                   property ParamCount;

  published {                                                             }
                   property MacroChar;
                   property Macros;
                   property Params;
                   property ParamCheck;
                   property DataSource;
                   property Sql;
                   property RequestLive;
                   property Active;
   end;

{                                                                              }
   implementation
{                                                                              }
{  TzEnhDataset                                                                }



  {    }       constructor TzEnhDataset.Create(AOwner: TComponent);
               begin
                        inherited Create(AOwner);
               end;

  {    }       destructor TzEnhDataset.Destroy;
               begin
                        inherited Destroy;
               end;

  {    }       function TzEnhDataset.Get_New_PID : string;
               var
                    PIQ : TEnh_TZQuery;
               begin
                    Result := '0';
                    if ( OV_PID_Insert )
                    and ( OV_PID_Insert_SQL.Text <> ''  )
                    and ( Database <> nil ) then
                    begin
                           PIQ := TCR_Query.Create(nil);
                           PIQ.Database := Database;
                           PIQ.sql.text := 'SELECT GEN_ID(' + FGeneratorName + ', 0) FROM RDB$DATABASE';
                           PIQ.active := true;
                           Result := PIQ.FieldList.Fields[0].AsString;
                           PIQ.Active := false;
                           PIQ.destroy;
                    end;
               end;


  {    }       procedure TzEnhDataset.DoBeforeInsert;
               begin
                   Edit;
                   {Zu Testzwecken wird davon ausgegangen das PID das erst Feld ist}
                   FieldList.fields[0].AsString := Get_New_PID;
                   inherited DoBeforeInsert;
               end;

{                                                                                }
end.
Mit Unterstützung ist soetwas sicherlich in Zeos einzuordnen und sicherlich aus dem Rohzustand zu bekommen.
Muß mir heute Mittag mal das CVS mal installieren. Soweit stelle ich das zunächst mal zur Diskussion

Einen Haken hat das allerdings noch. Das Lesen des Generators erhöht ihn leider nicht, sondern erst der Post.
Das hat einige Milisekunden Unsicherheit. Vielleicht hat Marabu da noch eine Idee.

Grüße // Martin
Martin Schaefer
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#29

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 11:07
Hallo Martin,

Zitat von mschaefer:
Das Lesen des Generators erhöht ihn leider nicht, sondern erst der Post.
du hattest nach dem aktuellen Wert eines Generators gefragt. Die Übergabe von 0 an den zweiten Parameter von GEN_ID() stellt sicher, dass der Wert nur ausgelesen und nicht verändert wird. Was du brauchst ist eher der Standard-Aufruf GEN_ID(GeneratorName, 1) - wobei die 1 eine Standardannahme sein sollte.

marabu
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
3.898 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#30

Re: Autowerte bei Firebird setzen

  Alt 13. Jun 2005, 11:17
Generell würde ich es bevorzugen, den Wert nach dem Posten zu erfragen und ihn dann in das RecordSet zu holen, so wie es oben bei MySQL im Moment schon der Fall ist. Dies würde dem insert into ... returning ... into ... von Oracle entsprechen, welches imho die sauberste Lösung ist. Und all das muss in den entsprechenden dbc-units eingebaut werden.

Ich sag's hier mal in aller Deutlichkeit:
Ich halte nichts davon, automatisch generierte Werte zum Client zu holen,
um diese wieder in die DB zu schreiben, wenn diese das selber kann!
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 05:51 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf