LDAP-Server abfragen ... mit SQL
In vielen Unternehmen haben LDAP-Server eine zentrale Bedeutung - nahezu alle Mitarbeiter sind dort mit ihren Kontaktdaten abgelegt - So kann es vorkommen, dass man aus der Datenbank heraus auf diese Informationen zugreifen möchte. Und die Oracle-Datenbank bringt dazu auch ein Hilfsmittel mit: DBMS_LDAP. Mit diesem PL/SQL-Paket kann man auf LDAP-Directories zugreifen und dort Informationen abrufen oder manipulieren. Allerdings ist es recht aufwändig, mit diesem Paket zu programmieren ... viel hübscher wäre es, wenn man mit einem SQL SELECT auf die Informationen zugreifen könne - dies würde die Aufbereitung der Daten bspw. in einer Web-Anwendung (Application Express-Bericht) massiv vereinfachen.
Der folgende Code ermöglicht genau dies. Die LDAP-Abfrage wird durch eine Table Function durchgeführt; diese Funktionen liefern keine skalaren Werte, sondern eine ganze Tabelle zurück (mehr zu Table Functions in diesem Blog). Es gibt hier aber noch eine Besonderheit zu beachten: Normalerweise muss man die "Rückgabetabelle" der Table Function durch einen Objekttypen (CREATE TYPE) festlegen und so beschreiben. Das folgende Beispiel geht etwas anders vor: Mit Hilfe des Oracle Data Cartridge Interface (ODCI) kann man ebenfalls Table Functions bauen und hier muss man vorher keine Objekttypen erstellen.
Wenn DBMS_LDAP in der Datenbank nicht vorhanden ist, kann der DBA es mit $ORACLE_HOME/rdbms/admin/catldap.sql einspielen. Doch genug der Vorrede: hier der Code
drop type ldapquery / CREATE type ldapquery as object( ldap_host varchar2(4000), ldap_port number, ldap_session raw(32), ldap_resultset raw(32), q_search_base varchar2(4000), q_search_filter varchar2(4000), q_return_fields varchar2(4000), q_timeout number, row_types anytype, last_entry_fetched number, static function query( p_ldap_host in varchar2, p_ldap_port in number, p_search_base in varchar2, p_search_filter in varchar2, p_return_fields in varchar2, p_timeout in number default 3 ) return anydataset pipelined using ldapquery, static function ODCITableDescribe( record_table out anytype, p_ldap_host in varchar2, p_ldap_port in number, p_search_base in varchar2, p_search_filter in varchar2, p_return_fields in varchar2, p_timeout in number ) return number, static function ODCITablePrepare ( sctx out ldapquery, tab_func_info in sys.ODCITabFuncInfo, p_ldap_host in varchar2, p_ldap_port in number, p_search_base in varchar2, p_search_filter in varchar2, p_return_fields in varchar2, p_timeout in number ) return number, static function ODCITableStart ( sctx in out ldapquery, p_ldap_host in varchar2, p_ldap_port in number, p_search_base in varchar2, p_search_filter in varchar2, p_return_fields in varchar2, p_timeout in number ) return number, member function ODCITableFetch ( self in out ldapquery, nrows in number, record_out out anydataset ) return number, member function ODCITableClose ( self in ldapquery ) return number ) /
create or replace package ldapquery_helper is function tokenize( p_string in varchar2, p_delim in varchar2 default ',' ) return dbms_ldap.String_collection; end ldapquery_helper; / create or replace package body ldapquery_helper is function tokenize( p_string in varchar2, p_delim in varchar2 default ',' ) return dbms_ldap.String_collection is v_startpos pls_integer := 1; v_comma_pos pls_integer; v_result_array dbms_ldap.string_collection; v_array_index pls_integer := 0; begin while v_startpos != 0 loop v_comma_pos := instr(p_string, p_delim, v_startpos); if v_comma_pos != 0 then v_result_array(v_array_index) := substr(p_string, v_startpos, v_comma_pos - v_startpos); v_startpos := v_comma_pos + 1; else v_result_array(v_array_index) := substr(p_string, v_startpos); v_startpos := v_comma_pos; end if; v_array_index := v_array_index + 1; end loop; return v_result_array; end tokenize; end ldapquery_helper; / CREATE or replace type BODY ldapquery as static function ODCITableDescribe( record_table out anytype, p_ldap_host in varchar2, p_ldap_port in number, p_search_base in varchar2, p_search_filter in varchar2, p_return_fields in varchar2, p_timeout in number ) return number as v_record_structure anytype; v_result_array dbms_ldap.string_collection; begin v_result_array := ldapquery_helper.tokenize(p_return_fields); anytype.begincreate(dbms_types.typecode_object, v_record_structure); for i in v_result_array.first..v_result_array.last loop v_record_structure.addattr( ANAME => v_result_array(i), TYPECODE => dbms_types.typecode_varchar2, PREC => null, SCALE => null, LEN => 4000, CSID => null, CSFRM => null, ATTR_TYPE => null ); end loop; v_record_structure.endcreate(); anytype.begincreate(dbms_types.typecode_table, record_table); record_table.setinfo(null, null, null, null, null, v_record_structure, dbms_types.typecode_object, 0); record_table.endcreate(); return odciconst.success; exception when others then -- indicate that an error has occured somewhere. return odciconst.error; end; static function ODCITablePrepare ( sctx out ldapquery, tab_func_info in sys.ODCITabFuncInfo, p_ldap_host in varchar2, p_ldap_port in number, p_search_base in varchar2, p_search_filter in varchar2, p_return_fields in varchar2, p_timeout in number ) return number is prec pls_integer; scale pls_integer; len pls_integer; csid pls_integer; csfrm pls_integer; record_desc anytype; aname varchar2(30); dummy pls_integer; begin dummy := tab_func_info.RetType.GetAttrElemInfo(null, prec, scale, len, csid, csfrm, record_desc, aname); sctx := ldapquery(p_ldap_host, p_ldap_port, null, null, p_search_base, p_search_filter, p_return_fields, p_timeout, record_desc, 0); return odciconst.success; end; static function ODCITableStart ( sctx in out ldapquery, p_ldap_host in varchar2, p_ldap_port in number, p_search_base in varchar2, p_search_filter in varchar2, p_return_fields in varchar2, p_timeout in number ) return number is v_ldap_session dbms_ldap.session; v_ldap_resultset dbms_ldap.message; v_bind_status pls_integer; v_search_status pls_integer; v_return_attrs dbms_ldap.string_collection; v_timeout dbms_ldap.timeval; begin v_return_attrs := ldapquery_helper.tokenize(p_return_fields); v_timeout.seconds := p_timeout; v_timeout.useconds := 0; v_ldap_session := dbms_ldap.init(p_ldap_host, p_ldap_port); v_bind_status := dbms_ldap.bind_s( ld => v_ldap_session ,dn => null ,cred => null ,meth => dbms_ldap.AUTH_SIMPLE ); v_search_status := dbms_ldap.search_st( ld => v_ldap_session, base => p_search_base, scope => dbms_ldap.SCOPE_SUBTREE, filter => p_search_filter, attrs => v_return_attrs, attronly => 0, res => v_ldap_resultset, tv => v_timeout ); sctx.ldap_session := v_ldap_session; sctx.ldap_resultset := v_ldap_resultset; return odciconst.success; end; member function ODCITableFetch ( self in out ldapquery, nrows in number, record_out out anydataset ) return number is v_return_attrs dbms_ldap.string_collection; v_att_values dbms_ldap.string_collection; v_field varchar2(4000); v_no_more_rows boolean := true; begin record_out := null; v_return_attrs := ldapquery_helper.tokenize(q_return_fields); begin anydataset.begincreate(dbms_types.typecode_object, self.row_types, record_out); record_out.addinstance; record_out.piecewise(); for i in v_return_attrs.first..v_return_attrs.last loop v_att_values := dbms_ldap.get_values( ld => ldap_session, ldapentry => ldap_resultset, attr => v_return_attrs(i) ); if v_att_values.exists(0) then v_field := v_att_values(0); else v_field := null; end if; record_out.setvarchar2(v_field); end loop; record_out.endcreate; ldap_resultset := dbms_ldap.next_entry( ld => ldap_session, msg => ldap_resultset ); exception when others then v_no_more_rows := false; end; if not v_no_more_rows then begin record_out.endcreate; exception when others then null; end; record_out := null; end if; return odciconst.success; end; member function ODCITableClose ( self in ldapquery ) return number is v_ldap_session dbms_ldap.session; v_unbind_status pls_integer; begin v_ldap_session := ldap_session; v_unbind_status := dbms_ldap.unbind_s( ld => v_ldap_session ); return odciconst.success; end; end; /
Ausprobieren ist dann ganz einfach ...
select * from table(
ldapquery.query(
'ldapserv.mydomain.com', -- Servername oder IP-Adresse
389, -- TCP/IP-POrt
'', -- Die Suche erfolgt ab diesem Eintrag im LDAP-Baum
'(cn=Czarski*)', -- Suchabfrage
'cn,c,title', -- Rückgabefelder
3 -- Timeout für Abfrage: 3 Sekunden
)
);
cn c title
-------------------- ------- --------------------------------------
Czarski,Carsten de Leitende/R Systemberater/In
1 Zeile wurde ausgewählt.
Kommentare:
Hallo ich habe die Sache mit der LDAP-Abfrage probiert, bekomme aber folgenden Fehler beim Ausführen des Selects
ORA-31202:DBMS_LDAP:LDAP_Client-/Server-Fehler:Fehler bei Vorgängen. 00000000:LdapErr: DSID-0C090627, comment: In order to perform this operation a succesful bind must be completed on the connection., data 0, vece
ORA-06512: in SYS.DBMS_SYS_ERROR, Zeile 86
ORA-06512: in SYS.DBMS_LDAP, Zeile 1455
ORA-06512: in SYS.DBMS_LDAP, Zeile 312
ORA-06512: in LDAP_TEST.LDAPQUERY, Zeile 105
Das ist nun ein Bereich, wo u.U. eine Anpassung an Ihren LDAP-Server nötig ist ... Das Beispiel geht davon aus, dass der LDAP-Server anonyme Anfragen zulässt - im BIND_S-Call werden NULL-Werte für "dn" (Username) und "cred" (Passwort) übergeben.
v_ldap_session := dbms_ldap.init(p_ldap_host, p_ldap_port);
v_bind_status := dbms_ldap.bind_s(
ld => v_ldap_session
,dn => null
,cred => null
,meth => dbms_ldap.AUTH_SIMPLE
);
Ihre Fehlermeldung deutet darauf hin, dass Ihr LDAP-Server eine "richtige" Anmeldung erwartet ... Dann muss das Skript entsprechend angepasst werden ...
Super Arbeit! Habe schon seit längerem nach einer Lösung mit diesem Ansatz gesucht. Habe den Type erweitert, sodass User/PWD für AD-Abfrage angegeben werden kann. Zusätzlich erstellte ich Views basierend auf ldapquery.query für eine komfortable Abfrage der Memberships.
Leider erhalte ich jedoch jeweils pro AD-Gruppe nur ein Rekord zurück, obwohl die Gruppe Member von mehreren anderen Gruppen ist.
Gibts im Resultset irgendwo eine Einschränkung, sodass nur ein FETCH erfolgt?
create or replace view lpadm_ad_base_groups_v
as
select
x."cn" base_group
,x."member" member_string
from table
( ldapquery.query
('xy.ch'
,389
,'sa_oracle'
,'*pwd*'
,'ou=Groups,ou=_test,dc=xyv,dc=ch'
,'(cn=*)'
,'cn,member'
,3)
) x;
CREATE OR REPLACE VIEW lpadm_ad_groups_memberships_v
AS
select base_group
,SUBSTR(member_string, INSTR(member_string, 'CN=')+3, INSTR(member_string, ',OU=')-4) is_member
,member_string
from lpadm_ad_base_groups_v;
Das ResultSet kann mehrere Sätze zurückliefern. Die Vorgehensweise ist die, dass mit ...
ldap_resultset :=
dbms_ldap.next_entry(
ld => ldap_session,
msg => ldap_resultset
);
jeweils auf den nächsten Datensatz vorgerückt wird. Ist der letzte erreicht, wird eine Exception ausgelöst; daraufhin wird record_out auf SQL NULL gesetzt - wodurch der Fetch beendet wird.
Ich habe das Beispiel auch schon mit mehreren Ergebniszeilen getestet - lief sehr gut.
Beim Compilieren der OT-Specification erhalte ich die Fehlermeldung:
(S5093) Expecting:), AGGREGATE AS AUTHID DETERMINISTIC IS PARALLEL_ENABLE PIPELINED
Trotzdem kann ich den Body compilieren und auch Ausführen. Könnte dies der Grund sein, dass nicht alle Rekords (Einträge im Active Directory) ausgelesen werden? Wir verwenden Ora 10g R2.
das ist schon möglich ...
S5093 ist eine seltsame Fehlermeldung; scheint mir nicht aus der Datenbank zu kommen. Arbeitest Du mit einem Werkzeug (TOAD, etc) ...?
Dann am besten den Code mal aus SQL*Plus heraus laufen lassen und dessen Fehlermeldungen ansehen ...
Ausgezeichnetes Script! Eine Frage, die sich mir stellt: gewisse Felder wie die objectGUID werden in unserer OracleDB als Schlüssel verwendet. Durch ein Script wird mir diese ID als hexadezimale Zahl (32Zeichen) nach Oracle geschrieben. Um nun direkt abzufragen, müsste ich dieses Feld nun ebenfalls hex darstellen bzw umformatieren können. rawtohex, rawidtochar, o.ä.?
Hallo Carsten,
gibt es eine Möglichkeit, mehrere AD-Server (IP-Adressen) zu übergeben? Oder anders, wenn ein bestimmter Server nicht erreichbar ist, ein Fehler abgefangen werden kann, um einen "Ersatz-Server" abzufragen?
Hi,
out-of-the-box geht das nicht; DBMS_LDAP kennt sowas wie ein Failover nicht. Man kann das natürlich noch selbst "dranprogrammieren"; das würde dann bedeuten, dass man eben eine Liste mit LDAP-Server-Adressen mitgibt, der PL/SQL-Code probiert diese aus, fängt evtl. auftretende Fehler ab und probiert im Bedarfsfall die nächste ...
Wäre noch ein wenig Arbeit ...
Viele Grüße
-Carsten
Hallo, das ist echt eine super Lösung ... leider hab ich mal noch 'ne dumme Anfängerfrage: Wie kann ich das Select-Statement in einer Procedure aufrufen (zum Beispiel als Cursor).
Hallo,
naja, ein "impliziter" Cursor könnte so aussehen ...
create or replace ...
begin
:
for c in (select ... from table(ldapquery.query(....))) loop
:
-- machwas
:
end loop;
end;
Hilft das ...?
-Carsten
Hallo, leider nicht, weil ich da immer folgenden Fehler bekomme: cannot access rows from a non-nested table item.
Danke
Hallo,
ok ... auch gerade erkannt. Das hier (arbeitet mit dem eigentlich für dynamisches SQL vorgesehenen OPEN ... FOR) tut es bei mir ...
set serveroutput on
declare
type c_t is ref cursor;
v_c c_t;
v_cn varchar2(4000);
begin
open v_c for
q'#select * from table(
ldapquery.query(
'meinldap.domain.com',
389,
'',
'(cn=Czarski*)',
'cn',
3
)
)#';
loop
fetch v_c into v_cn;
exit when v_c%NOTFOUND;
dbms_output.put_line(v_cn);
end loop;
end;
/
... funktioniert bei mir.
-Carsten
Danke, super ... so funktioniert es.
Hi,
ist es möglich bei der Abfrage die Anzahl der Treffer zu bestimmen z.B. nur 50 Treffer.
Danke
Marek
Hallo,
DBMS_LDAP bietet diese Möglichkeit leider nicht an; man kann in der SQL-Abfrage natürlich ein WHERE ROWNUM < x anhängen, aber dann werden dennoch alle Ergebnisse vom LDAP-Server geholt ...
Viele Grüße
-Carsten
ich würde gerne das ganze in einer Function verwenden, und als table casten, aber das gibt mir immer den Fehler cannot fetch rows from a non nested object.
Wenn ich nun einen eigenen type erstelle und den caste, dann bekomme ich den Fehler inkonsistente datentypen.
im reinen sql fenster funktioniert es problemlos.
select
cast(
multiset(
select * from table(cast(
ldapquery.query(
'', -- Servername oder IP-Adresse
389, -- TCP/IP-POrt
'',-- Die Suche erfolgt ab diesem Eintrag im LDAP-Baum
'(&(objectCategory=group))', -- Suchabfrage
'distinguishedname,sAMAccountName,mailnickname,AdsPath,CN', -- Rückgabefelder
10
) -- Timeout für Abfrage: 3 Sekunden
as t_adsget))
)as t_table_getUsersADS
)
into v_ret from dual;
Hallo
ich bekomme es einfach nicht hin Type und Package sind erstellt dann versuche ich das Teststatement auszuführen
select * from table(
ldapquery.query(
'AD Servername', -- Servername oder IP-Adresse
3268, -- TCP/IP-POrt
'', -- Die Suche erfolgt ab diesem Eintrag im LDAP-Baum
'(cn=*)', -- Suchabfrage
'cn,c', -- Rückgabefelder
3 -- Timeout für Abfrage: 3 Sekunden
)
);
bekome dann die meldung ora-03113 Unerwartetes ende der Kommunikation
habe keine Idee was ich da falsch mache?!?!?
Hallo,
das sieht nach einem Netzwerkproblem aus ... ist em Ende wirklich der LDAP-Server .. ist dieser einigermaßen LDAP-konform ..
Bei einem ORA-3113 wird i.d.R. noch eine Tracedatei geschrieben - vielleicht findet man dort mehr Informationen ...
Beste Grüße und ein gutes neues Jahr 2012!
-Carsten Czarski
Hallo Carsten,
beim Ausführen des Beispiel-Selects erhalte ich noch folgende Fehlermeldung:
ORA-24247: network access denied by access control list (ACL)
ORA-06512: at "SYS.DBMS_LDAP_API_FFI", line 25
ORA-06512: at "SYS.DBMS_LDAP", line 48
ORA-06512: at "APEX_TEST.LDAPQUERY", line 91
Muss mir der DBA hier noch irgendwelche Rechte geben?
Danke + Gruß
Daniel
Hallo,
jawohl - der DBA muss den Netzwerk-Connect auf den externen LDAP-Server zuerst mit dem Packet DBMS_NETWORK_ACL_ADMIN freigeben ...
Beste Grüße
-Carsten
Ok, das hat jetzt funktioniert.
Danke.
Gruß, Daniel
Ich erhalte nun die Meldung
ORA-31202: DBMS_LDAP: LDAP client/server error: No such object. 0000208D: NameErr: DSID-031001E5, problem 2001 (NO_OBJECT), data 0, best match of:
''
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 86
ORA-06512: at "SYS.DBMS_LDAP", line 1487
ORA-06512: at "SYS.DBMS_LDAP", line 312
.
Ist das ein Anmeldeproblem bei LDAP oder stimmt meine Abfrage nicht?
Danke + Gruß
Daniel
Hallo,
da ist wahrscheinlich was im LDAP-Server selbst schiefgegangen - am besten nehmen wir das "offline" ...
Schreib' mich doch einfach mit ein paar Details (welche konkrete Abfrage, welcher LDAP-Server) an ...
Beste Grüße
-Carsten
Ok, hab Dir eben eine Email geschickt.
Danke + Gruß
Daniel
Hallo, das funktioniert alles Super, Vielen Dank dafür.
Ich habe nur ein Problem ich lese verschiedene Gruppen aus und suche dann die Memebers dazu raus. Dort laufe ich auf eine Beschränkung von 1499 Sätzen. Gibt es irgendwo noch einen Parameter der wie z.B. sizelimit in nem VB-Script heisst??? Wie könnte man diese Problematik umgehen? Einstellung LDAP-Server? LG Dieter
Hallo Dieter,
aus dem Paket DBMS_LDAP ist mir keine entsprechende Einstellung bekannt. Es kann durchaus sein, dass der LDAP Server so konfiguriert ist, dass er maximal 1499 oder 1500 Ergebnisse ausliefert - LDAP Server sind ja gerade für Einzel-Lookups ausgelegt - "Massen-Selects" werden oft verhindert ...
Beste Grüße
-Carsten
Hi,
ich habe alles genau wie beschrieben gemacht und scheitere aber bereits beim Testen des ersten SQL. Dort erhalte ich folgende Fehlermeldung:
Fehlerbericht:
ORA-06550: Zeile 4, Spalte 27:
PLS-00302: Komponente 'LDAPQUERY' muss deklariert werden
ORA-06550: Zeile 4, Spalte 6:
PL/SQL: Statement ignored
ORA-06512: in Zeile 7
Mit der Bitte um Hilfe!
Das Problem existiert unter dem User SYS nicht, aber noch eine weitere Frage:
Was muss man tun, um mehrere Einträge zurückzuliefern? Ich erhalte nach wie vor nur den jeweils ersten Record ausgegeben (in meinem Fall den nur den ersten Mitarbeiter der AD-Gruppe).
Es wurde schonmal hier beschrieben:
ldap_resultset :=
dbms_ldap.next_entry(
ld => ldap_session,
msg => ldap_resultset
);
Allerdings steht dies exakt so in meiner TYPE-Definition und funktioniert leider nicht.
Please help! THX!!!
Hallo "Anonym",
eine Antwort auf beide Kommentare. Wenn er das Objekt "LDAPQUERY" nicht finden (bzw. nur als SYS findet), dann dürfte das daran liegen, dass es als SYS eingespielt wurde und nun versucht wird, es mit einem anderen User zu nutzen. Eine Lösung wäre, das EXECUTE Privileg zu granten.
Zwei zweiten Frage nach dem Select für mehrere Zeilen ...
Es ist im Posting unten erklärt ...
select * from table(
ldapquery.query(
'ldapserv.mydomain.com', -- Servername oder IP-Adresse
389, -- TCP/IP-POrt
'', -- Die Suche erfolgt ab diesem Eintrag im LDAP-Baum
'(cn=Czarski*)', -- Suchabfrage
'cn,c,title', -- Rückgabefelder
3 -- Timeout für Abfrage: 3 Sekunden
)
);
Beste Grüße
-Carsten
Wer das Problem mit den mehrfachen Datensätzen auch hat, hier die Lösung (danke an Carsten für den Support)! Folgende Member-Funktion ersetzen:
MEMBER FUNCTION odcitablefetch (
SELF IN OUT ldapquery,
nrows IN NUMBER,
record_out OUT ANYDATASET
)
RETURN NUMBER
IS
v_return_attrs DBMS_LDAP.string_collection;
v_att_values DBMS_LDAP.string_collection;
v_field VARCHAR2 (4000);
v_no_more_rows BOOLEAN := TRUE;
BEGIN
record_out := NULL;
v_return_attrs := ldapquery_helper.tokenize (q_return_fields);
BEGIN
ANYDATASET.begincreate (DBMS_TYPES.typecode_object,
SELF.row_types,
record_out
);
record_out.addinstance;
record_out.piecewise ();
FOR i IN v_return_attrs.FIRST .. v_return_attrs.LAST
LOOP
v_att_values :=
DBMS_LDAP.get_values (ld => ldap_session,
ldapentry => ldap_resultset,
attr => v_return_attrs (i)
);
v_field := '';
IF v_att_values.EXISTS (0)
THEN
FOR idx IN v_att_values.FIRST .. v_att_values.LAST
LOOP
IF v_field IS NULL
OR (LENGTH (v_field) + LENGTH (v_att_values (idx))) <
4000
THEN
v_field := v_field || v_att_values (idx) || ',';
END IF;
END LOOP;
v_field := SUBSTR (v_field, 1, LENGTH (v_field) - 1);
ELSE
v_field := NULL;
END IF;
record_out.setvarchar2 (v_field);
END LOOP;
record_out.endcreate;
ldap_resultset :=
DBMS_LDAP.next_entry (ld => ldap_session,
msg => ldap_resultset);
EXCEPTION
WHEN OTHERS
THEN
v_no_more_rows := FALSE;
END;
IF NOT v_no_more_rows
THEN
BEGIN
record_out.endcreate;
EXCEPTION
WHEN OTHERS
THEN
NULL;
END;
record_out := NULL;
END IF;
RETURN odciconst.success;
END;
Das Problem
ORA-06550: Zeile 4, Spalte 24:
PLS-00302: Komponente 'LDAPQUERY' muss deklariert werden
ORA-06550: Zeile 4, Spalte 6:
PL/SQL: Statement ignored
tritt auf ein einem Schema, das eine Tabelle besitzt die den gleichen Namen hat wie das Schema.
Problem reproduzieren:
- Im Schema TESTTEST arbeiten
- ldapquery einrichten und testen
select SELECT * FROM TABLE( ldapquery.query(... funktioniert
- Tabelle TESTTEST.TESTTEST erzeugen
select SELECT * FROM TABLE( ldapquery.query(... funktioniert noch
- Type ldapquery kompilieren: Select funktioniert nicht mehr, Fehlermeldung s.o.
Noch aufgefallen:
Die Spalte "24" in der Fehlermeldung hängt von der Länge des Schemanamens ab:
Spalte = Länge(Schemaname)+16
Kommentar veröffentlichen