Daten in andere Datenbank einfügen

Forum zu diversen Themen rund um die Firebird-Programmierung

Moderator: martin.koeditz

Antworten
haraldhuth
Beiträge: 2
Registriert: Mo 6. Aug 2018, 11:56

Hallo Zusammen,

ich habe ein spezielles Problem:

Eine Datenbank mit sog. Stammdaten;
Weitere Datenbanken die auf die Stammdaten verweisen.
Die Synchronisierung ist nicht das Problem.

Ich habe bisher neue Datensätze von außerhalb der Datenbanken eingefügt.

Nun soll eine Procedure dies tun.
Klappt auch gut; nur wenn ich den Insert-String als Eingabeparameter übergebe erhalte ich Fehlermeldung = Column unknown für die Daten die ebenfalls als Eingabeparameter übergeben werden. Das Mapping (Values :a, :b, :c) (a := :eingabeparama, b := :eingabeparamb, c := :eingabeparamc) wird als Eingabeparameter ignoriert. Auch Versuche dies in Hochkommas oder Anführungszeichen zu stellen haben nicht funktioniert. Der Eingabeparameter für den Datenbanknamen funktioniert.
Hier der Auszug:
RECREATE PROCEDURE SP_KOMM_NEU (
AAGSNAME VARCHAR(20),
AADRID INTEGER,
AAGSART INTEGER,
AGREMKENNUNG INTEGER,
AMITSD BOOLEAN,
AZUSATZDB VARCHAR(20),
AINSERTSTRING VARCHAR(250),
APARAMSTRING VARCHAR(100))
RETURNS (
AKOMMID INTEGER)
AS
BEGIN
/* Procedure text */
/* Daten in eine Tabelle der Datenbank */
insert into TABELLE
(felda, feldb, feldc, feldd)
values (:aagsname, :aadrid, :aagsart, :agremkennung)
returning ags_id into :akommid;

if (:amitsd) then
begin
/* Daten in eine Tabelle einer fremden Datenbank */
execute statement ('insert into tabelle (felda, feldb, feldc)
values (:a, :b, :c)') (a := :aagsname, b := :akommid, c := :aagsart)
with autonomous transaction
on external data source (:azusatzdb)
with caller privileges;
end
suspend;
END^

Wenn ich die Zeile execute Statement
ersetze durch: execute Statement (:ainsertstring) (:aparamstring)
ergibt die Fehlermeldungen. Auch der Versuch, beides in einen Eingabeparamter zu packen hat nicht funktioniert.
Im Programmcode sind Konstanten eingerichtet:
cstrinsert = 'insert into tabelle(felda, feldb, feldc) ' +
'values (:a, :b, :c)';
cstrparam = 'a := :aagsname, b := :akommid, c := :aagsart';

Viellicht hat jemand eine Idee dazu?
Vielen Dank schon mal.
mclemens
Beiträge: 5
Registriert: Mo 16. Apr 2018, 11:05

Hallo,

ich mache so etwas immer mit z.B. folgender Procedure.

execute statement('insert into xy_tabelle(STATUS_ID, COMMAND_ID, TYPE_ID, LINK_ID, COMMAND_TEXT)
values ( :STATUS_ID, :COMMAND_ID, :TYPE_ID, :LINK_ID,:COMMAND_TEXT)')
(STATUS_ID := STATUS_ID, COMMAND_ID := COMMAND_ID, TYPE_ID := TYPE_ID, LINK_ID := LINK_ID, COMMAND_TEXT := :COMMAND_TEXT)
on external data source CONNECTIONSTRING
as user USERNAME password password ;

Vielleicht hilft Ihnen das.
bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Leider ist das Ganze nicht volldynamisch.
Entweder du musst den gesamten Insert immer wieder neu zusammenbasteln, also auch die Parameter oder du musst die Parameter neutral benennen und auf eine gewisse Anzahl beschränken.

https://firebirdsql.org/rlsnotesh/rnfb2 ... stmnt.html

An dem Beispiel siehst du das Vorgehen:
S = 'INSERT INTO TTT VALUES (:a, :b, :a)';

EXECUTE STATEMENT (:S) (a := CURRENT_TRANSACTION, b := CURRENT_CONNECTION)

Wie du siehst, je Parameter ist eine eigene Variable zu übergben.
Da du ja jede Variable kennst, kannst du den Insert auch entsprechend zusammen bauen.

Aber wie sicher bist du, dass du nur einen Insert zu einer Zeit durchführst?
Oder generierst du je Tabelle eine Prozedur?
Und warum überhaupt eine Prozedur da dies die Sache ja komplizierter macht und das Ganze dann auch länger dauert (jeder Insert muss erst mal auf Syntax geprüft werden)?
Da du ja sowieso jede Variable kennen must hast du keinen Vorteil.
haraldhuth
Beiträge: 2
Registriert: Mo 6. Aug 2018, 11:56

Hallo Leute,

vielen Dank für die Hilfe.

@bfuerchau:
wie Du aus dem Prozedur-Text ersehen kannst, gehe ich nach Beschreibung vor, solange der Insert-String im Prozedur-Text steht. Das gleiche tue ich auch wenn ich den String als variable übergebe. Was dann nicht funktioniert.
Aber man ist ja manchmal etwas vernagelt: Beim Zusammenstellen des Insert-Strings kann man natürlich die Daten direkt übergeben.

Übrigens gibt es für jede Tabelle auf die verwiesen wird, eine solche Prozedur.
Mir geht es dabei um die Datenkonsistenz: Gibt es einen Fehler bei der Übergabe der Daten an die externe Datenbank, wird die gesamte Prozedur "zurück-gerollt". Dies ist innerhalb der Datenbank (Server) wesentlich einfacher zu implementieren als von außerhalb.

Und nochmals vielen Dank für Eure Hilfe.
bfuerchau
Beiträge: 485
Registriert: Mo 7. Mai 2018, 18:09
Kontaktdaten:

Denke jedoch beim direkten Zusammenbauen an die benötigte Verdoppelung von ggf. enthaltenen Hochkommatas.

Wenn du allerdings sowieso je Tabelle eine Prozedur baust, warum kannst du den Code nicht mit einzelnen Parametern erstellen an Stelle nun alle Werte in Strings zu casten und zusammen zu bauen?
Du definierst doch alle deine Variaben als Parameter, also gib diese doch alle an, so wie im Beispiel des Vorredners.
Antworten