# PDF als BLOB in DB ablegen ORACLE



## cullmann (13. Februar 2007)

Servus alle zusammen,

wollte ein PDF ein eine Oracle DB speichern, meine code sieht wei folgt aus:

```
declare
v_test_bfile bfile;

begin
  v_test_bfile := Bfilename('Bfile_data', 'TestDatei.txt');
  
  insert into dokumente(dokumentenID, docname, Lehrid, semesterid, kurzbeschreibung, dokument, fachid)
  values(dokumenteseq.nextval, 'Skript_OperationsResearch_1', 
                        112, 2, 'Viele Summenzeichen schinden eindruck', 
                        v_test_bfile, 212);


end;
```
Bfile_data ist mein directory alias, das entsprechende Recht hab ich auch  gegrantet. 
Leider funktionert meint code garnicht, bekomme immer folgende Fehlermeldung:

```
Error report:
ORA-06550: Zeile 10, Spalte 25:
PL/SQL: ORA-00932: Inkonsistente Datentypen: NUMBER erwartet, FILE erhalten
ORA-06550: Zeile 7, Spalte 3:
PL/SQL: SQL Statement ignored
```
Aber die spalte dokument ist als blob angelegt. 


hab in der Docu was zu dem Thema gefunden:

```
DBMS_LOB.LOADBLOBFROMFILE (
   dest_lob    IN OUT NOCOPY BLOB, 
   src_bfile   IN            BFILE, 
   amount      IN            INTEGER, 
   dest_offset IN OUT        INTEGER, 
   src_offset  IN OUT        INTEGER);
```

Was ich jetzt nicht ganz versetehe ist wofür ich diese Procedure brauche!?
Also wann kann ich mit einem insert arbeiten und wann muss ich auf das loadblobformfiel anwenden

Cullmann


----------



## cullmann (14. Februar 2007)

OK eine teil des Rätsels habe ich jetzt rausbekommen. 

mein code sieht jetzt wie folgt aus:

```
declare
v_test_bfile bfile := Bfilename('c:\', 'SQL10G.pdf');
--v_test_bfile bfile := Bfilename('Bfile_data', 'SQL10G.pdf');
v_zeiger blob; --Lediglich eine Referenz auf den BLOB
v_zeiger_offset INTEGER :=1;
v_source_offset INTEGER :=1;
V_err_msg Varchar2(200);

begin
 
  
  insert into dokumente(dokumentenID, docname, Lehrid, semesterid, kurzbeschreibung, dokument, fachid)
  values(dokumenteseq.nextval, 'Skript_OperationsResearch_1', 
                        144, 2, 'Viele Summenzeichen schinden eindruck', 
                        Empty_BLOB(), 239);
  
  select dokument into v_zeiger from dokumente
  --where dokumentenID = dokumentenseq.currval; warum geht das nicht
  where dokumentenID = 30;
  
  --Datei öffenen
  dbms_lob.fileopen(v_test_bfile, dbms_lob.file_readonly);
  
  --LOB öffnen
  --dbms_lob.OPEN(v_zeiger_offset, dbms_lob.lob_readwrite);
  
  --Datei in die Tabelle laden
  dbms_lob.LOADBLOBFROMFILE(v_zeiger,
                            v_test_bfile,
                            dbms_lob.lobmaxsize,
                            v_source_offset,
                            v_zeiger_offset);
    
   
                           
  DBMS_LOB.CLOSE(v_zeiger);
  DBMS_LOB.CLOSE(v_test_bfile);


end;
```

Das problem ist jetzt das die DB meine Verzeichnis nicht findet:


```
Error report:
ORA-22285: Verzeichnis oder Datei für FILEOPEN-Vorgang nicht vorhanden
ORA-06512: in "SYS.DBMS_LOB", Zeile 523
ORA-06512: in Zeile 22
```

Das Verzeichnis habe ich aber angelegt auch mein directoreyAlias ist richtig.
Hat einer ne idee?

cullmann


----------



## Thomas Darimont (14. Februar 2007)

Hallo,

schau mal hier für ein alternatives Beispiel:
http://www.tutorials.de/forum/relat...8452-datei-bild-oracle-tabelle-speichern.html

Gruß Tom


----------



## cullmann (14. Februar 2007)

Ok, danke. 

Aber die machen doch alles genau so wie ich. Nur das der einen relativen Pfad verwendet....
Ich raff einfach net warum meine DB das Verzeichnis nicht findest.

Achja, warum kann ich im pl/sql kein currval bei der sequence verwenden?


----------



## Exceptionfault (14. Februar 2007)

cullmann hat gesagt.:


> --where dokumentenID = dokumentenseq.currval; warum geht das nicht



Eine Sequence hat 2 Methoden, NEXTVAL und CURRVAL.

Mit NEXTVAL wird der nächste Wert zurückgegeben und die Sequence erhöht. CURRVAL liefert dann immer den Wert, der mit NEXTVAL abgefragt wurde. Das ganze ist natürlich SESSION abhängig, d.h. wenn 2 User gleichzeitig .NEXTVAL aufrufen bekommen sie unterschiedliche Werte. CURRVAL liefert dann auch jeder Session exakt den Wert den sie von NEXTVAL bekommen haben, und nicht wie oft vermutet den jetzt aktuellen Wert der Sequence. Somit wird auch klar, warum CURRVAL erst dann abgefragt werden kann, wenn mindestens einmal zuvor in der Session ein NEXTVAL aufgerufen wurde.

Die Richtige Deklaration für dein BFILE ist auf jeden Fall 
v_test_bfile bfile := Bfilename('Bfile_data', 'SQL10G.pdf');
und *nicht *
v_test_bfile bfile := Bfilename('c:\', 'SQL10G.pdf');
Die Funktion erwartet den Namen eines Oracle Directory Objekts. 

Man sollte auch bedenken, dass damit ein Verzeichnis auf dem Datenbankserver gemeint ist, NICHT auf dem Client der die Prozedur ausführt! Wenn du also Dateien vom Client in die Datenbank schieben willst musst du entweder dafür sorgen, dass die Dateien irgendwie auf den Datenbankserver gelangen, oder eine andere Methode suchen.


----------



## cullmann (14. Februar 2007)

Servus,

danke für deine ausführliche Antwort, hatte nicht gewusst das die sequence von der session abhängig ist, sehr geile. Aber wenn ich dich richtig verstanden habe kann ich auf currval zugreifen wenn ich zuvor ein nextval angefordert habe. 

Aber das hab ich doch bei dem insert gemacht, bekomme aber trotzdem diese Fehlermeldung:

```
FEHLER in Zeile 15:
ORA-06550: Zeile 15, Spalte 38:
PL/SQL: ORA-02287: Sequence-Nummer hier nicht zulässig
ORA-06550: Zeile 14, Spalte 3:
PL/SQL: SQL Statement ignored
```


----------



## cullmann (14. Februar 2007)

Achso das mit dem Verzeichnis läuft leider immer noch nicht. 
Also das directory hab ich wie folgt angelegt:

```
create directory bfile_data as 'c:\Blob_test';

--Grant  System durchgeführt!
grant read ON Directory bfile_data to icap;
```

und dieses Verzeichnis existiert auch gewiss auf meiner platte, die DB läuft auch auf meinem Rechner, also die Fehlerquelle kann es schommal net sein.


----------



## cullmann (14. Februar 2007)

So ne sauerei! habs raus, man muss den directory in grossbuchstaben angeben:

```
declare
--v_test_bfile bfile := Bfilename('Bfile_data','SQL10G.pdf');
v_test_bfile bfile := Bfilename('BFILE_DATA','SQL10G.pdf'); --GROSSBUUCHSTABEN
...
```

Verdammt und damit hab ich mich jetzt über drei std. aufgehalten..... schöner scheiss

Dann bleibt nur noch das probelm mit dem currval......

cullmann


----------



## cullmann (14. Februar 2007)

Ok das mit der sequence hab ich jetzt auch hinbekommen...

finde das aber net soll doll, aber es müßte doch so funktionieren?


```
begin
  --dbmcs_output.put_line(bfile_data);
  insert into dokumente(dokumentenID, docname, Lehrid, semesterid, kurzbeschreibung, dokument, fachid)
  values(dokumenteseq.nextval, 'Skript_OperationsResearch_1', 
                        144, 2, 'Viele Summenzeichen schinden eindruck', 
                        Empty_BLOB(), 239);
  
  select dokumenteseq.currval into v_pk_doc from dual;
  select dokument into v_zeiger from dokumente
  where dokumentenID = v_pk_doc;
 
  --Datei öffenen
  dbms_lob.fileopen(v_test_bfile, dbms_lob.file_readonly);
```


----------



## Exceptionfault (14. Februar 2007)

Die RETURNING Klausel ist hierfür genau richtig. Das hier erspart dir 2 zusätzliche SELECTs. 

```
INSERT INTO DOKUMENTE
    (   DOKUMENTENID, 
        DOCNAME, 
        LEHRID, 
        SEMESTERID, 
        KURZBESCHREIBUNG, 
        DOKUMENT, 
        FACHID
    )
VALUES
    (   DOKUMENTESEQ.NEXTVAL, 
        'Skript_OperationsResearch_1', 
        144, 
        2, 
        'Viele Summenzeichen schinden eindruck', 
        Empty_BLOB(), 
        239
    )
RETURNING 
    DOKUMENTENID,   
    DOKUMENT
INTO
    v_pk_doc,
    v_zeiger;
```


----------



## cullmann (14. Februar 2007)

super, besten dank. 

Probier das gleich mal aus.


----------

