* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download IBM Netezza Stored Procedures Developer`s Guide
Survey
Document related concepts
Transcript
IBM Netezza Release 7.1 IBM Netezza Stored Procedures Developer's Guide IBM Netezza Release 7.1 IBM Netezza Stored Procedures Developer's Guide Note Before using this information and the product it supports, read the information in “Notices” on page C-1 Revised: January 10, 2014 This edition applies to IBM Netezza Release 7.1 and to all subsequent releases until otherwise indicated in new editions. © Copyright IBM Corporation 2009, 2014. US Government Users Restricted Rights – Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. Contents Electronic emission notices . . . . . . . . . . . . . . . . . . . . . . . . . . . v Regulatory and compliance . . . . . . . . . . . . . . . . . . . . . . . . . . . ix About this publication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi If you need help . . . . . How to send your comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi . xi Chapter 1. Introduction to stored procedures . . . . . . . . . . . . . . . . . . . 1-1 Stored procedures . . . . . . . . . . . . . . . . . NZPLSQL language . . . . . . . . . . . . . . . SQL commands for stored procedures . . . . . . . . . Stored procedures input and return types . . . . . . . . How to create and use a stored procedure . . . . . . . . . How to execute a stored procedure . . . . . . . . . . . Best practices for stored procedure developers . . . . . . . Security considerations . . . . . . . . . . . . . . Cross-database access to stored procedures . . . . . . . Block quoting support . . . . . . . . . . . . . . SQL restrictions within the stored procedure . . . . . . . Best practices for Netezza administrators . . . . . . . . . Back up and restore stored procedures . . . . . . . . . Upgrade and patch Netezza systems that have stored procedures Downgrade Netezza systems that have stored procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1-1 1-2 1-2 1-2 1-3 1-3 1-3 1-3 1-4 1-5 1-6 1-6 1-6 1-7 1-7 Chapter 2. NZPLSQL statements and grammar . . . . . . . . . . . . . . . . . . 2-1 NZPLSQL structure . . . . . . . . . . . . . . Transaction commits and rollbacks in stored procedures . AUTOCOMMIT ON blocks . . . . . . . . . . . Comments . . . . . . . . . . . . . . . . . Variables and constants . . . . . . . . . . . . . Parameter passing . . . . . . . . . . . . . . Argument list and variables . . . . . . . . . . Scope of variables . . . . . . . . . . . . . . Data types and aliases . . . . . . . . . . . . Array variables . . . . . . . . . . . . . . . Expressions . . . . . . . . . . . . . . . . . Literals and math operations in expressions . . . . . Statements . . . . . . . . . . . . . . . . . Assignment. . . . . . . . . . . . . . . . Call another procedure . . . . . . . . . . . . Run dynamic queries . . . . . . . . . . . . Obtain other results status . . . . . . . . . . . Return from a procedure . . . . . . . . . . . Control Structures . . . . . . . . . . . . . . Conditional control . . . . . . . . . . . . . Iterative control . . . . . . . . . . . . . . Records . . . . . . . . . . . . . . . . . . Declaration . . . . . . . . . . . . . . . . Assignments . . . . . . . . . . . . . . . Iterate through the records of a query . . . . . . . Report messages and raise errors . . . . . . . . . Exceptions and error messages support . . . . . . . Return a result set . . . . . . . . . . . . . . © Copyright IBM Corp. 2009, 2014 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-1 . 2-2 . 2-3 . 2-4 . 2-5 . 2-6 . 2-6 . 2-7 . 2-9 . 2-10 . 2-11 . 2-12 . 2-15 . 2-15 . 2-16 . 2-16 . 2-17 . 2-17 . 2-17 . 2-17 . 2-19 . 2-20 . 2-20 . 2-20 . 2-21 . 2-22 . 2-23 . 2-25 iii REFTABLE and ROLLBACK commands . . Manage large data sets . . . . . . . . Advanced development topics . . . . . . Extend the NZPLSQL language with UDFs . Tips and best practices for stored procedures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-27 2-27 2-28 2-28 2-28 Chapter 3. Create and manage stored procedures . . . . . . . . . . . . . . . . . 3-1 Manage user account permissions. . . . . . . . . . Create a stored procedure . . . . . . . . . . . . Design a stored procedure . . . . . . . . . . . Create a stored procedure . . . . . . . . . . . Size-specific, generic, and variable argument procedures . Obfuscate the procedure body . . . . . . . . . . Call or invoke a stored procedure . . . . . . . . . Alter a stored procedure . . . . . . . . . . . . Comment on a stored procedure . . . . . . . . . . Drop a stored procedure . . . . . . . . . . . . Show information about a stored procedure . . . . . . NzAdmin administrative interface for stored procedures. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3-1 . 3-4 . 3-4 . 3-4 . 3-5 . 3-8 . 3-10 . 3-10 . 3-11 . 3-12 . 3-12 . 3-12 Appendix A. SQL command reference . . . . . . . . . . . . . . . . . . . . . . A-1 The ALTER PROCEDURE command . . . . . . The CALL and EXEC[UTE [PROCEDURE]] commands The CREATE [OR REPLACE] PROCEDURE commands The DROP PROCEDURE command . . . . . . . The SHOW PROCEDURE command . . . . . . Appendix B. Stored procedure examples Variable argument stored procedure . . . . Example of simulating an anonymous block . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A-1 A-3 A-5 A-7 A-9 . . . . . . . . . . . . . . . . . . . . B-1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B-1 . B-2 Notices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-1 Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C-3 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . X-1 iv IBM Netezza Stored Procedures Developer's Guide Electronic emission notices When you attach a monitor to the equipment, you must use the designated monitor cable and any interference suppression devices that are supplied with the monitor. Federal Communications Commission (FCC) Statement 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. Industry Canada Class A Emission Compliance Statement This Class A digital apparatus complies with Canadian ICES-003. Avis de conformité à la réglementation d'Industrie Canada Cet appareil numérique de la classe A est conforme à la norme NMB-003 du Canada. Australia and New Zealand Class A Statement This product is a Class A product. In a domestic environment, this product might cause radio interference in which case the user might be required to take adequate measures. European Union EMC Directive Conformance Statement This product is in conformity with the protection requirements of EU Council Directive 2004/108/EC on the approximation of the laws of the Member States relating to electromagnetic compatibility. IBM cannot accept responsibility for any failure to satisfy the protection requirements resulting from a nonrecommended modification of the product, including the fitting of non-IBM option cards. © Copyright IBM Corp. 2009, 2014 v This product is an EN 55022 Class A product. In a domestic environment, this product might cause radio interference in which case the user might be required to take adequate measures. Responsible manufacturer: International Business Machines Corp. New Orchard Road Armonk, New York 10504 914-499-1900 European Community contact: IBM Technical Regulations, Department M456 IBM-Allee 1, 71137 Ehningen, Germany Telephone: +49 7032 15-2937 Email: [email protected] Germany Class A Statement Deutschsprachiger EU Hinweis: Hinweis für Geräte der Klasse A EU-Richtlinie zur Elektromagnetischen Verträglichkeit Dieses Produkt entspricht den Schutzanforderungen der EU-Richtlinie 2004/108/EG zur Angleichung der Rechtsvorschriften über die elektromagnetische Verträglichkeit in den EUMitgliedsstaaten und hält die Grenzwerte der EN 55022 Klasse A ein. Um dieses sicherzustellen, sind die Geräte wie in den Handbüchern beschrieben zu installieren und zu betreiben. Des Weiteren dürfen auch nur von der IBM empfohlene Kabel angeschlossen werden. IBM übernimmt keine Verantwortung für die Einhaltung der Schutzanforderungen, wenn das Produkt ohne Zustimmung der IBM verändert bzw. wenn Erweiterungskomponenten von Fremdherstellern ohne Empfehlung der IBM gesteckt/eingebaut werden. EN 55022 Klasse A Geräte müssen mit folgendem Warnhinweis versehen werden: “Warnung: Dieses ist eine Einrichtung der Klasse A. Diese Einrichtung kann im Wohnbereich Funk-Störungen verursachen; in diesem Fall kann vom Betreiber verlangt werden, angemessene Maßnahmen zu ergreifen und dafür aufzukommen.” Deutschland: Einhaltung des Gesetzes über die elektromagnetische Verträglichkeit von Geräten Dieses Produkt entspricht dem “Gesetz über die elektromagnetische Verträglichkeit von Geräten (EMVG)”. Dies ist die Umsetzung der EU-Richtlinie 2004/108/EG in der Bundesrepublik Deutschland. Zulassungsbescheinigung laut dem Deutschen Gesetz über die elektromagnetische Verträglichkeit von Geräten (EMVG) (bzw. der EMC EG Richtlinie 2004/108/EG) für Geräte der Klasse A Dieses Gerät ist berechtigt, in Übereinstimmung mit dem Deutschen EMVG das EG-Konformitätszeichen - CE - zu führen. Verantwortlich für die Einhaltung der EMV Vorschriften ist der Hersteller: vi IBM Netezza Stored Procedures Developer's Guide International Business Machines Corp. New Orchard Road Armonk, New York 10504 914-499-1900 Der verantwortliche Ansprechpartner des Herstellers in der EU ist: IBM Deutschland Technical Regulations, Department M456 IBM-Allee 1, 71137 Ehningen, Germany Telephone: +49 7032 15-2937 Email: [email protected] Generelle Informationen: Das Gerät erfüllt die Schutzanforderungen nach EN 55024 und EN 55022 Klasse A. Japan VCCI Class A Statement 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. Japan Electronics and Information Technology Industries Association (JEITA) Statement Japan Electronics and Information Technology Industries Association (JEITA) Confirmed Harmonics Guidelines (products less than or equal to 20 A per phase) Japan Electronics and Information Technology Industries Association (JEITA) Statement Japan Electronics and Information Technology Industries Association (JEITA) Confirmed Harmonics Guidelines (products greater than 20 A per phase) Electronic emission notices vii Korea Communications Commission (KCC) Statement 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. Russia Electromagnetic Interference (EMI) Class A Statement People's Republic of China Class A Electronic Emission Statement Taiwan Class A Compliance Statement viii IBM Netezza Stored Procedures Developer's Guide Regulatory and compliance Regulatory Notices 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. Provide approved circuit breakers on all power sources. Product might be powered by redundant power sources. Disconnect ALL power sources before servicing. High leakage current. Earth connection essential before connecting supply. Courant de fuite élevé. Raccordement à la terre indispensable avant le raccordement au réseau. 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. © Copyright IBM Corp. 2009, 2014 ix x IBM Netezza Stored Procedures Developer's Guide About this publication 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. 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. If you need help If you are having trouble using the IBM Netezza appliance, follow these steps: 1. Try the action again, carefully following the instructions for that task in the documentation. 2. Go to the IBM Support Portal at: http://www.ibm.com/support. Log in using your IBM ID and password. You can search the Support Portal for solutions. To submit a support request, click the Service Requests & PMRs tab. 3. If you have an active service contract maintenance agreement with IBM, you can contact customer support teams by telephone. For individual countries, visit the Technical Support section of the IBM Directory of worldwide contacts (http://www.ibm.com/support/customercare/sas/f/handbook/contacts.html). How to send your comments You are encouraged to send any questions, comments, or suggestions about the IBM Netezza documentation. Send an email to [email protected] and include the following information: v The name and version of the manual that you are using v Any comments that you have about the manual v Your name, address, and phone number We appreciate your suggestions. © Copyright IBM Corp. 2009, 2014 xi xii IBM Netezza Stored Procedures Developer's Guide Chapter 1. Introduction to stored procedures This section provides an overview of the support for stored procedures in the IBM Netezza family of data warehouse appliances. 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. While such an application can be managed with a third-party business application that accesses the Netezza database to do these tasks, you can also use Netezza stored procedures to encapsulate this application as an object in the Netezza database. SQL provides the power to access and update the database information about the host, and the procedure language provides the logic for if-then-else branching and application processing. 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. © Copyright IBM Corp. 2009, 2014 1-1 NZPLSQL language You implement stored procedures on the IBM Netezza host by creating applications by using the NZPLSQL language. NZPLSQL is an interpreted language which is based on Postgres PL/pgSQL language and designed for the Netezza host environment. NZPLSQL is a scripting language embedded in SQL. As a procedural language, it has branch, loop, and subprogram structures while SQL provides the main program. The subprograms, known as procedures, can take arguments and declare internal variables. After they are stored in a database, these procedures can be called from within other databases on the same Netezza host. 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) SQL commands for stored procedures To support stored procedures in the IBM Netezza database, the Netezza SQL language includes commands for stored procedures: v v v v v ALTER PROCEDURE CALL or EXEC[UTE[ PROCEDURE]] CREATE [OR REPLACE] PROCEDURE DROP PROCEDURE SHOW PROCEDURE 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 Stored procedures input and return types IBM Netezza stored procedures are a hybrid between functions and procedures (as defined by the SQL:2003 standard for SQL-invoked routines). In the Netezza implementation, an NZPLSQL stored procedure takes only input arguments and supports a return value as functions do. Unlike functions, a stored procedure must 1-2 IBM Netezza Stored Procedures Developer's Guide be called by using CALL or a similar construct, and it is not allowed in the usual query locations where a built-in or standard function is allowed. A stored procedure can also be designed to return a result set. For more information, see “Return a result set” on page 2-25. How to create and use a stored procedure As a high-level summary, follow these steps to create and use a stored procedure. These steps are described in more detail in Chapter 3, “Create and manage stored procedures,” on page 3-1 1. Design the stored procedure logic and operation. 2. Define the stored procedure object by using the CREATE [OR REPLACE] PROCEDURE command. 3. Run or execute the procedure from the SQL command prompt. 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 How to execute a stored procedure You execute a stored procedure in the SQL command by using either the CALL or EXEC[UTE[ PROCEDURE]] commands. For example, if you have a stored procedure named updateacct(), you can run it by using any of the following commands: MYDB.SCHEMA(USER)=> MYDB.SCHEMA(USER)=> MYDB.SCHEMA(USER)=> MYDB.SCHEMA(USER)=> CALL updateacct(); EXEC updateacct(); EXECUTE updateacct(); EXECUTE PROCEDURE updateacct(); 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 Best practices for stored procedure developers The following sections describe some best practices for users who develop stored procedures. 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 Chapter 1. Introduction to stored procedures 1-3 stored procedure or the ID of the user who runs the procedure. The user account adds an additional layer of security (or expanded access) for the data that is processed by the stored procedure. 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. Cross-database access to stored procedures When you create a stored procedure by using the CREATE [OR REPLACE] PROCEDURE command, the command adds the procedure to the database and schema to which you are connected. You can access the procedure while connected to the database where the stored procedure is defined, and you can also run procedures in other schemas in the same database, or in other databases using the following methods: v Using fully-qualified object names when calling a procedure object that resides within a different database, for example: MYDB.SCHEMA(ADMIN)=> EXEC OTHERDB.SCHEMA.UPDATEACCT(); v Using a schema.object name when calling a procedure object that resides within a different schema of the same database, for example: MYDB.SCHEMA(ADMIN)=> EXEC SCH_TWO.UPDATEACCT(); v Using the PATH SQL session variable to specify the databases and/or schemas to search to find a procedure name that is not fully qualified. To use the PATH session variable, you enter a command similar to the following: MYDB.SCHEMA(ADMIN)=> SET PATH = <elem> [, <elem>]; The <elem> value can be a database, a schema, or the variables CURRENT_CATALOG, CURRENT_USER, CURRENT_SCHEMA, or CURRENT_PATH. Anything you specify as <elem> must resolve to a database name. For example: MYDB.SCHEMA(ADMIN)=> SET PATH = mydb, nzdb, customer; SET VARIABLE To display the PATH value, use the following command: MYDB.SCHEMA(ADMIN)=> SELECT CURRENT_PATH; CURRENT_PATH -----------------MYDB,NZDB,CUSTOMER (1 row) 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 1-4 IBM Netezza Stored Procedures Developer's Guide potential matches. Also, the Netezza system uses the PATH session variable to find only stored procedures, user-defined functions (UDFs), and user-defined aggregates (UDAs). Other object types such as tables, sequences, and so on, are not supported. If a stored procedure is invoked from a different database, unqualified objects bind to objects in the invoking database, not in the database where the stored procedure is defined. Unqualified stored procedures, UDFs, and UDAs are exceptions to this rule because the Netezza system first uses the PATH variable to search for those three object types before it searches within the invoking database. 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. Block quoting support Stored procedures are defined as a block or body of numerous lines of text. IBM Netezza provides a block-quoting mechanism to help ease the definition of the procedure body and to make the content more readable for debugging and learning. A section of text bounded by BEGIN_PROC and END_PROC is a block quote. The following is an example: CREATE OR REPLACE PROCEDURE name() RETURNS INT4 LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE string varchar; BEGIN string := ’This string is quoted’; END; END_PROC; 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'). Chapter 1. Introduction to stored procedures 1-5 Both BEGIN_PROC and END_PROC can appear inside a single or double-quoted string in normal SQL statements if the SQL statements are not inside a block quote. For example: select "BEGIN_PROC" from <table>; insert into <table> values (’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; Because nested BEGIN_PROC and END_PROC keywords have no quoting implications, the following example is not supported: CREATE OR REPLACE PROCEDURE name() RETURNS INT4 LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE string varchar; BEGIN -- The next statement is a syntax error since it is not quoted string := BEGIN_PROC This string is not quoted END_PROC; END; END_PROC; Related concepts: “Obfuscate the procedure body” on page 3-8 SQL restrictions within the stored procedure Within the body of a stored procedure, you can use most SQL commands to do the tasks that relate to database objects. 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 User’s Guide. Best practices for Netezza administrators The following topics describe some best practices for IBM Netezza administrators who manage Netezza systems that have stored procedures. Back up and restore stored procedures Any stored procedures that you create are backed up and restored by the IBM Netezza backup and restore operations. If you back up and restore obfuscated procedures, those restored procedures remain obfuscated. If you restore a database 1-6 IBM Netezza Stored Procedures Developer's Guide to a system that is running a release which does not support obfuscated procedures or VARARGS, for example, those procedures will not run and the queries that use them will return a syntax error. 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. Upgrade and patch Netezza systems that have stored procedures There are no special requirements or procedures necessary to preserve any stored procedures during an NPS upgrade to a new release. The stored procedures continue to operate in the same manner on the upgraded system as on the previous release. 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. Downgrade Netezza systems that have stored procedures If you downgrade your Netezza release, the stored procedures should continue to work after the downgrade. If the downgrade release does not support all the NZPLSQL features of the later release, any procedures that use those features will fail when executed after the downgrade. You can drop or alter those procedures to ensure that they conform to the NZPLSQL language support of the Netezza release that your system is running. Chapter 1. Introduction to stored procedures 1-7 1-8 IBM Netezza Stored Procedures Developer's Guide Chapter 2. NZPLSQL statements and grammar This section describes the NZPLSQL language, its structure, and how to use the language to create stored procedures. NZPLSQL is similar to the Postgres PL/pgSQL language. Some of the language descriptions in this section use the Postgres PL/pgSQL documentation. However, NZPLSQL has some differences that are based on the design and environment of the IBM Netezza system. NZPLSQL also includes some extensions to assist users who migrate stored procedures that are written in other languages to the Netezza environment. NZPLSQL structure The NZPLSQL language is a block-structured language. A block is defined as follows: << label >> [DECLARE declarations] BEGIN [AUTOCOMMIT ON|OFF] statements exception_handlers END; 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. The BEGIN statement specifies the start of a block, or a group of statements, within the body of the procedure. By default, a BEGIN statement operates in AUTOCOMMIT OFF mode, which causes the procedure to execute all the statements inside the block as one multi-statement transaction. Within the block, you can use most of the SQL commands that you can use at the SQL command line, but you cannot use the SQL commands that are prohibited for use within a SQL BEGIN/COMMIT transaction block. 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 © Copyright IBM Corp. 2009, 2014 2-1 established by an outer query; they cannot start or commit transactions, since IBM Netezza SQL does not have nested transactions. 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. Transaction commits and rollbacks in stored procedures The behavior of a stored procedure depends on whether it is called as a singleton SQL statement or within a SQL transaction block. 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); If the procedure issues a COMMIT or ROLLBACK statement within the procedure body, all changes made before the transaction statement are committed or rolled back, and the system implicitly starts a new transaction. All statements after the transaction command continue to run as a single multi-statement command, not as individual commands inside of a transaction block. When the stored procedure exits, any uncommitted changes are committed or rolled back as they would be with a stored procedure call before this change. A sample procedure called test3 follows. CREATE PROCEDURE TEST3() LANGUAGE NZPLSQL RETURNS INT AS BEGIN_PROC BEGIN statement1; COMMIT; statement2; statement3; RETURN 1234; END; END_PROC; 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. 2-2 IBM Netezza Stored Procedures Developer's Guide BEGIN; execute test3(); ROLLBACK; 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. Remember that if a BEGIN statement starts a transaction block before calling a stored procedure, the stored procedure always returns with an active transaction block, and you must issue a COMMIT or ROLLBACK statement to complete or abort that transaction. Even in the case where an exception causes the stored procedure to abort, you must still use COMMIT or ROLLBACK after the procedure exits. 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. An example of an AUTOCOMMIT block follows. CREATE PROCEDURE TEST4() LANGUAGE NZPLSQL RETURNS BOOLEAN BEGIN_PROC BEGIN AUTOCOMMIT ON GROOM TABLE MYTBL; RETURN TRUE; EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'ERROR: %', SQLERRM; RETURN FALSE; END; Note: Executing transactional statements such as COMMIT or ROLLBACK inside an AUTOCOMMIT ON block has no effect because those commands commit or roll back only their own statement. All previous statements are already committed. There is an implied COMMIT at the beginning of the AUTOCOMMIT ON block before any statement in the block is executed. Any exception that is raised by a command inside an AUTOCOMMIT ON block calls the exception block, in the same manner as a normal NZPLSQL statement block. The behavior of statements in an exception block attached to an AUTOCOMMIT ON block is based on the AUTOCOMMIT ON/OFF status of the parent block. If Chapter 2. NZPLSQL statements and grammar 2-3 an AUTOCOMMIT ON sub-block occurs within an AUTOCOMMIT ON block, the statements in the exception block are executed as singletons unless you issue a BEGIN within the exception block to change the behavior. 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; When an AUTOCOMMIT ON block is nested inside of an AUTOCOMMIT OFF block, an implicit commit occurs before the first statement is executed inside of the AUTOCOMMIT ON block and then an implicit commit occurs after each statement inside of the AUTOCOMMIT ON block. When an AUTOCOMMIT OFF block is nested inside of an AUTOCOMMIT ON block, the statements within the AUTOCOMMIT OFF block are executed as a multi statement transaction that is immediately committed at the end of the block. BEGIN AUTOCOMMIT ON BEGIN AUTOCOMMIT OFF Statement1; Statement2; END; /* an implicit commit occurs here */ END; Exception blocks for an AUTOCOMMIT ON block are executed if any of the statements within the AUTOCOMMIT ON block fails. Unlike a normal exception block, there is no need to issue a ROLLBACK inside an AUTOCOMMIT ON exception block. The statement that failed is automatically rolled back and a new transaction is immediately started before processing any statements in the exception block. 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. */ 2-4 IBM Netezza Stored Procedures Developer's Guide Block comments cannot be nested, but double dash comments can be enclosed in a block comment. A double dash comment can “hide” the block comment delimiters /* and */. Variables and constants All of the variables, rows, and records that are used in a block or its sub-blocks must be declared in the declarations section of a block. There are some exceptions, namely the loop variable of a FOR loop that iterates over a range of integer values, and some built-in variables like FOUND, ROW_COUNT, and LAST_OID. 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; A variable declaration has the following syntax: name [ CONSTANT ] type [ NOT NULL ] [ { DEFAULT | := } value ]; v The DEFAULT clause, if included, specifies the initial value assigned to the variable when the block is entered. If a DEFAULT clause is not specified, the variable uses the SQL NULL value as its default. v The CONSTANT option means that the variable cannot be changed; its value remains constant for the duration of the block. v If NOT NULL is specified, an assignment of a NULL value results in a runtime error. Since the default value of all variables is the SQL NULL value, all variables declared as NOT NULL must also specify a non-null default value. When specifying types in declarations, NUMERIC can be specified with or without a precision and scale. CHAR, NCHAR, VARCHAR, and NVARCHAR can be specified with or without a size. When these types are specified with a size or a precision/scale, assignment to the variable follows normal cast rules. If they are specified without sizes, assignment preserves the original source size or precision/scale. 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. Some examples of variable assignments follow: quantity INTEGER := 32; url varchar := ’http://mysite.com’; user_id CONSTANT INTEGER := 10; 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; Chapter 2. NZPLSQL statements and grammar 2-5 By using %TYPE, you do not have to know the data type of the structure that you are referencing. Also, if the data type of the referenced item changes in the future (for example, you change your table definition of user_id to become a REAL), you do not have to change your procedure definition. You can declare a row with the structure of a table, as follows: name table%ROWTYPE; 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. To name parameters, use the ALIAS FOR syntax. For example: CREATE OR REPLACE PROCEDURE p1 (int, varchar(ANY)) RETURNS int LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE pId ALIAS FOR $1; pName ALIAS FOR $2; BEGIN INSERT INTO t1 SELECT * FROM t2 WHERE id = pId; The example highlights the recommended convention to name parameters with a “p” prefix to differentiate them from variables. This convention is helpful because parameters are constant and cannot be modified. If a parameter must be updated (for example, to assign it a default value if it is null), assign the parameter to a variable and update the variable. For example: DECLARE pId ALIAS FOR $1; vID integer; BEGIN vId := ISNULL(pId, 0); INSERT INTO t1 SELECT * FROM t2 WHERE id = vId; Argument list and variables The arguments passed as input to procedures can be identified by using the names $1 (first argument), $2 (second argument), and so on. You can also use the $var notation, which takes the integer value of var to identify the input value specified in that order position. 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. IBM Netezza saves the OIDs of the input arguments in the PROC_ARGUMENT_TYPES array. The array has the same size as the number of parameters that are passed to the stored procedure. Its elements are of type OID and contain the OID type of the corresponding input argument. You can use the array to obtain the number and type of each argument. 2-6 IBM Netezza Stored Procedures Developer's Guide For example: CREATE OR REPLACE PROCEDURE test(VARARGS) RETURNS INT4 LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE num_args int4; typ oid; idx int4; BEGIN num_args := PROC_ARGUMENT_TYPES.count; RAISE NOTICE ’Number of arguments: %’, num_args; for i IN 0 .. PROC_ARGUMENT_TYPES.count - 1 LOOP typ := PROC_ARGUMENT_TYPES(i); idx := i+1; RAISE NOTICE ’argument $% is type % and has the value ’’%’’’, idx, typ, $idx; END LOOP; END; END_PROC; A sample call follows: MYDB.SCHEMA(USR2)=> CALL TEST (1, 3, 9::bigint, ’test value’, 324.56); NOTICE: Number of arguments: 5 NOTICE: argument $1 is type 23 and has the value ’1’ NOTICE: argument $2 is type 23 and has the value ’3’ NOTICE: argument $3 is type 20 and has the value ’9’ NOTICE: argument $4 is type 705 and has the value ’test value’ NOTICE: argument $5 is type 1700 and has the value ’324.56’ test -----(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; Chapter 2. NZPLSQL statements and grammar 2-7 In this example, the block labels inner and outer can be used to identify a specific val variable by using its fully qualified variable name. If you create this procedure as a stored procedure and run it, you would see output similar to the following: MYDB.SCHEMA(USER)=> call vals(); NOTICE: inner val != outer val 7 5 NOTICE: outer val is 5 5 VALS -----(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; The following is sample output for this stored procedure: MYDB.SCHEMA(USER)=> call vals(); NOTICE: inner val != outer val 7 5 NOTICE: The value of val is 1 NOTICE: The value of val is 2 NOTICE: The value of val is 3 NOTICE: The value of val is 4 NOTICE: The value of val is 5 NOTICE: The value of val is 6 NOTICE: The value of val is 7 NOTICE: The value of val is 8 NOTICE: The value of val is 9 NOTICE: The value of val is 10 NOTICE: inner val is still 7. Value 7 NOTICE: inner val is still 5. Value 5 VALS -----(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 2-8 IBM Netezza Stored Procedures Developer's Guide Data types and aliases The following table lists the supported data types by their preferred name form, and includes supported aliases and some notes about the values. For more information about the data types and values, see the IBM Netezza Database User’s Guide. Table 2-1. Supported data types for variables Data type Alias names Notes BOOLEAN BOOL A boolean field can store true values, false values, and null. You can use the following words to specify booleans: v true or false v on or off v ‘0’ or ‘1’ v 'true’ or ‘false’ v ‘t’ or ‘f’ v ‘on’ or ‘off’ v ‘yes’ or ‘no’ CHAR CHARACTER, CHAR(n), CHARACTER(n) Fixed-length character string, blank padded to length n. If you do not specify n, the default is an unsized CHAR value. The maximum character string size is 64,000. VARCHAR CHARACTER VARYING, VARCHAR(n), CHARACTER VARYING(n), CHAR VARYING(n) Variable length character string to a maximum length of n. If you do not specify n, the default is an unsized VARCHAR value. There is no blank padding, and the value is stored as entered. The maximum character string size is 64,000. NCHAR NATIONAL CHARACTER, NATIONAL CHAR(n), NCHAR(size) Fixed-length character string, blank padded to length n. If you do not specify n, the default is an unsized NCHAR value. The maximum length is 16,000 characters. NVARCHAR Variable length character string to a maximum length of n. If you do not NATIONAL specify n, the default is an unsized NVARCHAR value. The maximum CHARACTER VARYING, NATIONAL length is 16,000 characters. CHAR VARYING, NATIONAL CHAR VARYING(n), NATIONAL CHARACTER VARYING(n), and NVARCHAR(n) DATE TIMESTAMP Specifies a day with resolution that spans January 1, 0001 to December 31, 9999 (centered around 2000-01-01). DATETIME Has a date part and a time part, with seconds stored to 6 decimal positions. The value represents the number of microseconds since midnight 2000-01-01. Min: -63,082,281,600,000,000 (00:00:00, 1/1/0001) Max: 252,455,615,999,999,999 (23:59:59.999999, 12/31/9999) TIME TIME WITHOUT TIME Hours, minutes, and seconds to 6 decimal positions, ranging from ZONE 00:00:00.000000 to 23:59:59.999999. This value is microsecond resolution that represents the time of day only (midnight to one microsecond before midnight). Chapter 2. NZPLSQL statements and grammar 2-9 Table 2-1. Supported data types for variables (continued) Data type Alias names Notes INTERVAL TIMESPAN An interval of time. It has microsecond resolution and ranges from +/178000000 years. The time part represents everything but months and years (microseconds) and the month part represents months and years. For more information, see the section on IBM Netezza interval support in the IBM Netezza Database User’s Guide. TIME WITH TIME ZONE TIMETZ Hours, minutes, seconds to 6 decimal positions, and time zone offset from GMT. Ranging from 00:00:00.000000+13:00 to 23:59:59.999999-12:59. NUMERIC(p,s) NUMERIC, DEC, DEC(p,s), DECIMAL(p,s), DECIMAL Fixed-point numeric types with precision p and scale s. Precision can range from 1 to 38, scale from 0 to the precision. NUMERIC(p) is equivalent to NUMERIC(p,0). NUMERIC is an unsized numeric value. Although decimal is sometimes a distinct SQL data type, Netezza SQL treats it as an alias for NUMERIC. REAL FLOAT(p), FLOAT4 Floating point number with precision p. Precision values of 1 to 6 are equivalent to FLOAT(6), and are stored as a 4-byte value. Netezza SQL prefers the type name real, as float(p) is considered more of an alias for the preferred form. DOUBLE PRECISION DOUBLE, FLOAT, FLOAT(p), FLOAT8 Floating point number with precision p, from 7 to 15. Precision values 7 15 are equivalent to 15 and are stored as an 8-byte value. Netezza SQL prefers the type name double precision, as float(p) is considered more of an alias for the preferred form. INTEGER INT, INT4 32-bit values in range –2,147,483,648 to 2,147,483,647 BYTEINT INT1 8-bit values in the range –128 to 127 SMALLINT INT2 16-bit values in range –32,768 to 32,767 BIGINT INT8 64-bit values in range -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 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. COUNT returns the number of elements in the array. 2-10 IBM Netezza Stored Procedures Developer's Guide TRIM deletes the last size elements in the array (the default is 1). TRIM and EXTEND raise an exception if size is out of bounds. 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 In the expression, occurrences of variable identifiers are substituted by parameters and the actual values from the variables are passed to the executor in the parameter array. All expressions used in an NZPLSQL procedure are compiled and cached the first time they are encountered. Everything in NZPLSQL is cached, except for variable values and SQL plans. If there is a compile error (syntax error), the expression is not cached. The cached copy is preserved until one of the following happens: v The procedure body is modified. v The procedure is dropped. v The database session ends. 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; The second example follows: DECLARE logtxt ALIAS FOR $1; curtime timestamp; BEGIN curtime := ’now()’; INSERT INTO logtable VALUES (logtxt, curtime); RETURN curtime; 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. Chapter 2. NZPLSQL statements and grammar 2-11 In the second example, the Netezza SQL main parser does not know what type now() should become and therefore it returns a data type of text that contains the string now(). During the assignment to the local variable curtime, the NZPLSQL interpreter casts this string to the timestamp type by calling the text_out() and timestamp_in() functions for the conversion. 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. Literals and math operations in expressions If your stored procedures perform math operations in expressions, carefully consider the supported ranges for literals and the possible implicit typecasts that the IBM Netezza system might perform. These ranges and behaviors can cause unexpected results or overflow errors in complex math expressions. 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; 2-12 IBM Netezza Stored Procedures Developer's Guide If you create and run this stored procedure, the output would be similar to the following: NOTICE: NOTICE: NOTICE: n is 2147483647 n is 2147483648 n is 2147483648 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. Because arithmetic operations in a stored procedure are evaluated by invoking the backend executor, they are processed as SELECT statements. To more clearly see the calculated shape of the expression result, it can be helpful to use it to create a table, which can then be described by using the \d command. Printing the results might not provide enough insight to the resulting data types. 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) Another example follows: DEV.SCH1(ADMIN)=> create table test2 as select (4 + 1/5) loanrt; INSERT 0 1 DEV.SCH1(ADMIN)=> \d test2 Table "TEST2" Attribute | Type | Modifier | Default Value ----------+----------+----------+--------------LOANRT | INTEGER | | Distributed on hash: "LOANRT" 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: Chapter 2. NZPLSQL statements and grammar 2-13 DEV.SCH1(ADMIN)=> select * from TEST2; LOANRT -------4 (1 row) 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); 2-14 IBM Netezza Stored Procedures Developer's Guide RAISE NOTICE ’thisnum9_2 == %’, thisnum9_2; /* The following expression uses an explicit cast to increase the precision and scale of the intermediate evaluation. */ thisnum9_2 := million * (1 + 0.08::numeric(20,15)/365)^(365 * 20); RAISE NOTICE ’thisnum9_2 == %’, thisnum9_2; /* The following expression uses the numeric literal litespeed to convert the speed of light from miles per sec to miles per year. */ thisnum18 := litespeed * 60 * 60 * 24 * 365.25; RAISE NOTICE ’thisnum18 == %’, thisnum18; /* The following expression uses the integer 186282 to convert lightspeed from miles per sec to miles per year. In the right-side evaluation, however, the values overflowed the upper limit of an int several times during evaluation, which causes an overflow error. */ thisnum38 := 186282 * 60 * 60 * 24 * 365.25; RAISE NOTICE ’thisnum38 == %’, thisnum38; END; END_PROC; Sample output follows: NOTICE: thisnum9_2 == 4945731.93 NOTICE: thisnum9_2 == 4952164.15 NOTICE: thisnum18 == 5878612843200 NOTICE: Error occurred while executing PL/pgSQL function SP_EXPRESSIONS_NUMERIC02 NOTICE: line 16 at assignment ERROR: overflow in 32 bit arithmetic 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 expression’s result data type does not match the variable’s 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 type’s output-function and the variable’s type input-function. Note that this could potentially result in runtime errors generated by the type’s input functions. Several examples follow: user_id := 20; tax := subtotal * 0.06; For more information about IBM Netezza casting rules and behaviors, see the IBM Netezza Database User’s Guide. Chapter 2. NZPLSQL statements and grammar 2-15 Call another procedure All procedures defined in an IBM Netezza database return a value; the default value is NULL. Thus, the normal way to call a procedure is to run a SELECT query or to do an assignment (resulting in an NZPLSQL internal SELECT). 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 Run dynamic queries There might be times when you want to generate dynamic queries inside your NZPLSQL procedures. Or, you might have procedures that are designed to generate other procedures. For these situations, NZPLSQL provides the EXECUTE IMMEDIATE statement: EXECUTE IMMEDIATE query-string 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. A query run by an EXECUTE IMMEDIATE statement is prepared each time the statement is run. The query string can be dynamically created within the procedure to do actions on different tables and fields. 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. An example statement follows: EXECUTE IMMEDIATE ’UPDATE tbl SET’ || quote_ident(’fieldname’) || ’ = ’ || quote_literal(’newvalue’) || ’ WHERE ...’; This example demonstrates the use of the quote_ident and quote_literal functions. To ensure that strings are correctly processed for quotation marks or special characters, expressions that contain column and table identifiers should be passed to quote_ident. Expressions containing values that are literal strings in the constructed command should be passed to quote_literal. Both take the appropriate steps to return the input text enclosed in double quotation marks for quote_ident or quotation marks for quote_literal with any embedded special characters properly escaped. 2-16 IBM Netezza Stored Procedures Developer's Guide Obtain other results status There are two variables that provide system status indicators: ROW_COUNT and LAST_OID. v ROW_COUNT is the number of rows processed by the last SQL query sent down to the SQL engine. v LAST_OID is the object ID (oid) of the last row inserted by the most recent SQL query. 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 Return from a procedure Use the RETURN command to return data from a procedure. RETURN [expression] 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 All NZPLSQL IF statements require a corresponding END IF statement. In ELSE-IF statements, you need two END IF statements: one for the first IF and one for the second (ELSE IF). IF-THEN statements IF-THEN statements are the simplest form of an IF statement. The statements between THEN and END IF are executed if the condition is true. Otherwise, the statements that follow the END IF are executed. An example follows: IF v_user_id <> 0 THEN UPDATE users SET email = v_email WHERE user_id = v_user_id; END IF; Chapter 2. NZPLSQL statements and grammar 2-17 IF-THEN-ELSE 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 v_count INSERT return ELSE return END IF; > 0 THEN INTO users_count(count) VALUES(v_count); ’t’; ’f’; You can nest IF statements as in the following example: IF movies.genre = ’d’ THEN film_genre := ’drama’; ELSE IF movies.genre = ’c’ THEN film_genre := ’comedy’; END IF; 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. 2-18 IBM Netezza Stored Procedures Developer's Guide Iterative control With the LOOP, WHILE, FOR, and EXIT statements, you can control the flow of execution of your NZPLSQL program iteratively. 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 The EXIT statement terminates a loop. It has the following syntax: EXIT [ label ] [ WHEN expression ]; 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: Chapter 2. NZPLSQL statements and grammar 2-19 WHILE amount_owed > 0 AND gift_certificate_balance > 0 LOOP -- some computations here END LOOP; WHILE NOT boolean_expression LOOP -- some computations here END LOOP; 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. Some examples of FOR loops: FOR i IN 1 .. 10 LOOP -- some expressions here RAISE NOTICE ’i is %’,i; END LOOP; FOR i IN REVERSE 10 .. 1 LOOP -- some expressions here END LOOP; Related concepts: “Scope of variables” on page 2-7 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 ...; The target value can be a record, a row variable, or a comma-separated list of variables and record-fields or row-fields. This interpretation is different from the SQL interpretation of SELECT INTO, which is that the INTO target is a newly created table. (If you want to create a table from a SELECT result inside an NZPLSQL procedure, use the equivalent syntax CREATE TABLE AS SELECT.) 2-20 IBM Netezza Stored Procedures Developer's Guide If a row or a variable list is used as the target, the selected values must exactly match the structure of the target or targets, or a runtime error occurs. The FROM keyword can be followed by any valid qualification, grouping, or sorting that can be given for a SELECT statement. 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; FOUND is very similar to ROW_COUNT. For example, the following statement: IF FOUND is equivalent to this statement: IF ROW_COUNT >= 1 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 Iterate through the records of a query By using a special type of FOR loop, you can iterate through the results of a query and manipulate that data. The FOR IN loop syntax is as follows: [<<label>>] FOR record | row IN select_clause LOOP statements END LOOP; 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: Chapter 2. NZPLSQL statements and grammar 2-21 DECLARE mviews RECORD; -- Instead, if you did: -- mviews cs_materialized_views%ROWTYPE; -- this record is ONLY usable for the cs_materialized_views table BEGIN CALL cs_log(’Refreshing materialized views...’); FOR mviews IN SELECT * FROM cs_materialized_views ORDER BY sort_key LOOP -- Now "mviews" has one record from cs_materialized_views RAISE EXCEPTION, ’Can’t execute SQL while processing SQL for %’, mview.my_name; END LOOP; CALL cs_log(’Done refreshing materialized views.’); return 1; end; If the loop is terminated with an EXIT statement, the last assigned row is still accessible after the loop. The FOR-IN EXECUTE statement is another way to iterate over records: [<<label>>] FOR record | row IN EXECUTE text_expression LOOP statements END 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. Report messages and raise errors Use the RAISE statement to report messages and raise errors. The statement syntax follows: RAISE level ’format’ [, identifier [...]]; 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. The message levels are as follows: v DEBUG messages are written only to pg.log. v NOTICE messages are written to the database log and forwarded to the client application. v EXCEPTION messages are written to the database log, forwarded to the client application as non-fatal messages, and usually abort the transaction if they are not caught. The following is an example of a RAISE statement: RAISE NOTICE ’Calling cs_create_job(%)’, job_id; 2-22 IBM Netezza Stored Procedures Developer's Guide In the example, job_id replaces the % in the string and display the message to the client and in pg.log. RAISE EXCEPTION ’Inexistent ID --> %’, user_id; This EXCEPTION statement aborts the transaction (if the exception is not caught) and writes the message to the database log. Exceptions and error messages support Any error that occurs in an NZPLSQL procedure aborts the execution of the procedure, and it aborts the surrounding transaction as well. The system returns to the main loop to obtain the next query from the client application. It is not possible to catch all exceptions, especially if that action leaves the database in a bad state. 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 ... ] The NZPLSQL supports two clauses for exception processing: TRANSACTION_ABORTED Use the TRANSACTION_ABORTED clause to specify the statements that you want to run when an error occurs that causes the transaction to abort. In this case, a ROLLBACK is required to continue. Make sure that the ROLLBACK command is the first command in the exception handling statements. OTHERS Use the OTHERS clause to specify the statements to run when any error occurs within the procedure block. Errors such as a SQL parsing error do not abort the transaction, and thus would not match a TRANSACTION_ABORTED clause. 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; In this example, an error that aborts a transaction triggers the TRANSACTION_ABORTED clause and the stored procedure executes the ROLLBACK, the statements in statements_case1, and raises the error message. If the error did not cause the transaction to abort, the exception processing skips to Chapter 2. NZPLSQL statements and grammar 2-23 the OTHERS clause and the stored procedure runs the statements_case2 set and raises the notice message. If there were no errors in the block, the exception statements are skipped. 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; create or replace procedure sp_except02() returns BOOL LANGUAGE NZPLSQL AS BEGIN_PROC BEGIN CALL sp_except01(); END; END_PROC; create or replace procedure sp_except03() returns BOOL LANGUAGE NZPLSQL AS BEGIN_PROC BEGIN CALL sp_except02(); EXCEPTION WHEN OTHERS THEN RAISE NOTICE ’Caught exception’; END; END_PROC; In these examples, the exception is generated in sp_except01, in the block inner. The system first checks for an exception handler for block inner, which is not found. Control passes to the parent context, which is the procedure sp_except01, and an exception handler is also not found there. Control then passes to sp_except02, and finally sp_except03, where an exception handler is found and used. If an exception is not caught at any level, additional NOTICE-level log messages are sent to provide context about the error and where it occurred (line number and type of statement, unless the error is from a RAISE EXCEPTION statement). 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 2-24 IBM Netezza Stored Procedures Developer's Guide EXECUTE IMMEDIATE ’insert into NOTEXIST’ || ’values(1,1)’; EXCEPTION WHEN OTHERS THEN END; END_PROC; 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. To display the error, write the procedure as follows: CREATE PROCEDURE sp() RETURNS INTEGER LANGUAGE NZPLSQL AS BEGIN_PROC BEGIN EXECUTE IMMEDIATE ’insert into NOTEXIST’ || ’ values(1,1)’; EXCEPTION WHEN OTHERS THEN RAISE NOTICE ’Got exception: %’, SQLERRM; END; END_PROC; When you run this query, it displays the following output: NOTICE: Got exception: ERROR: Relation ’NOTEXIST’ does not exist Return a result set Typically, an NZPLSQL procedure returns a unique return value, but it can also return a result set in the form of a specified table. To create a stored procedure that returns a result set: v Define the stored procedure with a return value of “RETURNS REFTABLE (<table-name>)” to indicate that it returns a result set that looks like the specified table. v Inside the body of the procedure, use the variable REFTABLENAME to refer to the results table. 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); A description of tbl follows: DEV.SCH1(ADMIN)=> \d tbl Table "TBL" Attribute | Type | Modifier | Default Value -----------+---------+----------+--------------I | INTEGER | | I2 | BIGINT | | Distributed on hash: "I" 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 Chapter 2. NZPLSQL statements and grammar 2-25 BEGIN EXECUTE IMMEDIATE ’INSERT INTO ’ || REFTABLENAME ||’ values (1,1)’; EXECUTE IMMEDIATE ’INSERT INTO ’ || REFTABLENAME ||’ values (2,2)’; RETURN REFTABLE; END; END_PROC; A sample call to the returntwo stored procedure follows: DEV.SCH1(ADMIN)=> EXECUTE PROCEDURE returntwo(now()); I | I2 ---+---1 | 1 2 | 2 (2 rows) 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.) To use this in a procedure, you must insert your results in <temp-table-name> by using the REFTABLENAME variable to obtain the name. This SQL command must be invoked dynamically to use the variable. 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. Cross-database access for a REFTABLE procedure should work without problem as the temporary table will be created in the local database; it will retrieve the shape of the REFTABLE definition in the other database. 2-26 IBM Netezza Stored Procedures Developer's Guide The SQL that is executed (for example, CREATE TEMPORARY TABLE, DROP TABLE) uses the owner ID of the procedure as the effective user ID if EXECUTE AS OWNER is set; otherwise, if EXECUTE AS CALLER is set, the SQL uses the user ID of the account which calls or invokes the procedure. REFTABLE and ROLLBACK commands If a stored procedure returns a result set (REFTABLE), do not issue a ROLLBACK command inside the procedure body unless you first issue a COMMIT to create the temporary table for REFTABLE. Issuing a ROLLBACK without the prior COMMIT command causes your REFTABLE procedure to fail when executed. As a best practice, if your procedure body includes a ROLLBACK command, or if you call another procedure that could issue a ROLLBACK, specify the COMMIT command as the first statement in the REFTABLE procedure body. An example follows: DEV.SCH1(ADMIN)=> CREATE OR REPLACE PROCEDURE returntwo(timestamp) RETURNS REFTABLE(tbl) LANGUAGE NZPLSQL AS BEGIN_PROC BEGIN COMMIT; EXECUTE IMMEDIATE ’INSERT INTO ’ || REFTABLENAME ||’ values (1,1)’; EXECUTE IMMEDIATE ’INSERT INTO ’ || REFTABLENAME ||’ values (2,2)’; EXECUTE IMMEDIATE ’INSERT INTO ’ || REFTABLENAME ||’ values (3,3)’; COMMIT; EXECUTE IMMEDIATE ’INSERT INTO ’ || REFTABLENAME ||’ values (4,4)’; ROLLBACK RETURN REFTABLE; END; END_PROC; DEV.SCH1(ADMIN)=> EXECUTE returntwo(now()); I | I2 ---+---2 | 2 1 | 1 3 | 3 (3 rows) 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. Manage large data sets If users run stored procedures on large data sets, there might be situations where there is not enough memory to hold the results of a select on that table. For example, some stored procedures can read each record from a table and take action on each record: Chapter 2. NZPLSQL statements and grammar 2-27 FOR rec in SELECT * from tablenm LOOP --perform processing steps 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” Advanced development topics This section describes some topics that show how you can take advantage of user-defined functions and stored procedures to perform advanced programming and scripting on the Netezza system. Extend the NZPLSQL language with UDFs If you or other users at your site create user-defined functions (UDFs) for your IBM Netezza systems, you can use UDFs to extend the NZPLSQL language. These UDFs must be invoked by using SQL that is designed to run only on the Netezza host inside Postgres. For details about the use of UDFs to extend NZPLSQL, see the IBM Netezza User-Defined Functions Developer’s Guide. Tips and best practices for stored procedures This section describes some common tips and best practices for stored procedures. Control-C interrupt processing in loops 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. Query processing in loops 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 2-28 IBM Netezza Stored Procedures Developer's Guide caches its results before the inner query begins. Thus, deleting records from the table in the inner loop does not affect the SELECT query in the outer loop or change its results. Note: Although it can be common to run row-at-a-time operations, as used in the preceding example, you can significantly improve the performance of these procedures by designing them to operate on sets of records rather than single row operations. For example, if you recast the previous example to the following: DELETE from mytable2 where recid in (select recid from my table where type = ’d’) ; 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 Chapter 2. NZPLSQL statements and grammar 2-29 2-30 IBM Netezza Stored Procedures Developer's Guide Chapter 3. Create and manage stored procedures This section describes the basic management and user tasks associated with stored procedures, such as managing permissions, creating procedures, invoking procedures, and altering and dropping stored procedures. Related concepts: “SQL commands for stored procedures” on page 1-2 Manage user account permissions Before you create any stored procedures, familiarize yourself with the required account permissions necessary to create and manage these objects. The IBM Netezza admin user has full permission to manage and execute stored procedures. The database owner also has full permission to objects within the database that the owner owns. For release 7.0.3 and later systems that support multiple schemas in a database, the schema owner also has full permission to objects within that schema. In addition, the owner of the stored procedure has permission to manage and execute the stored procedure. 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 Administrator’s 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: © Copyright IBM Corp. 2009, 2014 3-1 v database is a specific database name or the keyword ALL to grant the privilege across all databases. You can omit a database name. v schema is a specific schema name or the keyword ALL for all schemas in the specified database. If you omit the database name, the scope is for ALL schemas or all the schemas of the specified name. Grant Create Procedure administration permission To grant Create Procedure administration permission, use the following command: GRANT CREATE PROCEDURE TO entity; 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; Grant all object permissions 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; Revoke Create Procedure administration permission To revoke Create Procedure administration permission, use the following command: REVOKE CREATE PROCEDURE FROM entity; For example, the following command revokes Create Procedure permissions from the group analysts: 3-2 IBM Netezza Stored Procedures Developer's Guide REVOKE CREATE PROCEDURE FROM GROUP analysts; Manage the Alter permission To grant Alter permission on an object, use the following command: GRANT ALTER ON object TO entity; To revoke Alter permission on an object, use the following command: REVOKE ALTER ON object FROM entity; 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; Manage the Execute permission To grant Execute permission on an object, use the following command: GRANT EXECUTE ON object TO entity; To revoke Execute permission on an object, use the following command: REVOKE EXECUTE ON object TO entity; 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; Manage the Drop permission To grant Drop permission on an object, use the following command: GRANT DROP ON object TO entity; To revoke Drop permission on an object, use the following command: REVOKE DROP ON object FROM entity; 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 Chapter 3. Create and manage stored procedures 3-3 Create a stored procedure The process to create a stored procedure is straightforward; typically, the time-consuming work is in the design of the stored procedure, and the debugging and testing of the procedure. This section describes the following key steps for creating a stored procedure: v Design a stored procedure v Create a stored procedure Design a stored procedure The first step is to design the procedure itself. Make sure that you outline the basic purpose and actions of the procedure, consider helpful error logging, and plan for exception handling. Review the NZPLSQL language and statements to create the body of the procedure. Create a stored procedure After you create the body of the stored procedure, you add it by using the CREATE [OR REPLACE] PROCEDURE command. You enter this command at a SQL command prompt. The CREATE PROCEDURE command creates a procedure. To use this command, you must be the admin user, own the database, own the schema (multi-schema systems), or have the Create Procedure privilege. The CREATE OR REPLACE PROCEDURE command creates a procedure if one does not already exist with the specified signature, or updates an existing procedure with the matching signature for the new (or different) field values. To replace a procedure, you must have the Alter privilege. 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 3-4 IBM Netezza Stored Procedures Developer's Guide You can also use the ALTER PROCEDURE command to modify certain characteristics of a defined procedure. Related concepts: “Alter a stored procedure” on page 3-10 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. If there are common use-cases where a procedure must accept different-sized strings or numerics, you can design the procedure to accept the largest of the possible values, or you can create a stored procedure with a different name to process the different data size, for example: TEST.TESTSCH(USR)=> CREATE PROCEDURE myproc_lgnum(numeric(4,1)) ... Procedures for overloading You can create stored procedures that have the same procedure name, but which have different argument signatures and return types. This process is called overloading the procedure definition. 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. The following example is some sample procedure definitions: TEST.TESTSCH(USR)=> CREATE PROCEDURE customer_name(VARCHAR(30), VARCHAR(30)) ... TEST.TESTSCH(USR)=> CREATE PROCEDURE customer_name(VARCHAR(30), VARCHAR(30), VARCHAR(30)) ... 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, generic, and variable argument procedures In the signature of a stored procedure, the <argument_type_list> can use three general forms: size-specific arguments, generic arguments, and variable arguments. This section describes these three formats and the benefits and considerations for using that type. 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 Chapter 3. Create and manage stored procedures 3-5 useful for error-checking of the input arguments and return values, but they can be somewhat limiting if your procedure processes strings or numerics that can vary in size when you run a query. 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... The stored procedure accepts an input string of up to 64,000 characters (the maximum for a VARCHAR). Within the body of the stored procedure, the code must process the strings and numerics with the plan that you can receive a string of any valid length. That is, you can check and obtain their size, process them as needed, and return the value for the procedure. 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. 3-6 IBM Netezza Stored Procedures Developer's Guide For arguments that have a specific size, the Netezza software also confirms that the size of the input value matches the defined signature size. If necessary, the Netezza software casts the input values to match the size specified in the signature. For example, if you declare a string of 20 characters [CHAR(20)] in a signature, the Netezza software implicitly truncates an input string that is longer than 20 characters or adds padding if the input string is less than 20 characters. 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. Generic procedure return value: 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. Chapter 3. Create and manage stored procedures 3-7 Use variable argument procedures to create one procedure that can be used for different combinations of input types. This process simplifies the development of stored procedures and reduces the need to create overloaded procedure definitions that do the same task for different types and numbers of arguments. Related concepts: “Argument list and variables” on page 2-6 Obfuscate the procedure body As shown in CREATE PROCEDURE examples, the procedure body is entered in readable text format. Users who have permission to show the procedure can use the VERBOSE option to review the procedure body. If your procedure body contains intellectual property, copyrighted material, or other algorithms that you do not want in clear text, you can obfuscate the body text. Related concepts: “Block quoting support” on page 1-5 “Show information about a stored procedure” on page 3-12 Create obfuscated procedures by using a wrapping procedure A common way to create an obfuscated stored procedure is by creating a stored procedure “wrapper” that takes the procedure definition and the procedure body, and creates the obfuscated procedure, as in the following example: TEST.TESTSCH(USR)=> CREATE OR REPLACE PROCEDURE wrap_proc(text, text) RETURNS BOOL LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE proc alias for $1; body alias for $2; enc text; sql text; BEGIN enc := wrap_nzplsql(body); sql := proc || ’’ || ’’ || quote_literal(enc) || ’’; RAISE NOTICE ’%;’, sql; EXECUTE IMMEDIATE sql; return true; END; END_PROC; CREATE PROCEDURE 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 AS’TlpQU1FMV1JBUDEwWWk5NUhrQzVhR0xyRFRxTWR3VE5sQT09JEdFQ1B5LzVkSU1KMTI 1a0dUK3NTWjlkb3ZGL3ZHalhpVExPVG5UajRkK3gxSkxvZVhKejdZQmJOVHN0aU1waFRlb mhoaWtYdHJUTVkKUUNrWDY5Nko5Rms2NlBIYUxra21xeWNZYXdWclBCQT0=’; 3-8 IBM Netezza Stored Procedures Developer's Guide wrap_proc ----------t (1 row) 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) Create obfuscated procedure body text As an alternative to using the wrap_proc() procedure method, you can also create the obfuscated body of the procedure in a separate step as follows: TEST.TESTSCH(USR)=> CALL wrap_nzplsql(BEGIN_PROC BEGIN RAISE NOTICE ’The customer name is alpha’; END; END_PROC); wrap_nzplsql ---------------------------------------------------------------------TlpQU1FMV1JBUDEwVE5jZlh5TnpYbndCNkV5VFFMRTBiQT09JGE5N2p6ZEdJSVZwTTRrWm RRM0I3WmUxZERZeWd6YkdjTWkxTzQrL1dCMmpqRGQvak9lUzFQQjArNGdlM08yZVdxUjRI MTFaTnROUmwKdk5xSm0wb1RPZz09 (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. Create obfuscated procedure definitions for a registration script If you plan to create a script that users run to register your stored procedures in their databases, you can use a wrapping procedure that takes as input the procedure definition and body, and which returns a CREATE OR REPLACE PROCEDURE command that has obfuscated body text. For example: TEST.TESTSCH(USR)=> CREATE OR REPLACE PROCEDURE return_wrap(TEXT, TEXT) RETURNS TEXT LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE proc alias for $1; body alias for $2; enc text; sql text; BEGIN enc := wrap_nzplsql(body); sql := proc || ’ ’ || ’’ || quote_literal(enc) || ’’; return sql; END; END_PROC; CREATE PROCEDURE Chapter 3. Create and manage stored procedures 3-9 Similar to the wrap_proc() procedure, specify the CREATE OR REPLACE main definition as a quoted text string in the first input value, and specify the unquoted BEGIN PROC/END PROC contents in the second input value. For example: TEST.TESTSCH(USR)=> CALL return_wrap(’CREATE OR REPLACE PROCEDURE customer() RETURNS INT4 LANGUAGE NZPLSQL AS’, BEGIN_PROC BEGIN RAISE NOTICE ’The customer name is alpha’; END; END_PROC); return_wrap ---------------------------------------------------------------------CREATE OR REPLACE PROCEDURE customer() RETURNS INT4 LANGUAGE NZPLSQL AS ’TlpQU1FMV1JBUDEwaTVJeHJnV1BLd1o0ZDVtNEtNMGxKQT09JCtiSlVDS1NHbkVrdVZja 01JR3Nrc2dTZlExWDdkaUpDeHdZWUp2dmlrUkZIeEpEQnR6dE1JSHMxOHRTR08xMG1IczJ FSk92R2F0Ti8KMGhKTGlUUEdIZz09’ (1 row) 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. Call or invoke a stored procedure To invoke or execute the sample stored procedure customer(), you can use any of the following SQL query forms: TEST.TESTSCH(USR)=> TEST.TESTSCH(USR)=> TEST.TESTSCH(USR)=> TEST.TESTSCH(USR)=> TEST.TESTSCH(USR)=> CALL customer(); EXEC customer(); EXECUTE customer(); EXECUTE PROCEDURE customer(); SELECT customer(); Any of these commands cause the procedure to output the following: NOTICE: The customer name is alpha CUSTOMER ---------(1 row) Related reference: Appendix A, “SQL command reference,” on page A-1 Alter a stored procedure After you define a stored procedure on the IBM Netezza system, you can use the ALTER PROCEDURE command to change some aspects of the procedure. 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: 3-10 IBM Netezza Stored Procedures Developer's Guide TEST.TESTSCH(USR)=> ALTER PROCEDURE customer() RETURNS INT8; ALTER PROCEDURE 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 To change the user execution property to EXECUTE AS CALLER, use a command similar to the following example: TEST.TESTSCH(USR)=> ALTER PROCEDURE customer() EXECUTE AS CALLER; ALTER PROCEDURE To change the procedure definition, use a command similar to the following example: TEST.TESTSCH(USR)=> ALTER PROCEDURE customer() AS BEGIN_PROC BEGIN RAISE NOTICE ’The customer name is beta’; END; END_PROC; ALTER PROCEDURE Related concepts: “Create a stored procedure” on page 3-4 Related reference: “The ALTER PROCEDURE command” on page A-1 Comment on a stored procedure As a best practice, add some descriptive comments on stored procedures by using the COMMENT ON command capability. 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 User’s Guide. Chapter 3. Create and manage stored procedures 3-11 Make sure that you specify a full procedure name and argument list, including correct sizes for numeric and string data types. Otherwise, you receive an error similar to the following example: Error: CommentProcedure: existing procedure name(argument type list) differs in size of string/numeric arguments Drop a stored procedure You can remove a stored procedure from the IBM Netezza system by using the DROP PROCEDURE command. 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 Show information about a stored procedure You can use the SHOW PROCEDURE command to display information about a stored procedure. A sample command follows for the example customer procedure: MYDB.TESTSCH(USR)=> SHOW PROCEDURE customer; RESULT | PROCEDURE | BUILTIN | ARGUMENTS ---------+-----------+---------+----------INTEGER | CUSTOMER | f | () (1 row) 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 NzAdmin administrative interface for stored procedures If you use the NzAdmin administrative interface, you can view information about the stored procedures defined on a IBM Netezza system and manage them. You cannot add or alter a stored procedure from the NzAdmin interface, but you can display its properties, change its owner, drop the procedure, and manage user and group permissions for procedures. 3-12 IBM Netezza Stored Procedures Developer's Guide To view the stored procedures, go to the Database tab of NzAdmin. Select a database and double-click Procedures to list the stored procedures that are defined in that database. Figure 3-1. The NzAdmin stored procedures window 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 Administrator’s Guide. Chapter 3. Create and manage stored procedures 3-13 3-14 IBM Netezza Stored Procedures Developer's Guide Appendix A. SQL command reference This section describes the IBM Netezza SQL commands that relate to the creation and management of stored procedures. The following table lists the SQL commands. Table A-1. Stored procedure SQL commands Command Description More information ALTER PROCEDURE Changes a stored procedure. “The ALTER PROCEDURE command.” CALL or EXEC[UTE [ PROCEDURE]] Runs a stored procedure. “The CALL and EXEC[UTE [PROCEDURE]] commands” on page A-3 CREATE [OR REPLACE] PROCEDURE Adds or updates a stored procedure. “The CREATE [OR REPLACE] PROCEDURE commands” on page A-5. DROP PROCEDURE Drops or deletes a stored procedure. “The DROP PROCEDURE command” on page A-7. SHOW PROCEDURE Displays information about stored procedures. “The SHOW PROCEDURE command” on page A-9. 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 The ALTER PROCEDURE command Use the ALTER PROCEDURE command to change a stored procedure. 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>; © Copyright IBM Corp. 2009, 2014 A-1 Inputs The ALTER PROCEDURE command takes the following inputs: Table A-2. ALTER PROCEDURE input Input Description name The name of the stored procedure that you want to change. You cannot change the name of the procedure. The procedure must be defined in the database to which you are connected. 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 OWNER If specified, the stored procedure uses the procedure owner ID for all access control and permission checks. This is the default. EXECUTE AS CALLER If specified, the stored procedure uses the ID of the user who called the 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 The ALTER PROCEDURE command has the following output Table A-3. ALTER PROCEDURE Output Output Description ALTER PROCEDURE The message that the system returns if the command is successful. ERROR: replacing procedure: permission denied. The message indicates that the user does not have Alter permission on the procedure. Error: FunctionAlter: existing UDX NAME(ARGS) differs in size of string/numeric arguments This error indicates that a stored procedure exists with the name but has different sizes specified for string or numeric arguments. To alter the stored procedure, make sure that you specify the exact argument type list with correct sizes. A-2 IBM Netezza Stored Procedures Developer's Guide Table A-3. ALTER PROCEDURE Output (continued) Output Description ERROR: FunctionAlter: function NAME does not exist with that signature This error indicates that the specified procedure name does not exist in the database. 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. 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 To change the execution ID from over to caller, enter: system(admin)=> ALTER PROCEDURE myproc(int4) EXECUTE AS CALLER; To change the owner for a procedure in a different schema, enter: MYDB.MYSCH(USER)=> ALTER PROCEDURE schtwo.myproc(int4) OWNER TO user2; Related concepts: “Alter a stored procedure” on page 3-10 The CALL and EXEC[UTE [PROCEDURE]] commands Use the CALL command, EXEC command, EXECUTE command, or EXECUTE PROCEDURE command to invoke a stored procedure on a IBM Netezza host. The CALL, EXEC, EXECUTE, EXECUTE PROCEDURE commands are identical in their behavior, inputs, and outputs. The different commands provide compatibility with other procedural language invocation methods. You can also use the SELECT command to invoke a stored procedure. Appendix A. SQL command reference A-3 Synopsis CALL procedure_name(arguments) EXEC procedure_name(arguments) EXECUTE procedure_name(arguments) EXECUTE PROCEDURE procedure_name(arguments) SELECT procedure_name(arguments) 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. You can specify a fully qualified object name to execute a procedure defined in a different database or schema. arguments Specifies a list of constant or literal arguments to the procedure. The arguments might be results of functions when the functions take only constant or literal arguments as well. 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 stored procedure. A procedure of that name exists, but it is expecting 'NAME(ARGS)' different input arguments. does not exist Unable to identify a function that satisfies the argument types You might need to add explicit typecasts 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. A-4 IBM Netezza Stored Procedures Developer's Guide v You must be the database admin user or own the current database or the current schema on systems that support multiple schemas. Usage The following examples provide some sample usage: MYDB.MYSCH(USER)=> MYDB.MYSCH(USER)=> MYDB.MYSCH(USER)=> MYDB.MYSCH(USER)=> CALL updateacct(); EXEC schema_two.myproc(); EXECUTE sales.dev.inventorysearch(umbrellas); EXECUTE PROCEDURE updateacct(); 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); The CREATE [OR REPLACE] PROCEDURE commands Use the CREATE OR REPLACE PROCEDURE command to create a stored procedure or to update an existing procedure with a new return type, execution permissions, or procedure body. Synopsis CREATE [OR REPLACE] PROCEDURE <name> (<arguments>) RETURNS <type> [ [ EXECUTE AS OWNER | EXECUTE AS CALLER ] ] LANGUAGE NZPLSQL AS <procedure_body>; Inputs The CREATE OR REPLACE PROCEDURE command takes the following inputs: Table A-6. CREATE OR REPLACE PROCEDURE inputs Input Description name The name of the stored procedure that you want to create or replace. This name is the SQL identifier that is used to invoke the procedure in a SQL expression. 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. Appendix A. SQL command reference A-5 Table A-6. CREATE OR REPLACE PROCEDURE inputs (continued) Input Description RETURNS <type> Specifies the type of data returned by the procedure. The <type> value can be an 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, although it can be empty, and it continues to exist after the procedure. EXECUTE AS OWNER If specified, the stored procedure runs by using the procedure owner ID for all access control and permission checks. This is the default. EXECUTE AS CALLER If specified, the stored procedure runs by using the ID of the user who called the procedure for all access control and permission checks. LANGUAGE Specifies the programming language used for the procedure. The default and only supported value is NZPLSQL. procedure_body Specifies the text of the procedure and must be enclosed with single quotation marks or a BEGIN_PROC/END_PROC pair. 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: permission denied. The message indicates that the user does not have Create Procedure permission. ERROR: User 'username' is not allowed to create/drop procedures. The system returns this message if your user account does not have permission to create a stored procedure. ERROR: Synonym 'name' already exists The system returns this message if a synonym exists with the name that you specified for the stored procedure. ERROR: ProcedureCreate: procedure NAME already exists with the same signature This error is returned when you issue a CREATE PROCEDURE command and a stored procedure with the same name and argument type list exists in the database. Use CREATE OR REPLACE PROCEDURE instead. NOTICE: FunctionCreate: existing UDX NAME(ARGS) differs in size of string/numeric arguments This message indicates that a stored procedure exists with the name but has different sizes specified for 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. A-6 IBM Netezza Stored Procedures Developer's Guide Description 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 To create a procedure called customername: MYDB.SCHEMA(USER)=> CREATE OR REPLACE PROCEDURE customer() RETURNS INT8 LANGUAGE NZPLSQL AS BEGIN_PROC BEGIN RAISE NOTICE ’The customer name is alpha’; END; END_PROC; To create a new procedure called customername in a different schema of the same database: MYDB.SCHEMA(USER)=> CREATE OR REPLACE PROCEDURE sch_two.customer() RETURNS INT8 LANGUAGE NZPLSQL AS BEGIN_PROC BEGIN RAISE NOTICE ’The customer name is alpha’; END; END_PROC; Related concepts: “Register generic procedures” on page 3-7 The DROP PROCEDURE command Use the DROP PROCEDURE command to remove an existing stored procedure from a database. Synopsis DROP PROCEDURE <name> (<arguments>) Appendix A. SQL command reference A-7 Inputs The DROP PROCEDURE command takes the following inputs: Table A-8. DROP PROCEDURE inputs Input Description name The name of the stored procedure that you want to drop. The procedure must be defined in the database to which you are connected. 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 The DROP PROCEDURE command has the following outputs: Table A-9. DROP PROCEDURE Outputs Output Description DROP PROCEDURE The message that the system returns if the command is successful. ERROR: DROP PROCEDURE: permission denied The user does not have Drop permission. ERROR: RemoveFunction: function 'NAME(ARGS)' does not exist The message that indicates that the specified procedure signature does not exist in the database. ERROR: Name: No such stored procedure The message that the system returns if the specified stored procedure does not exist in the current database. ERROR: RemoveFunction: existing UDX NAME(ARGS) differs in size of string/numeric arguments This error indicates that a stored procedure exists with the name but has different sizes specified for string or numeric arguments. To drop the stored procedure, make sure that you specify the exact argument type list with correct sizes. 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. The DROP PROCEDURE command has the following characteristics: Privileges required To drop a stored procedure, you must meet one of the following criteria: v You must have the Drop privilege on the PROCEDURE object. v You must have the Drop privilege on the specific stored procedure. v You must own the stored procedure. v You must be the database admin user or own the current database or the current schema on systems that supports multiple schemas. A-8 IBM Netezza Stored Procedures Developer's Guide Common tasks Use the DROP PROCEDURE command to drop an existing stored procedure from a database. Usage To drop a sample stored procedure named mycalc(), enter: system(admin)=> DROP PROCEDURE mycalc(); Related concepts: “Drop a stored procedure” on page 3-12 The SHOW PROCEDURE command Use the SHOW PROCEDURE command to display information about one or more stored procedures. The command checks your user account privileges to ensure that you are permitted to see information about the procedures. Synopsis SHOW PROCEDURE [ALL | <name>] [VERBOSE] Inputs The SHOW PROCEDURE command takes the following inputs: Table A-10. SHOW PROCEDURE inputs Input Description ALL Show information about all the stored procedures defined in the database. This is the default. name Show information about one or more stored procedures defined in the database. You can specify a partial name. The command displays information for all the procedures with names that begin with the specified characters. You cannot specify a full signature. VERBOSE Display detailed information about the stored procedure. Outputs The SHOW PROCEDURE command has the following output: Table A-11. SHOW PROCEDURE output Output Description error found "(" (at char num) syntax The message that the system returns if you specify a error, unexpected '(', expecting $end full signature, for example: show procedure returntwo(); Description The SHOW PROCEDURE command has the following characteristics: Privileges required Any user can run the SHOW PROCEDURE command. To see information about procedures in the output, you must be the admin user, own one or more procedures, own the current database or the schema on a system that Appendix A. SQL command reference A-9 supports multiple schemas, or have object privileges (such as Execute, List, Alter, or Drop) on one or more procedures or the Procedure object class. Common tasks Use the SHOW PROCEDURE command to display one or all stored procedures in a database. 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) To list all the stored procedures in a database, enter: MYDB.SCHEMA(ADMIN)=> SHOW PROCEDURE ALL; RESULT | PROCEDURE | BUILTIN | ARGUMENTS ----------------------------+------------------+---------+-----------------------BOOLEAN | BOOLPROC | f | (BOOLEAN) CHARACTER | CHARPROC | f | (CHARACTER(ANY)) CHARACTER | CHARPROCANY | f | (CHARACTER(ANY)) CHARACTER | CHARPROCANY2 | f | (CHARACTER(10)) REAL | FLOAT4PROC | f | (REAL) DOUBLE PRECISION | FLOAT8PROC | f | (DOUBLE PRECISION) BYTEINT | INT1PROC | f | (BYTEINT) Related concepts: “Show information about a stored procedure” on page 3-12 A-10 IBM Netezza Stored Procedures Developer's Guide Appendix B. Stored procedure examples This section contains examples of stored procedure definitions. Variable argument stored procedure The following is an example of a stored procedure that uses variable arguments and the $var value to obtain the data type of the input parameters: CREATE OR REPLACE PROCEDURE sp_varargs01(varargs) RETURNS INT4 LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE num_args int4; typ oid; idx int4; BEGIN num_args := PROC_ARGUMENT_TYPES.count; RAISE NOTICE ’Number of arguments is %’, num_args; for i IN 0 .. PROC_ARGUMENT_TYPES.count - 1 LOOP typ := PROC_ARGUMENT_TYPES(i); idx := i+1; RAISE NOTICE ’argument $% is type % value ’’%’’’, idx, typ, $idx; END LOOP; END; END_PROC; A sample call to the sp_varargs01 procedure follows: select sp_varargs01(true, ’test’::char(10), 62443234::int8, 123::int2, 123456::int4, 34343.4343::float4, 1212.2323::float8, ’test2’::varchar(10), ’2009-05-12’::date, ’13:14:05’::time, ’2009-05-12 08:10:10’::timestamp, ’2 days 1 hour’::interval, ’11:40:36+05’::timetz, 3243.4324234::numeric, 3243.4324234::numeric(7,2), 5::int1, ’foo’::nchar(20), ’foo’::nvarchar(20), null::int4); NOTICE: Number of arguments is 19 NOTICE: argument $1 is type 16 value ’t’ NOTICE: argument $2 is type 1042 value ’test ’ NOTICE: argument $3 is type 20 value ’62443234’ NOTICE: argument $4 is type 21 value ’123’ NOTICE: argument $5 is type 23 value ’123456’ NOTICE: argument $6 is type 700 value ’34343.4’ NOTICE: argument $7 is type 701 value ’1212.2323’ NOTICE: argument $8 is type 1043 value ’test2’ NOTICE: argument $9 is type 1082 value ’2009-05-12’ NOTICE: argument $10 is type 1083 value ’13:14:05’ NOTICE: argument $11 is type 1184 value ’2009-05-12 08:10:10’ NOTICE: argument $12 is type 1186 value ’2 days 01:00:00’ NOTICE: argument $13 is type 1266 value ’11:40:36+05’ NOTICE: argument $14 is type 1700 value ’3243.4324234’ NOTICE: argument $15 is type 1700 value ’3243.43’ NOTICE: argument $16 is type 2500 value ’5’ NOTICE: argument $17 is type 2522 value ’foo ’ NOTICE: argument $18 is type 2530 value ’foo’ NOTICE: argument $19 is type 23 value ’<NULL>’ sp_varargs01 -------------(1 row) © Copyright IBM Corp. 2009, 2014 B-1 Example of simulating an anonymous block The following is an NZPLSQL procedure that can execute anonymous blocks: CREATE OR REPLACE PROCEDURE exec_nzplsql_block(text) RETURNS BOOLEAN LANGUAGE NZPLSQL AS BEGIN_PROC DECLARE lRet BOOLEAN; DECLARE sid INTEGER; DECLARE nm varchar; DECLARE cr varchar; BEGIN sid := current_sid; nm := ’any_block’ || sid || ’()’; cr = ’CREATE OR REPLACE PROCEDURE ’ || nm || ’ RETURNS BOOL LANGUAGE NZPLSQL AS BEGIN_PROC ’ || $1 || ’ END_PROC’; EXECUTE IMMEDIATE cr; EXECUTE IMMEDIATE ’SELECT ’ || nm; EXECUTE IMMEDIATE ’DROP PROCEDURE ’ || nm; RETURN TRUE; END; END_PROC; An example call and output follows: MYDB.SCHEMA(USER)=> call exec_nzplsql_block(BEGIN_PROC DECLARE var char; BEGIN var:= ’test’; raise NOTICE ’This is a %’, var; END; END_PROC); NOTICE: This is a test EXEC_NZPLSQL_BLOCK -------------------t (1 row) B-2 IBM Netezza Stored Procedures Developer's Guide Notices This information was developed for products and services offered in the U.S.A. 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. IBM Director of Licensing IBM Corporation North Castle Drive Armonk, NY 10504-1785 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: IBM World Trade Asia Corporation Licensing 2-31 Roppongi 3-chome, Minato-ku Tokyo 106-0032, Japan 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. This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice. 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. © Copyright IBM Corp. 2009, 2014 C-1 Licensees of this program who wish to have information about it for the purpose of enabling: (i) the exchange of information between independently created programs and other programs (including this one) and (ii) the mutual use of the information which has been exchanged, should contact: IBM Corporation Software Interoperability Coordinator, Department 49XA 3605 Highway 52 N Rochester, MN 55901 U.S.A. Such information may be available, subject to appropriate terms and conditions, including in some cases, payment of a fee. 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. Any performance data contained herein was determined in a controlled environment. Therefore, the results obtained in other operating environments may vary significantly. Some measurements may have been made on development-level systems and there is no guarantee that these measurements will be the same on generally available systems. Furthermore, some measurements may have been estimated through extrapolation. Actual results may vary. Users of this document should verify the applicable data for their specific environment. Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products. 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: This information contains sample application programs in source language, which illustrate programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. C-2 IBM Netezza Stored Procedures Developer's Guide Each copy or any portion of these sample programs or any derivative work, must include a copyright notice as follows: © your company name) (year). Portions of this code are derived from IBM Corp. Sample Programs. © Copyright IBM Corp. _enter the year or years_. 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. Adobe is a registered trademark of Adobe Systems Incorporated in the United States, and/ or other countries. Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both. Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both. NEC is a registered trademark of NEC Corporation. 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. Other company, product or service names may be trademarks or service marks of others. Notices C-3 C-4 IBM Netezza Stored Procedures Developer's Guide Index Special characters $var variable 2-6 %, used in message formats 2-22 %ROWTYPE attribute[ROWTYPE attribute] 2-5 %TYPE attribute[TYPE attribute] 2-5 A account permissions, managing 3-1 admin user, permissions 3-1 aliases, for data types 2-9 ALTER PROCEDURE command A-1 using 3-10 ANY keyword 3-6 ANY keyword, for procedure input arguments 3-6 arithmetic evaluations, and stored procedures 2-12 array variables assigning a value 2-10 in NZPLSQL 2-10 reference support 2-10 assignment statement 2-15 AUTOCOMMIT ON blocks 2-3 B backups, and stored procedures 1-6 BEGIN_PROC keyword 1-5 best practices, stored procedures 1-3 block comments 2-4 block quoting support 1-5 block structured language 2-1 block, in NZPLSQL 2-1 C CALL command discarding results 2-16 example 3-10 usage A-3 call recursion limit 2-16 casting impact on stored procedures 2-12 input values to match signature sizes 3-6 COMMENT ON PROCEDURE command, using 3-11 comments best practices 3-11 in NZPLSQL 2-4 conditional control 2-17 CONSTANT option, variables 2-5 constants, in NZPLSQL 2-5 control statements conditional 2-17 IF-THEN statements 2-17 iterative 2-19 © Copyright IBM Corp. 2009, 2014 control structures 2-17 COUNT method, array variables 2-10 CREATE OR REPLACE PROCEDURE command A-5 generic arguments example 3-7 using 3-4 cross-database access, to stored procedures 1-4 D data types 2-9 DEBUG messages 2-22 declarations section, in NZPLSQL 2-1 DEFAULT clause, variables 2-5 disk space problems, avoiding for large datasets 2-27 double dash comments 2-4 downgrade cautions 1-7 DROP PROCEDURE command A-7 using 3-12 dropping when database is dropped 1-6 dynamic queries 2-16 E ELSE IF statements 2-17 ELSIF statements 2-17 END_PROC keyword 1-5 error handling, in NZPLSQL 2-23 errors, raising 2-22 EXCEPTION messages 2-22 EXCEPTION statement 2-23 EXEC command, using 3-10 execute as caller permissions 1-3 execute as owner permissions 1-3 EXECUTE command A-3 using 3-10 EXECUTE IMMEDIATE statement 2-16 EXECUTE PROCEDURE command, using 3-10 EXIT statement 2-19 expressions in NZPLSQL 2-11 string processing best practices 2-16 EXTEND method, array variables 2-10 F FOR IN loop statement 2-21 FOR loop, iteration step count 2-19 FOR statement 2-19 FOR-IN EXECUTE statement 2-21 fully-qualified object names, for stored procedures 1-4 G generic arguments, benefits of 3-6 generic procedures ANY keyword 3-6 input arguments 3-6 registering 3-7 generic return value 3-7 GRANT ALL command, create permission 3-1 GRANT command alter permission 3-1 create permission 3-1 drop permission 3-1 execute permission 3-1 H hiding the procedure body 3-8 I IF statements 2-17 IF-THEN-ELSE IF statements 2-17 IF-THEN-ELSE statements 2-17 implicit casting for procedure input values 3-6 in assignments 2-15 in stored procedures, best practices 2-12 infinite loop, handling 2-28 iterative control 2-19 L labels, used to identify variables 2-7 large datasets, managing 2-27 LAST_OID variable 2-17 loop processing 2-28 LOOP statement 2-19 loops infinite, handling 2-28 iterate over integer count 2-19 repeating while true 2-19 terminating 2-19 unconditional 2-19 M massively parallel processing (MPP), designing procedures for 2-28 message levels, types of 2-22 messages, reporting 2-22 N Netezza SQL commands for stored procedures 1-2 reference A-1 NOT NULL option, variables 2-5 NOTICE messages 2-22 X-1 NzAdmin administrative interface, for stored procedures 3-12 NZPLSQL language about 1-2 array variables 2-10 comments 2-4 constants 2-5 control structures 2-17 description of 2-1 dynamic queries 2-16 exception support 2-23 expressions 2-11 message and error reporting 2-22 procedural logic 1-2 record assignments 2-20 record variable 2-20 records 2-20 statements 2-15 variable datatypes 2-5 variables 2-5 O obfuscating procedures using in registration scripts 3-9 using wrap_nzplsql 3-8 outputs ALTER PROCEDURE command A-1 CREATE OR REPLACE PROCEDURE command A-5 DROP PROCEDURE command A-7 SHOW PROCEDURE command A-9 overflows, avoiding in stored procedures 2-12 overloading procedures 3-5 owner, stored procedure 3-1 P parameters 2-6 patches, and stored procedures 1-7 PATH SQL session variable 1-4 permissions 3-1 granting all 3-1 alter permission 3-1 create 3-1 drop permission 3-1 execute permission 3-1 managing 3-1 revoking create permission 3-1 drop permission 3-1 execute permission 3-1 PL/pgSQL language 1-2 privileges, commands ALTER PROCEDURE command A-1 CALL or EXECUTE PROCEDURE command A-3 CREATE PROCEDURE command A-5 privileges, managing for accounts 3-1 PROC_ARGUMENT_TYPES array 2-6 procedural programming language 1-1 procedures calling 2-16 X-2 procedures (continued) obfuscating 3-8 returning from 2-17 Q quote_ident function 2-16 quote_literal function 2-16 R RAISE statement 2-22 RECORD variable 2-20 records about 2-20 assignments 2-20 recursion limit, calls 2-16 registration script, with obfuscated procedures 3-9 restores, and stored procedures 1-6 RETURN command 2-17 return value, generic 3-7 REVOKE command alter permission 3-1 drop permission 3-1 revoking alter permission 3-1 ROLLBACK, using with REFTABLE 2-27 ROW_COUNT variable 2-17 S scoping, variables 2-7 SHOW PROCEDURE command A-9 using 3-12 signature about 3-5 used in permissions 3-1 SQL commands, for stored procedures A-1 SQLERRM variable 2-23 statements assignment 2-15 in NZPLSQL 2-15 section, in NZPLSQL 2-1 stored procedures 1-4, 1-6 about 1-1 account permission overview 3-1 altering 3-10, A-1 benefits of 1-1 best practices 1-3 block quoting support 1-5 call recursion limit 2-16 calling, starting 3-10 commenting on 3-11 creating 1-3, 3-4 creating or replacing A-5 designing 3-4 displaying information for 3-12 dropping 3-12, A-7 example use of 1-1 fully qualified name of 1-4 generic, registering 3-7 impact of implicit casting 2-12 input 1-2 IBM Netezza Stored Procedures Developer's Guide stored procedures (continued) limitations of size-specific input arguments 3-5 loop processing 2-28 managing 3-1 math best practices 2-12 obfuscating the body 3-8 owner of 3-1 PATH session variable 1-4 process to create 3-4 return types 1-2 run 1-3 security and access controls 1-1 security considerations 1-3 See also procedures. 1-1 showing A-9 signature 3-5 starting CALL A-3 using EXECUTE A-3 stored procedures result sets 1-2 user of 3-1 strings, processing in expressions 2-16 T transaction commits in stored procedures 2-2 TRIM method, array variables 2-10 U unconditional loop 2-19 upgrades, and stored procedures 1-7 V VARARGS keyword 2-6, 3-7 variable arguments, benefits of variable scoping 2-7 variables datatypes 2-5 in NZPLSQL 2-5 3-7 W WHILE statement 2-19 wrap_nzplsql built-in procedure 3-8 Part Number: 20470-05 Rev. 1 Printed in USA