![]() |
Re: Autowerte bei Firebird setzen
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 (:oops: 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 |
Re: Autowerte bei Firebird setzen
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:
Der PK ist dann vom Typ varchar(32) in der Firebird Datenbank.
var
MyGuid: TGUID; MyPK: string; begin CreateGUID(MyGuid); MyPK := StringReplace(Copy(GuidToString(MyGuid),2,36),'-','',[rfReplaceAll]); end; Gruß, Marcel |
Re: Autowerte bei Firebird setzen
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:
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 |
Re: Autowerte bei Firebird setzen
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) |
Re: Autowerte bei Firebird setzen
Hallo Martin,
Zitat:
SQL-Code:
Grüße vom marabu
SELECT GEN_ID(DeinGeneratorName, 0) FROM RDB$DATABASE
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. |
Re: Autowerte bei Firebird setzen
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 |
Re: Autowerte bei Firebird setzen
Zitat:
Aber Scherz beiseite, bin mal gespannt, was da nachher kommt. :wink: 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:
Ich denke, an dieser Stelle sollte man bei den anderen Protokollen auch ansetzen.
{**
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; Und da dann mit der angesprochenen Eigenschaft Sequenz/Generator-Name. |
Re: Autowerte bei Firebird setzen
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:
Mit Unterstützung ist soetwas sicherlich in Zeos einzuordnen und sicherlich aus dem Rohzustand zu bekommen.
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. 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 |
Re: Autowerte bei Firebird setzen
Hallo Martin,
Zitat:
marabu |
Re: Autowerte bei Firebird setzen
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! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz