Skip to Main Content

Database Software

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Learning Python for PL/SQL Developers: Part 4

unknown-1040115Oct 14 2016 — edited Aug 28 2017

by Arup Nanda

Part 4 of a five-part series that presents an easier way to learn Python by comparing and contrasting it to PL/SQL.

You may follow along with the Online Presentation: Learning Python for PL/SQL Developers - Part 4

Functions, Modules and File Operations

As is the case in most languages, Python provides repeatable code segments, similar to procedures and functions in PL/SQL. As you already know, in PL/SQL, a procedure does not return anything (although it can have an OUT parameter; but that's not a return, so it's not the same thing) and a function returns a single value. In Python, the equivalents of both PL/SQL procedures and functions is called simply a function. A Python function may or may not return anything. In this article, we will cover how to write functions and use them in your programs. As in the previous article in this series, we will see how to do something in PL/SQL and then do the equivalent in Python.

A function definition in PL/SQL has this general syntax format:

function FunctionName (
  Parameter1Name in DataType,
  Parameter2Name in DataType,
  ...
)
return ReturnDatatype
is
   localVariable1 datatype;
   localVariable2 datatype;
begin
   ... function code ...
    return ReturnVariable;
end;

A procedure definition in PL/SQL has this general syntax:

procedure ProcedureName(
  Parameter1Name in DataType,
  Parameter2Name in DataType,
  ...
)
is
   localVariable1 datatype;
   localVariable2 datatype;
begin
   ... procedure code ...
end;

A function definition in Python follows this simple syntax:

def FunctionName (Parameter1Name,Parameter2Name, ...):
        ... function code ...
  return ReturnVariable

Note some important properties of the Python function definition compared to the PL/SQL equivalent:

  • The definition starts with def followed by the name of the function.
  • The parameters come inside the parentheses.
  • Only the parameter names are listed. The datatypes are not mentioned, unlike with PL/SQL. Parameters are optional; a function doesn't need to have parameters.
  • There is a colon (:) at the end of the function name to mark the end of the name and beginning of the definition. Unlike PL/SQL, there is no "BEGIN ... END" construct.
  • There is no mention of what the function returns at the definition level. If you notice there is no mention of whether the function even returns anything at the definition level.
  • The indentation after the colon shows the code of the function. This is the same style followed in Python to mark "IF ... THEN ... ELSE" blocks or loops. Indentations mark the beginning and end of function code, not "begin ... end," as in PL/SQL.
  • The function may optionally return something at the final line. The syntax is the same as in PL/SQL: return ReturnVariable.

Now that you've got the basic idea about the syntax vis-a-vis PL/SQL, let's start with a very simple procedure in PL/SQL that accepts a principal amount and interest rate, computes the interest amount and the new principal after the interest is added, and displays the new principal.

Here is how we do it in PL/SQL. Note that I deliberately chose to use the Python naming convention, for example, pPrincipal, not a PL/SQL-style variable name such as p_principal.

PL/SQL

-- pl1.sql

declare

  procedure calcInt (

   pPrincipal     number,

   pIntRate       number

  ) is

    newPrincipal   number;

  begin

    newPrincipal := pPrincipal * (1+(pIntRate/100));

    dbms_output.put_line ('New Principal is '||newPrincipal);

  end;

begin

  calcInt(100,10);

end;

/

Here is the output:

New Principal is 110

PL/SQL procedure successfully completed.

Python

#py1.txt

def calcInt(pPrincipal, pIntRate):

    newPrincipal = pPrincipal * (1+(pIntRate/100))

    print ("New Principal is " + str(newPrincipal))

calcInt(100,10)

Executing it produces this:

C:\>python py1.txtNew Principal is 110.00000000000001

This shows an example of a very basic Python function that does not return anything, similar to a PL/SQL procedure. Now that you know the basics, let's explore some more intricate details of the syntax.

Default Value of Parameters

Sometimes you need to pass a default value to a parameter. This value is in effect if the user does not explicitly pass the parameter. Building on the previous procedure, suppose we want to make the parameter pIntRate optional, that is, make it a certain value (such as 5, when the user does not explicitly mention it). In PL/SQL, you mention the parameter this way:

ParameterName DataType := DefaultValue

In Python, it's exactly the same, but since the assignment operator in Python is "=" (not ":="), that's what you need to use. Besides, remember, you don't mention the datatype for parameters. Here is the general syntax:

ParameterName = DefaultValue

You can write the PL/SQL function this way (the changes are in bold):

PL/SQL

--pl2.sql

declare

  procedure calcInt (

    pPrincipal      number,

    pIntRate        number := 5

  ) is

   newPrincipal    number;

  begin

    newPrincipal := pPrincipal *(1+(pIntRate/100));

    dbms_output.put_line('New Principal is '||newPrincipal);

  end;

begin

  -- don't mention the pIntRate parameter.

  -- defaults to 5

  calcInt(100);

end;

/

The output is:

New Principal is 105

PL/SQL procedure successfully completed.

Python

#py2.txt

def calcInt(pPrincipal, pIntRate = 5):

   newPrincipal = pPrincipal * (1+(pIntRate/100))

   print ("New Principal is " + str(newPrincipal))

# Don't pass the 2nd parameter. Defaults to 5

calcInt(100)

Executing it produces this:

C:\>python py2.txt

New Principal is 105.0

If you need to have a string as a default variable, use double quotes:

# py2a.txt

def calcInt(pPrincipal, pIntRate = 5, pAccType = "Checking"):

   vIntRate = pIntRate

   if (pAccType == 'Savings'):

       # eligible for bonus interest

       vIntRate = pIntRate + 5

    newPrincipal = pPrincipal * (1+(vIntRate/100))

    print ("New Principal is " + str(round(newPrincipal)))

calcInt(100,10,'Savings')

Executing it produces this:

C:\>python py2a.txt

New Principal is 115

One important property of functions in Python is that the default values can be variables as well. This is not possible in PL/SQL. For instance, in PL/SQL the following will be illegal:

-- pl4.sql

declare

    defIntRate     number := 5;

    procedure calcInt (

            pPrincipal      number,

            pIntRate        number := defIntRate;

    ) is

...

But it's perfectly valid in Python. Let's see how:

# py4.txt

defIntRate = 5

def calcInt(pPrincipal, pIntRate = defIntRate):

   newPrincipal = pPrincipal * (1+(pIntRate/100))

   print ("New Principal is " + str(round(newPrincipal)))

calcInt(100)

Another important property of this variable assignment is that the assignment occurs only at the time of the declaration of the function, and is not affected afterwards. Take for instance the following:

# py4a.txt

# Assign the value to the variable

defIntRate = 5

# define the function

def calcInt(pPrincipal, pIntRate = defIntRate):

    newPrincipal = pPrincipal * (1+(pIntRate/100))

    print ("New Principal is " + str(round(newPrincipal)))

# change the variable value

defIntRate = 10

# call the function

calcInt(100)

What value will be printed? Will the function take the value of pIntRate as 5 or 10?

The answer is it will take the value of pIntRate as 5, not 10. Why? It's because when the function was defined, the value was 5. When the function was called, the value of pIntRate was 10; but that will not be considered. This is a very important property you need to keep in mind when learning Python as a PL/SQL developer. It's a major source of bugs if not taken into consideration.

Positional Parameters

You already know that in PL/SQL you do not have to provide the parameter values in the order in which they were defined in the procedure. You can pass values by specifying the parameter by name. For instance, if a procedure F1 assumes the parameters P1 and P2—in that _order_—you can call the procedure this way with the parameter values Val1 and Val2 respectively:

F1 (Val1, Val2);

But you can also call them with explicit parameter name assignments:

F1 (P2 => Val2, P1 => Val1);

This explicit naming allows you to order the parameters any way you want while calling the procedure. It also allows you to skip some non-mandatory parameters. In Python the equivalent syntax is this:

F1 (P2=Val2, P1=Val1)

So, just the operator "=>" is changed to "=." Let's see examples in both PL/SQL and Python.

PL/SQL

--pl3.sql

declare

   procedure calcInt (

     pPrincipal      number,

     pIntRate        number := 5

   ) is

      newPrincipal   number;

   begin

     newPrincipal := pPrincipal *(1+(pIntRate/100));

     dbms_output.put_line('New Principal is '||newPrincipal);

   end;

begin

   calcInt(pIntRate=>10, pPrincipal=>100);

end;

/

The output is this:

New Principal is 110

PL/SQL procedure successfully completed.

Python

#py3.txt

def calcInt(pPrincipal, pIntRate = 5, pAccType = "Checking"):

   vIntRate = pIntRate

   if (pAccType == 'Savings'):

      # eligible for bonus interest

      vIntRate = pIntRate + 5

   newPrincipal = pPrincipal * (1+(vIntRate/100))

   print ("New Principal is " + str(round(newPrincipal)))

calcInt(pAccType="Savings", pIntRate=10, pPrincipal=100)

One of the useful cases in PL/SQL is to define a default value only when the value is not explicitly provided. Take for instance, when the user didn't specify anything for the interest rate, and you want the default values to be based on something else, for example, the account type. If the account type is Savings (the default), the interest rate should should be 10 percent; otherwise, it should be 5 percent. Here is how you will need to write the function:

-- pl3b.sql

declare

   procedure calcInt (

     pPrincipal      number,

     pIntRate        number := null,

     pAccType       varchar2 := 'Savings'

   ) is

     newPrincipal    number;

     vIntRate        number;

  begin

     if (pAccType = 'Savings') then

        if (pIntRate is null) then

      vIntRate := 10;

        else

      vIntRate := pIntRate;

    end if;

     else

        if (pIntRate is null) then

           vIntRate := 5;

        else

           vIntRate := pIntRate;

        end if;

     end if;

     newPrincipal := pPrincipal * (1+(vIntRate/100));

     dbms_output.put_line('New Principal is '|| newPrincipal);

  end;

begin

  calcInt(100);

  calcInt(100, pAccType => 'Checking');

end;

/

The equivalent of this:

pIntRate       number := null,

in Python is this:

pIntRate = None

(Note the capitalization of None). Here is the complete Python code:

# py3b.txt

def calcInt(pPrincipal, pIntRate = None, pAccType = "Savings"):

   vIntRate = pIntRate

   if (pAccType == 'Savings'):

      if (pIntRate == None):

         vIntRate = 10

      else:

         vIntRate = pIntRate

   else:

      if (pIntRate == None):

         vIntRate = 5

      else:

         vIntRate = pIntRate

   newPrincipal = pPrincipal * (1+(vIntRate/100))

   print ("New Principal is " + str(round(newPrincipal)))

calcInt(100)

calcInt(100, 20)

calcInt(100, pAccType="Checking")

Here is the output when we execute the code:

C:\>python py3b.txtNew Principal is 110New Principal is 120New Principal is 105

Returning Values

So far we have talked about the equivalent procedures in PL/SQL, which do not return anything. In contrast, functions in PL/SQL return a value. Here is a simple example of a function that returns the interest rate for the account type, which is the parameter passed to it:

--pl5

declare

   function getIntRate

   (

      pAccType   in varchar2

   )

   return number

   is

      vRate    number;

   begin

      case pAccType

          when 'Savings' then vRate := 10;

          when 'Checking' then vRate := 5;

          when 'MoneyMarket' then vRate := 15;

       end case;

       return vRate;

   end;

begin

   dbms_output.put_line('Int Rate = '||getIntRate('Savings'));

   dbms_output.put_line('Int Rate = '||getIntRate('Checking'));

   dbms_output.put_line('Int Rate = '||getIntRate('MoneyMarket'));

end;

/

The equivalent of this:

return vRate;

in Python, fortunately, is exactly the same:

return vRate

Let's see how we can write the Python code. Remember, there is no CASE equivalent in Python; so we have to resort to the if ... elif ...else construct.

# py5.txt

def getIntRate (pAccType):

   if (pAccType == 'Savings'):

      vIntRate = 10

   elif (pAccType == 'Checking'):

      vIntRate = 5

   elif (pAccType == 'MoneyMarket'):

      vIntRate = 15

   return vIntRate

print('Int Rate = ', getIntRate ('Savings'))

print('Int Rate = ', getIntRate ('Checking'))

print('Int Rate = ', getIntRate ('MoneyMarket'))

Executing it produces this:

C:\>python py5.txt

Int Rate =  10

Int Rate =  5

Int Rate =  15

Documentation

When you write a lot of functions, you might lose track of what each one does. Others may be even more confused. You can add documentation for the function to show what the function does. In PL/SQL, you use this syntax:

/*  ... documentation ... */

In Python, the equivalent is to put lines between a pair of three double quotes. Anything inside the pair of three double quotes will be considered documentation.

# py6.txt

def myFunc (pParam1, pParam2):

   """"Version : 2.0

   Purpose      : The purpose comes here

   Created      : mm/dd/yyyy

   Author       : XXX

   Last Changed : mm/dd/yyyy

   Change History:

   Date    Ver Made By Description

   ------- --- ------- -----------------------------

   mm/dd/yy 1.0 XXX    Created

   mm/dd/yy 2.0 yyy    Changed something

   """

   vInt = pParam1 + pParam2

   return vInt

print(myFunc(1,2))

But, unlike PL/SQL, which interprets the text between /* and */ as comments, Python interprets this correctly as function documentation and not as mere comments. There is a special attribute called __doc__ of any function that holds this documentation, and if it is defined it can be called later. Here is how you can reference this attribute:

# py7.txt

def myFunc (pParam1, pParam2):

   """Version : 2.0

   Purpose      : The purpose comes here

   Created      : mm/dd/yyyy

   Author       : XXX

   Last Changed : mm/dd/yyyy

   Change History:

   Date    Ver Made By Description

   ------- --- ------- -----------------------------

   mm/dd/yy 1.0 XXX    Created

   mm/dd/yy 2.0 yyy    Changed something

   """

   vInt = pParam1 + pParam2

   return vInt

print(myFunc.__doc__)

If we execute it, we get this:

C:\>python py7.txtVersion : 2.0   Purpose      : The purpose comes here   Created      : mm/dd/yyyy   Author       : XXX   Last Changed : mm/dd/yyyy   Change History:   Date    Ver Made By Description   ------- --- ------- -----------------------------   mm/dd/yy 1.0 XXX    Created   mm/dd/yy 2.0 yyy    Changed something

The documentation is helpful in many ways for documenting your programs and checking them later. The documentation comes in very handy when you write modules and classes (explained later in this installment).

Annotations

PL/SQL functions are strongly and unmistakably typed; that is, you have given the datatype of input parameters and return values explicitly at the time of defining the function. When you check the function later, all you need to do is to describe the function in SQL*Plus as shown below:

SQL> describe myFunc

However, there is no such facility in Python. What if you need to know what the datatypes are? There is a special attribute called annotations for functions. This allows you to document the datatypes of the input parameters and return values. This is the generalized syntax:

def FunctionName (ParameterName: DataType, ParameterName: DataType) -> ReturnDataType

When you want to see the annotations, a special attribute of the function, __annotations__, holds the value. Let's see a simple example where a function accepts two parameters of int type and returns a value of int type as well.

# py8.txt

def myFunc (pParam1 : int, pParam2 : int) -> int:

   vInt = pParam1 + pParam2

   return vInt

print(myFunc(1,2))

print("Let's see the annotations")

print(myFunc.__annotations__)

When we execute it, we get this:

C:\>python py8.txt3Let's see the annotations{'pParam1': <class 'int'>, 'pParam2': <class 'int'>, 'return': <class 'int'>}

It shows the class, which is analogous (but not exactly the same as) the datatype, of the input parameters (int in this case) and the return value (also int). However, please note a very important property of annotations. This is merely a suggestion; nothing else. It's not binding. There is nothing that prevents you from changing the datatype of the Python code after declaring the parameter annotations. Here is a modified version of the code shown earlier, but instead of integers we pass strings.

# py8a.txt

def myFunc (pParam1 : int, pParam2 : int) -> int:

   vInt = pParam1 + pParam2

   return vInt

print(myFunc("My","World"))

print("Let's see the annotations")

print(myFunc.__annotations__)

When you execute it, this is the output:

C:\>python py8a.txtMyWorldLet's see the annotations{'pParam1': <class 'int'>, 'return': <class 'int'>, 'pParam2': <class 'int'>}

Not only does it execute just fine; it's grossly misleading. Its annotations show that the input and outputs are int; but they are actually strings. So, annotations are merely suggestive, not definitive, and—do not forget—optional.

Global and Local Variables

In PL/SQL packages, or even in procedures, you can define variables where the scope of that variable is important. Take this simple procedure for instance. Here a variable named v1 is defined in two places—inside and outside the function—and assigned values in two places. Which value is shown where? Let's see:

-- pl9.sql

declare

   v1    number;

   function myFunc (

      p1 number,

      p2 number

   )

      return number

      is

      v1 number;

   begin

      v1 := p1+p2;   

      dbms_output.put_line('inside the function');

      dbms_output.put_line ('v1='||v1);

      return v1;

   end;

begin

   dbms_output.put_line('outside the function');

   v1 := 10;

   dbms_output.put_line ('v1='||v1);

   dbms_output.put_line ('the output of the function is '||myfunc(20,30));

end;

/

Executing it produces this:

outside the function

v1=10

inside the function

v1=50

the output of the function is 50

The values are differently assigned and maintained. So, when you reference a variable named v1, you have to pay attention to its scope, that is, where it is defined. That is where the value will be changed. In the case above, values set inside the function will be different from the value outside. It's exactly the same way in Python:

#py9.txt

def myFunc (p1, p2):

  v1 = p1 + p2

  print('inside the function')

  print ('v1 = ', v1)

  return v1

print('outside the function')

v1 = 10

print('v1=', v1)

print('The output of the function is ',myFunc(20,30))

Executing it produces this:

C:\>python py9.txt

outside the function

v1= 10

inside the function

v1 =  50

The output of the function is  50

In fact, the scope of the local variables is strictly inside the function. It's completely independent; so they can be even different datatypes.

#py9a.txt

def myFunc (p1, p2):

  v1 = p1 + p2

  print('inside the function')

  print ('local v1 = ', v1)

  return v1

print('outside the function')

v1 = 10

print('global v1=', v1)

p1 = 'Hello'

p2 = 'World'

print('The output of the function is ',myFunc(20,30))

print('Global p1 and p2 = ',p1,p2,sep=' ')

Executing it produces this:

C:\>python py9a.txt

outside the function

global v1= 10

inside the function

local v1 =  50

The output of the function is  50

Global p1 and p2 =  Hello World

inside the function

v1 =  50

The output of the function is  50

The scope is something you should pay attention to. The scope of a variable is determined at the time of its first appearance. Since there is no such thing called "declaration of variables" (variables are declared at the time of the assignment of values), whether a variable is local or global depends on when it was first referenced. Consider the following Python code.

#py10a.txt

1 v1 = 100

2 def myFunc (p1, p2):

3    print ('v1=',v1)

4    v2 = p1 + p2

5    print('inside the function')

6    print ('v2=', v2)

7    return v2

8

9 print('The output of the function is ',myFunc(20,30))

What do you think the output will be? On line 9, we call the function, which in turn goes to line 2 where the function is declared. Immediately inside the function, we print the variable v1; but wait, there is no variable v1 defined inside the function at that point. In fact, there is no variable called v1 in that function. Will this print statement (line 3) work, then? Let's see:

C:\>python py10a.txt

v1= 100

inside the function

v2= 50

The output of the function is  50

It may defy logic, but it did work. The fact is that there is no variable called v1 at all in the function; therefore, whenever there is a reference to variable named v1, Python will check if there is a global variable of that name. In this case, there is a global variable called v1 (line 1);  therefore, Python assumes that's what you meant on line 3.

However, what happens if we have a local variable called v1 as well in the function?

#py10b.txt

1 v1 = 100

2 def myFunc (p1, p2):

3    print ('v1=',v1)

4    v1 = p1 + p2

5    print('inside the function')

6    print ('v1=', v1)

7    return v1

8

9 print('The output of the function is ',myFunc(20,30))

When we execute this code, here is the output:

C:\>python py10b.txt

Traceback (most recent call last):

File "py10b.txt", line 9, in <module>

   print('The output of the function is ',myFunc(20,30))

File "py10b.txt", line 3, in myFunc

   print ('v1=',v1)

UnboundLocalError: local variable 'v1' referenced before assignment

What happened? Why didn't it work this time? The error is pretty clear; it's in line 3.

   print ('v1=',v1)

UnboundLocalError: local variable 'v1' referenced before assignment

This is because v1 is a local variable in this function, defined in line 4. However, before we defined it, we referenced it in line 3; hence, the error. Pay particular attention to this behavior. In summary, if you reference a local variable with the same name as a global variable, you must have declared a local variable before referencing it in the function. If you don't have have a local variable of the same name,  a reference to that will not fail; it will succeed. The global variable will be referenced instead.

Argument Array

Suppose you are writing a small function to add all the numbers. There is a sum function already available; but assume it wasn't and you write your own function. The problem is that you have to accept a series of numbers as arguments and—worse yet—the number of arguments is not known at the declaration time of the function. For instance, the name of function is mySum. To get the sum of three numbers—1, 2 and 3—you would call this:

mySum (1,2,3)

It has three arguments. To get the sum of four numbers—1, 2, 3, and 4—you would call this:

mySum (1,2,3,4)

This time, there are four arguments, and so on. The number of arguments is not known at the time of the definition of the function. How would you write the function then? This is something for which there is no PL/SQL equivalent. Readers familiar with C language may remember pointers by reference. C accepts an array of numbers or strings. However, you have to use an array, not pure primitive datatypes such as numbers. Python excels in this case. It allows an array of arguments as well, but since it doesn't require a prior declaration, arguments passed will be implicitly be treated as an array. The trick is to prefix the parameter name with an asterisk Let's see an example of the mySum function that accepts any amount of numbers and returns the sum:

#py11.txt

1 def mySum(*numList):

2    tot = 0

3    for n in numList:

4       print n

5       tot = tot + n

6    return tot

7

8 print ('Total=',mySum(1,2,3))

Notice the * before the parameter name, numList, which indicates that it is an array. Therefore in line 3, we can extract each element of the array and print them as a demo (line 4). We add each element to a variable called tot and finally return the variable. When we execute it, we get this:

C:\>python py11.txt

1

2

3

Total= 6

You can pass any number of parameters in this case. This is a very powerful feature of Python functions.

Named Argument

Remember passing options in a UNIX shell script? You can use something as simple as argument1=value1 argument2=value2, and so on. Sometimes you may need to write a similar program in Python as well. Not only will you not know the number of arguments in advance; you may not know even the argument names while declaring the parameters as well. Once again, there is no equivalency in PL/SQL. Fortunately it's a breeze in Python. You can prefix a double asterisk (**) before the name of the parameter, which indicates a dictionary collection in Python. Remember the dictionary datatype? If you don't, go back to Part 1 of this series to refresh your memory. In summary, a dictionary in Python is a set of key-value pairs.

Here is a small program where we accept a list of key-value pairs and check if they are twins, that is, whether the value is the same as the key.

#py12.txt

1 def checkTwins (**wordList):

2    words = sorted(wordList.keys())

3    for w in words:

4       print (w,':',wordList[w])

5       if (w==wordList[w]):

6          print('Twins Found')

7

8 checkTwins (

9         firstWord="first",

10         secondWord="second",

11         thirdWord="thirdWord"

12 )

We put the entire dictionary in a variable called words (line 2) after sorting it (sorting is not necessary; but I did it to refresh your memory on the sorted function). Then we iterate over each pair in that variable (line 3) and print each pair (line 4). In line 5, we compare the value and the key and if they are the same, we print the fact that they are twins. When we execute the program, we get the following output:

C:\>python py12.txt

firstWord : first

secondWord : second

thirdWord : thirdWord

Twins Found

Notice how the keys and their corresponding values are printed.

Stored Functions

So far, we have talked about defining functions right there in the Python script, analogous to declaring inline PL/SQL functions and procedures. However, if you use specific code a lot, you may want to create a stored procedure (or function) that is stored in the database and called as often as needed without redefining it. In Python, you can also store functions; but since there is no database, these are stored in files in groups called modules. A module is analogous to a stored package in PL/SQL. Just like packages have functions and procedures, modules contain functions.

Let's see an example of a simple module called intModule that has two functions: getIntRate() and calcInt(). To create this module, simply create a file named intModule.py with the following content:

#intModule.py

def getIntRate (pAccType):

  if (pAccType in ('Savings','S')):

     vIntRate = 10

  elif (pAccType in ('Checking','C')):

     vIntRate = 5

  elif (pAccType in ('MoneyMarket','M')):

     vIntRate = 15

  else:

     vIntRate = 0

  return vIntRate

def calcInt (pPrincipal, pAccType):

  vIntRate = getIntRate (pAccType)

  vInt = pPrincipal * vIntRate / 100

  return vInt

vAllowed = True

This is the "module," the equivalent of a package in PL/SQL. The package name equivalent is the module name, which is intModule (note the case). There is no such thing called "creating" the package. Python p

Comments

Post Details

Added on Oct 14 2016
5 comments
4,179 views