Академический Документы
Профессиональный Документы
Культура Документы
Release 7.1
IBM Netezza
Release 7.1
Note
Before using this information and the product it supports, read the information in Notices on page C-1
Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-1
Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-3
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X-1
This equipment was tested and found to comply with the limits for a Class A
digital device, according to Part 15 of the FCC Rules. These limits are designed to
provide reasonable protection against harmful interference when the equipment is
operated in a commercial environment. This equipment generates, uses, and can
radiate radio frequency energy and, if not installed and used in accordance with
the instruction manual, might cause harmful interference to radio communications.
Operation of this equipment in a residential area is likely to cause harmful
interference, in which case the user is required to correct the interference at their
own expense.
Properly shielded and grounded cables and connectors must be used to meet FCC
emission limits. IBM is not responsible for any radio or television interference
caused by using other than recommended cables and connectors or by
unauthorized changes or modifications to this equipment. Unauthorized changes
or modifications might void the authority of the user to operate the equipment.
This device complies with Part 15 of the FCC Rules. Operation is subject to the
following two conditions: (1) this device might not cause harmful interference, and
(2) this device must accept any interference received, including interference that
might cause undesired operation.
Responsible manufacturer:
Dieses Gert ist berechtigt, in bereinstimmung mit dem Deutschen EMVG das
EG-Konformittszeichen - CE - zu fhren.
IBM Deutschland
Technical Regulations, Department M456
IBM-Allee 1, 71137 Ehningen, Germany
Telephone: +49 7032 15-2937
Email: tjahn@de.ibm.com
This product is a Class A product based on the standard of the Voluntary Control
Council for Interference (VCCI). If this equipment is used in a domestic
environment, radio interference might occur, in which case the user might be
required to take corrective actions.
This is electromagnetic wave compatibility equipment for business (Type A). Sellers
and users need to pay attention to it. This is for any areas other than home.
Install the NPS system in a restricted-access location. Ensure that only those
people trained to operate or service the equipment have physical access to it.
Install each AC power outlet near the NPS rack that plugs into it, and keep it
freely accessible.
High leakage current. Earth connection essential before connecting supply. Courant
de fuite lev. Raccordement la terre indispensable avant le raccordement au
rseau.
Homologation Statement
This product may not be certified in your country for connection by any means
whatsoever to interfaces of public telecommunications networks. Further
certification may be required by law prior to making any such connection. Contact
an IBM representative or reseller for any questions.
Review the topics in this publication to create and use stored procedures on a IBM
Netezza data warehouse appliance. These topics describe the NZPLSQL Netezza
procedural language, provide an overview of the language and statements, and
how to create, alter, and drop procedures by using Netezza SQL commands.
To use these topics, you should be familiar with the Netezza systems and
architecture and Netezza SQL commands and how to access a Netezza database.
You should also be familiar with the general concepts of stored procedures, how to
create structured language programs, and how to debug applications.
Stored procedure support is available in Netezza Release 4.6 and later. These topics
describe changes available in Release 7.1 and later.
Stored procedures
IBM Netezza stored procedures combine the benefits of SQL to query and
manipulate database information with the benefits of a procedural programming
language to handle data processing, transaction logic, and application branching
behaviors.
For example, if you have a database that contains customer information, inventory,
and sales records, you might also have an application that processes the sale of an
item in inventory. When an order request arrives, the application might be
designed to query the database to determine how many items of that type are
available in inventory, and then to take the following actions:
v If the available inventory is less than the order number, the application processes
the request for the available number and notifies an order administrator to order
more inventory to complete the purchase.
v If the available inventory is greater than the order request, the application
processes the order and updates the database to show the reduction in the
current inventory.
v If the inventory is discontinued, the application saves the order request and
returns a message that the item is no longer available. It can also query for
related or replacement inventory to report alternative merchandise.
Because the application is on the Netezza host, the application performance can
benefit from its location onsite by avoiding the network time between an
application client system and the Netezza host. The application itself also becomes
easier to maintain, as it is in only one location (the Netezza host) and thus
versioning and updates need only be made in one place to keep the application
up-to-date for all users.
With Netezza stored procedures, you can also take advantage of security and
access benefits. Stored procedures can be defined to run with the credentials of the
user who created the procedure or the credentials of the user who is running the
procedure. The procedure manages the access to information contained in various
base tables and views. You can grant a user permission to run a stored procedure
without granting that user explicit access to underlying tables or views.
The NZPLSQL language provides for the following types of procedural logic:
v Conditionals (if/else)
v Looping (while, for)
v Execution of SQL (including dynamic SQL)
v Variables
v Returning a scalar result or a result set
v Input arguments
v Execution in the calling context (session and transaction)
v Extending functionality (adding NZPLSQL library routines)
You can use any SQL tool that supports ODBC, JDBC, OLE-DB to enter these
commands. This publication contains examples that use the nzsql command-line
tool.
In addition to these procedure-specific commands, you can also use the commands
GRANT and REVOKE to allow or deny access to procedures, and COMMENT ON
to add descriptions and details to the procedure definitions.
Related concepts:
Chapter 3, Create and manage stored procedures, on page 3-1
Related reference:
Appendix A, SQL command reference, on page A-1
A stored procedure can also be designed to return a result set. For more
information, see Return a result set on page 2-25.
As with other IBM Netezza objects, the Netezza admin user can create, list, and
execute stored procedures by default. The admin user can also grant other users
permission to create, list, and execute stored procedures on the Netezza system.
Related concepts:
Manage user account permissions on page 3-1
You can also use the SELECT command to execute a procedure; however, you
cannot specify a FROM clause. For example:
MYDB.SCHEMA(USER)=> SELECT updateacct();
To execute the procedure, the user must be the owner of or have permission to
execute the updateacct() procedure.
Related reference:
Appendix A, SQL command reference, on page A-1
Security considerations
When you define a stored procedure, you can specify whether the IBM Netezza
system executes the procedure by using the ID of the owner who created the
For example, if the admin user creates a stored procedure and specifies execute as
owner permission, which is the default, then any user who is allowed to execute
the procedure will do so as the admin user. With the admin user privileges, the
procedure could access data in tables or views that the logged-in database user
might not have permission to access. If the user bsmith creates the stored
procedure, then users who can execute the procedure will do so as the user bsmith.
If a procedure should access only the data that the executing user is allowed to
see, define the stored procedure as execute as caller. In this case, the procedure
uses the user ID of the database user who executes the procedure. The procedure
can access only the data that the calling user is permitted to see.
The Netezza system uses the PATH variable during the lookup of any unqualified
procedures. It searches the current database if PATH is not set; otherwise it
searches the databases and schemas specified in PATH, in the order that they are
specified. The Netezza system uses the first match that it finds, even if a better
match might exist in a subsequent database. A poorer match is one that might
require implicit casting of arguments or that causes an error due to multiple
If you plan to invoke cross-database calls to stored procedures that access data in
other databases, make sure that the stored procedure uses fully qualified object
names to refer to those data objects.
Write operations do not work across databases. For any procedures which contain
insert, update, delete, create, truncate, alter, or drop commands, make sure that
you are connected to the database where the stored procedure is defined.
As shown in the example, quotation marks are not escaped within the
block-quoted string. The string content is always written literally. Backslashes have
no special escape meaning.
The stored procedure body is in clear text format by default. Privileged users can
use the SHOW PROCEDURE VERBOSE command and interfaces such as
NzAdmin to review the stored procedure. If necessary, you can hide the
procedure code when you create the procedure.
Block quotes are intended for use only in NZPLSQL body quoting or stored
procedure invocation. The execution commands CALL and EXEC[UTE[
PROCEDURE]] support them, although SELECT does not. They can be used inside
a stored procedure body to build DDL statements where they are allowed, but they
have no quoting implications inside the body. If they are used inside the body,
make sure that there are an equal number of both keywords and that they match
(a BEGIN_PROC appears before the corresponding END_PROC) to avoid errors. If
your program logic dictates that they are not matching, they must be broken up
(that is, 'BEGIN_' || 'PROC').
If you want to do this inside a block quote body, then you must have a matching
END_PROC. For example:
CREATE OR REPLACE PROCEDURE name() RETURNS INT4 LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
string varchar;
BEGIN
string := This string is quoted;
-- This comment is the match for below BEGIN_PROC
insert into va values (END_PROC);
END;
END_PROC;
You cannot use SQL commands that are prohibited for use within a
BEGIN/COMMIT transaction block within the body of a stored procedure. Starting
in release 7.1, you can define a BEGIN AUTOCOMMIT ON block within the body,
and within that block you can use all SQL commands, even those prohibited for
use in a BEGIN/COMMIT transaction block such as GENERATE STATISTICS and
GROOM TABLE. For more information, see AUTOCOMMIT ON blocks on page
2-3.
For a description of the transaction control practices and command restrictions, see
the IBM Netezza Database Users Guide.
If you drop a database, all the objects defined in the database including stored
procedures are likewise dropped. If the Netezza system supports multiple schemas
in a database, and you define stored procedures in that schema, dropping the
schema will likewise drop all the objects in that schema. As a best practice, you
should keep backup copies of your source CREATE OR REPLACE PROCEDURE
definitions in a safe location outside of the Netezza system. Make sure that you
have recent backups of your Netezza systems in the event that you need to recover
from an accidental deletion or change, or to restore Netezza services as part of a
disaster recovery situation.
If the upgrade release introduces any new features or changes that can affect the
operation of stored procedures, Netezza describes the changes in the release notes.
Before you install any new release or service pack, review the release notes to
familiarize yourself with any new features, changes, fixes, and known issues for
that release. Make sure that you have a recent backup of your Netezza system
before you upgrade the system.
NZPLSQL structure
The NZPLSQL language is a block-structured language.
You can specify label as an optional way to identify a block in an EXIT statement,
or to qualify the names of the variables declared in the block.
The variables declared in the declarations section that precedes a block are
initialized to their default values every time that the block is entered, not just once
per procedure call.
Starting in release 7.1, if you specify the BEGIN AUTOCOMMIT ON syntax, the
procedure executes each statement in the block as a singleton statement with an
implied COMMIT after each statement. By committing after each statement, the
block adds support for SQL commands that are not allowed with in a BEGIN block
such as GROOM TABLE, GENERATE STATISTICS, and the other commands that
are prohibited for use within a BEGIN/COMMIT SQL transaction block. Within a
BEGIN/END block, you can specify COMMIT or ROLLBACK commands to either
commit or roll back all the changes in the current transaction.
Note: The BEGIN/END syntax for grouping statements in NZPLSQL is not the
same as the BEGIN/COMMIT SQL database commands for transaction control.
The NZPLSQL BEGIN/END keywords are used only for grouping; they do not
start or end a transaction. Procedures are always executed within a transaction
The statements section of a block can contain zero, one, or more sub-blocks. A
sub-block is used for logical grouping or to localize variables to a small group of
statements.
All of the keywords and identifiers are not case-sensitive and can be used in mixed
uppercase and lowercase mode. Identifiers are automatically converted to
uppercase, as they are in general SQL statements, unless they are enclosed in
quotation marks to keep them case-sensitive.
The exception_handlers section is an optional section that you can use to catch and
process an error that occurs in the statements section. If an error does not occur, the
exception_handlers section is ignored. For more information, see Exceptions and
error messages support on page 2-23.
When a stored procedure is called as a singleton SQL statement, the changes made
by the stored procedure are committed when the procedure exits or rolled back if
the procedure aborts.
CALL MYPROCEDURE(123);
Assume that you run the test3 procedure as a singleton SQL statement such as
EXECUTE test3(). The procedure executes statement1 and commits that change.
The procedure then runs statement2 and statement3, returns the 1234 value, and
exits. If the statements complete without error, the statement2 and statement3
changes are committed when the procedure exits.
Assume that you run the procedure inside a BEGIN transaction block such as the
following example.
When you call the test3 procedure within a transaction block, the procedure
executes statement1 and commits it, then executes statement2 and statement3, but
those statements are not yet committed. The procedure returns control to the
transaction block, which then calls a ROLLBACK command. In this case, the
changes made by statement2 and statement3 are rolled back, but statement1 was
already committed by the COMMIT statement inside the stored procedure body. If
the outside transaction block called a COMMIT instead of a ROLLBACK,
statement2 and statement3 would both be committed by transaction block
COMMIT command.
AUTOCOMMIT ON blocks
Each statement within a stored procedure BEGIN AUTOCOMMIT ON block is
executed as a singleton statement with an implied commit immediately after the
statement. This behavior is similar to running a series of SQL commands on the
command line, not inside a BEGIN/COMMIT transaction block.
You can specify all SQL commands inside an AUTOCOMMIT ON block, including
EXECUTE IMMEDIATE, IF statements, FOR statements, and so on. There are no
restrictions on the SQL statements. For each statement that is used inside an
AUTOCOMMIT ON block, the database changes are automatically committed after
each statement is executed.
The NZPLSQL language allows statement blocks to be nested within each other.
This behavior is supported by AUTOCOMMIT ON blocks as well, so it is possible
to nest AUTOCOMMIT ON|OFF blocks within each other. The syntax BEGIN
AUTOCOMMIT OFF is the default and is identical to BEGIN without an
AUTOCOMMIT clause.
BEGIN
Statement1;
BEGIN AUTOCOMMIT ON
/* an implicit commit occurs here */
Statement2;
/* an implicit commit occurs here */
Statement3;
/* an implicit commit occurs here */
END
END;
Comments
Comments within the NZPLSQL language can start with either a double dash or a
forward-slash asterisk.
v A double dash (--) starts a comment that extends to the end of the line. For
example:
-- This is a comment line.
v A forward-slash asterisk pair (/*) starts a block comment, which extends to the
next occurrence of the ending sequence which is an asterisk forward-slash (*/)
pair. For example:
/* This is a block comment,
which can span multiple lines.
Any code inside the block such as:
url varchar := http://www.ibm.com
is ignored. */
NZPLSQL variables can have any SQL data type, such as INTEGER, VARCHAR,
and CHAR. Some sample variable declarations follow:
user_id INTEGER;
quantity NUMERIC(5,2);
url VARCHAR;
The default value is evaluated each time the procedure is called. So assigning
now() to a variable of type timestamp causes the variable to be set to the time of
the actual procedure call, not the time when the procedure was precompiled into
its bytecode.
By using the %TYPE and %ROWTYPE attributes, you can declare variables with
the same data type or structure of another database item (for example, a table
field).
The %TYPE attribute provides the data type of a variable or database column. You
can use this attribute to declare variables that hold database values. For example, if
you have a column named user_id in your users table, you can declare a variable
with the same data type as user_id as follows:
user_id users.user_id%TYPE;
The table value must be an existing table or view name of the database. The fields
of the row are accessed by using the dot notation.
Only the user attributes of a table row are accessible in the row. You cannot access
an OID or other system attribute because the row could be from a view. The fields
of the row type inherit the sizes or precision for CHAR, NCHAR, and NUMERIC
data types from the table.
Parameter passing
In NZPLSQL, parameters are not named. Instead, only the data types are passed,
and parameters are referenced by their position.
BEGIN
vId := ISNULL(pId, 0);
INSERT INTO t1 SELECT * FROM t2 WHERE id = vId;
You can specify 0 - 64 arguments. If you specify VARARGS in the input argument
list, users can input any number of arguments up to a maximum of 64.
(1 row)
Related concepts:
Variable arguments on page 3-7
Scope of variables
When you explicitly declare a new variable (or name), the scope of the variable is
the block in which it is defined.
For example, the following sample defines a variable named val in the DECLARE
section of the <<outer>> block, and then defines another val variable in the
DECLARE section of the <<inner>> block. Although the variables have the same
name, these variables are two different variables:
<<outer>>
DECLARE
val int4;
BEGIN
val := 5;
<<inner>>
DECLARE
val int4;
BEGIN
val := 7;
RAISE NOTICE inner val != outer val % %, val, outer.val;
END;
RAISE NOTICE outer val is 5 %, val;
END;
(1 row)
When you declare variables for loop iterators, the iterator variables have their own
unique scope. For example, you can use a variable named val as a loop iterator. By
using the same sample procedure, this would give you three unique val variables
in your procedure:
<<outer>>
DECLARE
val int4;
BEGIN
val := 5;
<<inner>>
DECLARE
val int4;
BEGIN
val := 7;
RAISE NOTICE inner val != outer val % %, val, outer.val;
FOR val IN 1 .. 10 LOOP
--Note that this is a NEW val variable for the loop.
RAISE NOTICE The value of val is %, val;
END LOOP;
RAISE NOTICE inner val is still 7. Value %, inner.val;
END;
RAISE NOTICE outer val is still 5. Value %, val;
END;
(1 row)
As shown in the output, the val variable of the loop iterator has its own scope. It
has its own value and does not affect the other two val definitions. Within the
loop, if you need to call a specific variable that is defined outside the for loop, you
can use the fully qualified form of the variable name (label.variable).
Related concepts:
Iterative control on page 2-19
Netezza SQL prefers the type name real, as float(p) is considered more of
an alias for the preferred form.
DOUBLE DOUBLE, FLOAT, Floating point number with precision p, from 7 to 15. Precision values 7 -
PRECISION FLOAT(p), FLOAT8 15 are equivalent to 15 and are stored as an 8-byte value.
Array variables
In addition to normal scalar variables, NZPLSQL also supports array variables. To
declare an array variable, use the following syntax:
name VARRAY(size) OF type;
All of the elements of the array are initially set to the SQL NULL value for the
declared type. To assign a value to an element, do the following:
name(idx) := value;
This syntax raises an exception if the index (idx) is out of bounds. The following
methods are supported:
name.EXTEND(size)
name.COUNT
name.TRIM(size)
The EXTEND method extends the array by the specified size. If size is omitted, the
default is 1.
Array references are allowed almost anywhere variable references are allowed,
with the following exceptions:
v As an argument to RAISE
v As an INTO variable
v As the variable in a FOR LOOP
v As part of a default value
Expressions
All expressions used in NZPLSQL statements are processed by using the backend
executor.
Expressions that appear to contain constants could require runtime evaluation (for
example, by using 'now()' for the timestamp type) so it is impossible for the
NZPLSQL parser to identify real constant values other than the NULL keyword.
All expressions are evaluated internally by running a query such as the following:
SELECT expression
The type checking done by the IBM Netezza SQL main parser has some side
effects for the interpretation of constant values. For example, the following two
examples are different in how constant values are interpreted. The first example
follows:
DECLARE
logtxt ALIAS FOR $1;
BEGIN
INSERT INTO logtable VALUES (logtxt, now());
RETURN now();
END;
In the first example, when the Netezza SQL main parser prepares the plan for the
INSERT, it interprets now() as a timestamp because the target field of logtable is of
that type. It interprets both instances of now() each time it runs.
If record fields are used in expressions or statements, the data types of fields
should not change between calls to the same expression or statement.
The Netezza system checks for overflows when performing integer arithmetic. For
example, all integer literals are 32-bit (signed) numbers by default, which supports
a range of values from -2147483648 to 2147483647. If you perform math operations
on a literal, the system checks for and returns an error if it detects an overflow. For
example, the following stored procedure defines a numeric value n, assigns it the
largest supported value (2147483647) and then adds 1 to the value:
CREATE OR REPLACE PROCEDURE num() RETURNS BOOL LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
n NUMERIC;
BEGIN
n := 2147483647;
RAISE NOTICE n is %, n;
n := 2147483647 + 1;
RAISE NOTICE n is %, n;
END;
END_PROC;
If you create and run this stored procedure, the procedure fails and returns an
integer overflow error:
NOTICE: n is 2147483647
NOTICE: Error occurred while executing PL/pgSQL function NUM
NOTICE: line 6 at assignment
ERROR: overflow in 32 bit arithmetic
To avoid an overflow condition, you can use a cast operation to cast n to a higher
precision type, or assign values to intermediate values. For example, the following
stored procedure creates the overflow issue for the numeric value n but uses casts
to numerics or bigints to increase the range of valid values:
CREATE OR REPLACE PROCEDURE num() RETURNS BOOL LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
n NUMERIC;
BEGIN
n := 2147483647;
RAISE NOTICE n is %, n;
n := 2147483647::numeric + 1;
RAISE NOTICE n is %, n;
n := 2147483647::bigint + 1;
RAISE NOTICE n is %, n;
END;
END_PROC;
As this example shows, explicit casts during arithmetic evaluations and careful use
of literals, constants, and types can help to increase the accuracy of the expressions
used in your stored procedures.
If you use floating point numbers in expressions, Netezza attempts to cast it into a
numeric if possible, with a specific precision and scale that it calculates with
internally defined casting rules.
In the arithmetic expression that follows, Netezza casts the precision and scale
based on internal Netezza SQL behavior rules:
DEV.SCH1(ADMIN)=> create table test as select (1 + 0.08/365) interest;
INSERT 0 1
DEV.SCH1(ADMIN)=> \d test
Table "TEST"
Attribute | Type | Modifier | Default Value
----------+--------------+----------+---------------
INTEREST | NUMERIC(8,6) | |
Distributed on hash: "INTEREST"
In the sample table, the Netezza internal casting rules evaluated the expression
1+0.08/365 and determined that the field would be a numeric value with 8
digits of precision and 6 digits of scale. The following command shows the actual
value saved in the row:
DEV.SCH1(ADMIN)=> select * from TEST;
INTEREST
----------
1.000219
(1 row)
In the previous example, Netezza is evaluating three integer values (4, 1, and 5).
The Netezza system uses integer as the type for the new column. If you display
the column value, as follows, you can see that the decimal portion of the value
was truncated:
A similar example follows, but instead of the expression 1/2, this expression uses
the numeric value .5 instead, as follows:
DEV.SCH1(ADMIN)=> create table test3 as select (4 + .5) loanrt;
INSERT 0 1
DEV.SCH1(ADMIN)=> \d test3
Table "TEST3"
Attribute | Type | Modifier | Default Value
----------+---------------+----------+---------------
LOANRT | NUMERIC(3,1) | |
Distributed on hash: "LOANRT"
DEV.SCH1(ADMIN)=> select * from TEST3;
LOANRT
--------
4.5
(1 row)
In this example, the .5 value is interpreted as 0.5, and thus cast to numeric(3,1).
In addition to the casts that can occur when math expressions are parsed, Netezza
functions can also cause an implicit typecast. For example, the function sqrt()
takes and returns a double precision value. The following example uses the
function to define a table column:
DEV.SCH1(ADMIN)=> create table test4 as select (sqrt(42));
INSERT 0 1
DEV.SCH1(ADMIN)=> \d test4
Table "TEST4"
Attribute | Type | Modifier | Default Value
----------+------------------+----------+---------------
SQRT | DOUBLE PRECISION | |
Distributed on hash: "SQRT"
DEV.SCH1(ADMIN)=> select * from TEST4;
SQRT
-----------------
6.4807406984079
(1 row)
In the test4 example, the sqrt() function causes Netezza to cast the input integer
value to a double and to return a double.
Remember these behaviors when you work with stored procedures that use
arithmetic expressions to evaluate data. The implicit casts might not provide the
value that you would expect if you evaluated the same arithmetic expression with
a calculator. An example follows:
CREATE OR REPLACE PROCEDURE sp_expressions_numeric02() RETURNS NUMERIC
LANGUAGE NZPLSQL AS
BEGIN_PROC
DECLARE
thisnum9_2 NUMERIC(9,2);
million NUMERIC(9,2) := 1000000.00;
thisnum18 NUMERIC(18);
litespeed NUMERIC := 186282;
thisnum38 NUMERIC(38);
BEGIN
/* The following expression causes implicit casts in the math
evaluation, reducing the precision and scale of the result. */
thisnum9_2 := million * (1 + 0.08/365)^(365 * 20);
Statements
This section describes the types of statements that are explicitly understood by the
NZPLSQL parser. Any statements that are not specified by using these conventions
(and thus are not understood by the NZPLSQL parser) are assumed to be SQL
commands and sent to the database engine to execute. The resulting query should
not return any data.
Assignment
To assign a value to a variable or row/record field, use the assignment statement
as follows:
identifier := expression;
If the expressions result data type does not match the variables data type but the
types are compatible, or the variable has a size/precision that is known (as for
char(20)), the result value is implicitly cast by the NZPLSQL bytecode interpreter
using the result types output-function and the variables type input-function. Note
that this could potentially result in runtime errors generated by the types input
functions.
For more information about IBM Netezza casting rules and behaviors, see the IBM
Netezza Database Users Guide.
However, there are cases where you might not be concerned with the result of the
procedure. In these cases, use the CALL statement to call the procedure, as follows:
CALL query
The CALL statement runs a SELECT query and discards the result. Identifiers such
as local variables are still substituted into input parameters.
There is a maximum stored procedure call recursion limit of 1024. If the call
recursion exceeds this value, the following error message is returned:
ERROR: stored procedure recursion limit exceeded
The query-string value is a string of type text which contains the query to be
executed.
When working with dynamic queries, make sure that you escape any quotation
marks in NZPLSQL.
The results from SELECT queries are discarded by EXECUTE IMMEDIATE, and
SELECT INTO is not currently supported within EXECUTE IMMEDIATE. So, the
only way to extract a result from a dynamically created SELECT is to use the FOR
... EXECUTE form, described in Iterate through the records of a query on page
2-21.
LAST_OID is useful only after an INSERT query, and then only when the insert
happens on a catalog table. In practice, LAST_OID is not likely to be useful.
In addition to these variables, you can also use the FOUND and IS NULL variables
to do special conditional processing based on record results.
Related concepts:
Assignments on page 2-20
The procedure terminates and the value of expression is returned to the upper
executor. If expression is not provided, NULL is assumed.
The return value of a procedure can be undefined. If control reaches the end of the
top-level block of the procedure without encountering a RETURN statement,
NULL is assumed. The result of the expression is automatically cast into the return
type of the procedure as described for assignments.
Control Structures
Control structures are a useful and important part of the NZPLSQL language. You
can use NZPLSQL control structures to manipulate SQL data in a flexible and
powerful way.
Conditional control
You use IF statements to take action based on certain conditions. NZPLSQL has
three forms of IF statements:
v IF-THEN
v IF-THEN-ELSE
v IF-THEN-ELSE IF
IF-THEN statements
IF-THEN-ELSE statements add an ELSE branch for cases when the IF-THEN
condition evaluates to FALSE. You can specify the statements to run in the ELSE
section. For example:
IF parentid IS NULL or parentid =
THEN
return fullname;
ELSE
return hp_true_filename(parentid) || / || fullname;
END IF;
IF-THEN-ELSE IF statements
When you use the "ELSE IF" statement, you are nesting an IF statement inside the
ELSE statement. Thus, you need one END IF statement for each nested IF and one
for the parent IF-ELSE. For example:
IF movies.genre = d THEN
film_genre := drama;
ELSE IF movies.genre = c THEN
film_genre := comedy;
END IF;
END IF;
While this form works, it can become a little tedious and error-prone if there are
many alternatives to check. Thus, the language offers the alternative syntax by
using ELSIF or ELSEIF, as follows:
IF movies.genre = d THEN
film_genre := drama;
ELSIF movies.genre = c THEN
film_genre := comedy;
ELSIF movies.genre = a THEN
film_genre := action;
ELSIF movies.genre = n THEN
film_genre := narrative;
ELSE
-- An uncategorized genre form has been requested.
film_genre := Uncategorized;
END IF;
The IF-THEN-ELSIF-ELSE form offers some flexibility and eases the coding process
when you need to check many alternatives in one statement. While it is equivalent
to nested IF-THEN-ELSE-IF-THEN commands, it needs only one END IF
statement.
LOOP statement
The LOOP statement defines an unconditional loop that repeats until terminated
by an EXIT statement or a RETURN statement (which terminates the procedure
and the loop). It has the following syntax:
[<<label>>]
LOOP
statements
END LOOP;
The optional label can be used by EXIT statements of nested loops to specify which
level of nesting is terminated.
EXIT statement
If you do not specify a label, the innermost loop is terminated and the statement
that follows END LOOP runs next. If you specify a label, it must be the label of
the current or an upper level of nested loop or blocks. Then the named loop or
block is terminated and control continues with the statement after the
corresponding END of the loop or blocks.
Examples:
LOOP
-- some computations
IF count > 0 THEN
EXIT; -- exit loop
END IF;
END LOOP;
LOOP
-- some computations
EXIT WHEN count > 0;
END LOOP;
BEGIN
-- some computations
IF stocks > 100000 THEN
EXIT;
END IF;
END;
WHILE statement
With the WHILE statement, you can loop through a sequence of statements if the
evaluation of the condition expression is true.
[<<label>>]
WHILE expression LOOP
statements
END LOOP;
For example:
FOR statement
By using the FOR statement, you can create a loop that iterates over a range of
integer values.
[<<label>>]
FOR name IN [ REVERSE ] expression .. expression LOOP
statements
END LOOP;
The variable name is automatically created as type integer and exists only inside
the loop. The two expressions for the lower and upper bound of the range are
evaluated only when entering the loop. The iteration step is always 1.
Records
Records are similar to row types, but they have no predefined structure. They are
used in selections and FOR loops to hold one database row from a SELECT
operation.
Declaration
Variables of type RECORD can be used for different selections. Accessing a record
or an attempt to assign a value to a record field when there is no row in it results
in a runtime error. To declare a RECORD variable:
name RECORD;
Assignments
You can use the following query to assign a complete selection into a record or
row:
SELECT expressions INTO target FROM ...;
After a record or row is assigned to a RECORD variable, you can use the "." (dot)
notation to access fields in that record as follows:
DECLARE
users_rec RECORD;
full_name varchar;
BEGIN
SELECT * INTO users_rec FROM users WHERE user_id=3;
full_name := users_rec.first_name || || users_rec.last_name;
There is a special variable named FOUND of type boolean that can be used
immediately after a SELECT INTO to check whether an assignment was successful.
The following example uses the NOT FOUND form to raise an exception if a
SELECT INTO statement does not match on the requested input name:
SELECT * INTO myrec FROM EMP WHERE empname = myname;
IF NOT FOUND THEN
RAISE EXCEPTION employee % not found, myname;
END IF;
You can also use the IS NULL (or ISNULL) conditionals to test whether a RECORD
or ROW is NULL. If the selection returns multiple rows, only the first is moved
into the target fields. All others are silently discarded. For example:
DECLARE
users_rec RECORD;
full_name varchar;
BEGIN
SELECT * INTO users_rec FROM users WHERE user_id=3;
IF users_rec.homepage IS NULL THEN
-- user entered no homepage, return "http://"
return http://;
END IF;
END;
Related concepts:
Obtain other results status on page 2-17
The record or row is assigned all the rows that result from the select clause and the
loop body runs for each. An example follows:
If the loop is terminated with an EXIT statement, the last assigned row is still
accessible after the loop.
This form is similar to the previous form, except that the source SELECT statement
is specified as a string expression. The main difference between the two is the
syntax and use of variables to build the SQL to run. The first form is faster to
evaluate.
Inside format, the percent character (%) is used as a placeholder for a subsequent,
comma-separated identifier. You can specify more than one % and identifier pair,
as follows:
RAISE NOTICE Welcome % %, firstname, lastname;
In this example, the notice message substitutes the value of firstname for the first
% character, and substitutes the value of lastname for the second % character.
This EXCEPTION statement aborts the transaction (if the exception is not caught)
and writes the message to the database log.
To catch and process an error that occurs in a procedure block, you can add an
exception-handling section at the end of a block by using the EXCEPTION
keyword. If no error occurs, the exception-handling section is ignored. Within the
exception-handling section, you can specify one or more exception handlers by
using WHEN clauses that specify the exception to match and the statements to run
when a match occurs. An EXCEPTION statement has the following form:
EXCEPTION
WHEN clause THEN
statements
[ WHEN ... ]
You can specify both clauses in an exception block, as in the following example.
When an error occurs in the procedure, the procedure code uses the first matching
exception clause and executes the statements in that clause. Any clauses after the
match are ignored. As a best practice, specify the OTHERS clause last because it
matches any type of error.
EXCEPTION
WHEN TRANSACTION_ABORTED THEN
ROLLBACK;
statements_case1
RAISE ERROR Procedure failed: %, sqlerrm;
WHEN OTHERS THEN
statements_case2
RAISE NOTICE Caught error, continuing %, sqlerrm;
The variable SQLERRM contains the text of an error message that is caught. In the
absence of an exception block, the exception propagates up to the next stored
procedure in the call stack. If sproc1 calls sproc2, which generates an exception,
but sproc2 does not have an exception handler, then the system looks for a handler
in sproc1. The system also looks at the enclosing block declarations.
For example:
create or replace procedure sp_except01() returns BOOL LANGUAGE
NZPLSQL AS
BEGIN_PROC
DECLARE
r record;
BEGIN
<<inner>>
BEGIN
SELECT * INTO r FROM NONEXISTENT;
END;
END;
END_PROC;
If you include exception handlers in stored procedures, the handlers catch any
errors and the errors are not displayed. For example:
CREATE PROCEDURE sp() RETURNS INTEGER LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
Assuming that NOTEXIST does not exist in the database, the query does not
display any error output because the error was handled by the exception handler.
The table specified in the RETURNS value must exist at the time that the stored
procedure is created, although the table can be empty. The table continues to exist
after the stored procedure completes. You cannot drop the reference table while the
stored procedure is defined. (That is, you must drop the stored procedure or
modify it to return a different reference table before you can drop the table.)
For example, the following stored procedure, returntwo, returns a result set by
using the reference table feature. The reference table that it uses, tbl, was
previously defined by using the following command:
CREATE TABLE tbl (i INT4, i2 bigint);
After you confirm that the reference table exists, you can use the following
command to define the stored procedure returntwo:
DEV.SCH1(ADMIN)=> CREATE OR REPLACE PROCEDURE returntwo(timestamp) RETURNS
REFTABLE(tbl) LANGUAGE NZPLSQL AS
BEGIN_PROC
Restriction: You cannot specify a WHERE clause in a query that calls a stored
procedure that returns a result set.
When you call or invoke the stored procedure by using a SQL command such as
SELECT procedure(), CALL procedure(), EXECUTE procedure(), and so on, the
database does the following:
v Generates a table name TEMPFUNC<oid> where oid is the object ID of the
procedure that was invoked
v Checks if the table name exists; if it does, it issues a DROP TABLE
<temp-table-name> command
v Issues a CREATE TEMPORARY TABLE <temp-table-name> as select * from
<table-name> LIMIT 0 to create the table for the results set with no initial
contents
v Returns the results of SELECT * from <temp-table-name> where proc(args) is
NULL (This situation is the only situation in which a stored procedure is
allowed to be invoked with a FROM clause and where the return value is used
as part of a query.)
Additionally, you must return NULL in your procedure by one of the following
means:
v RETURN REFTABLE;
v RETURN NULL;
v RETURN;
v Not specifying a RETURN clause.
If you do not return NULL, the procedure returns an error. The recommended
method to return NULL is RETURN REFTABLE.
One REFTABLE procedure can call another, but you encounter unusual results if a
REFTABLE procedure calls itself (either directly or recursively) because of the
temporary table logic; therefore, avoid designing a REFTABLE procedure which
calls itself.
As shown in the example, your procedure can call the COMMIT command as
needed, but the first COMMIT ensures that the temporary table exists for
processing within the body.
The following message is an example of the error that occurs when the
ROLLBACK ran without a prior COMMIT:
DEV.SCH1(ADMIN)=> EXECUTE returntwo(now());
NOTICE: Error occurred while executing PL/pgSQL function RETURNTWO
NOTICE: line 1 at SQL statement
ERROR: Cannot use ROLLBACK from within a stored procedure which uses
a REFTABLE without a COMMIT first.
END LOOP:
The SELECT operation runs first and caches its results in memory or as a
temporary file on disk, depending upon the size of the result set. The procedure
then applies the steps in the inner processing loop.
If the table (tablenm) is very large, such as a table with millions of rows or one
with many thousands of large rows, the temporary file can be a huge file that uses
the free disk space on the IBM Netezza host. Use caution when your stored
procedures process very large tables.
Note: In the Netezza environment, these types of select loops that operate on
single rows are not optimized for performance in the Netezza environment. Where
possible, recast the loop to operate on record sets.
Related concepts:
Tips and best practices for stored procedures
If the procedure encounters an infinite loop, you can press Control-C to interrupt
the loop. This key sequence should cause an exception (which is not catchable) and
thus cause the loop and the procedure call to be interrupted and return.
Within stored procedures, there can be loop designs that appear to use concurrent
queries to process the results. For example, the following procedure uses a SELECT
to gather information, which is then processed for a possible DELETE action:
FOR rec in SELECT * from mytable LOOP
IF rec.type = 'd' THEN
EXECUTE IMMEDIATE 'DELETE FROM mytable2 WHERE recid = ' || rec.id;
END IF;
END LOOP;
While it appears that the outer FOR loop SELECT and the inner EXECUTE
IMMEDIATE queries are running at the same time, the SELECT query finishes and
This procedure design can take advantage of the IBM Netezza massively parallel
processing (MPP) environment to run much quicker.
Related concepts:
Manage large data sets on page 2-27
As the admin user or any user who has account management permissions, you can
grant other users permission to create, manage, or execute the stored procedures
on a Netezza system. You can assign permissions by using the IBM Netezza
Performance Portal User's Guide, NzAdmin user interface, or by using the GRANT
and REVOKE SQL commands. For details about managing users and groups, and
assigning permissions by using the NzAdmin interface, see the IBM Netezza System
Administrators Guide.
If you use SQL commands to manage account permissions, the database to which
you are connected has meaning when you run the GRANT command. If you are
connected to the SYSTEM database, the privilege applies to all databases. If you
are connected to a specific database, the privilege applies only within that
database.
Starting in release 7.0.3, you can use a fully qualified object notation to set the
scope of object privileges from any database. The fully qualified object notation has
the format database.schema.object, where:
v database is a specific database name or the keyword ALL to grant the privilege
across all databases.
v schema is a specific schema name or the keyword ALL for all schemas in the
specified database value.
v object is the class PROCEDURE for all stored procedures, or a full signature
such as customer(VARCHAR(20)).
Make sure that you specify the correct signature for the object, including the sizes
for numeric and string data types, otherwise you receive an error similar to the
following example:
ERROR: GrantRevokeCommand: existing UDX NAME(ARGS) differs in size of
string/numeric arguments
You can use a similar format to set the scope of administrative privileges from any
database. The scope notation has the format IN database.schema, where:
For example, the following command grants Create Procedure permissions to the
user bsmith:
GRANT CREATE PROCEDURE TO bsmith;
If you run this command while connected to the SYSTEM database, the privilege is
granted to the user in all databases. If you are connected to a specific database, the
privilege is granted to the user in only that database.
Using the release 7.0.3 fully qualified name form, you could also issue the
command from any database and specify an IN clause to set the privilege scope.
For example, the following command grants the user Create Procedure privilege in
all databases and schemas:
GRANT CREATE PROCEDURE IN ALL.ALL TO bsmith;
The following command grants the user Create Procedure privilege in the database
named NORTH and the schema named SALES:
GRANT CREATE PROCEDURE IN NORTH.SALES TO bsmith;
To grant users or a group with all object permissions, use the following command:
GRANT ALL ON PROCEDURE TO entity;
This command gives the user or group the Alter, Drop, List, and Execute privileges
for procedures and other permissions such as Insert, Delete, and others that are not
used for procedures.
For example, the following command grants object permissions to the user bsmith:
GRANT ALL ON PROCEDURE TO bsmith;
For example, the following command grants object permissions to the user bsmith,
and is scoped to the database (and schema, if applicable) in which you run the
command:
GRANT ALL ON PROCEDURE TO bsmith;
For example, the following command revokes Create Procedure permissions from
the group analysts:
For example, to grant Alter permissions for the sample stored procedure
returntwo() to the user asmith:
GRANT ALTER ON returntwo(timestamp) TO asmith;
For example, to revoke Alter permissions on the returntwo() procedure from the
group sales:
REVOKE ALTER ON returntwo(timestamp) FROM GROUP sales;
For example, to grant Execute permissions for the sample procedure returntwo()
to the user bsmith:
GRANT EXECUTE ON returntwo(timestamp) TO bsmith;
For example, to revoke Execute permissions for the sample procedure returntwo()
from the group sales:
REVOKE EXECUTE ON returntwo(timestamp) FROM GROUP sales;
For example, to grant Drop permissions for the sample procedure returntwo() to
the user pcollins:
GRANT DROP ON returntwo(timestamp) TO pcollins;
For example, to revoke Drop permissions for the sample procedure returntwo()
from the user bsmith:
REVOKE DROP ON returntwo(timestamp) FROM bsmith;
Related tasks:
How to create and use a stored procedure on page 1-3
This section describes the following key steps for creating a stored procedure:
v Design a stored procedure
v Create a stored procedure
For example, the following procedure customer() writes a customer name string to
the database log by using the RAISE NOTICE statement:
TEST.TESTSCH(USR)=> CREATE PROCEDURE customer()
RETURNS INT4 LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
RAISE NOTICE The customer name is alpha;
END;
END_PROC;
CREATE PROCEDURE
Since the execution user permissions were not specified on the command line, the
command uses the default of EXECUTE AS OWNER.
If you want to change the customer procedure to specify a new return value, you
can use a CREATE OR REPLACE PROCEDURE command similar to the following,
but you must specify all the required fields (such as language and the complete
procedure body) even if their values did not change, as follows:
TEST.TESTSCH(USR)=> CREATE OR REPLACE PROCEDURE customer()
RETURNS INT8 LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
RAISE NOTICE The customer name is alpha;
END;
END_PROC;
CREATE PROCEDURE
Procedure signatures
Each stored procedure has a signature; that is, a unique identification in the form
<procedure_name>(<argument_type_list>). Signatures must be unique within the
same database; that is, they cannot duplicate the signature of another stored
procedure. The <argument_type_list> component does not consider data type sizes
to be differentiators. For example, you cannot create two procedures called
myproc(numeric(3,2)) and myproc(numeric(4,1)) in the same database. The larger
numeric size is not sufficient to create a unique signature.
For example, assume that you have a procedure called customer_name() that can
take two or three input strings, which represent the first, middle (if specified), and
surname of a customer.
If a user calls customer_name with two input strings, the system uses the first (two
argument) procedure. If the user specifies three input strings, the procedure uses
the second procedure that accepts three input strings.
You can use overloading to support different combinations of input values and
return types. However, overloading and uniquely named but similar procedures
have a maintenance overhead; if you need to update or redesign the body of the
procedure, update each procedure definition with the changes that you want to
make.
Size-specific arguments
With size-specific arguments, you declare the type and size of all input arguments,
and the type and size of the return value. Specific data type size declarations are
For example, the following example creates a stored procedure that takes a string
of up to 20 VARCHAR characters:
TEST.TESTSCH(USR)=> CREATE PROCEDURE customer(VARCHAR(20))
RETURNS INT4 LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
remaining text omitted for example...
Constant data type sizes can result in implicit casts, such as casting a smaller input
value to fit a larger declared size. For example, it can increase the precision of a
numeric or add padding to strings. If you choose too small a size, you risk loss of
precision if IBM Netezza casts a larger input numeric to a smaller numeric or
truncates input strings that exceed the input argument size.
Generic-size arguments
Generic-size (or any-size) arguments offer more flexibility for strings and numerics.
You can declare character strings or numerics by using the ANY keyword in the
signature (or in the return value). For example:
TEST.TESTSCH(USR)=> CREATE PROCEDURE customer(VARCHAR(ANY))
RETURNS VARCHAR(ANY) LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
remaining text omitted for example...
Generic-size arguments help you to avoid specific limits for the input strings and
numerics, or to use overly large or maximum size values that result in unnecessary
resource allocation for the procedure. This format can also reduce the need to
register and maintain similar procedures that take different input arguments or
have different return values, and possible casting of input values.
Supported generic argument types: You use the ANY keyword to indicate that an
argument is generic. The following data types support the ANY keyword as a size
specifier:
v CHAR or NCHAR
v VARCHAR or NVARCHAR
v NUMERIC
For example, to specify a numeric data type of precision 10 and scale 2, you
specify it as NUMERIC(10,2). To specify a numeric data type that can take any
size, you specify is as NUMERIC(ANY). Likewise, to specify a variable character
string that can take any size, you declare it as VARCHAR(ANY).
Generic arguments in the procedure signature: You can define generic arguments
and the standard data-type-and-size-specific arguments in the signature of a stored
procedure. The IBM Netezza software verifies that all the input arguments match
the required number and data types of the signature.
For generic arguments, the argument values are passed to the procedure without
any casting or changes. For example, if you declare a CHAR(ANY) input value, the
procedure accepts character strings of any length up to the supported maximum; it
checks to make sure that the input value is a valid character string and that it
occurs in the expected place of the signature.
The Netezza software performs some implicit castings for the input values. For
example, if you define an input argument as VARCHAR(ANY) in the signature,
but you pass an input of CHAR(200) to the procedure, the procedure casts the
CHAR(200) to VARCHAR(200). The procedure uses the data type of the signature
and the size of the input value to determine the casting change.
If you use ANY for a return value size, your procedure calculates the size of the
numeric or string return value from the RETURN expression and returns it.
Register generic procedures: When you register a stored procedure that uses
generic arguments, you use the keyword ANY to declare character or numeric data
types as generic.
An example follows:
MYDB.TESTSCH(USR)=> CREATE PROCEDURE itemfind(NUMERIC(ANY))
RETURNS CHAR(ANY) LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
/* Body of procedure... intentionally omitted from example*/
END;
END_PROC;
In this example, the itemfind() procedure takes an input numeric data type of any
valid size and returns char value of any size.
Related reference:
The CREATE [OR REPLACE] PROCEDURE commands on page A-5
Variable arguments
Variable-argument procedures offer even more flexibility than generic-size
arguments. With variable argument procedures, you specify only the VARARGS
keyword in the argument_type_list. Users can specify from 0 to 64 input values of
any supported data type as input arguments. For example:
TEST.TESTSCH(USR)=> CREATE PROCEDURE customer(VARARGS)
RETURNS VARCHAR(ANY) LANGUAGE NZPLSQL AS
BEGIN_PROC
BEGIN
remaining text omitted for example...
Within the body of the stored procedure, the code must process the input values
and manage them as needed.
Call the wrap_proc() procedure and specify the CREATE OR REPLACE main
definition in the first input value; then specify the BEGIN PROC/END PROC
contents in the second input value. You must surround the main definition (the
first input value) with single quotation marks. Do not enclose the second input
value (the procedure body) in single quotation marks because the wrap_nzplsql()
built-in procedure takes the text as it would be specified for a CREATE OR
REPLACE PROCEDURE command. An example follows:
TEST.TESTSCH(USR)=> CALL wrap_proc(CREATE OR REPLACE PROCEDURE customer()
RETURNS INT4 LANGUAGE NZPLSQL AS,
BEGIN_PROC
BEGIN
RAISE NOTICE The customer name is alpha;
END;
END_PROC);
NOTICE: CREATE OR REPLACE PROCEDURE customer() RETURNS INT4 LANGUAGE
NZPLSQL
ASTlpQU1FMV1JBUDEwWWk5NUhrQzVhR0xyRFRxTWR3VE5sQT09JEdFQ1B5LzVkSU1KMTI
1a0dUK3NTWjlkb3ZGL3ZHalhpVExPVG5UajRkK3gxSkxvZVhKejdZQmJOVHN0aU1waFRlb
mhoaWtYdHJUTVkKUUNrWDY5Nko5Rms2NlBIYUxra21xeWNZYXdWclBCQT0=;
When you call an obfuscated procedure, the system uses internal routines to
read the obfuscated body text and run the procedure. The behavior and output
of the obfuscated procedure is identical to a cleartext version of the procedure, for
example:
TEST.TESTSCH(USR)=> CALL customer();
NOTICE: The customer name is alpha
customer
----------
(1 row)
The wrap_nzplsql() built-in procedure generates the obfuscated body text, which
you can input directly to a CREATE OR REPLACE PROCEDURE command, as
follows:
TEST.TESTSCH(USR)=> CREATE OR REPLACE PROCEDURE customer() RETURNS INT4
LANGUAGE NZPLSQL AS
TlpQU1FMV1JBUDEwVE5jZlh5TnpYbndCNkV5VFFMRTBiQT09JGE5N2p6ZEdJSVZwTTRrW
mRRM0I3WmUxZERZeWd6YkdjTWkxTzQrL1dCMmpqRGQvak9lUzFQQjArNGdlM08yZVdxUjR
IMTFaTnROUmwKdk5xSm0wb1RPZz09;
CREATE PROCEDURE
As shown in the example, you must enclose the obfuscated body text in single
quotation marks for the CREATE OR REPLACE PROCEDURE command.
The return value is a CREATE OR REPLACE PROCEDURE command that you can
use in your registration script to define your stored procedure without displaying
the procedure body text to the script user.
(1 row)
Related reference:
Appendix A, SQL command reference, on page A-1
You can modify a stored procedure to change the following aspects of the
procedure:
v RETURNS value
v Execution user property (EXECUTE AS OWNER versus EXECUTE AS CALLER)
v The body of the procedure
v The owner of the procedure
You cannot change the procedure name or argument type list. You must drop the
existing procedure and create a procedure with the new name and argument type
list.
For example, the following sample commands can be used to change the
customer procedure. To change the return value type, use a command similar to
the following example:
To change the owner of the procedure to user, use a command similar to the
following example:
TEST.TESTSCH(USR)=> ALTER PROCEDURE customer() OWNER TO user ;
ALTER PROCEDURE
For example:
COMMENT ON PROCEDURE customer() IS A procedure that displays a
customer name.;
COMMENT
An IBM Netezza SQL query user can display these comments by using the nzsql
\dd <name> command switch, or the \dd switch shows all comments for all
procedures. Consider using a comment template that includes information about
the author, version, and description in the following format:
COMMENT ON PROCEDURE <procedure name> (<argument type list>) IS
Author: <name>
Version: <version>
Description: <description>;
For example:
COMMENT ON PROCEDURE customer() IS Author: bsmith
Version: 1.0 Description: A procedure that writes a customer name to
the database log file.;
To comment on a stored procedure, you must either be the Netezza admin user,
the owner of the procedure, or you must have Alter permissions for procedure
objects. For more information about COMMENT ON, see the IBM Netezza Database
Users Guide.
For example, to drop the customer procedure, use a command similar to the
following example:
DROP PROCEDURE customer();
DROP PROCEDURE
Related reference:
The DROP PROCEDURE command on page A-7
The sample output shows the return value (RESULT), the procedure name, f (false)
to indicate that this is a user-defined procedure (not a built-in or system-supplied
procedure), and the argument list for the procedure (an empty list in this example).
The command displays information for any procedures with names that begin with
the specified characters. For example, if you have two procedures named customer
and customerid, this example command displays information for both procedures.
The command also offers a VERBOSE mode that displays more information about
the procedure, including the procedure body, comments (if supplied), owner,
execution user, and other information. If the procedure is obfuscated, the
procedure body is not in clear text; it is in an unreadable format.
Related concepts:
Obfuscate the procedure body on page 3-8
Related reference:
The SHOW PROCEDURE command on page A-9
The Procedures list shows the signature, return type, owner, and creation date of
each procedure. Double-click a procedure to obtain information about the
procedure definition, or to view or manage the privileges for the procedure. For
more information about using the NzAdmin interface, see the IBM Netezza System
Administrators Guide.
Related concepts:
Call or invoke a stored procedure on page 3-10
How to execute a stored procedure on page 1-3
SQL commands for stored procedures on page 1-2
You can change the return value, execution setting, owner, and body of a
procedure, but you cannot change the name or argument list with this command.
You can add or remove the VARARGS value in an otherwise empty argument list.
To change the name or argument list of a stored procedure, you must drop the
procedure and create a procedure with the new name or argument type list.
Synopsis
ALTER PROCEDURE <name> (<args>) [ RETURNS <type>]
[ EXECUTE AS OWNER | EXECUTE AS CALLER ] [AS <procedure_body>];
ALTER PROCEDURE <name> (<args>) OWNER TO <user>;
For systems that support multiple schemas, you can specify a name in
the format schema.procedure to change a procedure in a different
schema of the current database.
args A list of input argument data types for the stored procedure. You can
also specify the VARARGS value to create a variable argument
procedure where users can input up to 64 values of any supported data
type. VARARGS is a mutually exclusive value; you cannot specify any
other arguments in the list.
You cannot change the argument list or sizes. You can remove
VARARGS from the argument list, or add it to an otherwise empty
argument list.
RETURNS <type> Specifies the type of data returned by the procedure. The <type> value
can be a IBM Netezza data type or the value REFTABLE (<table-name>)
to indicate that it returns a result set that looks like the specified table.
The table must exist, and it continues to exist after the procedure. The
table can be empty, but it must exist in the database.
EXECUTE AS If specified, the stored procedure uses the procedure owner ID for all
OWNER access control and permission checks. This is the default.
EXECUTE AS If specified, the stored procedure uses the ID of the user who called the
CALLER procedure for all access control and permission checks.
procedure_body Specifies the text or body of the procedure. The body must be enclosed
with single quotation marks or enclosed by a BEGIN_PROC/
END_PROC pair.
When you alter the procedure, you can obfuscate the body to mask the
content from users who have permission to show the procedure.
Outputs
Description
You cannot alter a stored procedure that is currently in use in an active query.
After the transaction completes for an active query, the Netezza system processes
the ALTER PROCEDURE command.
Privileges required
To alter a procedure, you must meet one of the following criteria:
v You must have the Alter privilege on the PROCEDURE object.
v You must have the Alter privilege on the specific procedure.
v You must own the procedure.
v You must be the database admin user or own the current database or the
current schema on systems that supports multiple schemas.
Common tasks
You can use the ALTER PROCEDURE command to change the execution
user ID of the procedure, its return value, or the procedure body itself.
You can also use the ALTER PROCEDURE command to change the owner
of a procedure as follows:
ALTER PROCEDURE <name> (<arguments>) OWNER TO <name>;
Usage
Inputs
The CALL and EXEC[UTE [PROCEDURE] commands take the following inputs:
Table A-4. CALL and EXEC[UTE [PROCEDURE]] inputs
Input Description
procedure_name The name of the stored procedure that you want to invoke. If you
specify only a procedure name, the system searches the current
database and schema, and then search PATH to find the procedure.
Outputs
The CALL and EXEC[UTE [PROCEDURE] commands have the following outputs:
Table A-5. CALL and EXEC[UTE [PROCEDURE]] outputs
Output Description
ERROR: This error indicates that the current user account does not have Execute
EXECUTE PROC: permission for the stored procedure.
Permission
denied.
ERROR: Function This message indicates that the user entered incorrect arguments for the
'NAME(ARGS)' stored procedure. A procedure of that name exists, but it is expecting
does not exist different input arguments.
Unable to
identify a
function that
satisfies the
argument types
Description
Privileges required
To invoke a stored procedure, you must meet one of the following criteria:
v You must have the Execute privilege on the PROCEDURE object.
v You must have the Execute privilege on the specific procedure.
v You must own the procedure.
Usage
You can also use the SELECT command to run a procedure; however, you cannot
specify a FROM clause. For example:
MYDB.MYSCH(USER)=> SELECT updateacct();
MYDB.MYSCH(USER)=> SELECT inventorysearch(umbrellas);
Synopsis
CREATE [OR REPLACE] PROCEDURE <name> (<arguments>)
RETURNS <type> [ [ EXECUTE AS OWNER | EXECUTE AS CALLER ] ] LANGUAGE
NZPLSQL AS <procedure_body>;
Inputs
If the stored procedure exists, you cannot change the name with the
CREATE OR REPLACE command.
For systems that support multiple schemas, you can specify a name in
the format schema.procedure to create a procedure in a different
schema of the current database. You cannot create a procedure in a
different database.
arguments Specifies a list of fully specified argument data types. You can also
specify the VARARGS value to create a variable argument procedure
where users can input up to 64 values of any supported data type.
VARARGS is a mutually exclusive value; you cannot specify any other
arguments in the list.
If the stored procedure exists, you cannot change the argument type list
with the CREATE OR REPLACE command. You can change some
aspects of the argument types; for example, you can change the size of
a string or the precision and scale of a numeric value. You can also
remove VARARGS from the argument list, or add it to an otherwise
empty argument list.
You can obfuscate the body to mask the content from users who have
permission to show the procedure.
Outputs
The CREATE [OR REPLACE] PROCEDURE command has the following outputs:
Table A-7. CREATE [OR REPLACE] PROCEDURE outputs
Output Description
CREATE PROCEDURE The message that the system returns if the command
is successful.
ERROR: creating procedure: The message indicates that the user does not have
permission denied. Create Procedure permission.
ERROR: User 'username' is not The system returns this message if your user account
allowed to create/drop procedures. does not have permission to create a stored
procedure.
ERROR: Synonym 'name' already The system returns this message if a synonym exists
exists with the name that you specified for the stored
procedure.
ERROR: ProcedureCreate: This error is returned when you issue a CREATE
procedure NAME already exists PROCEDURE command and a stored procedure with
with the same signature the same name and argument type list exists in the
database. Use CREATE OR REPLACE PROCEDURE
instead.
NOTICE: FunctionCreate: existing This message indicates that a stored procedure exists
UDX NAME(ARGS) differs in size with the name but has different sizes specified for
of string/numeric arguments string or numeric arguments. If you did not intend to
change the stored procedure signature, check the
signature and ensure that it is correct.
ERROR: Can't specify arguments to You cannot specify both the VARARGS value and any
a varargs procedure other argument value in the arguments list. The
VARARGS value is mutually exclusive.
When you create a stored procedure, the signature of the stored procedure (that is,
its name and argument type list) must be unique within its database. No other
stored procedure can have the same name and argument type list in the same
database.
You cannot change the stored procedure name or the argument type list with the
CREATE OR REPLACE command. You can change some aspects of the argument
types; for example, you can change the size of a string or the precision and scale of
a numeric value, and you can add or remove the VARARGS value in an otherwise
empty argument list. To change the name or argument type list of a stored
procedure, you must drop the stored procedure and then create a stored procedure
with the new name or argument type list.
You cannot replace a stored procedure that is currently in use in an active query.
After the transaction completes for an active query, the Netezza system processes
the CREATE OR REPLACE PROCEDURE command.
Privileges required
You must have Create Procedure permission to use the CREATE
PROCEDURE command. Also, if you use CREATE OR REPLACE
PROCEDURE to change a stored procedure, you must have Create
Procedure and Alter permission to change it.
Common tasks
Use the CREATE PROCEDURE command to create and become the owner
of a new stored procedure. You can use the ALTER PROCEDURE
command to change the owner of a procedure.
Usage
Synopsis
DROP PROCEDURE <name> (<arguments>)
For systems that support multiple schemas, you can specify a name in
the format schema.procedure to drop a procedure in a different schema
of the current database. You cannot drop a procedure in a different
database.
arguments A list of input arguments to uniquely identify the stored procedure.
Outputs
Description
You cannot drop a stored procedure that is currently in use in an active query.
After the transaction completes for an active query, the IBM Netezza system
processes the DROP PROCEDURE command. The stored procedure must be
defined in the current database.
Usage
Synopsis
SHOW PROCEDURE [ALL | <name>] [VERBOSE]
Inputs
Outputs
Description
Usage
To show the sample stored procedure named returntwo, use the following
command:
MYDB.SCHEMA(ADMIN)=> SHOW PROCEDURE returntwo;
RESULT | PROCEDURE | BUILTIN | ARGUMENTS
--------------------------+-----------+---------+-------------
REFTABLE(MYDB.USER.TBL) | RETURNTWO | f | (TIMESTAMP)
(1 row)
To show verbose information for the sample stored procedure named returntwo,
use the following command. The sample output is formatted to fit the page area.
MYDB.SCHEMA(ADMIN)=> SHOW PROCEDURE returntwo VERBOSE;
RESULT | PROCEDURE | BUILTIN | ARGUMENTS | OWNER | EXECUTEDASOWNER |
VARARGS | DESCRIPTION | PROCEDURESOURCE
-------------------------+-----------+---------+-------------+-------+-----------------+
--------+--------------+-----------------
REFTABLE(MYDB.USER.TBL) | RETURNTWO | f | (TIMESTAMP) | USER | t |
f |This is a sample stored procedure |
DECLARE
BEGIN
EXECUTE IMMEDIATE INSERT INTO || REFTABLENAME || values (1,1);
EXECUTE IMMEDIATE INSERT INTO || REFTABLENAME || values (2,2);
RETURN REFTABLE;
END;
(1 row)
If the stored procedure is obfuscated, the VERBOSE mode shows the obfuscated
body text, as follows:
MYDB.SCHEMA(ADMIN)=> SHOW PROCEDURE customer VERBOSE;
RESULT | PROCEDURE | BUILTIN | ARGUMENTS | OWNER | EXECUTEDASOWNER | VARARGS |
DESCRIPTION | PROCEDURESOURCE
-------------------------+-----------+---------+-------------+-------+-----------------+
--------+--------------+-----------------
BIGINT | CUSTOMER | f | () | USR | t | f |
| TlpQU1FMV1JBUDEwVE5jZlh5TnpYbndCNkV5VFFMRTBiQT09JGE5N2p6ZEdJSVZwTTRrWmRRM0I3
WmUxZERZeWd6YkdjTWkxTzQrL1dCMmpqRGQvak9lUzFQQjArNGdlM08yZVdxUjRIMTFaTnROUmwKdk5xSm0wb1RPZz
09
(1 row)
(1 row)
IBM may not offer the products, services, or features discussed in this document in
other countries. Consult your local IBM representative for information on the
products and services currently available in your area. Any reference to an IBM
product, program, or service is not intended to state or imply that only that IBM
product, program, or service may be used. Any functionally equivalent product,
program, or service that does not infringe any IBM intellectual property right may
be used instead. However, it is the user's responsibility to evaluate and verify the
operation of any non-IBM product, program, or service.
IBM may have patents or pending patent applications covering subject matter
described in this document. The furnishing of this document does not grant you
any license to these patents. You can send license inquiries, in writing, to: This
information was developed for products and services offered in the U.S.A.
For license inquiries regarding double-byte (DBCS) information, contact the IBM
Intellectual Property Department in your country or send inquiries, in writing, to:
The following paragraph does not apply to the United Kingdom or any other
country where such provisions are inconsistent with local law:
INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS
PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS
FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or
implied warranties in certain transactions, therefore, this statement may not apply
to you.
Any references in this information to non-IBM Web sites are provided for
convenience only and do not in any manner serve as an endorsement of those Web
sites. The materials at those Web sites are not part of the materials for this IBM
product and use of those Web sites is at your own risk.
IBM may use or distribute any of the information you supply in any way it
believes appropriate without incurring any obligation to you.
IBM Corporation
Software Interoperability Coordinator, Department 49XA
3605 Highway 52 N
Rochester, MN 55901
U.S.A.
The licensed program described in this document and all licensed material
available for it are provided by IBM under terms of the IBM Customer Agreement,
IBM International Program License Agreement or any equivalent agreement
between us.
All statements regarding IBM's future direction or intent are subject to change or
withdrawal without notice, and represent goals and objectives only.
All IBM prices shown are IBM's suggested retail prices, are current and are subject
to change without notice. Dealer prices may vary.
This information contains examples of data and reports used in daily business
operations. To illustrate them as completely as possible, the examples include the
names of individuals, companies, brands, and products. All of these names are
fictitious and any similarity to the names and addresses used by an actual business
enterprise is entirely coincidental.
COPYRIGHT LICENSE:
your company name) (year). Portions of this code are derived from IBM Corp.
Sample Programs.
If you are viewing this information softcopy, the photographs and color
illustrations may not appear.
Trademarks
IBM, the IBM logo, ibm.com and Netezza are trademarks or registered trademarks
of International Business Machines Corporation in the United States, other
countries, or both. If these and other IBM trademarked terms are marked on their
first occurrence in this information with a trademark symbol ( or ), these
symbols indicate U.S. registered or common law trademarks owned by IBM at the
time this information was published. Such trademarks may also be registered or
common law trademarks in other countries. A current list of IBM trademarks is
available on the web at "Copyright and trademark information" at
http://www.ibm.com/legal/copytrade.shtml.
Microsoft, Windows, Windows NT, and the Windows logo are trademarks of
Microsoft Corporation in the United States, other countries, or both.
UNIX is a registered trademark of The Open Group in the United States and other
countries.
Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other
names may be trademarks of their respective owners.
Red Hat is a trademark or registered trademark of Red Hat, Inc. in the United
States and/or other countries.
D-CC, D-C++, Diab+, FastJ, pSOS+, SingleStep, Tornado, VxWorks, Wind River,
and the Wind River logo are trademarks, registered trademarks, or service marks
of Wind River Systems, Inc. Tornado patent pending.
APC and the APC logo are trademarks or registered trademarks of American
Power Conversion Corporation.
Notices C-3
C-4 IBM Netezza Stored Procedures Developer's Guide
Index
Special characters control structures 2-17
COUNT method, array variables 2-10
generic procedures
ANY keyword 3-6
$var variable 2-6 CREATE OR REPLACE PROCEDURE input arguments 3-6
%, used in message formats 2-22 command A-5 registering 3-7
%ROWTYPE attribute[ROWTYPE generic arguments example 3-7 generic return value 3-7
attribute] 2-5 using 3-4 GRANT ALL command, create
%TYPE attribute[TYPE attribute] 2-5 cross-database access, to stored permission 3-1
procedures 1-4 GRANT command
alter permission 3-1
A create permission 3-1
account permissions, managing 3-1 D drop permission 3-1
execute permission 3-1
admin user, permissions 3-1 data types 2-9
aliases, for data types 2-9 DEBUG messages 2-22
ALTER PROCEDURE command A-1 declarations section, in NZPLSQL 2-1
using 3-10 DEFAULT clause, variables 2-5 H
ANY keyword 3-6 disk space problems, avoiding for large hiding the procedure body 3-8
ANY keyword, for procedure input datasets 2-27
arguments 3-6 double dash comments 2-4
arithmetic evaluations, and stored
procedures 2-12
downgrade cautions 1-7
DROP PROCEDURE command A-7
I
array variables IF statements 2-17
using 3-12
assigning a value 2-10 IF-THEN-ELSE IF statements 2-17
dropping when database is dropped 1-6
in NZPLSQL 2-10 IF-THEN-ELSE statements 2-17
dynamic queries 2-16
reference support 2-10 implicit casting
assignment statement 2-15 for procedure input values 3-6
AUTOCOMMIT ON blocks 2-3 in assignments 2-15
E in stored procedures, best
ELSE IF statements 2-17 practices 2-12
B ELSIF statements 2-17
END_PROC keyword 1-5
infinite loop, handling 2-28
iterative control 2-19
backups, and stored procedures 1-6 error handling, in NZPLSQL 2-23
BEGIN_PROC keyword 1-5 errors, raising 2-22
best practices, stored procedures 1-3
block comments 2-4
EXCEPTION messages 2-22
EXCEPTION statement 2-23
L
block quoting support 1-5 labels, used to identify variables 2-7
EXEC command, using 3-10
block structured language 2-1 large datasets, managing 2-27
execute as caller permissions 1-3
block, in NZPLSQL 2-1 LAST_OID variable 2-17
execute as owner permissions 1-3
loop processing 2-28
EXECUTE command A-3
LOOP statement 2-19
using 3-10
C EXECUTE IMMEDIATE statement 2-16
loops
infinite, handling 2-28
CALL command EXECUTE PROCEDURE command,
iterate over integer count 2-19
discarding results 2-16 using 3-10
repeating while true 2-19
example 3-10 EXIT statement 2-19
terminating 2-19
usage A-3 expressions
unconditional 2-19
call recursion limit 2-16 in NZPLSQL 2-11
casting string processing best practices 2-16
impact on stored procedures 2-12 EXTEND method, array variables 2-10
input values to match signature M
sizes 3-6 massively parallel processing (MPP),
COMMENT ON PROCEDURE command, F designing procedures for 2-28
message levels, types of 2-22
using 3-11 FOR IN loop statement 2-21
comments messages, reporting 2-22
FOR loop, iteration step count 2-19
best practices 3-11 FOR statement 2-19
in NZPLSQL 2-4 FOR-IN EXECUTE statement 2-21
conditional control 2-17 fully-qualified object names, for stored N
CONSTANT option, variables 2-5 procedures 1-4 Netezza SQL commands
constants, in NZPLSQL 2-5 for stored procedures 1-2
control statements reference A-1
conditional 2-17
IF-THEN statements 2-17 G NOT NULL option, variables 2-5
NOTICE messages 2-22
iterative 2-19 generic arguments, benefits of 3-6
Printed in USA