Breaking BITSTREAM in to Multiple parts using WMB/ESQL - ibm-mq

I have a BITSTREAM from XML message. An I want to break in to multiple parts of equal size depending upon of the length of stream using ESQL i.e. if my bitstream 1000 characters I want to break it in to 200character equal sets. And late I want to pass this parts to a store procedure to insert or update the table. I have BITSREAM Something like this
DECLARE vBlobMsgBody BLOB;
DECLARE refIn REFERENCE TO Environment.OriginalXML;
DECLARE vEncoding INT InputRoot.Properties.Encoding;
DECLARE vCCSID INT InputRoot.Properties.CodedCharSetId;
DECLARE vMsgBitStream BLOB ASBITSTREAM(refIn,1208);
How I will be to do that?

You can use the same function of CHARACTER variables.
SO you can use functions like:
DECLARE BLOB_LENGTH INTEGER LENGTH(vMsgBitStream);
DECLARE FIRST_PART BLOB SUBSTRING(vMsgBitStream FROM 1 FOR 200);

Related

Create var inside a for loop PLSQL ORACLE 11G

i have a function that puts a number in a var (var1). if var1 = 3 then create 3 new variables and assign a value for later send that values in an out type. I don't know how can i do, my code is something like this where "pos" acts like an INSTR() that i know its each 13 chars. And "newvar||var1" is because i want my vars names be newvar1, newvar2, newvar3, etc.:
FOR n IN 1..var1
LOOP
pos NUMBER(4):= 0;
newvar||var1 NUMBER(3);
newvar||var1 := SUBSTR(TO_NUMBER(numberInsideString), 1, 1+pos);
pos := pos+13;
END LOOP;
My question is, how a person who really know PLSQL would do that, im learning PLSQL please help. thank you.
What you want to try to do suggests that you need a one dimensional array in order repeatedly to assign new values for each iteration within the loop. One of the types in OWA package such as vc_arr(composed of VARCHAR2 data type values) is handy to define an array.
Coming to the code, you can start with moving the variables into the declaration section, and write such a simple code as a sample exercise
SET serveroutput ON
DECLARE
pos INT := 0;
numberInsideString VARCHAR2(100):='as12df34sdg345apl8976gkh4f11öjhöh678u7jgvj';
newvar OWA.vc_arr;
BEGIN
FOR n IN 1..3
LOOP
newvar(n) := SUBSTR(numberInsideString, 1, 1+pos);
pos := pos+5;
Dbms_Output.Put_Line(newvar(n));
END LOOP;
END;
/
a
as12df
as12df34sdg

Reading data from LONG data column in oracle gives Replacement Characters ���

I am trying to read data from a LONG column in Oracle which is storing an Image file. When doing so I am getting following :
IL 39 321 30580� 3� 10 0 59��
����\0\u0010JFIF\0\u0001\u0001\0\0\0\0\0\0\0��\0C\0\b\u0006\u0006\
I think the question marks are not allowing me to decode the string.
What is the meaning of these �� ?
Thanks,
In general you should not use LONG data type at all. It is deprecated for ages.
Apart from that, data type LONG is used for text data, i.e. like VARCAHR2 or CLOB. You cannot use it for binary data like images.
Update based on comment
Try this function to convert LONG to BLOB - Good luck!
CREATE OR REPLACE FUNCTION ConvertLONG(InChar IN LONG) RETURN BLOB IS
dest_lob BLOB;
lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
dest_offset INTEGER := 1;
src_offset INTEGER := 1;
read_offset INTEGER := 1;
warning INTEGER;
BEGIN
DBMS_LOB.CREATETEMPORARY(dest_lob, TRUE);
DBMS_LOB.CONVERTTOBLOB(dest_lob, TO_LOB(InChar), DBMS_LOB.LOBMAXSIZE, dest_offset, src_offset, DBMS_LOB.DEFAULT_CSID, lang_context, warning);
RETURN dest_lob;
END;
First of all, you should avoid using LONG data type columns and switch to BLOB (or CLOB, depending on what you plan to store in there). In your case, as that column contains images, that would be a BLOB.
You can't expect a SQL SELECT statement to return an image "as is" (i.e. to actually see that image on the screen) - all you get is that heap of junk characters. That's expected, it is a binary file, after all.
As you use TOAD, go to Schema Browser, open that table, view its data, right-click column that stores images and choose "Export Blobs (Longs, Raws ...)" from the menu. Follow instructions and export images into some folder on a disk.
Otherwise, you'd have to create an application (for example, using Apex) which is capable of displaying/downloading images.
If that's not what you are trying to do (as you mentioned that you'd want to "decode" a string), could you explain it?

PL/SQL difference between DEFAULT and assignment operator

I'm newbie in PL/SQL and this question might seem to be 'childish' so I'm sorry in advance, but Google didn't help me at all...
Is there any difference between following procedures?
Procedure p1(a Number DEFAULT 0) Is
Begin
DBMS_OUTPUT.put_line(a);
End;
Procedure p2(a Number := 0) Is
Begin
DBMS_OUTPUT.put_line(a);
End;
I have checked them, so when I call both of them without args the output is 0, but I'm not sure if there are any side effects.
If you follow Oracle's documentation
You can use the keyword DEFAULT instead of the assignment operator to
initialize variables. You can also use DEFAULT to initialize
subprogram parameters, cursor parameters, and fields in a user-defined
record.
Use DEFAULT for variables that have a typical value. Use the
assignment operator for variables (such as counters and accumulators)
that have no typical value.
DECLARE
blood_type CHAR DEFAULT 'O'; -- Same as blood_type CHAR := 'O';
hours_worked INTEGER DEFAULT 40; -- Typical value
employee_count INTEGER := 0; -- No typical value
BEGIN
NULL;
END;
/
So I guess internally is the same.
Let's take a look to the documentation of the latest Oracle release (12c R1) at the moment of writing. You explicitly ask for subprogram parameters so let's take that first.
Default Values for IN Subprogram Parameters:
When you declare a formal IN parameter, you can specify a default value for it. A formal parameter with a default value is called an optional parameter, because its corresponding actual parameter is optional in a subprogram invocation. If the actual parameter is omitted, then the invocation assigns the default value to the formal parameter.
The documentation doesn't mention default keyword but it still works. Example (in 12c R1):
declare
function f1(a in number) return number is begin return a; end;
function f2(a in number := 2) return number is begin return a; end;
function f3(a in number default 3) return number is begin return a; end;
begin
dbms_output.put_line(f1(1));
dbms_output.put_line(f2);
dbms_output.put_line(f3);
end;
/
Prints 1, 2, 3 as expected.
However as it's not mentioned in the authorative documentation I discourage the use of default keyword in this context.
Other interesting context is Initial Values of Variables and Constants:
To specify the initial value, use either the assignment operator (:=) or the keyword DEFAULT, followed by an expression.
And that's the only time default keyword is mentioned. All documentation examples use assigment only.
Conclusion
Technically default keyword and assigment are the same and work in both contextes, but only assigment is promoted in the documentation. I think Oracle is effectively deprecating the default keyword in this context and thus I won't recommend the use of it in new PL/SQL code. Assigment operator makes the same job with zero fuss.

Replace Illegal XML characters with value from table Oracle PL\SQL

I have a requirement to check all text fields in a Database schema for any Illegal XML characters and replace them with a predefined set of acceptable values. This is to form part of a Data transformation rule, than can be called from other functions. So this function could be asked to called over a billion times on our dataset, so I need it to operate really efficiently.
i.e. & = AND ,
' = APOS
An example of what needs to be achieved by the function should be:
Update sometable set somefield = functioncall('f&re'd');
should result in
somefield having the value of ' fANDreAPOSd'
This is to carried out by a generic type PL/SQL function that takes an input of a text field and iterate through that field and replace all illegal values.
I have had a look at http://asktom.oracle.com/pls/asktom/f?p=100:11:0::NO::P11_QUESTION_ID:2612348048
http://decipherinfosys.wordpress.com/2007/11/27/removing-un-wanted-text-from-strings-in-oracle/
For some ideas, but I have my concerns over efficiency and the flexibility of these soltuions.
The way the client wants to handle the solution is to have a table configured to contain an illegal character and it's prefered replacement. The function then uses the values selected from this table to preform the replacements.
well, not exactly what you want, but consider this:
create type xmltest is object (s clob);
select XMLTYPE.createXml(xmltest('a& and ''')) from dual;
XMLTYPE.CREATEXML(XMLTEST('A&'''))
-------------------------------------------------------------------------------------
<XMLTEST>
<S>a& &apos;</S>
</XMLTEST>
However the list of predefined of XML entities is quite small, so there wouldn't be an issue replacing them with replace
If this is because of XML I'll support hal9000 - you should let Oracle do that for you. E.g. XML functions do it automatically:
SQLPLUS> set define off
SQLPLUS> select xmlelement("e", 'foo & bar <> bar "hemingway''s"') from dual;
XMLELEMENT("E",'FOO&BAR<>BAR"HEMINGWAY''S"')
--------------------------------------------------------------------------------
<e>foo & bar <> bar "hemingway&apos;s"</e>

How to read byte headers of untyped files and then use and display that data when they are file streams in Free Pascal and Lazarus

I am trying to learn Free Pascal using Lazarus and one of my pet projects involves reading the 64 byte headers of a particular set of untyped files that cannot be read and displayed using text or ASCII related procedures (so cannot be outputted directly to Memo boxes etc).
So far, I have devised the following code which does, I think, read in the 64 bytes of the header and I am using TStreams and a "Select Directory" dialog box to do this, based on advice received via the Lazarus IRC. My question though is how to actually USE the data that is read into the buffer from the header? For example, in the headers, there are sequences of 8 bytes, then 16 bytes, then 2 bytes and so on that I want to "work on" to generate other output that will eventually be converted to a string to go into my string grid.
Some of what I have so far is based on what I found here written by Mason Wheeler near the end (http://stackoverflow.com/questions/455790/fast-read-write-from-file-in-delphi) but it only shows how to read it in, not how to use it. I also read this (http://stackoverflow.com/questions/4309739/best-way-to-read-parse-a-untyped-binary-file-in-delphi) but again, it shows you how to READ the data too, but not subsequently USE the data. Any guidance wamrly received! So far, the code below just outputs single value integer numbers to the edit box, as opposed to, say, a range of 8 hexadecimal values.
PS - I am new to programming so please be gentle! Nothing too complex.
procedure TForm1.ProbeFile(FileIterator: TFileIterator);
type
TMyHeader = Array[1..64] of packed record
First8Bytes,
Next16Bytes,
Next2Bytes: byte;
end;
var
FI : TFileIterator; //File Iterator class
SG : TStringGrid;
NumRead : SmallInt;
FileToProbe: TStream;
header: TMyHeader;
begin
FI := TFileIterator.Create;
SG := TStringGrid.Create(self);
// Open the file and read the header
FileToProbe := TFileStream.Create(FileIterator.FileName, fmOpenRead);
try
FileToProbe.seek(0, soFromBeginning);
FileToProbe.ReadBuffer(header, SizeOf(header));
edit1.text := IntToStr(header[0].First8Bytes); // Just outputs '0' to the field? If I try '10' it ooutputs '29' and so on
finally
FileToProbe.Free;
end;
Please forgive me if I misunderstood your question.
As I understand it there is a header of 64 bytes. The first 8 bytes belong together, then the next 16 bytes and finally another 2 bytes.
To me it seems the declaration for this header should be:
TMyHeader = packed record
First8Bytes: array[0..7] of byte;
Next16Bytes: array [0..15] of byte;
Next2Bytes: array [0..1] of byte;
// add more if you like
end;
This recordtype has a size of 8+16+2 = 26 bytes.
Your code that reads the header looks ok to me, So I won't repeat that.
The next16bytes in your header can be retrieved, for example, like this:
edit1.text:= '';
// needs a declaration of a variable "i" as integer
for i:= 0 to 15 do
edit1.text:= edit1.text + IntToStr(header.next16bytes[i]) + '-';
Change the value of the first byte in the next2bytes part of your header as follows (again as an example):
header.next2bytes[0]:= 123;
Finally, you could write your changes back to the header of the file with help of the filetoprobe.writebuffer method.

Resources