PDA

View Full Version : SQL - Abfrage mit IF-CLAUSE via SYSCOLUMNS



urrumpel
02-08-21, 11:45
trim(SYSTEM_COLUMN_NAME) = BERIC00001
----------------------------------------------------------------
Dieses Skript funktioniert nicht:


SELECT *
FROM mytable
WHERE (SELECT trim(SYSTEM_COLUMN_NAME)
FROM syscolumns
WHERE SYSTEM_TABLE_SCHEMA = 'mylib'
and SYSTEM_TABLE_NAME = 'mytable'
and COLUMN_NAME = 'mycolumn'
) = 2020
Auswahlfehler für Feld *N.

SELECT/OMIT-Fehler in Feld Cast(Translate(Strip(QADBIFLD_1.DBIFLD, Both,'
'),, Teildatei mytable.


------------------------------------------------------------------
Dieses funktioniert prima ... Wieso kann ich nicht BERIC00001 durch trim(SYSTEM_COLUMN_NAME) ersetzen, da das Ergebnis des SUBSELECTes für SYSTEM_COLUMN_NAME doch BERIC00001 ist?


SELECT *
FROM mytable
WHERE (SELECT BERIC00001
FROM syscolumns
WHERE SYSTEM_TABLE_SCHEMA = 'mylib'
and SYSTEM_TABLE_NAME = 'mytable'
and COLUMN_NAME = 'mycolumn'
) = 2020

B.Hauser
02-08-21, 12:52
Der Spalten-Name ist alphanumerisch, deshalb muss der Spalten-Name, sowie der Vergleichswert in Hochkommata gesetzt werden und '2020' ist zudem kein zulässiger Spalten-Name.

Birgitta

Fuerchau
02-08-21, 13:18
Wobei ich mich frage, was du damit überhaupt erreichen willst.
Du kannst die Spalte deiner Tabelle sowohl mit dem langen als auch mit dem Systemnamen ansprechen.
Daher weiß ich nicht, da du beide Namen kennst, warum das deine Abfrage noch bestätigen soll;-).

urrumpel
02-08-21, 14:58
Danke für das Feedback.

Das Problem ist, dass wir ein eigenes Framework einsetzen (ich bin in einer anderen Fraktion und kenne das nicht näher), welches das " - Zeichen anscheinend nicht verarbeiten kann.

Wir haben Tabellen - Attribute, die z.B. "Berichtsjahr" heißen. Wenn ich via SQL - Abfrage - kein Problem....

Select ... where "Berichtsjahr" = 2020 oder Select .... where BERIC00001 = 2020 geht.

Wird das aber unser Framework eingebunden, geht es anscheinend nicht....
Jetzt wollte ich den Systemnamen eben aus SYSCOLUMNS auslesen und dann den verwenden.

Wenn in dem SUBSELECT der Systemname direkt steht, klappt es, wenn ich den Systemnamen aus SYSTEM_COLUMN_NAME ermittle eben nicht, obwohl er m.E. doch genau den Wert 'BERIC00001' ermittelt....

@Birgitta: Ja, wenn ich = '2020' nehme, fällt das Skript nicht auf die Nase, ermittelt aber auch nichts. Das Subselect ermittelt 'eigentlich' den Spaltennamen BERIC00001 und der soll mit dem Wert 2020 verglichen werden. Wenn ich in den SUBSELECT den Spaltennamen 'BERIC00001' direkt eintrage klappt es, wie gesagt.

Hoffe, ich konnte mich verständlich machen?

Andreas_Prouza
02-08-21, 15:10
Bei ... SELECT BERIC00001 FROM syscolumns ... bekommst du den Wert von der Spalte BERIC00001.
Also bei ... (SELECT BERIC00001 FROM syscolumns) = 2020
... bekommst du (2020) = 2020
Bei ... (SELECT trim(SYSTEM_COLUMN_NAME) FROM syscolumns) = 2020
... bekommst du ('BERIC00001') = 2020

Das was du willst ist eigentlich ein Dynamisches SQL.
Also du ermittelst dir deinen Sys-Column und dann bastelst du dir dein SQL in einer Variable zusammen.
Machst ein Prepare und dann einen Cursor basierend auf dem Prepare.

lg Andreas

urrumpel
02-08-21, 15:49
Danke..., das ich 'BERIC00001' erhalte habe ich mir schon gedacht, warum das so ist weiß ich allerdings nicht so genau... Man kriegt das auch mit STRIP nicht weg.... -ok + schade.

Das SQL dynamisch basteln würde passen danke - aber mein Ziel war es, es rein im SQL-Editor hinzukriegen...

Ich gebe das mal unserer 'Frameworker' weiter - vlt. finden die eine Lösung.
Keine Ahnung wie die zugreifen, selbst SELECT * FROM... where BERIC00001 = 2020 klappt nicht


Fehlersituation beim Verarbeiten einer Ergebnismenge: Fehler beim Auslesen eines Attributes an der Stelle BERIC00001 als Datentyp getLong.
Caused by: de.framework.status.EgfTSLException: Fehlersituation beim Verarbeiten einer Ergebnismenge: Fehler beim Auslesen eines Attributes an der Stelle BERIC00001 als Datentyp getLong.
at de.framework.persistence.CSqlResultSet.mpcOnError( Unknown Source)
at de.framework.persistence.CSqlResultSet.mccGetInteg erWFieldByName(Unknown Source)
at de.sdrc3db.persistence.daos.daotab.Cdaotabmytable. mccBuildDo(Cdaotabmytable.java:356)
... 11 more
Caused by: com.ibm.as400.access.AS400JDBCSQLSyntaxErrorExcept ion: An undefined column name was detected.
at com.ibm.as400.access.JDError.createSQLExceptionSub Class(JDError.java:891)
at com.ibm.as400.access.JDError.throwSQLException(JDE rror.java:418)
at com.ibm.as400.access.JDError.throwSQLException(JDE rror.java:395)
at com.ibm.as400.access.JDServerRow.findField(JDServe rRow.java:519)
at com.ibm.as400.access.AS400JDBCResultSet.findColumn (AS400JDBCResultSet.java:575)
at com.ibm.as400.access.AS400JDBCResultSet.getLong(AS 400JDBCResultSet.java:3133)
... 13 more

Fuerchau
02-08-21, 15:54
Dann must du der anderen Fraktion ein Mapping der Spalten LongName zu Systemnamen bereitstellen, denn die SQL's müssen ja direkt so aufgebaut werden.
Namen (Feldnamen, Tabellennamen) sind nicht als Parameter erlaubt.
D.h., derjenige, der den SQL bastelt, benötigt die korrekten Feldnamen um dieses tun zu können.

Das ist übrigens ein häufiges Problem von Microsoftprodukten (wie PowerQuery/Power-BI), die nur ihre eckigen Klammern für Feldnamen kennen und von SQL-Standard nichts wissen wollen.
Alternativ musst du halt eine View erstellen, die Namen nur in Großbuchstaben bereitstellt, also BERICHTSJAHR statt "Berichtsjahr". Diese dürfen dann auch länger als 10 Stellen sein.

Bei z.B. PowerBI kann man dann irgendwo auf erweitert klicken und den SQL native direkt eingeben.
Notfalls kann man auch einen SQL-Server mit Views auf einen Linked-Server nach der Methode:

select * from OpenQuery(MyAs400, "Select * from Mylib.MyTable")

bereitstellen.

PS:
Und "SELECT BERIC00001 FROM syscolumns" geht alleine schon deshalb nicht, weil BERIC00001 kein Spaltenname von syscolumns ist.

urrumpel
02-08-21, 17:00
Danke - Wird wohl auf eine View hinauslaufen...

Vorher probieren wir noch was anderes - evtl. ist beim Zugriff auf die i5 die QSYS2 nicht in der LIBL, wir haben die SYSCOLUMNS mal in der LIB, die in jedem fall im Zugriff ist erstellt.

Das SELECT BERIC00001 FROM SYSCOLUMS als SUBSELECT wie o.a. angeführt funktioniert....
Nur beim substituieren mit SYSTEM_COLUMN_NAME eben nicht....

Danke erstmal, wenn wir nicht weiterkommen, melde ich mich nochmal.

Fuerchau
02-08-21, 17:20
Dann zeige mir mal den Spaltennamen BERIC00001 in der Tabelle SYSCOLUMNS:
https://www.ibm.com/docs/en/i/7.2?topic=views-syscolumns

Ein Select 'BERIC00001' from SYSCOLUMNS liefert dir die Konstante.

Was ich hier eher vermute ist, dass du einen Fehler bekommst: "Variable BERIC00001 nicht gefunden", da SQL immer davon ausgeht, dass bei unbekannten Namen in den Tabellen dann eine SQL-Variable mit dem Namen vorhanden sein muss, dessen Inhalt dann ausgelesen wird.

Die SYSCOLUMNS wird i.Ü. bei Schemaabfragen via SQL automatisch verwendet.
Wenn du einen SQL CREATE COLLECTION erstellst, erhälst du verschiedene SYS-Views in deiner LIB mit eingeschänkter Sicht auf diese Lib. Also auch eine SYSCOLUMNS-View.