read first 1kb of a blob from oracle - oracle

I wish to extract just the first 1024 bytes of a stored blob and not the whole file. The reason for this is I want to just extract the metadata from a file as quickly as possible without having to select the whole blob.
I understand the following:
select dbms_lob.substr(file_blob, 16,1)
from file_upload
where file_upload_id=504;
which returns it as hex. How may I do this so it returns it in binary data without selecting the whole blob?
Thanks in advance.

DBMS_LOB.SUBSTR will, for a BLOB, return a RAW. Most environments will render that in hex.
You can use the DUMP function to view it in some other formats.
select dump(dbms_lob.substr(product_image,10,1),10),
dump(dbms_lob.substr(product_image,10,1),16),
dump(dbms_lob.substr(product_image,10,1),17)
from APEX_DEMO.DEMO_PRODUCT_INFO
where product_id = 9;
This returns the first 10 bytes of the BLOB in decimal (eg 0-255), hex and character. The latter may throw some unprintable garbage to the screen and, if the client and database character sets do not match, undergo some 'translation'.
You can use UTL_RAW.CAST_TO_VARCHAR2 which may give you what you want.
select utl_raw.cast_to_varchar2(dbms_lob.substr(product_image,10,1)) chr
from APEX_DEMO.DEMO_PRODUCT_INFO
where product_id = 9

Related

DB2/400 : Difference beetwen BLOB and CLOB

What's the difference beetwen BLOB and CLOB on DB2/400 ?
This data has the same Length ( 1 through 2 147 483 647 )
Thank's
CLOB = Character Large Object
BLOB = Binary Large Object
Characters can be translated between CCSIDs, binary data will not be.
If you're dealing with character data, XML, JSON, plain text, use a CLOB.
If you're dealing with binary data, .ZIP .PDF, then use a BLOB.
Example, you store a CCSID 37 (EBCDIC US ENGLISH) CLOB and retrieve it via JDBC. The data will be translated to unicode by the JDBC driver. The hexadecimal representation of the data will be different.
Same data as a BLOB will be returned unchanged, hexadecimal representation will be unchanged on both sides.

Import blob through SAS from ORACLE DB

Good time of a day to everyone.
I face with a huge problem during my work on previous week.
Here ia the deal:
I need to download exel file (blob) from ORACLE database through SAS.
I am using:
First step i need to get data from oracle. I used the construction (blob file is nearly 100kb):
proc sql;
connect to oracle;
create table SASTBL as
select * from connection to oracle (
select dbms_lob.substr(myblobfield,1,32767) as blob_1,
dbms_lob.substr(myblobfield,32768,32767) as blob_2,
dbms_lob.substr(myblobfield,65535,32767) as blob_3,
dbms_lob.substr(myblobfield,97302,32767) as blob_4
from my_tbl;
);
quit;
And the result is:
blob_1 = 70020202020202...02
blob_2 = 02020202020...02
blob_3 = 02020202...02
I do not understand why the field consists from "02"(the whole file)
And the length of any variable in sas is 1024 (instead of 37767) $HEX2024 format.
If I ll take:
dbms_lob.substr(my_blob_field,2000,900) from the same object the result will mush more similar to the truth:
blob = "A234ABC4536AE7...."
The question is: 1. how can i get binary data from blob field correctly trough SAS? What is my mistake?
Thank you.
EDIT 1:
I get the information but max string is 2000 kb.
Use the DBMAX_TEXT option on the CONNECT statement (or a LIBNAME statement) to get up to 32,767 characters. The default is probably 1024.
PROC SQL uses SQL to interact with SAS datasets (create tables, query tables, aggregate data, connect externally, etc.). The procedure mostly follows the ANSI standard with a few SAS specific extensions. Each RDMS extends ANSI including Oracle with its XML handling such as saving content in a blob column. Possibly, SAS cannot properly read the Oracle-specific (non-ANSI) binary large object type. Typically SAS processes string, numeric, datetime, and few other types.
As an alternative, consider saving XML content from Oracle externally as an .xml file and use SAS's XML engine to read content into SAS dataset:
** STORING XML CONTENT;
libname tempdata xml 'C:\Path\To\XML\File.xml';
** APPEND CONTENT TO SAS DATASET;
data Work.XMLData;
set tempdata.NodeName; /* CHANGE TO REPEAT PARENT NODE OF XML. */
run;
Adding as another answer as I can't comment yet... the issue you experienced is that the return of dbms_lob.substr is actually a varchar so SAS limits it to 2,000. To avoid this, you could wrap it in to_clob( ... ) AND set the DBMAX_TEXT option as previously answered.
Another alternative is below...
The code below is an effective method for retrieving a single record with a large CLOB. Instead of calculating how many fields to split the clob into resulting in a very wide record, it instead splits it into multiple rows. See expected output at bottom.
Disclaimer: Although effective it may not be efficient ie may not scale well to multiple rows, the generally accepted approach then is row pipelining PLSQL. That being said, the below got me out of a pinch if you can't make a procedure...
PROC SQL;
connect to oracle (authdomain=YOUR_Auth path=devdb DBMAX_TEXT=32767 );
create table clob_chunks (compress=yes) as
select *
from connection to Oracle (
SELECT id
, key
, level clob_order
, regexp_substr(clob_value, '.{1,32767}', 1, level, 'n') clob_chunk
FROM (
SELECT id, key, clob_value
FROM schema.table
WHERE id = 123
)
CONNECT BY LEVEL <= regexp_count(clob_value, '.{1,32767}',1,'n')
)
order by id, key, clob_order;
disconnect from oracle;
QUIT;
Expected output:
ID KEY CHUNK CLOB
1 1 1 short_clob
2 2 1 long clob chunk1of3
2 2 2 long clob chunk2of3
2 2 3 long clob chunk3of3
3 3 1 another_short_one
Explanation:
DBMAX_TEXT tells SAS to adjust the default of 1024 for a clob field.
The regex .{1,32767} tells Oracle to match at least once but no more than 32767 times. This splits the input and captures the last chunk which is likely to be under 32767 in length.
The regexp_substr is pulling a chunk from the clob (param1) starting from the start of the clob (param2), skipping to the 'level'th occurance (param3) and treating the clob as one large string (param4 'n').
The connect by re-runs the regex to count the chunks to stop the level incrementing beyond end of the clob.
References:
SAS KB article for DBMAX_TEXT
Oracle docs for REGEXP_COUNT
Oracle docs for REGEXP_SUBSTR
Oracle regex syntax
Stackoverflow example of regex splitting

SQLPLUS displaying of tables with CLOB types

I have a table which has 3 columns. I have a NUMBER column, CLOB column, and BLOB column. how can i use some sort of SELECT * statement in order to display what I have entered into this table, not just a partial piece of the long character strings i have in there. The only way I know of displaying a long string form a CLOB would be using the DBMS_LOB.substr technique. My BLOB column is currently all NULL so not too worried about displaying that section, Just the number column with its associated CLOB. Thanks!
See here How to query a CLOB column in Oracle
When getting the substring of a CLOB column and using a query tool that has size/buffer restrictions
sometimes you would need to set the BUFFER to a larger size.
For example while using SQL Plus use the SET BUFFER 10000 to set it to 10000 as the default is 4000.
Running the DMBS_LOB.substr command you can also specify the amount of characters you want to return and the offset from which.
So using DMBS_LOB.substr(column, 3000) might restrict it to a small enough amount for the buffer.
See oracle documentation for more info on the substr command
DBMS_LOB.SUBSTR (
lob_loc IN CLOB CHARACTER SET ANY_CS,
amount IN INTEGER := 32767,
offset IN INTEGER := 1)
RETURN VARCHAR2 CHARACTER SET lob_loc%CHARSET;

oracle: what is the oracle equivalent data type for COMMENT?

What is the datatype in oracle i should be using to store comment boxes? I was going to use LONG but it only allows one. Or should I just use VARCHAR2 and set it really large?
What is the longest comment you want to be able to support?
If your comments are less than 4000 bytes in length, you can use a VARCHAR2(4000). If your comments are longer than 4000 bytes in length, you can use a CLOB. A CLOB can store any character data supported by your database character set.

How do I select part of a BLOB field in Oracle?

I have a table in Oracle that stores files as byte arrays in a BLOB field. I want my client to be able to download the stored file in small chunks (as opposed to downloading the whole thing all at once) so I can display a progress bar.
How can I write an Oracle query that retrieves only part of the contents of a BLOB field? I imagine it would be something like this:
SELECT PARTOF(BLOBFIELD, 1000, 2000) AS CHUNK FROM tbl WHERE ID = 1
if I wanted to get 1000 bytes from BLOBFIELD starting at byte 2000.
As a secondary question, are there any performance issues with this? If Oracle has to load the entire BLOB field into memory in order to return part of it, then this wouldn't be a very good idea.
Can you use DBMS_LOB.READ (lob_loc, amount, offset, buffer)?

Resources