Change in between the dbms_output procedure? - oracle

i had a problem when i am using dbms_output package. When i am executing the following code it display integer is 0
declare
v integer;
asq dbms_output.chararr;
begin
dbms_output.put('hi');
dbms_output.put_line('hello!');
asq(1):='sun';
asq(2):='ant';
dbms_output.put_line(asq(1));
dbms_output.put_line(asq(2));
dbms_output.get_lines(asq,v);
dbms_output.put_line('integer is '||v);
end;
but when i am executing the following code i am getting integer is 3
declare
v integer:=5;
asq dbms_output.chararr;
begin
dbms_output.put('hi');
dbms_output.put_line('hello!');
asq(1):='sun';
asq(2):='ant';
dbms_output.put_line(asq(1));
dbms_output.put_line(asq(2));
dbms_output.get_lines(asq,v);
dbms_output.put_line('integer is '||v);
end;
can any one help me why the variation is there in the two procedures

As per documentation, the second parameter to GET_LINES
procedure is IN OUT parameter. It tells the procedure, number of lines to be retrieved from buffer. After the procedure call, it holds number of lines actually retrieved.
In your first example, the value of v is null. So no lines are retrieved and v is assigned the value 0.
In your second example, the value if v is 5. So you are requesting 5 lines, but since there are only three lines(hihello!, sun, ant), three lines are put into array asq and v is assigned 3.

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 a text file and constructing a matrix from it

I need to construct a matrix; a number of columns and rows are also in the first row of the matrix, I'll make an example so its more clearer.
4 3
1 2 3
5 6 7
9 10 8
1 11 13
Where m=4 (number of rows) and n=3 (number of columns)
This is an example of a text file. Is something like this even possible?
Program Feb;
const
max=100;
type
Matrix=array[1..max,1..max] of integer;
var datoteka:text;
m,n:integer;
counter:integer;
begin
assign(datoteka,'datoteka.txt');
reset(datoteka);
while not eoln(datoteka) do
begin
read(datoteka, m);
read(datoteka, n);
end;
repeat
read eoln(n)
until eof(datoteka)
write (m,n);
end.
My code isn't a big help, cause I don't know how to write it.
First, have a look at the code I wrote to do the task, and then look at my explanation below.
program Matrixtest;
uses
sysutils;
var
NoOfCols,
NoOfRows : Integer;
Source : TextFile;
Matrix : array of array of integer;
FileName : String;
Row,
Col : Integer; // for-loop iterators to access a single cell of the matrix
Value : Integer;
begin
// First, construct the name of the file defining the matrix
// This assumes that the file is in the same folder as this app
FileName := ExtractFilePath(ParamStr(0)) + 'MatrixDef.Txt';
writeln(FileName); // echo it back to the screen so we can see it
// Next, open the file
Assign(Source, FileName);
Reset(Source);
read(Source, NoOfRows, NoOfCols);
writeln('Cols: ', NoOfCols, 'Rows: ', NoOfRows);
SetLength(Matrix, NoOfCols, NoOfRows);
readln(source); // move to next line in file
// Next, read the array data
for Row := 1 to NoOfRows do begin
for Col := 1 to NoOfCols do begin
read(Source, Value);
Matrix[Col - 1, Row - 1] := Value;
end;
end;
// Display the array contents
for Row := 1 to NoOfRows do begin
for Col := 1 to NoOfCols do begin
writeln('Row: ', Row, ' contents', Matrix[Col - 1, Row - 1]);
end;
end;
Close(Source); // We're done with the file, so close it to release OS resources
readln; // this waits until you press a key, so you can read what's been displayed
end.
In your program, you can use a two-dimensional array to represent your matrix. Free Pascal supports multi-dimensional arrays; see https://wiki.lazarus.freepascal.org/Multidimensional_arrays for more information.
This is a complex task, so it helps to know how to do more basic things like reading an array of a size known at compile-time from a text file.
The wrinkle in this task is that you are supposed to read the dimensions (numbers of rows and columns) of the matrix at run-time from the file which contains the matrix's contents.
One inefficient way to do this would be to declare the matrix array with huge dimensions, larger than anything you would expect in practice, using the type of array declaration in the Wiki page linked above.
A better way is to use dynamic arrays, whose dimensions you can set at run-time. To use this, you need to know:
How to declare a dynamic array in Free Pascal
How to set the dimensions of the array at run-time, once you've picked them up from your matrix-definition file (hint: SetLength is the way to do this)
The fact that a Free Pascal dynamic array is zero-based
The easiest way of managing zero-based arrays is to write your code (in terms of Row and Column variables) as if the matrix were declared as array[1..NoOfRows, 1..NoOfColumns] and subtract one from the array indexes only when you actually access the array, as in:
Row := 3;
Column := 4;
Value := Matrix[Row - 1, Column - 1];

Ada thread to pass auto random generated data to a procedure

How would i go about creating a procedure that is a thread which continuously passes automatic random generated data within a specified range.
I currently would have to manually enter in each bit of data in the console using this procedure below. I want to creatre a procedure that when running is able to pass data to this procedure as if it was being typed into the console itself.
procedure Analyse_Data is
Data : Integer;
begin
DT_Put_Line("Data input by user");
loop
DT_Get(Data,"Data must be taken as a whole number");
exit when (Data >=0) and (Data <= Maximum_Data_Possible);
DT_Put("Please input a value between 0 and ");
DT_Put(Maximum_Data_Possible);
DT_Put_Line("");
end loop;
Status_System.Data_Measured := Data_Range(Data);
end Analyse_Data;
I havent included the specification files (.ads)
I am new to Ada and any help would be appreciated.
Use an instance of Discrete_Random to generate some number of random data values in the desired range:
subtype Valid_Range is Natural range 0 .. Maximum_Data_Possible;
package Some_Value is new Ada.Numerics.Discrete_Random(Valid_Range);
G : Some_Value.Generator;
…
procedure Generate is
N : Valid_Range;
begin
for I in 1 .. Count loop
N := Some_Value.Random(G);
Put(N);
end loop;
end;
Save the values to a file:
./generate > test_data.txt
Feed that file to your program using I/O redirection from the command line:
./analyse_data < test_data.txt
The exact details will depend on you actual program. See this related Q&A regarding empty lines in standard input.

pass by value/ reference / result

procedure p(x : integer);
begin
a := 5;
x := x + 2;
end
Write down the value of the variable a after execution of the following code:
a := 10;
p(a);
for each of the following parameter passing mechanisms:
(i) call by value. a. 7,10
(ii) call by reference. a. 12,12
(iii) call by value-result. a. 7,7
Got an exam on this next week and I have got the answers for the mock paper but I am confused to how X is assigned to a in the procedure call. help would be awesome
thanks
(i) call by value
Whatever value is passed into p() is copied onto p()'s stack. That copy is used in the body of p(), so the original value is never changed. If a starts as 7 it will end as 7.
(ii) call by reference
A reference to the original value is provided to p(), so that changes to the value that reference points to affect the original variable. a will have a new value after p() returns.
If a starts as 12, it will end as 7 because it is first assigned the value of 5 in the body of p() and then that value is increased by 2.
(iii) call by value-result
This is similar to call by reference, except that no alias is created between the formal and actual parameters. See details.

Are Oracle PL/SQL arrays indexed from 0 or from 1?

I have in front of me a piece of code like this:
FOR row IN 1..l_RowSet(1).count
LOOP
l_a_variable := l_RowSet(1)(row);
END LOOP;
l_RowSet is an ApEx type -- apex_plugin_util.t_column_value_list -- defined thus:
type t_column_value_list is table of wwv_flow_global.vc_arr2 index by pls_integer;
where wwv_flow_global.vc_arr2 is defined as
type vc_arr2 is table of varchar2(32767) index by binary_integer;
The vc_arr2 is passed back to my code from the apex_plugin_util.get_data function. The vc_arr2 is indexed by column number, not by row.
As best I can make out this means that the data is effectively stored in a 2D array, indexed by column and then by row.
When using the LOOP statement, would this be indexed from zero or from one? Because it seems to me that I ought to be able to make that LOOP redundant, ie:
l_a_variable := l_RowSet(1)(1);
But I'd need to know in advance whether to give 0 or 1 as the initial row.
I can't find a clear answer in the Oracle docs (unsurprisingly, "index" is a fairly widely-used term) and a look through SO doesn't show anybody else with the same question either.
An associative array isn't necessarily dense. There may be an element at index 0, there may be an element at index -1, there may be an element at index 1. Or you might have elements at indexes 17, 42, and 127. The code you posted implies that the associative array is dense and that the indexes start at 1.
In the specific case of apex_plugin_util.get_data the collection should be dense and should start at 1. If the loop is actually not doing anything other than what you posted, you could replace it by fetching the last element of l_RowSet(1), i.e.
l_a_variable := l_RowSet(1)(l_RowSet(1).count);

Resources