SQLs in DB2-Tabelle speichern
- Dieses Thema hat 6 Antworten und 1 Teilnehmer, und wurde zuletzt aktualisiert vor 17 Jahre, 2 Monaten von
Anonym.
-
AuthorPosts
-
15. März 2006 um 16:11 Uhr #2671
AnonymInaktivHallo zusammen,
wir beabsichtigen regelmäßig auszuführende SQLs in einer DB2-Tabelle abzuspeichern. Das Design der Tabelle könnte zum Beispiel so aussehen:
CREATE TABLE DB.RBJE6T
(RBJE6_ANLAGE CHAR(4) NOT NULL
,RBJE6_SQLID CHAR(20) NOT NULL
,RBJE6_GILTVON TIMESTAMP NOT NULL
,RBJE6_GILTBIS TIMESTAMP NOT NULL
,RBJE6_SQL VARCHAR(30000) NOT NULL
WITH DEFAULT
,RBJE6_LASTUSER CHAR(8) NOT NULL
,RBJE6_LASTUPDATE TIMESTAMP NOT NULL WITH DEFAULT
,PRIMARY KEY
(
RBJE6_ANLAGE
,RBJE6_SQLID
,RBJE6_GILTVON
,RBJE6_GILTBIS
)
)
IN RU005D.RBJE6S
CCSID EBCDIC
;Auf der entsprechenden Zielanlage sollen jetzt in einem ersten STEP die SQLs ausgelesen werden (DSNTIAUL oder REXX) und dann in einem zweiten STEP ausgeführt werden. Werden neue SQLs gebraucht, werden die auf der Entwicklungsanlage getestet und ein Ladebestand erstellt. Dieser wird dann auf die Zielanlage gesendet und in die Tabelle RBJE6T mit RESUME YES dazugeladen.
Probleme:
Nachdem ich die SQLs unter SPUFI getestet habe, wie bekomme ich Sie mit möglichst Standardverfahren (keine EXTRA-REXX oder EDIT MACROS) in die Tabelle?
Gibt es Probleme mit dem Zeilenumbruch, wenn ich den VARCHAR(30000) Column auslese und an der falschen Stelle den Zeilenumbruch mache?
Wäre ein Tabellendesign, dass die Zeilennummer beinhaltet sinnvoller?
Habt ihr so etwas schon mal gemacht oder im Einsatz?
Was ist alles zu beachten?
Alternativvorschläge zum Design der SQL-Tabelle?
Meine Wünsche:
Einfach Übertragung von SPUFI-SQLs in die Tabelle
Einfaches Entladen der SQLs um sie dann auszuführen.
Möglichst alles mit Standard-Verfahren ohne viel Zusatzprogrammierung.
Vielen Dank im voraus.
Gruß Klaus
16. März 2006 um 7:36 Uhr #3080
AnonymInaktivHallo Klaus,
alternativ kannst du mit CHAR (72)-Strings arbeiten, d. h. du legst die Zeilen genauso ab wie sie in dem SPUFI-PO sind. Dann brauchst du aber eine Verwaltung, aus welchen Zeilen ein SQL-Member besteht.
Wenn du das SQL in einer Zeile packen willst (wie vorgeschlagen), hast du die Probleme beim entladen. DSNTEP2 liest m. W. nur die ersten 72 Stellen vom SYSIN und verkettet diese bis zum Semikolon. D. h. du musst hier für einen entsprechenden Umbruch sorgen. Du kannst aber den SQL-String alle 72 hart umbrechen, d. h. du musst nicht bis zum nächsten Blank oder so zu warten.
Alternativ wäre vielleicht noch der Einsatz einer STP oder sogar die Ausführung über eine UDF möglich, allerdings hört sich das nicht wirklich nach geringem Aufwand an.MfG Rolf
16. März 2006 um 8:03 Uhr #3370
AnonymInaktivHallo Rolf,
Danke für Deine Anmerkungen.
Wenn ich den Vorschlag mit den einzelenen Zeilen je 72-CHAR umsetze, brauche ich ja so etwas wie eine Zeilennummer.
Lösungen die mir hier einfallen:
1. Der Verfasser des SQLs pflegt die Zeilennummern manuell im Editor.
2. wie 1. aber mit Unterstützung eines EDIT-Macros
Könnte man auch dem LOAD-beibringen die Zeilennummern (am liebsten beginnend bei 1) zu füllen?
Vielleicht ein Online LOAD (sharelevel change) mit einem TRIGGER der immer die nächste Zeilennummer ermittelt?
Gruß Klaus
P.S.: Ich glaube die Lösung mit den fixen 72-Stelligen Zeilen gefällt mir immer besser.
16. März 2006 um 8:11 Uhr #3551
AnonymInaktiv… würde da eine GENERATED-Column nehmen. Allerdings numeriert die die gesamte Tabelle durch, nicht nur innerhalb eines SQL-Members.
Alternativ wäre noch die Verwendung einer Sequence möglich, die kann man aber (noch) nicht im Load ansprechen (kommt vielleicht bald… ;-)).
Falls du statt Load mit Insert arbeiten willst, würde auch noch was ganz Wildes gehen: Bei jedem neuen SQL wird eine Sequence angelegt, die dann für den Insert der Zeilen verwendet wird. Anschließend Sequence droppen. Dadruch wäre eine Numerierung innerhalb eines SQLs durch eine Sequence möglich…MfG Rolf
20. März 2006 um 13:52 Uhr #3677
AnonymInaktivHallo zusammen,
hier die Lösung für die ich mich entschieden habe.
Mit Hilfe von TRIGGERN wird aus der ersten SQLZEILE alles herausgefiltert was in die Tabelle hineingehört. Die Nummerrierung der SQLZEILENR übernimmt auch ein Trigger.
Funktioniert mit INSERT und auch mit LOAD SHRLEVEL CHANGE. Einzige Konvention: Die erste Zeile muß so aussehen:— A=C403 B=NORMALER 4711-SQL GV=01.01.1991 GB=31.3.2099 U=OTTO
Hinter den Gleichheitszeichen stehen die Werte nach denen der Tigger sucht (A= Anlage; B= Bezeichnung etc.)
Gruß Klaus
P.S. Wer an allen Details interresiert ist, kann sich bei mir melden. Leider hat es nicht hier ins Forum hineingepaßt(DDL + TRIGGER + LOAD-JCL + SELECT-Output) . Aber vielleicht ist das auch besser so.
DDL für Tabelle:
CREATE TABLE DB.RBJE6T
(RBJE6_ANLAGE CHAR(4) NOT NULL WITH DEFAULT ‚INIT‘
,RBJE6_SQLBEZ CHAR(20) NOT NULL WITH DEFAULT ‚INIT‘
,RBJE6_SQLZEILENR DEC(4) NOT NULL WITH DEFAULT
,RBJE6_GILTVON DATE NOT NULL WITH DEFAULT
‚01.01.0001‘
,RBJE6_GILTBIS DATE NOT NULL WITH DEFAULT
‚31.12.2999‘
,RBJE6_SQLZEILE CHAR(72) NOT NULL WITH DEFAULT,RBJE6_LASTUSER CHAR(8) NOT NULL WITH DEFAULT
,RBJE6_LASTUPDATE TIMESTAMP NOT NULL WITH DEFAULT
,PRIMARY KEY
(
RBJE6_ANLAGE
,RBJE6_SQLBEZ
,RBJE6_SQLZEILENR
)
)
IN RU005D.RBJE6S
CCSID EBCDIC
;Und jetzt die TRIGGER DDL (delimiter ist #):
— ANLAGE + SQLBEZ (BEI ERSTEM INSERT) SETZEN AUS SQLZEILE
CREATE TRIGGER DB.RBJE6AI1
AFTER INSERT
ON DB.RBJE6T
REFERENCING NEW AS NEW
FOR EACH ROW MODE DB2SQL
WHEN (
NEW.RBJE6_ANLAGE = ‚INIT‘
AND NEW.RBJE6_SQLBEZ = ‚INIT‘
AND POSSTR(NEW.RBJE6_SQLZEILE,’A=‘) > 0
AND POSSTR(NEW.RBJE6_SQLZEILE,’B=‘) > 0
AND POSSTR(NEW.RBJE6_SQLZEILE,’GV=‘) > 0
AND POSSTR(NEW.RBJE6_SQLZEILE,’GB=‘) > 0
AND POSSTR(NEW.RBJE6_SQLZEILE,’U=‘) > 0
AND POSSTR(NEW.RBJE6_SQLZEILE,‘–‚ ) > 0
)BEGIN ATOMIC
UPDATE DB.RBJE6T O
SET RBJE6_ANLAGE = SUBSTR(NEW.RBJE6_SQLZEILE
, POSSTR(NEW.RBJE6_SQLZEILE,’A=‘) + 2
, 4
)
, RBJE6_SQLBEZ = SUBSTR(NEW.RBJE6_SQLZEILE
, POSSTR(NEW.RBJE6_SQLZEILE,’B=‘) + 2
, 20
)
, RBJE6_GILTVON = SUBSTR(NEW.RBJE6_SQLZEILE
, POSSTR(NEW.RBJE6_SQLZEILE,’GV=‘) + 3
, 10
)
, RBJE6_GILTBIS = SUBSTR(NEW.RBJE6_SQLZEILE
, POSSTR(NEW.RBJE6_SQLZEILE,’GB=‘) + 3
, 10
)
, RBJE6_LASTUSER = SUBSTR(NEW.RBJE6_SQLZEILE
, POSSTR(NEW.RBJE6_SQLZEILE,’U=‘) + 2
, POSSTR(NEW.RBJE6_SQLZEILE,’U=‘) + 2
, 6
)
, RBJE6_SQLZEILENR = 1WHERE O.RBJE6_ANLAGE = ‚INIT‘
AND O.RBJE6_SQLBEZ = ‚INIT‘
AND O.RBJE6_SQLZEILENR = 0
;
END
#
— ANLAGE SETZEN BEI ZWEITEM BIS N-TEN SATZ
CREATE TRIGGER DB.RBJE6AI2
AFTER INSERT
ON DB.RBJE6T
REFERENCING NEW AS NEW
FOR EACH ROW MODE DB2SQL
WHEN (
NEW.RBJE6_ANLAGE = ‚INIT‘
)
BEGIN ATOMIC
UPDATE DB.RBJE6T
SET RBJE6_ANLAGE =(SELECT RBJE6_ANLAGE FROM DB.RBJE6T
WHERE RBJE6_LASTUPDATE =
(SELECT MAX(RBJE6_LASTUPDATE) FROM
DB.RBJE6T
WHERE RBJE6_ANLAGE <> ‚INIT‘
)
)
, RBJE6_SQLBEZ = (SELECT RBJE6_SQLBEZ FROM DB.RBJE6T
WHERE RBJE6_LASTUPDATE =
(SELECT MAX(RBJE6_LASTUPDATE) FROM
DB.RBJE6T
WHERE RBJE6_SQLBEZ <> ‚INIT‘
)
)
WHERE RBJE6_ANLAGE = ‚INIT‘
;
END
#
— SQLZEILENR SETZEN 1 BZW MAX + 1
CREATE TRIGGER DB.RBJE6AI3
AFTER INSERT
ON DB.RBJE6T
REFERENCING NEW AS NEW
FOR EACH ROW MODE DB2SQL
WHEN (
NEW.RBJE6_SQLZEILENR = 0
)
BEGIN ATOMIC
UPDATE DB.RBJE6T
SET RBJE6_SQLZEILENR =(
SELECT MAX(RBJE6_SQLZEILENR)
+ 1
FROM DB.RBJE6T
WHERE RBJE6_LASTUPDATE =
(SELECT MAX(RBJE6_LASTUPDATE) FROM
DB.RBJE6T
WHERE RBJE6_SQLZEILENR > 0
)
)
— WHERE O.RBJE6_ANLAGE = NEW.RBJE6_ANLAGE
— AND O.RBJE6_SQLBEZ = NEW.RBJE6_SQLBEZ
WHERE RBJE6_SQLZEILENR = 0
;
END
#
27. April 2006 um 15:40 Uhr #3769
AnonymInaktivHallo Klaus,
auch wenn Du Dich schon für eine Lösung entschieden hast (habs erst jetzt gesehen), hier noch eine Alternative (die ich in ähnlichen Verfahren anwende):
ich stringe mir einen SQL-Befehl (z.B. mit Infos aus dem Katalog) im QMF zusammen (ob der lange SQL nun eingegeben ist oder ermittelt wird, ist ja nu Wurscht). Über die FORM (F9) formatiere ich mir die Ausgabe mit WIDTH 72 und EDIT CT (wortweiser Zeilenumbruch) so, dass ich den Report exportieren und ausführen kann.
Das ganze kannst Du dann natürlich auch als Batch-QMF ausführen (Call PROC (F= … EXP REP…)
Hoffe, ich konnte auch mal helfen 😉
Alexander
12. Juli 2006 um 15:46 Uhr #3827
AnonymGastIch habe mir hierfür ein Programm geschrieben, das SQLs von Datasets beliebiger Breite (bis 32K) verarbeitet.
Rüdiger
-
AuthorPosts
You must be logged in to reply to this topic.