What's the difference between pls_integer and binary_integer? - oracle

I've inherited some code which is going to be the base for some additional work. Looking at the stored procs, I see quite a lot of associative-arrays.
Some of these are indexed by binary_integers, some by pls_integers. Are there any differences between the two?
I had a look at the documentation, but apart from this line:
The PL/SQL data types PLS_INTEGER and BINARY_INTEGER are identical. For simplicity, this document uses PLS_INTEGER to mean both PLS_INTEGER and BINARY_INTEGER.
I couldn't find any difference between the two. So what's the difference? Are both around for historical/compatibility reasons?
I'm using Oracle 10gR2

Historical reasons. They used to be different before 10g:
On 8i and 9i, PLS_INTEGER was noticeably faster than BINARY_INTEGER.
When it comes to declaring and manipulating integers, Oracle offers lots of options, including:
INTEGER - defined in the STANDARD package as a subtype of NUMBER, this datatype is implemented in a completely platform-independent fashion, which means that anything you do with NUMBER or INTEGER variables should work the same regardless of the hardware on which the database is installed.
BINARY_INTEGER - defined in the STANDARD package as a subtype of INTEGER. Variables declared as BINARY_INTEGER can be assigned values between -231+1 .. 231-1, aka -2,147,483,647 to 2,147,483,647. Prior to Oracle9i Database Release 2, BINARY_INTEGER was the only indexing datatype allowed for associative arrays (aka, index-by tables), as in:
TYPE my_array_t IS TABLE OF VARCHAR2(100)
INDEX BY BINARY_INTEGER
PLS_INTEGER - defined in the STANDARD package as a subtype of BINARY_INTEGER. Variables declared as PLS_INTEGER can be assigned values between -231+1 .. 231-1, aka -2,147,483,647 to 2,147,483,647. PLS_INTEGER operations use machine arithmetic, so they are generally faster than NUMBER and INTEGER operations. Also, prior to Oracle Database 10g, they are faster than BINARY_INTEGER. In Oracle Database 10g, however, BINARY_INTEGER and PLS_INTEGER are now identical and can be used interchangeably.

binary_integer and pls_integer both are same. Both are PL/SQL datatypes with range -2,147,648,467 to 2,147,648,467.
Compared to integer and binary_integer pls_integer very fast in excution. Because pls_intger operates on machine arithmetic and binary_integer operes on library arithmetic.
pls_integer comes from oracle10g.
binary_integer allows indexing integer for assocative arrays prior to oracle9i.
Clear example:
SET TIMING ON
declare
num integer := 0;
incr integer := 1;
limit integer := 100000000;
begin
while num < limit loop
num := num + incr;
end loop;
end;
PL/SQL procedure successfully completed.
Elapsed: 00:00:20.23
ex:2
declare
num binary_integer := 0;
incr binary_integer := 1;
limit binary_integer := 100000000;
begin
while num < limit loop
num := num + incr;
end loop;
end;
/
PL/SQL procedure successfully completed.
Elapsed: 00:00:05.81
ex:3
declare
num pls_integer := 0;
incr pls_integer := 1;
limit pls_integer := 100000000;
begin
while num < limit loop
num := num + incr;
end loop;
end;
/

Another difference between pls_integer and binary_integer is that when calculations involving a pls_integer overflow the PL/SQL engine will raise a run time exception. But, calculations involving a binary_integer will not raise an exception even if there is an overflow.

Related

How to convert pls_number to varchar2 in oracle?

I tried to convert pls_integer to varchar2 using to_char but it is not working.
I also tried pls_integer to number and number to varchar2 using to_number and to_char methods, but that also not working. I am getting an error :
Pls00306 - wrong number or types of arguments in call 'to_number'.
Can you please help.
There's no need to do anything special just assign. Oracle allows implicit data type conversion between pls_integer and varchar2. See table 3-10 at the bottom of this page
declare
l_number pls_integer;
l_varchar varchar2(1);
begin
l_number := 8;
l_varchar := l_number;
end;

Datatype of the PLSQL For loop counter

I understand that the index variable/counter for the PL/SQL For loop is defined implicitly by the loop construct
BEGIN
FOR v_counter IN 1..5 LOOP
DBMS_OUTPUT.PUT_LINE ('v_counter = '||v_counter);
END LOOP;
END;
What is the datatype of this variable. Tempted to say BINARY_INTEGER or PLS_INTEGER as this would allow for negative values of counters too , and both perform better as far as calculations are concerned.
Is this inference right ? Are there any other considerations ?
The documentation here:
http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/for_loop_statement.htm#LNPLS1536
States simply "integer".
Previous thread here:
What's the difference between pls_integer and binary_integer?
Points out that binary_integer = pls_integer.
So it likely doesn't matter, since they (now) behave the same.

"READ" constant in PLSQL

I found the following PL/SQL code but I am unable to find it as a valid constant declaration from Oracle documentation.
Can anyone explain me what this means?
create or replace package file_security authid current_user is
READ constant pls_integer := 1;
WRITE constant pls_integer := 2;
EXEC constant pls_integer := 4;
procedure grant_permission(
p_file_path in varchar2,
p_grantee in varchar2,
p_permission in pls_integer
);
end file_security;
The package declares three constants (called READ, WRITE and EXEC) and a function, which would supposedly accept a binary mask of those constants as its third parameter.
None of those words are reserved in Oracle, they "have a special meaning to Oracle but are not reserved words and so can be redefined"

Is there a way to get the PL/SQL maximum pls_integer?

Is there a way to determine the maximum possible value of a pls_integer either by a language predefined constant or a function? I can find the maximum on the internet (2^31 - 1 = 2,147,483,647), but I don't want to hard code it.
Cheers :)
I don't think this is possible. Why? Because it is not needed - PLS_INTEGER's maximal value is due to its maximal size - 4 bytes (and it is a signed datatype).
What is more, as stated in documentation about PL/SQL datatypes, PLS_INTEGER is actually a BINARY_INTEGER. Look at the definition of PLS_INTEGER in the Oracle's STANDARD package:
subtype pls_integer is binary_integer;
And then take a look at the definition of BINARY_INTEGER:
subtype BINARY_INTEGER is INTEGER range '-2147483647'..2147483647;
Nowhere in the STANDARD package header can you find a constant which holds the maximal value of those datatypes.
I don't think there is any constant that you can use; however, if it is so vital not to hard code any values, you can calculate the maximum value with the method given below.
This solution is based on the assumption that the maximum value would be in the form of 2^b-1 where b is the number of bits.
This is the function you can use:
CREATE FUNCTION MAX_PLS_INTEGER_SIZE RETURN PLS_INTEGER AS
p PLS_INTEGER;
b NUMBER;
BEGIN
b := 0;
WHILE TRUE LOOP
BEGIN
p := POWER(2, b)-1;
b := b + 1;
EXCEPTION WHEN OTHERS THEN
EXIT;
END;
END LOOP;
RETURN p;
end;
After you create the function, you can test it:
SELECT MAX_PLS_INTEGER_SIZE FROM DUAL;
Result:
MAX_PLS_INTEGER_SIZE
--------------------
2147483647

Alternative to dbms_output.putline

I am creating a dynamic query in a procedure and now want to see it through dbms_output.putline, but my query contains more than 255 characters.
How to view the query?
What are the alternates of dbms_output.putline?
There's a little bit of confusion going on.
In Oracle 9i dbms_output.put_line is limited to 255 characters. This restriction was removed in 10g and is similarly not present in Oracle 11g.
You have tagged your question oracle10g, which means that you're limited to 32,767 bytes, the standard PL/SQL maximum.
try mess around something like
create or replace procedure custom_output(in_string in varchar2 )
is
out_string_in long default in_string;
str_len number;
loop_count number default 0;
begin
str_len := length(out_string_in);
while loop_count < str_len
loop
dbms_output.put_line( substr( out_string_in, loop_count +1, 255 ) );
loop_count := loop_count +255;
end loop;
end;
/

Resources