ibm db2 9.7 postgresql to db2 porting...

97
IBM DB2 9.7 PostgreSQL to DB2 porting guide Prepared by: IM Partner Technologies - DB2 LUW – Americas Information Management, IBM Software Group January 2010

Upload: others

Post on 21-Jun-2020

33 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

IBM DB2 9.7

PostgreSQL to DB2 porting guide

Prepared by:

IM Partner Technologies - DB2 LUW – Americas Information Management, IBM Software Group

January 2010

Page 2: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

2 2

Table of Contents 1. INTRODUCTION.......................................................................................................5 2. ENABLEMENT OVERVIEW.....................................................................................6

2.1 What is PostgreSQL? ......................................................................................................... 6 2.2 What is DB2 Express-C?.................................................................................................... 7 2.3 Architectural similarities...................................................................................................... 7 2.4 What to expect during the process..................................................................................... 9

3. DATA TYPE MAPPING ..........................................................................................11 3.1 PostgreSQL data types .................................................................................................... 11 3.2 DB2 data types ................................................................................................................. 13 3.3 Comparison of data types................................................................................................. 14 3.4 Some important differences.............................................................................................. 16

3.4.1 Boolean.................................................................................................................... 16 3.4.2 CHARACTER VARYING(n) and VARCHAR(n) limits ............................................. 17 3.4.3 TEXT data type ........................................................................................................ 17 3.4.4 Support of NUMERIC data type............................................................................... 17

4. DATA DEFINITION LANGUAGE (DDL).................................................................19 4.1 Tables ............................................................................................................................... 19

4.1.1 SERIAL columns...................................................................................................... 20 4.1.2 Specifying a TABLESPACE location ....................................................................... 20 4.1.3 Specifying storage USING INDEX TABLESPACE .................................................. 20 4.1.4 WITH and WITHOUT OIDS Clause......................................................................... 21 4.1.5 Constraints............................................................................................................... 21

4.1.5.1 CHECK constraint.............................................................................................. 21 4.1.5.2 NOT NULL constraint......................................................................................... 21 4.1.5.3 UNIQUE constraint ............................................................................................ 22 4.1.5.4 PRIMARY KEY constraint.................................................................................. 22 4.1.5.5 FOREIGN KEY constraint.................................................................................. 23 4.1.5.6 Column default values ....................................................................................... 25

4.2 Temporary tables.............................................................................................................. 26 4.3 Data partitioning ............................................................................................................... 28

4.3.1 Table partitioning in PostgreSQL............................................................................. 28 4.3.2 Range partitioning in DB2........................................................................................ 31 4.3.3 Physical design and partitioning options in DB2...................................................... 34

4.4 Indexes ............................................................................................................................. 34 4.4.1 CONCURRENTLY option for CREATE INDEX ....................................................... 35 4.4.2 Create index specification USING method .............................................................. 35 4.4.3 CREATE INDEX ON (expression) ........................................................................... 35 4.4.4 CREATE INDEX ON (opclass) ................................................................................ 36 4.4.5 ASC, DESC and NULLS FIRST, NULLS LAST....................................................... 36 4.4.6 Creating an index WITH storage attributes.............................................................. 37 4.4.7 Specifying an index table space location................................................................. 38 4.4.8 CREATE INDEX using a WHERE predicate ........................................................... 38

4.5 Views ................................................................................................................................ 39 4.5.1 View compatibility .................................................................................................... 39 4.5.2 Temporary views...................................................................................................... 40 4.5.3 Updateable views..................................................................................................... 40

4.6 Sequence objects ............................................................................................................. 40 4.7 Comments on database objects....................................................................................... 41

Page 3: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

3 3

5. DATA MANIPULATION LANGUAGE (DML) .........................................................43 5.1 INSERT statement............................................................................................................ 43 5.2 UPDATE statement .......................................................................................................... 44 5.3 DELETE statement........................................................................................................... 46 5.4 SELECT statement (queries)............................................................................................ 47

5.4.1 Inner and Outer joins ............................................................................................... 47 5.4.2 Type casting in queries............................................................................................ 47 5.4.3 CASE expression in queries .................................................................................... 48 5.4.4 Sorting NULL values................................................................................................ 48 5.4.5 Restricting results with LIMIT and OFFSET ............................................................ 49 5.4.6 Values list................................................................................................................. 49 5.4.7 Recursive queries .................................................................................................... 50 5.4.8 PERFORM statement .............................................................................................. 51

5.5 SQL Function Mapping..................................................................................................... 51 5.5.1 Numeric function mapping ....................................................................................... 51 5.5.2 Character function mapping..................................................................................... 52 5.5.3 Date and Time function mapping............................................................................. 53 5.5.4 Sample UDFs........................................................................................................... 54

5.5.4.1 INITCAP in DB2 ................................................................................................. 54 5.5.4.2 LPAD in DB2...................................................................................................... 55

6. SQL PROCEDURAL LANGUAGES.......................................................................56 6.1 Stored procedures and functions...................................................................................... 56 6.2 Comparison of PL/pgSQL and SQL PL syntax ................................................................ 56 6.3 Block labeling ................................................................................................................... 58 6.4 RETURNS statement ....................................................................................................... 58 6.5 LANGUAGE statement..................................................................................................... 60 6.6 PL/pgSQL specific attributes ............................................................................................ 60 6.7 Working with variables...................................................................................................... 61

6.7.1 Variable names ........................................................................................................ 61 6.7.2 Declaring variables .................................................................................................. 61 6.7.3 Using an ALIAS for parameters ............................................................................... 62 6.7.4 %TYPE .................................................................................................................... 63 6.7.5 %ROWTYPE............................................................................................................ 63

6.8 Basic Statements.............................................................................................................. 64 6.8.1 SET assignment....................................................................................................... 64 6.8.2 VALUES statement .................................................................................................. 64 6.8.3 NULL statement ....................................................................................................... 64 6.8.4 RETURN statement ................................................................................................. 64

6.9 Control Structures............................................................................................................. 66 6.9.1 IF and CASE statements ......................................................................................... 66 6.9.2 The difference between ELSIF and ELSEIF............................................................ 66 6.9.3 LOOP statement ...................................................................................................... 67 6.9.4 Records and cursors................................................................................................ 67 6.9.5 Working with DB2 cursors and result sets ............................................................... 68

6.10 Condition Handling....................................................................................................... 69 6.10.1 RAISE Statement ................................................................................................ 69 6.10.2 EXCEPTION Statement Block............................................................................. 70 6.10.3 GET DIAGNOSTICS Statement.......................................................................... 70 6.10.4 DECLARE HANDLER Statement........................................................................ 71 6.10.5 SIGNAL Statement .............................................................................................. 72

6.11 Using Dynamic SQL..................................................................................................... 73 6.12 Triggers ........................................................................................................................ 74

6.12.1 FOR EACH ROW and FOR EACH STATEMENT............................................... 75

Page 4: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

4 4

6.12.2 Classified as BEFORE or AFTER ....................................................................... 75 6.12.3 Multiple events on a single object ....................................................................... 75 6.12.4 Multiple triggers for a single event type............................................................... 75 6.12.5 Cascading triggers............................................................................................... 76 6.12.6 Access to transition data and values................................................................... 76 6.12.7 Enabling PostgreSQL triggers in DB2 ................................................................. 77

6.13 PostgreSQL Rules........................................................................................................ 80 7. BASIC SECURITY..................................................................................................82

7.1 Authentication................................................................................................................... 82 7.2 Authorization..................................................................................................................... 83 7.3 Privileges .......................................................................................................................... 83 7.4 Data Control Language (DCL).......................................................................................... 83

7.4.1 Creating a RESTRICTIVE database in DB2............................................................ 83 7.4.2 Instance administrative authority ............................................................................. 84 7.4.3 Database administrative authority ........................................................................... 84 7.4.4 Creating a new database user and granting user privileges ................................... 84

8. MIGRATION ISSUES .............................................................................................85 8.1 Name identifiers................................................................................................................ 85 8.2 Database name length ..................................................................................................... 85 8.3 Column default derived from function............................................................................... 86 8.4 TYPE declarations in functions and procedures .............................................................. 86 8.5 SUBSTR restrictions......................................................................................................... 86 8.6 DEFAULT parameters in functions................................................................................... 87 8.7 Boolean variables and IF statements ............................................................................... 87 8.8 INTERVAL data type ........................................................................................................ 88 8.9 Un-typed NULL values in a SELECT list .......................................................................... 89 8.10 Combined action triggers ............................................................................................. 89 8.11 BEFORE triggers that modify the database................................................................. 89 8.12 Using a function’s expression as an index key ............................................................ 90 8.13 Limitation on table row width........................................................................................ 90 8.14 Disabling triggers.......................................................................................................... 91

9. ADDITIONAL RESOURCES ..................................................................................92 9.1 Education and learning..................................................................................................... 92 9.2 Download products and technologies .............................................................................. 93 9.3 Discussion groups and forums ......................................................................................... 93 9.4 References ....................................................................................................................... 93

9.4.1 PostBooks: An Open Source ERP........................................................................... 93 9.4.2 PostgreSQL Documentation .................................................................................... 93 9.4.3 DB2 Documentation................................................................................................. 93 9.4.4 developerWorks Articles .......................................................................................... 94

APPENDIX A - USING THE IBM DATA MOVEMENT TOOL (IDMT)............................95

Page 5: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

5

1. 0BIntroduction

This document is a technical guide describing the process of enabling a PostgreSQL database application to operate under IBM DB2 Version 9.7 for Linux, UNIX, and Windows (LUW).

This guide is intended to be used to visualize the scope of effort and assist the porting effort by addressing technical issues and identifying the differences between PostgreSQL and DB2 both in functionality and syntax.

While this document contains content that targets a specific migration from a PostgreSQL 8.3 database to DB2 9.7 Express-C, this material can be a useful reference for all development between the two database servers regardless of version.

Regardless of whether a porting effort will be completely manual or if tools will be utilized, this document can provide value. Obviously, if the port is performed manually, this guide will provide the greatest value. If the port will utilize tools, then analysis can be performed using this guide to determine how much of the application the tools will convert, and how much must be converted manually. In any case, this guide is intended to be used to both visualize the scope of a porting effort and to assist in the porting effort by exploring the technical issues. This document is intended to be a living document. Errors of omission, suggestions regarding more effective solutions as well as all other suggestions should be sent to Sam Marino ( [email protected]) and Sreeni Paidi ( [email protected]) so they might be incorporated into future revisions.

Authors Sam Marino, Enablement Consultant, IM Technical Enablement, IBM Software Group

Sreeni Paidi, Enablement Consultant, IM Technical Enablement, IBM Software Group

Contributors Ted Wasserman, for content from his developerWorks article titled Leverage your PostgreSQL V8.1 skills to learn DB2, Version 8.2

Reviewers Chris Braudy, Migration Consultant, WW Migration Center, IBM Software Group

Page 6: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

6

2. 1BEnablement Overview

2.1 10BWhat is PostgreSQL? PostgreSQL is an open source object-relational database system. It has more than 15 years of active development and a proven architecture that has earned it a strong reputation for reliability, data integrity, and correctness. It runs on all major operating systems, including Linux, UNIX (AIX, BSD, HP-UX, SGI IRIX, Mac OS X, Solaris, Tru64), and Windows. It is fully ACID compliant, has full support for foreign keys, joins, views, triggers, and stored procedures (in multiple languages). It includes most SQL92 and SQL99 data types, including INTEGER, NUMERIC, BOOLEAN, CHAR, VARCHAR, DATE, INTERVAL, and TIMESTAMP. It also supports storage of binary large objects, including pictures, sounds, or video. It has native programming interfaces for C/C++, Java, .Net, Perl, Python, Ruby, Tcl, ODBC and others. An enterprise class database, PostgreSQL boasts sophisticated features such as Multi-Version Concurrency Control (MVCC), point in time recovery, table spaces, asynchronous replication, nested transactions (savepoints), online/hot backups, a sophisticated query planner/optimizer, and write ahead logging for fault tolerance. It supports international character sets, multi-byte character encodings, Unicode, and it is locale-aware for sorting, case-sensitivity, and formatting. It is highly scalable both in the sheer quantity of data it can manage and in the number of concurrent users it can accommodate. There are active PostgreSQL systems in production environments that manage in excess of 4 terabytes of data. Some general PostgreSQL limits are included in the table below.

Limit Value

Maximum Database Size Unlimited

Maximum Table Size 32 TB

Maximum Row Size 1.6 TB

Maximum Field Size 1 GB

Maximum Rows per Table Unlimited

Maximum Columns per Table 250 - 1600 depending on column types

Maximum Indexes per Table Unlimited

Page 7: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

7

2.2 11BWhat is HDB2 Express-CH? HIBM DB2 Express-C 9.7 H is a no-charge version of DB2 Express 9 database server. It is designed to be up and running in minutes, is easy-to-use and embed, includes self-management features, and embodies all of the core capabilities of DB2 for Linux, UNIX, and Windows such as pureXML. DB2 Express-C offers the same core data server base features as other DB2 Express editions and provides a solid base to build and deploy applications developed using C/C++, Java, .NET, PHP, Ruby on Rails, Python and other programming languages.

Community based assistance is available at the HDB2 Express-C developerWorks forumH. You can optionally choose to purchase a low-cost yearly subscription (Fixed Term License or FTL) that comes with full technical support, access to software updates (i.e. fixpacks), and includes additional features like High Availability clustering and Data Replication. ISVs and business partners who want to embed a no-charge database with their solutions can distribute DB2 Express-C without paying any fees or royalties to IBM.

Limit Value

Maximum Database Size Unlimited

Maximum Table Size 512 GB in regular tablespace and 16384 GB in a large DMS tablespace.

Maximum Row Size 1.6 TB

Maximum Rows per Table 128 x 1010

Maximum Columns per Table 500 – 1012 (depends on the page size)

Maximum Indexes per Table 32767

2.3 12BArchitectural similarities There are some similarities in the architectural design of PostgreSQL and DB2. Both database systems are based on a client-server architecture, where the client tier is independent of the server. In both cases, a client application wishing to use a database makes a request over the network and is served by a process on the server (postmaster on PostgreSQL, db2agent on DB2). PostgreSQL uses a simple process-per-user client/server model in which one client process connects to exactly one server process. The main process, called postmaster, listens at a specified TCP/IP port for incoming connections and spawns a new server process called postgres every time a connection is requested. The PostgreSQL processes communicate with each other using semaphores and shared memory to ensure data integrity during concurrent data access. Database files are accessed through shared disk buffers.

Page 8: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

8

Figure 1: PostgreSQL Architecture

Spawn Server Process

Postgres Server (Backend)

PostmasterDaemon Process

Server Processes

DB Requests and Results via Library

API

Client Interface Library

Client Application

Client Processes

Shared Disk

Buffers

Shared Tables

Shared Memory

Kernel Disk

Buffers

Operating System

Disk Storage

Create

Read / Write

SQL Queries and Results

Initial Connection Request and

Authentication

In DB2, coordinator agents (db2agent) coordinate the work on behalf of an application and communicate to other agents, using inter-process communication (IPC) or remote communication protocols. All connection requests from client applications, whether they are local or remote, are allocated a corresponding coordinator agent. When intra-partition parallelism is enabled, extra worker agents, called subagents (db2agentp) are spawned by the coordinator agent to help perform the work in parallel. DB2 accesses database files through buffer pools. It has the ability to fetch data into the buffer pools and move data out of the buffer pool asynchronously using prefetcher (db2pfchr) and page cleaner (db2pclnr) processes. The log writer process (db2loggw) flushes log records from the log buffer to the log files on disk, while the log reader process (db2loggr) reads the database log files during transaction processing (in other words, rollback), restart recovery, and roll-forward operations.

Figure 2: DB2 Architecture

Page 9: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

9

Clients

Client Application

Client Application

DB2 Client Library

Shared memory and semaphores, TCPIP, Named Pipes. NetBIOS, SNA, IPX/SPX

DB2 Server

Hard Disk

Log Buffer

LoggerBuffer Pool(s)

Coordinator Agent Coordinator Agent

Subagents Subagents

Logical Agent Pool

Prefetchers

Hard Disk Page Cleaners

Log

Please refer to the following two developerWorks articles for complete overview and comparison of PostgreSQL and DB2 architectures:

Leverage your PostgreSQL V8.1 skills to learn DB2, Version 8.2 HUhttp://www.ibm.com/developerworks/data/library/techarticle/dm-0603wasserman2/index.html Migrate from MySQL or PostgreSQL to DB2 Express-C HUhttp://www.ibm.com/developerworks/data/library/techarticle/dm-0606khatri/ U

2.4 13BWhat to expect during the process Both DB2 and PostgreSQL take pride in standards compliance. Both database’s SQL implementation strongly conforms to the ANSI-SQL 92/99 standards. This provides a significant advantage to your enablement.

Keep in mind is that most relational database vendors implement a similar set of features, for example all have tables, views, indexes, triggers, all support the SQL language, and so on. In fact, the database definition language, or DDL syntax used to define and create the objects is very similar across the different database vendors. However, there are sometimes slight variations you need to take into account. For example, there may be some behavioral differences between how a particular feature or object is implemented. Maybe the same feature exists in both, but is used in a different way. Maybe the feature is

Page 10: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

10

proprietary, in other words it does not conform to any standard, in which case some type of workaround is required.

Typically though, SQL syntax conforming to the SQL standard is portable to DB2 without many changes. It is the proprietary syntax or extensions that require workarounds. Generally speaking, most proprietary extensions encountered in by enablement efforts have acceptable workarounds.

Applications that are written using a standards-based interface driver, for example JDBC interfaces usually require few changes to work with DB2 apart from SQL syntax modifications. That is because the driver interface methods are fairly standard across different database vendors.

Page 11: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

11

3. 2BData Type Mapping

Relational databases implement most of the data types based on the SQL ANSI standard. However, not every database platform supports each and every data type defined by the standards committees. Furthermore, vendor data types of a given name may be implemented differently from what the standard may specify and even differently from all other database vendors. As a result, although many PostgreSQL and DB2 data types are similar in either their name or meaning or both, many differences can be noted as well.

Let us look at commonly used data types in PostgreSQL and DB2.

3.1 14BPostgreSQL data types

Data Type Remark

BIGSERIAL, SERIAL8 Stores an auto-incrementing unique integer value up to 8 bytes of data

BIT A fixed-length bit string

BITVARYING(n), VARBIT(n) A variable-length bit string n bits in length

BOOLEAN Stores a logical Boolean (true/false/unknown) value of either TRUE, t, true, y, yes and 1; FALSE, f, false, n, no and 0.

BYTEA Raw binary data used to store large binary objects such as graphics. Uses 4 bytes plus the length of the binary string for storage

CHAR(n), CHARACTER(n) Contains a fixed-length character string padded with spaces up to a length of n.

DATE Holds a calendar date (year, month, day) in a 4-byte storage space

DATETIME Holds a calendar date and time of day

NUMERIC(p,s),

DECIMAL(p,s)

Stores exact numeric values with a precision (p) and a scale (s) of 0 or higher. Precision can be up to 1000 digits.

NUMERIC Without any precision or scale creates a column in which numeric values of any precision and scale can be

Page 12: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

12

Data Type Remark

stored, up to the implementation limit on precision.

NUMERIC(p) Stores numeric values with the given precision and a scale or 0.

Data Type Remark

FLOAT4, REAL Stores floating-point numbers with a precision of 8 or less and 6 decimal places

FLOAT8,

DOUBLE PRECISION Stores floating-point numbers with a precision of 16 or less and 15 decimal places

SMALLINT Stores signed or unsigned 2-byte integers

INTEGER Stores signed or unsigned 4-byte integers

INT8 BIGINT

Stores signed or unsigned 8-byte integers

SERIAL, SERIAL4 Stores an auto-incrementing unique integer value using up to 4 bytes of its storage.

TEXT Stores large, variable-length, character-string data up to 1 GB. PostgreSQL automatically compresses TEXT strings.

TIME (WITHOUT TIME ZONE | WITH TIME ZONE)

Holds the time of day and stores either no time zone in 8 bytes of storage or the time zone of the database server using 12 bytes of storage.

TIMESTAMP (WITHOUT TIME ZONE |WITH TIME ZONE)

Stores the date and time and stores either no time zone or the time zone of the database server and uses 8 bytes of storage.

VARCHAR(n), CHARACTER VARYING(n), CHARACTER VARYING

Stores variable-length character strings up to a length of n. Trailing spaces are not stored.

Page 13: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

13

3.2 15BDB2 data types

Data Type Remark

BIGINT

A big integer is an eight-byte integer with a precision of 19 digits. The range of big integers is -9 223 372 036 854 775 808 to +9 223 372 036 854 775 807.

BLOB

BLOB(n) Holds variable-length binary data up to 2 GB in length. Lengths over 1 GB are not logged

CHAR(n), CHARACTER(n) Holds fixed-length character data up to 254 bytes in length. Uses 'n' bytes of storage

CHAR(n) FOR BIT DATA Holds fixed-length binary values

CLOB, CLOB(n) Holds variable-length character data up to 2 GB in length. Lengths over 1 GB are not logged

DATE Holds a calendar date without time of day. Uses 4 bytes of storage

DEC(p,s), DECIMAL(p,s), NUM(p,s), NUMERIC(p,s)

Holds a precision (p) of 1 to 31 and a scale (s) of 0 to 31. Uses (p/2) +1 bytes of storage. The maximum range is -1031+1 to 1031-1.

DECFLOAT(p)

A decimal floating-point value is an IEEE 754r number with a decimal point. The position of the decimal point is stored in each decimal floating-point value. The maximum precision is 34 digits. The range of a decimal floating-point number is either 16 or 34 digits of precision, and an exponent range of 10-383 to 10+384 or 10-6143 to 10+6144, respectively.

DOUBLE, DOUBLE PRECISION, FLOAT

Holds floating point numbers and uses 8 bytes of storage.

FLOAT(p)

Holds a precision (p) of 1 to 53. If p <= 24 then a synonym for REAL. If p >= 25 then is a synonym for DOUBLE PRECISION

Page 14: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

14

Data Type Remark

GRAPHIC(n)

Used for National Language Support (NLS) and fixed-length character strings (usually DBCS) up to 127 bytes in length. Uses n*2 bytes of storage for double-byte character sets or n bytes of storage for single-byte character sets.

INT INTEGER

A large integer is a four-byte integer with a precision of 10 digits. The range of large integers is -2 147 483 648 to +2 147 483 647.

REAL

A single-precision floating-point number is a 32-bit approximation of a real number. The number can be zero or can range from:

1.1754943508222875e-38 to 3.4028234663852886e+38.

SMALLINT A small integer is a two-byte integer with a precision of 5 digits. The range of small integers is -32 768 to 32 767.

TIME Holds the time of day and uses 3 bytes of storage

TIMESTAMP Stores the date (year, month, day) and time (hour, minute, second) with up to a precision of 6 for microseconds. Uses 10 bytes of storage

VARCHAR(n), CHAR VARYING(n), CHARACTER VARYING(n)

Holds variable length character data up to 32,672 bytes in length. Uses n+2 bytes of storage

VARCHAR(n) FOR BIT DATA Stores binary data in variable-length. Uses n bytes of storage

VARGRAPHIC(n) Holds variable-length double-byte character data up to 16,336 characters in length. Uses (n*2)+2 bytes of storage

3.3 16BComparison of data types

PostgreSQL DB2 Remark

BIGSERIAL SERIAL8 BIGINT Use IDENTITY Attribute to

simulate auto-increment

Page 15: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

15

PostgreSQL DB2 Remark

feature. Refer to section Error! Reference source not found. for more on SERIAL data types

BIT CHAR(n) FOR BIT DATA

For length up to 254 bytes

BIT VARYING(n) VARBIT(n)

VARCHAR(n) FOR BIT DATA Use if up to 32,672 bytes

BYTEA BLOB Can be used if between 32K and 2GB bytes

BOOLEAN - DB2 doesn’t have a Boolean data type. See section X3.4.1 X for more information.

CHAR(n) CHARACTER (n) CHAR(n) Up to 254 bytes

DATE DATE Use the CURRENT TIMEZONE special register to transform the date.

DATETIME TIMESTAMP Use the CURRENT TIMEZONE special register to transform the date.

DECIMAL(p,s) NUMERIC(p,s) DECIMAL(p,s) For precision > 31, Use

DOUBLE

NUMERIC(p) SMALLINT, BIGINT,

INTEGER Use appropriate data type based on the precision.

NUMERIC DECFLOAT(34) See section X3.4.4 X.

FLOAT4 REAL REAL Can use either NUMERIC or

FLOAT

FLOAT8 DOUBLE PRECISION DOUBLE PRECISION

Use DOUBLE PRECISION for large number or use NUMERIC if precision < 31

Page 16: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

16

PostgreSQL DB2 Remark

SMALLINT SMALLINT

INTEGER INTEGER

INT8 BIGINT BIGINT

VARCHAR(n) CHARACTER VARYING(n) CHARACTER VARYING

VARCHAR(n)

If 'n' is 32K or less. DB2 requires you to specify 'n' while postgres does not enforce a value for 'n'

SERIAL, SERIAL4 INTEGER

Use with IDENTITY attribute. See section Error! Reference source not found. for more information.

TEXT VARCHAR(n), CLOB

Use VARCHAR if length is less than 32K bytes otherwise use BLOB if size is more than 32K bytes. See section X3.4.3 X.

TIME WITHOUT TIME ZONE TIME WITH TIME ZONE TIME DB2 doesn’t include time

zone.

TIMESTAMP WITHOUT TIME ZONE TIMESTAMP WITH TIME ZONE

TIMESTAMP DB2 doesn’t include time zone.

3.4 17BSome important differences

3.4.1 65BBoolean DB2 9.7 does not support BOOLEAN as a column’s data type in a table definition. The choice of data type is relatively easy; either SMALLINT or CHAR(1). This issue’s greatest impact is on the application-side, where all code referencing and testing a BOOLEAN column will need appropriate logic to test the condition and branch procedurally.

In DB2, a BOOLEAN data type can only be used as: • A local variable in a compound SQL (compiled) statement

• A parameter of an SQL routine

Page 17: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

17

• The returns type of an SQL function

• A global variable

3.4.2 66BCHARACTER VARYING(n) and VARCHAR(n) limits In Postgres, CHARACTER VARYING(n) and VARCHAR(n) are available for use as variable size character data. Both of these types can store strings up to n characters (not bytes) in length. If character varying is used without a length specification the type accepts strings of any size. Note, the latter characteristic is a PostgreSQL extension. The VARCHAR data type in DB2 has a maximum length of 32672.

3.4.3 67BTEXT data type It is a common practice in PostgreSQL table definitions to use TEXT column with no size for most of the character and variable length character data.

This introduces a data analysis requirement when porting the table definitions to DB2 because you need to know the maximum possible length of each TEXT column in order to map it to an appropriate VARCHAR(n) or CLOB(n) column in DB2. Use a DB2 VARCHAR data type if less than 32K data is ever stored in the column.

PostgreSQL example: CREATE TABLE accnt ( … accnt_number text, accnt_descrip text, accnt_comments text, accnt_profit text, accnt_sub text, …)

DB2 syntax: CREATE TABLE accnt ( … accnt_number varchar(10), accnt_descrip varchar(30), accnt_comments clob(100000), accnt_profit varchar(10), accnt_sub varchar(10), …)

3.4.4 68BSupport of NUMERIC data type PostgreSQL allows use of NUMERIC data type with no precision and scale for the numeric data columns. This presents a data analysis requirement when porting to DB2 because you need to know what type of data is stored in that column (interger, or a real number) and you also need to know the maximum possible value of the column in order to map it to an appropriate column data type in DB2. Choose the appropriate data type in DB2 based

Page 18: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

18

on the type and maximum length of the value stored in the column. DECFLOAT(34) is probably the best choice in most cases.

PostgreSQL example: CREATE TABLE flrpt ( … flrpt_beginning numeric, flrpt_ending numeric, flrpt_debits numeric, …)

DB2 syntax: CREATE TABLE flrpt ( flrpt_beginning DECFLOAT(34), flrpt_ending INTEGER, flrpt_debits BIGINT, …)

Page 19: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

19

4. 3BData Definition Language (DDL)

In this section, let us take a look at how PostgreSQL and DB2 handle statements to create and alter database objects such as tables, indexes, views, and sequences.

4.1 18BTables There are two types of tables in PostgreSQL: a regular table and a temporary table. Regular tables, just like in any other relational databases, are used to store persistent user data in the database. Temporary tables are used by applications that work with data in the database, where the results from manipulation of the data need to be stored temporarily in a table. Temporary tables are automatically dropped at the end of a session or, optionally, at the end of the current transaction. Any indexes created on a temporary table are automatically temporary as well.

CREATE TABLE statement is used to create regular and temporary tables in PostgreSQL and DB2. Let us look at the high level overview of CREATE TABLE syntax in PostgreSQL and DB2 with an example to create a regular table.

PostgreSQL example: CREATE TABLE apaccnt ( apaccnt_id serial NOT NULL, apaccnt_vendtype_id integer, apaccnt_vendtype text, apaccnt_ap_accnt_id integer NOT NULL, apaccnt_prepaid_accnt_id integer, apaccnt_discount_accnt_id integer, CONSTRAINT apaccnt_pkey PRIMARY KEY (apaccnt_id) USING INDEX TABLESPACE 8KIDXSPC ) TABLESPACE 8KTBLSPC WITH (OIDS=TRUE);

DB2 syntax: CREATE TABLE APACCNT ( APACCNT_ID INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1, CACHE 20), APACCNT_VENDTYPE_ID INTEGER, APACCNT_VENDTYPE VARCHAR(20), APACCNT_AP_ACCNT_ID INTEGER NOT NULL, APACCNT_PREPAID_ACCNT_ID INTEGER, APACCNT_DISCOUNT_ACCNT_ID INTEGER, CONSTRAINT apaccnt_pkey PRIMARY KEY (apaccnt_id) ) IN 8KTBLSPC

Page 20: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

20

INDEX IN 8KIDXSPC;

As you can see in the above examples, syntax of the CREATE TABLE statement is very identical in PostgreSQL and DB2 with a few variations.

Please read the chapter on data type mapping for more information on the data type substitutions.

4.1.1 69BSERIAL columns The data type serial is not a true data type, but it is a unique identifier column.

This is same as an IDENTITY column in DB2. A serial column in PostgreSQL can be replaced with either an IDENTITY column or a column with a default value assigned from a sequence.

PostgreSQL SERIAL column definition: <column_name> SERIAL NOT NULL

DB2 IDENTITY column definition: <column_name> INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1, CACHE 20)

Note: In PostgreSQL, the type names serial and serial4 are equivalent. They both create integer columns. The type names BIGSERIAL and serial8 work the same way, except that they create a BIGINT column.

4.1.2 70BSpecifying a TABLESPACE location TABLESPACE clause defines name of the tablespace in which the newly created table resides.

This is same as the IN clause in DB2. TABLESPACE clause in PostgreSQL should be replaced with IN clause in DB2.

PostgreSQL: TABLESPACE <tablespace_name>

DB2: IN <tablespace_name>

4.1.3 71BSpecifying storage USING INDEX TABLESPACE USING INDEX TABLESPACE clause allows selection of the tablespace in which the index associated with a UNIQUE or PRIMARY KEY constraint will be created. If not specified, the default_tablespace is will be the location, or the PostgreSQL temp_tablespaces if the table is temporary.

Page 21: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

21

This clause should be replaced with INDEX IN clause in DB2. In DB2, INDEX IN clause specifies name of the tablespace in which indexes of the given table are created.

PostgreSQL: USING INDEX TABLESPACE <tablespace_name>

DB2 definition: INDEX IN <tablespace_name>

4.1.4 72BWITH and WITHOUT OIDS Clause The WITH OIDS=TRUE (or WITH OIDS) clause specifies that the rows of the new table should have OIDs (object identifiers) assigned to them. OIDS=FALSE (or WITHOUT OIDS) specifies that the rows should not have OIDs. If OIDS is not specified, the default setting depends upon the Hdefault_with_oidsH configuration parameter in PostgreSQL.

PostgreSQL community doesn't recommend using OIDs in new applications. It is recommended to use a SERIAL or other sequence generator as the table's primary key.

If a table is defined WITH OIDS=TRUE clause and if the application does make use of OIDs to identify specific rows of a table, it is recommended in DB2 to create an additional identity column (or a column with a sequence generator) with a unique constraint enforced on the column.

4.1.5 73BConstraints Databases allow you to define constraints on columns and tables. Constraints give you as much control over the data in your tables as you wish. If a user attempts to store data in a column that would violate a constraint, an error is raised. This applies even if the value came from the default value definition.

Both PostgreSQL and DB2 allow you to define the following types of constraints on the columns and the tables with slight or no differences:

4.1.5.1 134BCHECK constraint

A check constraint allows you to specify that the value in a certain column must satisfy a Boolean expression. There is no difference in the way a check constraint is defined in PostgreSQL and DB2.

PostgreSQL example: price numeric CHECK (price > 0)

DB2 example: price decimal(10,2) CHECK (price > 0)

4.1.5.2 135BNOT NULL constraint

A not-null constraint specifies that a column must not assume the null value. It is defined exactly the same way in PostgreSQL and DB2.

Page 22: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

22

PostgreSQL example: aropen_docdate date NOT NULL

DB2 example: aropen_docdate date NOT NULL

4.1.5.3 136BUNIQUE constraint

PostgreSQL allows null values in columns defined as UNIQUE or the columns used in a composite UNIQUE constraint. Hence in PostgreSQL, two null values are not considered equal. That means even in the presence of a unique constraint it is possible to store duplicate rows that contain a null value in at least one of the constrained columns.

This behaviour is not allowed in DB2. DB2 doesn’t allow null values in the columns defined as UNIQUE or the columns used in a composite UNIQUE constraint. NOT NULL constraint must be explicitly enforced on these columns.

PostgreSQL example: CREATE TABLE budghead ( budghead_id serial NOT NULL, budghead_name text, budghead_descrip text, CONSTRAINT budghead_pkey PRIMARY KEY (budghead_id), CONSTRAINT budghead_budghead_name_key UNIQUE (budghead_name) ) WITH (OIDS=FALSE);

DB2 example: CREATE TABLE budghead ( budghead_id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY (start with 2, increment by 1, cache 20), budghead_name varchar(100) NOT NULL, budghead_descrip varchar(200), CONSTRAINT budghead_pkey PRIMARY KEY (budghead_id), CONSTRAINT budghead_budghead_name_key UNIQUE (budghead_name) );

4.1.5.4 137BPRIMARY KEY constraint

A primary key is unique and not null. Both in PostgreSQL and DB2, a table can have at most one primary key. It indicates that a column or group of columns can be used as a unique identifier for rows in the table. A primary key is defined exactly the same way in PostgreSQL and DB2.

PostgreSQL example: CREATE TABLE addr ( addr_id serial NOT NULL, … CONSTRAINT addr_pkey PRIMARY KEY (addr_id)

Page 23: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

23

);

DB2 example: CREATE TABLE ADDR ( ADDR_ID INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 8, INCREMENT BY 1, CACHE 20), … CONSTRAINT addr_pkey PRIMARY KEY (addr_id) );

4.1.5.5 138BFOREIGN KEY constraint

A foreign key constraint maintains referential integrity between two tables.

Implementing Foreign Key in PostgreSQL Let us first look at how foreign key is implemented in PostgreSQL.

One of the following two syntaxes can be used to define a foreign key in PostgreSQL.

Column Constraint: REFERENCES reftable [ ( refcolumn ) ] [ MATCH matchtype ] [ ON DELETE action ] [ ON UPDATE action ] (column constraint)

Table Constraint: FOREIGN KEY ( column [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH matchtype ] [ ON DELETE action ] [ ON UPDATE action ] (table constraint) These clauses specify a foreign key constraint, which requires that a group of one or more columns of the new table must only contain values that match values in the referenced column(s) of some row of the referenced table. If refcolumn is omitted, the primary key of the reftable is used. The referenced columns must be the columns of a unique or primary key constraint in the referenced table. Note that foreign key constraints cannot be defined between temporary tables and permanent tables.

• The MATCH clause specifies how value(s) inserted into the referencing column(s) is matched against the values of the referenced table and referenced columns using the given match type. There are three match types: MATCH FULL, MATCH PARTIAL, and MATCH SIMPLE, which is also the default. MATCH FULL will not allow one column of a multicolumn foreign key to be null unless all foreign key columns are null. MATCH SIMPLE allows some foreign key columns to be null while other parts of the foreign key are not null. MATCH PARTIAL is not yet implemented.

• The ON DELETE clause specifies the action to perform when a referenced row in the referenced table is being deleted.

• The ON UPDATE clause specifies the action to perform when a referenced column in the referenced table is being updated to a new value.

• Following are the possible actions for ON DELETE and ON UPDATE.

Page 24: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

24

• NO ACTION or RESTRICT - Either these produce an error indicating that the deletion or update would create a foreign key constraint violation. NO ACTION is the default action.

• CASCADE - Delete any rows referencing the deleted row, or update the value of the referencing column to the new value of the referenced column, respectively.

• SET NULL - Set the referencing column(s) to null.

• SET DEFAULT - Set the referencing column(s) to their default values.

Implementing Foreign Key in DB2 Now let us take a look at how foreign keys are implemented in DB2.

One of the following two syntaxes can be used to define a foreign key in DB2.

Column Constraint: REFERENCES reftable [ ( refcolumn ) ] [ ON DELETE action ] [ ON UPDATE action ]

Table Constraint: FOREIGN KEY ( column [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ ON DELETE action ] [ ON UPDATE action ] There is no MATCH clause in DB2 when defining foreign key. However, when multicolumn foreign key is defined on a table in DB2, its MATCH behaviour is equivalent to MATCH SIMPLE in PostgreSQL. That means DB2 doesn’t support MATCH FULL.

Following are the possible actions for ON DELETE in DB2.

• NO ACTION (default)

• RESTRICT

• CASCADE

• SET NULL As you can see, DB2 doesn’t have SET DEFAULT as a possible ON DELETE action. When porting to DB2, remember to change your ON DELETE action to a supported action if you are using SET DEFAULT in PostgreSQL.

Following are the only possible ON UPDATE actions in DB2.

• NO ACTION (default) • RESTRICT

DB2 doesn’t have CASCADE, SET NULL, and SET DEFAULT as the possible ON UPDATE actions. Likewise, when porting to DB2, it will be necessary to change the ON UPDATE to a supported action if any of the unsupported actions are in use.

Page 25: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

25

4.1.5.6 139BColumn default values

PostgreSQL uses DEFAULT clause and DB2 uses WITH DEFAULT clause to assign a default value for a column in the create table statement. The keyword WITH in WITH DEFAULT is optional in DB2.

PostgreSQL example: DEFAULT default_expr

DB2 syntax: [WITH] DEFAULT default_expr

The value is any variable-free expression. The data type of the default expression must match the data type of the column.

The default expression will be used in any insert operation that does not specify a value for the column. If there is no default for a column, then the default is NULL if the column accepts NULL values.

DB2 accepts the following default values:

• A constant

• Datetime-special-registers (CURRENT DATE, CURRENT TIME, or CURRENT TIMESTAMP)

• User-special-registers (CURRENT USER, SESSION_USER, SYSTEM_USER) • CURRENT SCHEMA special register

• GENERATED column value

• EMPTY_CLOB(), EMPTY_DBCLOB(), or EMPTY_BLOB() - Specifies a zero-length string as the default for the column. The column must have the data type that corresponds to the result data type of the function.

In DB2, a cast-function can be applied on the default value in the default clause, when the column is defined as a distinct type, BLOB or datetime (DATE, TIME or TIMESTAMP) data type.

Things to watch for when porting from PostgreSQL: Unlike PostgreSQL, DB2 doesn’t allow assigning the return value of a user-defined function as a default value.

For example, the following assignment is not allowed in DB2: arapply_curr_id integer DEFAULT basecurrid()

PostgreSQL allows using system-defined type-conversion functions like bpchar, text etc. Remove type-casting or use equivalent function when porting to DB2.

Page 26: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

26

PostgreSQL example: flhead_type character(1) NOT NULL DEFAULT 'A'::bpchar

DB2 syntax: flhead_type character(1) NOT NULL DEFAULT 'A' Use appropriate special registers in DB2

PostgreSQL example: bankrec_created timestamp without time zone NOT NULL DEFAULT ('now'::text)::timestamp(6) with time zone

DB2 syntax: bankrec_created timestamp NOT NULL DEFAULT CURRENT TIMESTAMP

4.2 19BTemporary tables In this section, let’s talk about how the temporary tables are implemented in PostgreSQL and DB2 and any changes that need to be made when porting to DB2.

Temporary Table implementation in PostgreSQL Following is the syntax of CREATE TABLE command used to create a temporary table in PostgreSQL. CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE table_name (columns_definition) [ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP }] PostgreSQL requires each session to issue its own CREATE TEMPORARY TABLE command for each temporary table to be used. This allows different sessions to use the same temporary table name for different purposes.

PostgreSQL's behavior of temporary tables is similar to that of DB2. PostgreSQL will accept the GLOBAL and LOCAL keywords in a temporary table declaration, but they have no effect.

Existing permanent tables with the same name are not visible to the current session while the temporary table exists, unless they are referenced with schema-qualified names. Any indexes created on a temporary table are automatically temporary.

Temporary table implementation in DB2 Following is the syntax of CREATE / DECLARE TABLE command used to create a temporary table in DB2. {CREATE | DECLARE} GLOBAL TEMPORARY TABLE table_name (columns_definition) [ON COMMIT { PRESERVE ROWS | DELETE ROWS }] [NOT LOGGED {ON ROLLBACK DELETE ROWS | ON ROLLBACK PRESERVE ROWS} | LOGGED] [WITH REPLACE]

Page 27: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

27

[IN tablespace-name] In DB2 9.7, either you can either create or declare a global temporary table. (Created temporary tables are new in DB2 9.7.)

The definition of a CREATED temporary table is stored persistently in the DB2 catalog. Although the contents of a created temporary table is private to a session (just like DECLARED temporary tables), its definition is shared across all concurrent sessions. The persistent storage of the created temporary table definition results in the following operational differences:

After an application session defines a created temporary table, concurrently running sessions do not have to redefine it.

You can reference a created temporary table in SQL functions, triggers, and views. Any connection can refer to a created temporary table at any time without the need for a setup script to initialize the created temporary table.

Just as with a DECLARED temporary table, each session that selects from a created temporary table retrieves only rows that the same session has inserted. When the session terminates, the rows of the table associated with the session are deleted. The DECLARE GLOBAL TEMPORARY TABLE statement also defines a temporary table for the current session. However, the declared temporary table description does not appear in the system catalog. It is not persistent and cannot be shared with other sessions. Each session that defines a declared global temporary table of the same name has its own unique description of the temporary table. When the session terminates, the rows of the table are deleted, and the description of the temporary table is dropped. Any compiled program accessing a DECLARED temporary table must have a definition of the table in the program to allow the program to be compiled.

ON COMMIT specifies the action taken on the global temporary table when a COMMIT operation is performed. The default is DELETE ROWS.

LOGGED or NOT LOGGED specifies whether operations for the table are logged. The default is LOGGED.

ON ROLLBACK specifies the action that is to be taken on the not logged global temporary table when a ROLLBACK (or ROLLBACK TO SAVEPOINT) operation is performed. The default is DELETE ROWS.

WITH REPLACE indicates that, in the case that a declared temporary table already exists with the specified name, the existing table is replaced with the temporary table defined by this statement (and all rows of the existing table are deleted). When WITH REPLACE is not specified, then the name specified must not identify a declared temporary table that already exists in the current session

IN tablespace-name identifies the table space in which the declared temporary table will be instantiated. The table space must exist and be a USER TEMPORARY table space. If this clause is not specified, a table space for the table is determined by choosing the USER TEMPORARY table space with the smallest sufficient page size over which the authorization ID of the statement has USE privilege.

Page 28: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

28

Things to watch for when porting: The default ON COMMIT action in DB2 is DELETE ROWS where as the default in PostgreSQL is PRESERVE ROWS.

There is no ON COMMIT DROP option available in DB2.

Make sure there is a user temporary tablespace created with sufficient page size for the temporary table and the authorization ID..

4.3 20BData partitioning Data partitioning is an organizational scheme in which table data is divided across multiple data partitions according to values in one or more partitioning columns of the table. A typical table partitioning column is a date column; each partition is then defined in DDL to encompass a meaningful date range (e.g., each partition holds rows for one month, one quarter, or one year). Data from a given table is partitioned into multiple storage objects, which can be in different table spaces.

There are many benefits of table partitioning:

• Improved query performance

• Increased table capacity

• Bulk loads and deletes can be handled by easily attaching to and detaching data from a table

4.3.1 74BTable partitioning in PostgreSQL PostgreSQL supports partitioning via table inheritance. Each partition must be created as a child table of a single parent table. The parent table itself is normally empty; it exists just to represent the entire data set.

The following forms of partitioning can be implemented in PostgreSQL:

• Range Partitioning - The table is partitioned into "ranges" defined by a key column or set of columns, with no overlap between the ranges of values assigned to different partitions. For example one might partition by date ranges.

• List Partitioning -= The table is partitioned by explicitly listing which key values appear in each partition.

There is no difference in syntax between range and list partitioning; those terms are descriptive only.

Implementing Partitioning in PostgreSQL – with an example Implementing table partitioning in PostgreSQL is a long process. You will see how simple it is to implement partitioning in DB2 in the following section. But first, let us look at how it is done in PostgreSQL

Create the master table, from which all of the partitions will inherit.

Page 29: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

29

This is an empty table and data is never inserted into this table. Do not define any check constraints on this table, unless you intend them to be applied equally to all partitions. You shouldn’t create any indexes or unique constraints on this table either since it is an empty table. For example:

CREATE TABLE orders ( orderkey NUMERIC NOT NULL, partkey NUMERIC, suppkey NUMERIC, linenumber NUMERIC, quantity NUMERIC, extendedprice NUMERIC, shipdate DATE );

Create the child tables that each inherit from the master table. Call them partition tables. These partition tables will not add any columns to the set that is inherited from the master. Add table constraints to the partition tables to define the allowed key values in each partition. Ensure that the constraints guarantee that there is no overlap between the key values permitted in different partitions. In the following example, the master orders table will be partitioned on the shipdate column to store 12 months data for 2009, each month in a separate partition. We have to create 12 partition tables by inheriting the above defined master table. CREATE TABLE orders_y2009_jan ( CHECK ( shipdate >= DATE '2009-01-01' AND shipdate < DATE '2009-02-01' ) ) INHERITS (orders); CREATE TABLE orders_y2009_feb ( CHECK ( shipdate >= DATE '2009-02-01' AND shipdate < DATE '2009-03-01' ) ) INHERITS (orders); . . CREATE TABLE orders_y2009_dec ( CHECK ( shipdate >= DATE '2009-12-01' AND shipdate < DATE '2010-01-01' ) ) INHERITS (orders);

Each of these partitions are complete tables in their own right, but they inherit their definitions from the orders table.

You probably need to create indexes on the key columns too. CREATE INDEX orders_y2009_jan_shipdate

ON orders_y2009_jan (shipdate);

CREATE INDEX orders_y2009_feb_shipdate ON orders_y2009_feb (shipdate);

.

Page 30: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

30

. CREATE INDEX orders_y2009_dec_shipdate

ON orders_y2009_dec (shipdate);

In order to have the data to be redirected into the appropriate partition table when your application inserts into the master table, define triggers to locate the partition into which the row should be added. Do this with a complex trigger function, for example: CREATE OR REPLACE FUNCTION orders_insert_trigger() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.shipdate >= DATE '2009-01-01' AND NEW.shipdate < DATE '2009-02-01' ) THEN INSERT INTO orders_y2009_jan VALUES (NEW.*); ELSIF ( NEW.shipdate >= DATE '2006-02-01' AND NEW.shipdate < DATE '2009-03-01' ) THEN INSERT INTO orders_y2009_feb VALUES (NEW.*); ... ELSIF ( NEW.shipdate >= DATE '2009-12-01' AND NEW.shipdate < DATE '2010-01-01' ) THEN INSERT INTO orders_y2009_dec VALUES (NEW.*); ELSE RAISE EXCEPTION 'Date out of range. Fix the or ders_insert_trigger() function!'; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql; After creating the function, create a trigger which calls the trigger function: CREATE TRIGGER insert_orders_trigger BEFORE INSERT ON orders FOR EACH ROW EXECUTE PROCEDURE orders_insert_trigger(); Note: When adding a new partition, you must redefine the trigger function. This is a sizable maintenance task. However, the trigger definition does not need to be updated.

Managing Partitions in PostgreSQL – with an example Now let us look at how an existing partition can be dropped and a new partition can be added in PostgreSQL.

Dropping a partition The simplest option for removing old data is to drop the partition that is no longer necessary: DROP TABLE orders_y2009_jan;

Page 31: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

31

Another option that is often preferable is to remove the partition from the partitioned table but retain access to it as a table in its own right: ALTER TABLE orders_y2009_jan NO INHERIT orders;

Note: In both these cases, you can update the trigger function to remove the code related to the dropped / detached partition.

Adding a new partition Add a new partition to handle new data. Create an empty partition in the partitioned table just as the original partitions were created above: CREATE TABLE orders_y2010_jan ( CHECK ( shipdate >= DATE '2010-01-01'

AND shipdate < DATE '2010-02-01' ) ) INHERITS (orders);

As an alternative, create the new table outside the partition structure, and make it a proper partition later. This allows the data to be loaded, checked, and transformed prior to it appearing in the partitioned table: CREATE TABLE orders_y2010_jan (LIKE orders INCLUDING DEFAULTS INCLUDING CONSTRAINTS); ALTER TABLE orders_y2010_jan ADD CONSTRAINT y2010_jan CHECK ( shipdate >= DATE '2010-01-01'

AND shipdate < DATE '2010-02-01' ); copy orders_y2010_jan from 'c:\data\jan2010data'; ALTER TABLE orders_y2010_jan INHERIT orders;

4.3.2 75BRange partitioning in DB2 Range partitioning in DB2 is also referred to as table partitioning or data partitioning. This data organization scheme is one in which table data is divided across multiple storage objects called data partitions or ranges according to values in one or more table columns. Each data partition is stored separately and can be in different table spaces.

Implementing Range Partitioning in DB2 – with an example In the following example we demonstrate the method for porting the PostgreSQL table partitions discussed in section 5.1.3.1 to a DB2 partitioned table. CREATE TABLE orders ( orderkey DECIMAL(10,0) NOT NULL, partkey INTEGER, suppkey INTEGER, linenumber INTEGER, quantity DECIMAL(12,2), extendedprice DECIMAL(12,2), shipdate DATE ) PARTITION BY RANGE(shipdate)

Page 32: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

32

PARTITION y2009_jan STARTING '1/1/2009', PARTITION y2009_feb STARTING '2/1/2009', PARTITION y2009_mar STARTING '3/1/2009', … PARTITION y2009_dec STARTING '12/1/2009' ENDING ‘12/31/2009' );

No other actions are necessary. Child tables and triggers are not needed.

Managing Partitions in DB2 – with an example Now let us look at how an existing partition can be dropped and a new partition can be added in DB2.

Dropping a partition Drop a partition in DB2 by simply detaching (rolling-out) a partition as shown below. ALTER TABLE orders DETACH PARTITION y2009_jan INTO orders_y2009_jan;

Adding a new partition Attaching (rolling-in) data as a new data partition in a table is just as easy. The data that is to be rolled-in is first loaded into a separate (staging) table, transformed or cleansed if needed, and then attached to an existing table as shown in the following example. CREATE TABLE y2010_jan_orders . . . -- load / insert desired data into y2010_jan_orders -- transform or cleanse new data if neeeded ALTER TABLE orders ATTACH PARTITION y2010_jan STARTING '01/01/2010' ENDING '01/31/2010' FROM TABLE y2010_jan_orders; COMMIT; SET INTEGRITY . . . COMMIT;

Note: Before the rolled-in data is visible to applications, a SET INTEGRITY statement needs issued (to validate the new data and perform maintenance for global indexes) and the work committed.

More partitioning examples in DB2:

Example 1:

Page 33: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

33

In the following example, we are going to use a “shorthand” notation that automatically generates 12 partitions of uniform size; that is, one partition for each month over a one-year period. Note that MINVALUE and MAXVALUE will accept any values that fall below and above the defined ranges. CREATE TABLE orders ( orderkey DECIMAL(10,0) NOT NULL, … shipdate DATE ) PARTITION BY RANGE(shipdate) (STARTING MINVALUE, STARTING '1/1/2009' ENDING '12/31/2009' EVERY 1 MONTH, ENDING AT MAXVALUE);

Example 2:

The following example illustrates table partitioning using manual syntax, which is required when the partitioning key is composed of a composite column. This syntax also allows specification of a different table space for each partition (desired in some implementations to facilitate backup strategies). CREATE TABLE sales ( year INT, month INT, … ) IN tbsp1, tbsp2, tbsp3, tbsp4, tbsp5, tbsp6, tbsp7, tbsp8 PARTITION BY RANGE (year, month) (STARTING FROM (2001, 1) ENDING (2001,3) IN tbsp1, ENDING (2001,6) IN tbsp2, ENDING (2001,9) IN tbsp3, ENDING (2001,12) IN tbsp4, ENDING (2002,3) IN tbsp5, ENDING (2002,6) IN tbsp6, ENDING (2002,9) IN tbsp7, ENDING AT MAXVALUE);

Example 3:

DB2 provides a method of table partitioning that is based on a generated expression of a column. Depending on the situation, table partitioning on a generated column may be used in a similar way to list partitioning in PostgreSQL. CREATE TABLE customer ( cust_id INT, cust_prov CHAR(2), cust_prov_gen GENERATED ALWAYS AS (CASE WHEN cust_prov = 'AB' THEN 1 WHEN cust_prov = 'BC' THEN 2

Page 34: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

34

WHEN cust_prov = 'MB' THEN 1 WHEN cust_prov = ‘SA’ THEN 3

... WHEN cust_prov = 'YT' THEN 13 ELSE 14

END) ) IN tbsp_ab, tbsp_bc, tbsp_mb, .... tbsp_remainder PARTITION BY RANGE (cust_prov_gen) (STARTING 1 ENDING 14 EVERY 1); In the previous example, numeric values are generated based on values for CUST_PROV. The numeric values populate the generated column, CUST_PROV_GEN, on which table partitioning is based.

Because an automatic version of the syntax is used in this example, it is sufficient to list the table spaces for each partition with a single IN clause. If the manual version of the syntax was used and each partition was defined individually, then an IN clause for each partition would be required.

4.3.3 76BPhysical design and partitioning options in DB2 DB2 can be designed to organize data in many other ways as well. These different data organization schemes can be specified at the database or table level.

The other data organization methods available on DB2 are:

• Database partitioning (also known as hash partitioning and DPF)

• Multidimensional clustering (also called MDCs)

• Combined organization schemes While complete coverage of DB2 partitioning features is beyond the scope of this guide, the following Web sites provide resources to learn about different DB2 data partitioning features and the best approach to implement each of them:

DB2 partitioning features - An overview for data warehouses HUhttp://www.ibm.com/developerworks/db2/library/techarticle/dm-0608mcinerney/

Introducing DB2 9, Part 2: Table partitioning in DB2 9 HUhttp://www.ibm.com/developerworks/db2/library/techarticle/dm-0605ahuja2/

Database Partitioning, Table Partitioning, and MDC for DB2 9 HUhttp://www.redbooks.ibm.com/abstracts/sg247467.html

4.4 21BIndexes Indexes are of vital importance to the performance of query processing. Indexes are created to shorten the access path to the data stored within a table and decrease the amount of I/O required to find and load a set of data.

Page 35: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

35

While the basic format is the same and can be processed by either database, the extensions supported by each provide a number of differences between PostgreSQL and DB2. The following statement will create a B-tree index based on the column title in the table films on both databases: CREATE UNIQUE INDEX title_idx ON films (title); Both PostgreSQL and DB2 provide a CREATE INDEX statement as an extension of their supported SQL. There are no provisions for indexes in the SQL standard so differences are expected. Both databases apply proprietary nuances for efficiencies of storage and access.

The following options are provided by Postgres and you must addressed these prior to migration:

4.4.1 77BCONCURRENTLY option for CREATE INDEX When this option is used, PostgreSQL will build the index without taking any locks that prevent concurrent inserts, updates, or deletes on the table. A standard index build locks out writes (but not reads) on the table until it's done. CREATE INDEX CONCURRENTLY title_idx ON films (title); In contrast, DB2 allows read and write access to the table while an index is being created. No keyword specification is necessary. For the identical behavior in DB2 as Postgres, simply remove the CONCURRENTLY keyword. To circumvent DB2’s default behavior, and keep the table locked during index creation use the DB2 LOCK TABLE statement to explicitly lock the table prior to issuing the CREATE INDEX statement. The table can be locked in either SHARE or EXCLUSIVE mode, using SHARE when read access is to be permitted. LOCK TABLE films IN EXCLUSIVE MODE; CREATE INDEX CONCURRENTLY title_idx ON films (title);

4.4.2 78BCreate index specification USING method When creating a PostgreSQL index the CREATE INDEX statement supports and option for specifying the indexing method for control of the index’s internal structure. Postgres supports 4 index methods; B-tree, R-tree, hash, or GiST.

All DB2 indexes are created using a balanced tree (b-tree). PostgreSQL’s default method is btree, which is compatible with DB2.

4.4.3 79BCREATE INDEX ON (expression) PostgreSQL supports creating an index using the result of an expression operating on one or more columns of the table. Expressions can range from the simple to the complex depending upon the tasks you want to accomplish. One benefit of utilizing indexes based on expressions is improved performance.

Page 36: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

36

A common example of the most prevailing use of an index built on an expression is the use of the result returned from the UPPER function shifting case of a character column. This is used to create a case insensitive column and corresponding index key which can be used by the database’s query optimizer when considering the query’s data access plan.

Expression-based indexes are not supported in DB2. However there is a facility for emulating this functionality. Refer to the Migration Issues section and HUsing a Function as an Index KeyH for a suggested solution applicable to creating an UPPER (or LOWER) expression-based index. Alternatively, to support a case insensitive search, you can define a generated column in DB2 which automatically stores an upper case version of a table column.

4.4.4 80BCREATE INDEX ON (opclass) In PostgreSQL, an operator class can be specified for each column of an index. The operator class identifies the operators to be used by the index for that column. For example, a B-tree index on four-byte integers would use the int4_ops class; this operator class includes comparison functions for four-byte integers. The main point of having operator classes is that for some data types, there could be more than one meaningful ordering. In practice the default operator class for the column's data type is usually sufficient.

DB2 does not support operator classes.

4.4.5 81BASC, DESC and NULLS FIRST, NULLS LAST When creating an index both PostgreSQL and DB2 can specify the sort order of the column values included in the index key definition. Both databases use the keywords ASC for ascending and DESC for descending. When the sort order is not specified both databases will default to ascending (ASC). CREATE UNIQUE INDEX itemcost_master_idx ON itemcost USING btree ( itemcost_item_id ASC, itemcost_costelem_id DESC, itemcost_lowlevel ASC ); PostgreSQL has additional support applying a rule which specifies can modify the sequence order of data containing NULL values. The keywords NULL FIRST or NULL LAST can designate where in the requested sort order that NULL values should be returned. NULLS FIRST specifies that nulls sort before non-nulls. NULLS LAST specifies that nulls sort after non-nulls.

The Postgres default null handling rule is determined by the sort order. If the sort order is not specified or specified to be ascending (ASC) then NULLS LAST is the default. With a descending (DESC) sequence NULLS FIRST is the default.

The matching defaults can assist in migrations. By default, DB2 will sort ASC with NULLS LAST. When overriding the order to DESC will cause DB2 to sort NULLS FIRST. Both databases default to the same sorting behavior.

Page 37: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

37

CREATE UNIQUE INDEX itemcost_master_idx ON itemcost USING btree ( itemcost_item_id ASC, itemcost_costelem_id DESC NULLS LAST, itemcost_lowlevel ASC );

PostgreSQL’s default behavior in each default scenario is the same as DB2’s. An item requiring a custom migration solution would occur if the Postgres database has indexes with non-default sort ordering of nulls (i.e. NULLS FIRST with an ASC sequence or NULLS LAST with an ascending sort). CREATE UNIQUE INDEX itemcost_master_idx ON itemcost USING btree ( itemcost_item_id ASC NULLS FIRST, itemcost_costelem_id DESC, itemcost_lowlevel ASC );

4.4.6 82BCreating an index WITH storage attributes The WITH clause can specify storage attributes for PostgreSQL indexes. Each index method (i.e. USING method) has it’s own set of allowed characteristics.

The FILLFACTOR for an index is a percentage that determines how full the index method will try to pack index pages. The leaf pages are filled to this percentage during initial index build, and also when extending the index at the right (largest key values):

PostgreSQL example: CREATE UNIQUE INDEX title_idx ON films (title) WITH (FILLFACTOR = 70); B-tree indexes use a default FILLFACTOR of 90, but any value from 10 to 100 can be selected. If the table is static then FILLFACTOR 100 is best to minimize the index's physical size. For heavily updated tables, a smaller FILLFACTOR is better to minimize the need for page splits.

Any other index method, used in conjunction with a corresponding storage parameter, is not supported by DB2 and should be removed from index creation DDL.

As DB2 only supports B-tree indexes, only the PostgreSQL FILLFACTOR needs to be facilitated between the databases for enablement. DB2’s CREATE INDEX statement supports PCTFREE which is comparable to the PostgreSQL FILLFACTOR. PCTFREE specifies what percentage of each index page to leave as free space when building and maintaining the index. Additional entries are placed in an index page at least integer percent of free space is left on each page. The value of integer can range from 0 to 99. If a value greater than 10 is specified, only 10 percent free space will be left in non-leaf pages. The default is 10.

DB2 syntax: CREATE UNIQUE INDEX title_idx ON films (title) PCTFREE 10;

Page 38: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

38

4.4.7 83BSpecifying an index table space location Postgres’ CREATE INDEX statement supports a designation of the table spaces in which to create the index. The designation for index location in DB2 is on the CREATE TABLE statement:

PostgreSQL example: CREATE INDEX itemcost_master_idx ON itemcost USING btree ( itemcost_item_id, itemcost_costelem_id, itemcost_lowlevel ) TABLESPACE idxtbsp;

DB2 syntax: CREATE TABLE itemcost ( itemcost_id integer NOT NULL DEFAULT, itemcost_item_id integer NOT NULL, itemcost_costelem_id integer NOT NULL, itemcost_stdcost numeric(16,6) NOT NULL DEFAULT 0, itemcost_posted date, itemcost_actcost numeric(16,6) NOT NULL DEFAULT 0, itemcost_updated date, itemcost_curr_id integer NOT NULL DEFAULT 0, CONSTRAINT itemcost_pkey PRIMARY KEY (itemcost_id), CONSTRAINT itemcost_itemcost_costelem_id_fkey FOREIGN KEY (itemcost_costelem_id) REFERENCES costelem (costelem_id) ON UPDATE NO ACTION ON DELETE NO ACTION ) IN data_tbsp INDEX IN index_tbsp;

4.4.8 84BCREATE INDEX using a WHERE predicate

Where a Postgres’ CREATE INDEX includes the use of a WHERE clause, a partial index is created. The partial index is an index that contains entries for only a portion of a table, usually a portion that is more useful for indexing than the rest of the table.

DB2 does not support a partial index. The keyword WHERE and the predicate must be removed. The resulting index will be created on all rows in the table.

DB2 Best Practice: RUNSTATS Once an index is created and data is loaded into the table, issue a RUNSTATS command to update statistics collected on the database tables, columns, and indexes. These statistics are used to determine the optimal access path to the tables. By issuing the RUNSTATS command, the database manager can determine the characteristics of the new index.

Page 39: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

39

If data has been loaded before the CREATE INDEX statement is issued, it is recommended that the COLLECT STATISTICS option on the CREATE INDEX statement be used as an alternative to the RUNSTATS command:

Example 1: Create an index named IDX1 on a table named TAB1, and collect basic index statistics on index IDX1. CREATE INDEX IDX1 ON TAB1 (col1) COLLECT STATISTICS

Example 2: Create an index named IDX2 on a table named TAB1, and collect detailed index statistics on index IDX2: CREATE INDEX IDX2 ON TAB1 (col2) COLLECT DETAILED STATISTICS

Example 3: Create an index named IDX3 on a table named TAB1, and collect detailed index statistics on index IDX3 using sampling: CREATE INDEX IDX3 ON TAB1 (col3) COLLECT SAMPLED DETAILED STATISTICS

4.5 22BViews Both PostgreSQL and DB2 implement views in basically the same conceptual classification. A view is not physically materialized. Instead, the view's underlying query is run every time the view is referenced in a SQL statement.

Views are implemented in PostgreSQL as a database rule. Internally a SELECT processed against a view will invoke a rule which substitutes the base tables and columns from the view’s definition.

4.5.1 85BView compatibility Both PostgreSQL and DB2 view definitions adhere to the SQL standard which has specifications for some additional capabilities applied using the CREATE VIEW statement: CREATE VIEW name [ ( column_name [, ...] ) ] AS query [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]

The optional clauses are:

• CASCADED - Check for integrity on this view and on any dependent view. The default is CASCADED when neither CASCADED nor LOCAL is specified.

• LOCAL - Check for integrity on this view • CHECK OPTION - This option has to do with updatable views. All INSERT and

UPDATE commands on the view will be checked to ensure data satisfy the view-defining condition.

View definitions can be converted easily as the syntax of PostgreSQL and DB2 are nearly identical. In the example below, the only modification needed is to remove any casting of a resulting column’s data type.

Page 40: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

40

PostgreSQL example: CREATE OR REPLACE VIEW api.itemfile AS SELECT item.item_number::character varying AS item_number, url.url_title AS title, url.url_url AS url, ‘’::text as ur.url_description FROM item, url WHERE item.item_id = url.url_source_id AND url.url_source = 'I'::text;

DB2 syntax: CREATE OR REPLACE VIEW api.itemfile AS SELECT item.item_number AS item_number, url.url_title AS title, url.url_url AS url, ‘’ as url.url_description FROM item, url WHERE item.item_id = url.url_source_id AND url.url_source = 'I';

4.5.2 86BTemporary views If specified, a PostgreSQL view can be created as a temporary view. Temporary views are automatically dropped at the end of the current session.

DB2 does not support temporary views but does support temporary tables. A temporary table, once populated with data, can represent a temporary view. If any of the tables referenced by the view are temporary, the view is created as a temporary view (whether TEMPORARY is specified or not).

4.5.3 87BUpdateable views Currently, all PostgreSQL views are read only; the system will not allow an insert, update, or delete on a view. You can get the effect of an updatable view by creating rules that rewrite inserts, etc. on the view into appropriate actions on other tables. For more information see the section on XPostgreSQL Rules X in this document.

DB2 supports delete-able, insert-able and update-able views. To allow updates, a view must satisfy a number of requirement which will allow inserts, updates and deletes (e.g., based on a single table). When a view is based on multiple tables or of otherwise sufficient complexity to preclude updates, implement DB2 INSTEAD OF triggers on the object to make the view operate as updateable.

4.6 23BSequence objects Some minor differences must be addressed to satisfy the DB2 syntax requirements for the CREATE SEQUENCE statement. DB2 requires additional keywords, B and WITH, to be included in the sequence object’s specification.

Page 41: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

41

Another conversion issue is the result of PostgreSQL allowing a minimum value of 1 when specifying the CACHE size attribute. The minimum value of cache size for DB2 is 2. The recommended solution is to remove CACHE 1

PostgreSQL example: CREATE SEQUENCE accnt_accnt_id_seq INCREMENT 1 MINVALUE 1 MAXVALUE 2147483647 START 126 CACHE 1;

Required DB2 syntax: CREATE SEQUENCE accnt_accnt_id_seq INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 126 CACHE 2; -or- CREATE SEQUENCE accnt_accnt_id_seq INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 126;

4.7 24BComments on database objects Both DB2 and Postgres support the storage of additional description information for select database objects. The COMMENT ON command modifies a descriptive field for a database object stored in the database system catalogs. Many objects common across the two databases can be maintained with a derivative of the COMMENT ON syntax which specifies the type of object.

Both PostgreSQL and DB2 support the following syntax of the COMMENT ON command as well as derivatives for a variety of objects: COMMENT ON TABLE public.addr IS ‘Trading partner address master’

However, DB2 requires a different syntax for maintaining comments on two objects; databases and views.

COMMENT ON DATABASE While PostgreSQL allows COMMENT ON DATABASE DB2 supports the CHANGE DATABASE command for modifying a database’s comment:

PostgreSQL example: COMMENT ON DATABASE demo IS ‘Test database for demo purposes’

Page 42: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

42

DB2 syntax: CHANGE DATABASE SAMPLE COMMENT WITH "Test database for demo purposes"

COMMENT ON VIEW PostgreSQL supports COMMENT ON VIEW, while DB2 applies comments to views using the COMMENT ON TABLE command:

Postgres example: COMMENT ON VIEW api.accountchar IS 'Account Characteristics view';

DB2 syntax: COMMENT ON TABLE api.accountchar IS 'Account Characteristics view';

Page 43: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

43

5. 4BData Manipulation Language (DML)

Migration issues as they apply to DML statements; INSERT, UPDATE, DELETE, and TRUNCATE statements.

5.1 25BINSERT statement Insert command is used to insert new rows into a table in PostgreSQL and DB2.

Syntax of the INSERT statement in PostgreSQL: INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) | Query } [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ] For the most part, insert statement in PostgreSQL looks like an INSERT in the other relational databases including DB2, with a couple of exceptions that we will discuss in the following section.

Syntax of the INSERT statement in DB2: INSERT INTO table [ ( column [, ...] ) ] { VALUES ( { expression | DEFAULT } [, ...] ) | Query [WITH RR | RS | CS | UR] } For the most part, insert statement in DB2 also looks like an INSERT in the other relational databases, except that you can specify isolation level at which select query is executed when you use insert…select.

When porting to DB2: When inserting a row consisting entirely of default values, PostgreSQL allows you to use DEFAULT VALUES clause in the insert statement, provided there is no not-null column defined in the table without a default. This is not available in DB2. You would have to provide the column list and use DEFAULT as the value for each column in the values list.

PostgreSQL example: CREATE TABLE SALES(

Page 44: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

44

STORE_ID SMALLINT DEFAULT 1 , SALES_DATE DATE DEFAULT NOW(), TOTAL NUMERIC(8, 2) DEFAULT 0 ) ; INSERT INTO sales DEFAULT VALUES;

DB2 syntax: CREATE TABLE SALES ( STORE_ID SMALLINT WITH DEFAULT 1, SALES_DATE DATE WITH DEFAULT CURRENT DATE, TOTAL DECIMAL (8, 2) WITH DEFAULT 0 ) ; INSERT INTO sales(store_id, sales_date, total)

VALUES (default, default, default);

The optional RETURNING clause in PostgreSQL causes INSERT to compute and return value(s) based on each row actually inserted. This is primarily useful for obtaining values that were supplied by defaults, such as a serial sequence number. However, any expression using the table's columns is allowed.

For example, the following insert statement returns the value of default SALES_DATE inserted by the insert statement into the table. Let us assume that it returned 2009-07-17. INSERT INTO sales VALUES(2, default, 100) RETURNING sales_date; SALES_DATE 2009-07-17

In DB2, this is accomplished using the "SELECT FROM FINAL TABLE" construct: SELECT sales_date FROM FINAL TABLE (INSERT INTO sales VALUES(2, default,100))

5.2 26BUPDATE statement An UPDATE statement is used to update one or more rows in a table in PostgreSQL and DB2.

Syntax of the UPDATE statement in PostgreSQL: UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression | DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [ FROM fromlist ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

The syntax of UPDATE is similar to the syntax of UPDATE in other relational databases, including DB2, with a few exceptions that we will cover in the following section.

Page 45: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

45

Syntax of the UPDATE statement in DB2: UPDATE [ ONLY ] table | full-select SET { column = { expression | DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] ) } [ WHERE condition | WHERE CURRENT OF cursor_name ] [WITH RR | RS | CS | UR] Let us first look at a couple of things that are DB2 specific. We will then talk about things that are specific to PostgreSQL and how to handle them when porting to DB2. DB2 allows full-select as the object of the update operation. In this case the full-select must be updatable (i.e., no grouping functions, no table joins).

For example:

Update the salary and the commission column of the employee with employee number 000120 to the average of the salary and of the commission of the employees of the updated row's department, respectively. UPDATE (SELECT EMPNO, SALARY, COMM, AVG(SALARY) OVER (PARTITION BY WORKDEPT), AVG(COMM) OVER (PARTITION BY WORKDEPT) FROM EMPLOYEE E) AS E(EMPNO, SALARY, COMM, AVGSAL, AVGCOMM) SET (SALARY, COMM) = (AVGSAL, AVGCOMM) WHERE EMPNO = '000120'

The previous statement is semantically equivalent to the following statement, but requires only one access to the EMPLOYEE table, whereas the following statement specifies the EMPLOYEE table twice. UPDATE EMPLOYEE EU SET (EU.SALARY, EU.COMM) = (SELECT AVG(ES.SALARY), AVG(ES.COMM) FROM EMPLOYEE ES WHERE ES.WORKDEPT = EU.WORKDEPT) WHERE EU.EMPNO = '000120' Using WITH clause in DB2, known as a common table expression, you can also specify isolation level at which UPDATE statement is executed.

When porting to DB2: With the FROM clause, PostgreSQL allows columns from other tables to appear in the WHERE condition and the update expressions.

When a FROM clause is present, the target table is joined to the tables mentioned in the from list, and each output row of the join represents an update operation for the target table.

The FROM clause, is not allowed in DB2 update statement. You must use sub-queries to port UPDATE statements with FROM clause.

Page 46: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

46

PostgreSQL example: UPDATE employees SET sales_count = sales_count + 1 FROM accounts WHERE accounts.name = 'Acme Corporation' AND employees.id = accounts.sales_person;

DB2 syntax (which also works in PostgreSQL): UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts

WHERE name = 'Acme Corporation');

The optional RETURNING clause causes UPDATE to compute and return value(s) based on each row actually updated. Any expression using the table's columns, and/or columns of other tables mentioned in FROM, can be computed. The new (post-update) values of the table's columns are used. Just like in the INSERT statement in DB2, this is not allowed in the UPDATE statement either. You would have to issue a select statement to know the value or define a trigger on the update statement.

5.3 27BDELETE statement DELETE statement is used to delete one or more rows in a table in PostgreSQL and DB2.

Syntax of the DELETE statement in PostgreSQL: DELETE FROM [ ONLY ] table [ [ AS ] alias ] [ USING usinglist ] [ WHERE condition | WHERE CURRENT OF cursor_name ] [ RETURNING * | output_expression [ [ AS ] output_name ] [, ...] ]

Syntax of the DELETE statement in DB2: DELETE FROM [ ONLY ] table | full-select [ WHERE condition | WHERE CURRENT OF cursor_name ] [WITH RR | RS | CS | UR] Let us first look at a couple of things that are DB2 specific. We will then talk about things that are specific to PostgreSQL and how to handle them when porting to DB2. DB2 allows full-select as the object of the delete operation. In this case the full-select must be delete-able.

For example, following statement deletes all the duplicate employee rows from the EMPLOYEE table. An employee row is considered to be a duplicate if the last names match. Keep the employee row with the smallest first name in lexical order. DELETE FROM (SELECT ROWNUMBER() OVER (PARTITION BY LASTNAME ORDER BY FIRSTNME)

Page 47: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

47

FROM EMPLOYEE) AS E(RN) WHERE RN = 1 Using WITH clause in DB2, you can also specify isolation level at which DELETE statement is executed.

When porting to DB2: In PostgreSQL, you can delete rows in a table using information contained in other tables in the database by specifying additional tables in the USING clause.

This is not allowed in DB2. You can rewrite the delete statement in DB2 using a sub-query.

PostgreSQL example: DELETE FROM films USING producers WHERE producer_id = producers.id AND producers.name = 'foo';

DB2 syntax (which also works in PostgreSQL): DELETE FROM films WHERE producer_id IN (SELECT id FROM producers WHERE name = 'foo');

5.4 28BSELECT statement (queries)

5.4.1 88BInner and Outer joins Both PostgreSQL and DB2 support ANSI SQL syntax for all the table expressions including inner and outer joins.

The following statement is valid in both PostgreSQL and DB2: SELECT * FROM ORDERS LEFT OUTER JOIN ORDER_DETAILS ON ORDERS.ORDERID = ORDER_DETAILS.ORDERID;

5.4.2 89BType casting in queries PostgreSQL allows using system-defined type-conversion functions like bpchar, text etc.

When porting to DB2: Remove type-casting or use equivalent function when porting to DB2.

PostgeSQL example: SELECT PACK.PACK_ID AS SOPACK_ID, PACK.PACK_HEAD_ID AS SOPACK_SOHEAD_ID, PACK.PACK_PRINTED AS SOPACK_PRINTED, PACK.PACK_SHIPHEAD_ID AS SOPACK_COSMISC_ID FROM PACK WHERE PACK.PACK_HEAD_TYPE = 'SO'::text;

Page 48: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

48

DB2 syntax: SELECT PACK.PACK_ID AS SOPACK_ID, PACK.PACK_HEAD_ID AS SOPACK_SOHEAD_ID, PACK.PACK_PRINTED AS SOPACK_PRINTED, PACK.PACK_SHIPHEAD_ID AS SOPACK_COSMISC_ID FROM PACK WHERE PACK.PACK_HEAD_TYPE = 'SO';

5.4.3 90BCASE expression in queries Both PostgreSQL and DB2 allow CASE expressions in queries. For example, the following statement requires no changes when porting to DB2: SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME, CASE WHEN EDLEVEL < 15 THEN 'SECONDARY' WHEN EDLEVEL < 19 THEN 'COLLEGE' ELSE 'POST GRADUATE' END FROM EMPLOYEE;

5.4.4 91BSorting NULL values In PostgreSQL, NULLS FIRST and NULLS LAST options can be used to determine whether nulls appear before or after non-null values in the sort ordering. By default, null values sort as if larger than any non-null value, that is, NULLS LAST is the default for ASC order.

When porting to DB2: In DB2 sorts also, NULL values are considered the highest value and are therefore ordered last in ASC sorts and first in DESC sorts. DB2 doesn’t support NULLS FIRST and NULLS LAST options.

In case where NULLS LAST is used in DESC sorts or NULLS FIRST is used in ASC sorts in PostgreSQL, when porting to DB2 the NVL function can be used to replace the column value with the lowest value if the column contains a NULL value.

PostgreSQL example: SELECT ACCTNO, ACCTTYPE, BALANCE FROM ACCOUNTS ORDER BY BALANCE NULLS FIRST;

DB2 syntax: SELECT ACCTNO, ACCTTYPE, BALANCE FROM ACCOUNTS ORDER BY NVL(BALANCE,-1); Note: In the previous DB2 example, we modify value of BALANCE to-1.

Page 49: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

49

5.4.5 92BRestricting results with LIMIT and OFFSET In PostgreSQL, LIMIT and OFFSET clauses in a query allow you to retrieve just a portion of the rows that are generated by the rest of the query.

LIMIT n says return no more than n rows. Similarly, OFFSET n says to skip n rows before beginning to return rows.

When porting to DB2: In DB2, you can use FETCH FIRST n ROWS ONLY clause which is equivalent to LIMIT n.

PostgreSQL example: SELECT * FROM EMPLOYEE ORDER BY EMPID LIMIT 10;

DB2 syntax: SELECT * FROM EMPLOYEE ORDER BY EMPID FETCH FIRST 10 ROWS ONLY;

When porting to DB2: DB2 does not provide a clause that is equivalent to LIMIT n. Use a workaround like the MINUS operator with FETCH FIRST n ROWS clause.

PostgreSQL example: SELECT * FROM EMPLOYEE ORDER BY EMPID OFFSET 10;

DB2 syntax: (SELECT * FROM EMPLOYEE ORDER BY EMPID) MINUS (SELECT * FROM EMPLOYEE ORDER BY EMPID FETCH FIRST 10 ROWS ONLY);

5.4.6 93BValues list In PostgreSQL as well as DB2, VALUES clause derives a result table using the specified values, using expressions or row expressions, for each column of a row in the result table. Multiple rows may be specified. This is most commonly used to generate a constant table within a larger query.

When porting to DB2: VALUES list in a query can be ported to DB2 with minimal or no change.

PostgreSQL example:

Page 50: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

50

UPDATE employee SET salary = salary * b.increase FROM (VALUES(1, 1.2), (2, 1.4), (3, 1.6)) AS b (deptid, increase) WHERE employee.deptid = b.deptid;

DB2 syntax: UPDATE employee a SET salary = (select a.salary * b.increase FROM (VALUES(1, 1.2), (2, 1.4), (3, 1.6)) AS b (deptid, increase) WHERE a.deptid = b.deptid);

5.4.7 94BRecursive queries Recursive queries are supported in PostgreSQL from version 8.4. Recursive queries are typically used to deal with hierarchical or tree-structured data.

The WITH clause allows for the definition of a named query within a statement, which can be referred to at a later point in the same statement. This is called a Common Table Expression (CTE). CTEs are by now supported in most major SQL-based DBMS, including DB2 and PostgreSQL.

Unlike a regular CTE, a recursive CTE is referred to within its very own definition in recursive CTE. A recursive CTE consists of two parts combined with a UNION ALL.

When porting to DB2: Unlike Oracle, both PostgreSQL and DB2 follow SQL Standard for recursive queries. PostgreSQL uses keyword RECURSIVE to distinguish between non-recursive CTE and a recursive CTE. When porting to DB2, remove the keyword RECURSIVE from the query.

PostgreSQL example: WITH RECURSIVE n(empid, name) AS (SELECT empid, name FROM emp WHERE name = 'Goyal' UNION ALL SELECT nplus1.empid, nplus1.name FROM emp as nplus1, n WHERE n.empid = nplus1.mgrid); SELECT name FROM n;

DB2 syntax: WITH n(empid, name) AS (SELECT empid, name FROM emp WHERE name = 'Goyal' UNION ALL SELECT nplus1.empid, nplus1.name FROM emp as nplus1, n WHERE n.empid = nplus1.mgrid); SELECT name FROM n;

Page 51: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

51

For more information on recursive queries support in DB2, see this developer works article at: HUhttp://www.ibm.com/developerworks/data/library/techarticle/dm-0510rielau/

5.4.8 95BPERFORM statement The PERFORM statement in PostgreSQL executes a SQL query but discards the results. It is typically used to evaluate an expression or SELECT query as a boolean true or false.

PostgreSQL example: PERFORM 1 FROM EMPLOYEE WHERE DEPT = 10; IF FOUND THEN … END IF;

When porting to DB2, SQL PL does not support a PERFORM statement. There are two relatively simple ways to emulate this statement. One, is to issue a SELECT COUNT(*) against the table, store the row count in a variable and test the variable. The second is to use SQL PL support for IF EXISTS. See examples of both below:

DB2 syntax (using COUNT): SELECT COUNT(*) INTO v_count FROM employee WHERE dept = 10; IF v_count > 0 THEN … END IF;

DB2 syntax (using EXISTS): IF EXISTS (SELECT 1 FROM EMPLOYEE WHERE DEPT = 10) THEN … END IF;

5.5 29BSQL Function Mapping This section provides a mapping of database SQL functions between PostgreSQL and DB2. Identified below are some of the most commonly used functions. Please refer to PostgreSQL and DB2 SQL documentation for more information on each function’s input requirements and output result:

5.5.1 96BNumeric function mapping

PostgreSQL DB2 Comments

ABS ABS Returns the absolute value.

ACOS ACOS Returns the arc cosine.

ASIN ASIN Returns the arc sine.

ATAN ATAN Returns the arc tangent.

ATAN2 ATAN2 Returns the arc tangent (two value).

Page 52: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

52

CEIL CEILING

CEIL CEILING

Returns the smallest integer greater or equal to the argument.

COS COS Returns the cosine.

EXP EXP Returns the exponential function of the argument.

FLOOR FLOOR Largest integer not greater than argument.

LN LN Returns the natural logarithm.

LOG LOG Returns the natural logarithm.

LOG(10,n1) LOG10(n1) Returns the common logarithm (base 10).

MOD(y,x) MOD(y,x) Remainder of y/x

POWER(x,y) POWER(x,y) X raised to the power of y

RANDOM RAND Random value in the range 0.0 <= x < 1.0

ROUND(arg1,arg2) ROUND(arg1,arg2) Round to arg2 decimal places

SIGN SIGN Sign of the argument (-1, 0, +1)

SIN SIN Returns the sine.

SINH SINH Returns the hyperbolic sine.

SQRT SQRT Returns the square root.

TAN TAN Returns the tangent.

TRUNC(n[,m]) TRUNC(n[,m]) TRUNCATE(n[,m])

Truncate to m decimal places

5.5.2 97BCharacter function mapping

PostgreSQL DB2 Comments

ASCII ASCII Returns the ASCII code of a character.

CHR CHR Returns an ASCII character for given n

INITCAP N/A Returns characters with the first letter of each word in uppercase and the reset of letters in lowercase. Can be implemented with UDF. See an example given below.

STRPOS POSSTR, POSITION, and LOCATE

Location of specified substring in string, but note the argument order.

LENGTH LENGTH Returns a length of the string.

LPAD(arg1,arg2,arg3) N/A Returns arg1, left-padded to length arg2 characters with the sequence of characters in arg3.

Page 53: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

53

Can be implemented with UDF. See an example given below.

LTRIM LTRIM Removes blanks from the beginning of a string expression.

REPEAT(arg1,arg2) REPEAT(arg1,arg2) Returns a character string composed of arg1 repeated arg2 times.

REPLACE(arg1,arg2,arg3) REPLACE(arg1,arg2,arg3) Replaces all occurrences of srg2 in arg1 with arg3

RPAD N/A Returns the first argument value, right-padded to the length specified in the 2nd argument with characters specified in the third argument.

Can be implemented with user defined fun (UDF).

RTRIM RTRIM Remove blanks from the end of a string expression.

SUBSTR SUBSTR SUBSTRING

Returns a substring of a string.

TRANSLATE TRANSLATE Returns a string in which one or more characters in a string are converted to other characters.

POSITION POSITION Position function has different signature in DB2.

5.5.3 98BDate and Time function mapping

PostgreSQL DB2 Comments

CURRENT_DATE CURRENT DATE Returns the current date.

CURRENT_TIMESTAMP CURRENT TIMESTAMP Returns the current date and time. Note: in PostgreSQL, the CURRENT_TIMESTAMP function also returns time zone.

CURRENT_TIME CURRENT TIME Returns the current time. Note: in PostgreSQL, the CURRENT_TIME function also returns time zone.

DOW DAYOFWEEK Returns the day of the week from a value. Please note the integer value differences between DB2 and PostgreSQL: - in DB2 1 is Sunday 2 is

Page 54: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

54

Monday…7 is Saturday - in PostgreSQL 0 is Sunday, 1 is Monday… 6 is Saturday.

DOY DAYOFYEAR Returns the day of the year from a value.

EXTRACT() YEAR(), MONTH(), DAY() HOUR(), MINUTE(), SECOND(), MICROSECOND()

Extracts and returns the value of a specified datetime field from a datetime expression.

TIMEZONE CURRENT TIMEZONE Returns the value of the database time zone. Note that PostgreSQL returns the time zone offset from UTC, measured in seconds. Positive values correspond to time zones east of UTC, negative values to zones west of UTC.

NOW() Implement using CURRENT TIMESTAMP + CURRENT TIMEZONE

Returns the current timestamp.

AGE (timestamp, timestamp) N/A Subtract arguments, producing a "symbolic" result that uses years and months. For example, age(timestamp '2001-04-10', timestamp '1957-06-13') is 43 years 9 months 27 days. Can be implemented with UDF.

AGE (timestamp) N/A Subtract from CURRENT_DATE (at midnight). Can be implemented with UDF.

5.5.4 99BSample UDFs

5.5.4.1 140BINITCAP in DB2 ---------------------------------------------------------------------- -- DB2 UDB UDF(User-Defined Function) Samples for Migration -- Description: Convert first character of each word to uppercase -- and other characters to lowercase. -- Words are separated by non-alphanumeric character(s). ---------------------------------------------------------------------- CREATE FUNCTION INITCAP (C1 VarChar(4000)) RETURNS VarChar(4000) SPECIFIC INITCAPPostgreSQL LANGUAGE SQL CONTAINS SQL NO EXTERNAL ACTION DETERMINISTIC

Page 55: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

55

BEGIN ATOMIC DECLARE AN Char(62) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; DECLARE C1L Integer; DECLARE Pos, Flag, NewFlag Integer; DECLARE RetVal VarChar(4000); SET C1L = LENGTH(C1); SET (Pos, Flag, RetVal) = (1, 0, ''); WHILE Pos <= C1L DO SET NewFlag = SIGN(LOCATE(SUBSTR(C1,Pos,1),AN)); SET RetVal = RetVal || CASE WHEN Flag = 0 AND NewFlag = 1 THEN UPPER(SUBSTR(C1,Pos,1)) WHEN Flag = 1 AND NewFlag = 1 THEN LOWER(SUBSTR(C1,Pos,1)) ELSE SUBSTR(C1,Pos,1) END; SET (Pos, Flag) = (Pos + 1, NewFlag); END WHILE; RETURN RetVal; END

5.5.4.2 141BLPAD in DB2 ------------------------------------------------------------------- -- DB2 UDB UDF(User-Defined Function) Samples for Migration -- Description: Add repeatedly C2 to the left of parameter 1 (C1 or I1) -- and return N byte. ------------------------------------------------------------------- CREATE FUNCTION LPAD (C1 VarChar(4000), N integer, C2 VarChar(4000)) RETURNS VARCHAR(4000) LANGUAGE SQL DETERMINISTIC CONTAINS SQL NO EXTERNAL ACTION RETURN CASE WHEN N > length(C1) THEN substr(repeat(C2,(N-length(C1)+length(C2))/(length(C2)+1-sign(length(C2)))),1,N-length(C1)) || C1 ELSE substr(C1,1,N) END; END

Page 56: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

56

6. 5BSQL Procedural Languages

In this chapter we will discuss differences between PostgreSQL’s Procedural Language (PL/pgSQL) and DB2’s SQL Procedural Language (SQL PL), which are used for server side programming.

PL/pgSQL and SQL PL are both block-structured languages with many similarities. Assignments, loops, and conditional statements are very similar in both the languages.

6.1 30BStored procedures and functions Stored procedures and functions are the programs developed in a procedural language that are stored in the database server and executed on demand.

• There are many benefits of routines. A few benefits are:

• Code will be parsed at the time of procedure creation which eliminates the need to re-parse the statements every time you execute the statements in the program.

• Network traffic between client and database server is reduced.

• Code can be efficiently reused by multiple users and client programs.

• Routines improve overall performance of the database management system by enabling application functionality to be performed on the database server.

6.2 31BComparison of PL/pgSQL and SQL PL syntax In PL/pgSQL, CREATE FUNCTION statement is used to create both stored procedures and functions. IDB2 has separate create statements for procedures and functions.

PL/pgSQL CREATE FUNCTION Syntax: CREATE OR REPLACE FUNCTION function-name (parameter(s)-declaration) [RETURNS data-type(s)] AS [ label ] [ DECLARE declarations ] BEGIN statements END; [ label ] LANGUAGE language [attributes];

DB2 CREATE FUNCTION syntax: CREATE OR REPLACE FUNCTION function-name (parameter(s)-declaration) [RETURNS data-type(s) | ROW column-list | TABLE column-list] LANGUAGE language [ label: ] BEGIN

Page 57: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

57

[declarations] statements END [ label ] [function-terminator]

DB2 CREATE PROCEDURE syntax: CREATE OR REPLACE PROCEDURE procedure-name (parameter(s)-declaration) LANGUAGE language [ label: ] BEGIN [declarations] statements END [ label ] [procedure-terminator]

Compare the structures of PL/pgSQL and SQL PL with a simple user defined function example.

PL/pgSQL in PostgreSQL: CREATE OR REPLACE FUNCTION avgcost(integer) RETURNS numeric AS $BODY$ DECLARE pItemsiteid ALIAS FOR $1; _value NUMERIC; _qoh NUMERIC; BEGIN SELECT itemsite_value, itemsite_qtyonhand INTO _value, _qoh FROM itemsite WHERE(itemsite_id=pItemsiteid); IF (_qoh = 0) THEN RETURN 0; END IF; RETURN _value / _qoh; END; $BODY$ LANGUAGE 'plpgsql' VOLATILE COST 100;

SQL PL in DB2: CREATE OR REPLACE FUNCTION avgcost (pItemsiteid integer) RETURNS DECFLOAT(34) LANGUAGE SQL P1: BEGIN DECLARE p_value DECFLOAT(34); DECLARE p_qoh DECFLOAT(34); SELECT itemsite_value, itemsite_qtyonhand INTO p_value, p_qoh FROM public.itemsite WHERE(itemsite_id=pItemsiteid); IF (p_qoh = 0) THEN RETURN 0; END IF; RETURN p_value / p_qoh;

Page 58: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

58

END P1 As the above example shows, routines in PL/pgSQL and SQL PL have very similar body structure with some variations. See some variations in the following sections.

6.3 32BBlock labeling The code of a PL/pgSQL function is specified in CREATE FUNCTION as a string literal. Generally, one writes the function body as a "dollar-quoted" string literal. In the dollar-quoting approach, you choose a different dollar-quoting delimiter for each level of nesting. In the above example, $BODY$ is used to label the function body.

In DB2, it is not required to label a block of a routine but one can label the body with a unique label name, if needed to uniquely identify each block in the routine. The above DB2 example used label P1. Note the difference in the way the body is labeled in PL/pgSQL and SQL PL.

6.4 33BRETURNS statement Both in PL/pgSQL and SQL PL, RETURNS statement is used to specify data type and order of returning data. Both PostgreSQL and SQL PL can return result sets to the calling program.

Syntax of RETURNS statement in PostgreSQL: RETURNS [ return-data-type | SETOF result-set | TABLE column-definition ]

Where: RETURNS return-data-type specifies the data type of a single value the function returns.

RETURNS SETOF result-set is used when a function returns a result-set with the definition that either matches a user table or a user defined record.

RETURNS TABLE column-definition can also be used in the place of SETOF record when the function returns more than one row, where the definition of the record doesn’t match any existing user tables. CREATE FUNCTION sum_n_product_with_tab (x int, OUT sum int, OUT product int) RETURNS SETOF record AS $$ SELECT $1 + tab.y, $1 * tab.y FROM tab; $$ LANGUAGE SQL; CREATE FUNCTION sum_n_product_with_tab (int) RETURNS TABLE (sum int, product int) AS $$ SELECT $1 + tab.y, $1 * tab.y FROM tab; $$ LANGUAGE SQL;

Syntax of RETURNS statement in DB2: RETURNS [ return-data-type | ROW column-definition | RECORD | TABLE column-definition ]

Page 59: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

59

Where:

RETURNS return-data-type specifies that the function returns a single value with the given data type.

RETURNS ROW column-definition specifies that the output of the function is a single row.

RETURNS RECORD specifies that the output of the function is a single row. It is similar to row-type variables, but it has no predefined structure.

RETURNS TABLE column-definition specifies that the function returns more than one row.

When porting to DB2:

Returning single value:

Syntax is exactly same in PostgreSQL and SQL PL when the function returns a single value. Replace the data type in PostgreSQL with an equivalent data type supported by DB2.

PL/pgSQL: CREATE OR REPLACE FUNCTION avgcost(integer) RETURNS numeric AS…

SQL PL: CREATE OR REPLACE FUNCTION avgcost (pItemsiteid integer) RETURNS DECFLOAT(34)

Returning set of values:

RETURNS SETOF result set in PL/pgSQL should be replaced with either RETURNS ROW or RETURNS TABLE in SQL PL.

Result set can be name of a user table in PL/pgSQL where it implicitly copies the column-definition of the user table. This is not allowed in SQL PL. Be sure to explicitly provide the column definition.

PL/pgSQL example: CREATE FUNCTION bomitem(integer, integer) RETURNS SETOF bomitem AS…

DB2 SQL PL syntax: CREATE FUNCTION bomitem (pItemid integer, pRevid integer) RETURNS TABLE (bomitem_id integer, bomitem_parent_item_id integer…)

Returning RECORD: RETURNS RECORD in PL/pgSQL should be replaced with RETURNS TABLE in DB2 SQL PL.

PL/pgSQL example:

Page 60: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

60

CREATE OR REPLACE FUNCTION timestamp_parts(timestamp without time zone) RETURNS record LANGUAGE 'plpgsql' AS $$ DECLARE p_time_stamp ALIAS FOR $1; l_rec record; BEGIN SELECT to_char(p_time_stamp, 'YYYY')::integer AS p_year, to_char(p_time_stamp, 'Q')::integer AS p_quarter, to_char(p_time_stamp, 'MM')::integer AS p_month, to_char(p_time_stamp, 'DD')::integer AS p_day, to_char(p_time_stamp, 'D')::smallint AS p_dow, to_char(p_time_stamp, 'HH24')::smallint AS p_hour, INTO l_rec; RETURN l_rec; END $$ ;

DB2 example: CREATE OR REPLACE FUNCTION timestamp_parts (p_time_stamp TIMESTAMP) RETURNS TABLE (p_year INT, p_quarter INT, p_month INT, p_day INT, p_dow SMALLINT, p_hour SMALLINT) BEGIN RETURN SELECT TO_CHAR(p_time_stamp, 'YYYY') , TO_CHAR(p_time_stamp, 'Q') , TO_CHAR(p_time_stamp, 'MM'), TO_CHAR(p_time_stamp, 'DD'), TO_CHAR(p_time_stamp, 'D'), TO_CHAR(p_time_stamp, 'HH24') FROM SYSIBM.SYSDUMMY1; END

6.5 34BLANGUAGE statement In both database systems, the LANGUAGE statement defines the name of the language that the function is implemented.

In PL/pgSQL the language can be plpgsql, SQL, C, or the name of a user-defined procedural language. The name can be enclosed by single quotes. The LANGUAGE statement appears after the body of the routine i.e after the main block in the routine.

In DB2, the language can be SQL, C/C++, Java, .NET CLR, OLE, OLEDB. The LANGUAGE statement appears at the beginning of the routine i.e. before the main block in the routine.

6.6 35BPL/pgSQL specific attributes When porting to DB2, PL/pgSQL specific attributes must be removed from the routine.

Page 61: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

61

For example, the VOLATILE attribute in the above PL/pgSQL inform the query optimizer about the behavior of the function. VOLATILE indicates that the function value can change even within a single table scan, so no optimizations can be made.

Similarly, the COST attribute in the previous function example gives the expected execution cost of the function.

6.7 36BWorking with variables

6.7.1 100BVariable names In PL/pgSQL, a variable name can start with _ (underscore). This is not allowed in DB2. Replace variable names with no underscore [ _ ] as the starting character.

PL/pgSQL example: _value NUMERIC;

DB2 SQL PL syntax: p_value DECFLOAT(34);

6.7.2 101BDeclaring variables In PL/pgSQL, all the variables must be declared in the declarations section of the block that starts with DECLARE.

For example: CREATE OR REPLACE FUNCTION avgcost(integer) RETURNS numeric AS $BODY$ DECLARE pItemsiteid ALIAS FOR $1; _value NUMERIC; _qoh NUMERIC; BEGIN …. END;

In SQL PL, each variable is declared with a DECLARE statement and all the variables are declared in the block after the BEGIN statement.

For example: CREATE OR REPLACE FUNCTION avgcost (pItemsiteid integer) RETURNS DECFLOAT(34) LANGUAGE SQL P1: BEGIN DECLARE p_value DECFLOAT(34); DECLARE p_qoh DECFLOAT(34); … END P1

Page 62: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

62

6.7.3 102BUsing an ALIAS for parameters In PL/pgSQL, parameters passed to functions are named with the identifiers $1, $2, etc. depending on their position in the calling signature.

Optionally, aliases can be declared for the parameters to increase readability. Either the alias or the numeric identifier can then be used to refer to the parameter value in the procedure body.

There are two ways to create an alias. One way, which was the only way available before PostgreSQL 8.0, is to explicitly declare an alias, using the declaration syntax name ALIAS FOR $n;

PL/pgSQL example: CREATE OR REPLACE FUNCTION avgcost(integer) RETURNS numeric AS $BODY$ DECLARE pItemsiteid ALIAS FOR $1; _value NUMERIC; _qoh NUMERIC; BEGIN …. END; The preferred way is to give a name to the parameter in the CREATE FUNCTION command. This is same as how the alias is created in SQL PL. For example, the previous alias declaration in PL/pgSQL before version 8 can be replaced with the following:

PL/pgSQL example (from version 8) CREATE OR REPLACE FUNCTION avgcost(pItemsiteid integer) RETURNS numeric AS $BODY$ DECLARE _value NUMERIC; _qoh NUMERIC; BEGIN …. END;

When porting to DB2: Only the format supported prior to the release of PostgreSQL 8.0 will contain the syntax which requires conversion. Since version 8, PostgreSQL has supported the naming of input parameters in the routine’s execution signature in the same way as DB2. Functions which declare variables as an ALIAS will need to be provided as a named parameter to the DB2 routine.

Postgres example: CREATE OR REPLACE FUNCTION checkprivilege(varchar(30)) RETURNS boolean AS $BODY$

Page 63: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

63

DECLARE pPrivilege ALIAS FOR $1; …. END;

DB2 syntax: CREATE OR REPLACE FUNCTION checkprivilege(pPrivilege VARCHAR(30)) RETURNS boolean BEGIN …. END;

6.7.4 103B%TYPE In PL/pgSQL, %TYPE attribute can be used when declaring a parameter or variable that will be used to hold column values in a table to ensure that type compatibility between table columns and PL/pgSQL variables is maintained.

Use of the %TYPE attribute is not supported in DB2 Express-C, Express, and Personal Editions. You can use ANCHOR DATA TYPE clause to anchor data type of a variable to a column in a table, just like %TYPE

Syntax: DECLARE variable ANCHOR DATA TYPE TO schema.tablename.columnname;

For example: DECLARE p_value ANCHOR DATA TYPE TO PUBLIC.itemsite.itemsite_value;

6.7.5 104B%ROWTYPE The %ROWTYPE attribute is used to declare PL/pgSQL variables of type record with fields that correspond to the columns of a table. When used, each field in the PL/pgSQL record takes on the data type of the corresponding column in the table. Use of the %ROWTYPE attribute is also not supported in DB2 Express-C, Express, and Personal Editions. Here also you can use ANCHOR DATA TYPE TO clause to anchor data type to a row of a table.

DB2 syntax: DECLARE variable ANCHOR DATA TYPE TO ROW OF table-name | view-name | cursor-variable-name;

DB2 example: DECLARE accnt_row ANCHOR DATA TYPE TO ROW OF PUBLIC.ACCNT;

Page 64: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

64

6.8 37BBasic Statements

6.8.1 105BSET assignment In PL/pgSQL, an assignment of a value to a variable is defined as variable := expression;

PostgreSQL example: pTotalCost := pCost + pCommission;

In DB2, an assignment is done with a SET statement as shown below. SET variable = expression;

DB2 example: SET pTotalCost = pCost + pCommission;

6.8.2 106BVALUES statement Alternatively in DB2, an assignment can be done with a VALUES statement to set one or multiple variables at one time. This is an efficient way set multiple variables in a loop.

For example: VALUES ( (pCost + pCommission), (pCost + pCount) ) INTO pTotalCost, pAvgCost;

or VALUES (pCost + pCommission, pCost + pCount) INTO pTotalCost, pAvgCost;

6.8.3 107BNULL statement PL/pgSQL allows NULL statement as a placeholder statement that does nothing.

For example: BEGIN ... EXCEPTION WHEN no_data_found THEN NULL; END; In SQL PL there is no NULL statement. Use an empty statement list instead (i.e., remove the NULL statement).

6.8.4 108BRETURN statement The RETURN statement returns data from the function. There are two types of RETURN statements in PL/pgSQL

Page 65: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

65

RETURN Expression RETURN with an expression terminates the function and returns the value of expression to the caller. This is the simplest form of return statement and can be easily ported to DB2.

RETURN NEXT and RETURN QUERY PL/pgSQL functions can also be declared to return a table. RETURN NEXT or RETURN QUERY is used to return a table in PL/pgSQL.

These statements do not actually exit from the function. They simply append zero or more rows to the function's result set. Execution then continues with the next statement in the PL/pgSQL function. As successive RETURN NEXT or RETURN QUERY commands are executed, the result set is built up. A final RETURN with no argument makes the control exit the function.

When porting to DB2: SQL PL in DB2 also supports returning a result set at the end of function execution. However there are no RETURN NEXT and RETURN QUERY statements in DB2. Modify the function to return a result set with appropriate result set type.

PL/pgSQL example: CREATE OR REPLACE FUNCTION bomitem(integer, integer) RETURNS SETOF bomitem AS $BODY$ DECLARE pItemid ALIAS FOR $1; pRevid ALIAS FOR $2; _row bomitem%ROWTYPE; BEGIN FOR _row IN SELECT * FROM bomitem LOOP RETURN NEXT _row; END LOOP; RETURN; END; $BODY$ LANGUAGE 'plpgsql';

DB2 SQL PL syntax: CREATE OR REPLACE FUNCTION bomitem (pItemid integer, pRevid integer) RETURNS TABLE ( bomitem_id integer, bomitem_parent_item_id integer, bomitem_seqnumber integer, bomitem_item_id integer, bomitem_qtyper decimal(20,8)...) LANGUAGE SQL BEGIN RETURN SELECT * FROM PUBLIC.BOMITEM

Page 66: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

66

WHERE bomitem_parent_item_id=pItemid AND bomitem_rev_id=pRevid; END

If RETURN NEXT statement is used as a place holder to append rows to the result set before the final result set is returned to the calling program or client, replace RETURN NEXT functionality in PL/pgSQL with global temporary table in SQL PL.

6.9 38BControl Structures

6.9.1 109BIF and CASE statements Both PL/pgSQL and SQL PL support IF and CASE statements for conditional execution of statements in a block. No changes are required to the structure of these conditional statements when porting to DB2.

6.9.2 110BThe difference between ELSIF and ELSEIF There is no functional difference between PL/pgSQL’s ELSIF statement and DB2’s SQL PL equivalent ELSEIF, however it will be necessary to manually edit PostgreSQL functions and substitute syntax to DB2’s supported keyword.

PL/pgSQL example: . . . IF (p_per_type = 'quarter') THEN l_per_type := 'month'; l_per_num := p_per_num * 3; ELSIF (p_per_type = 'week') THEN l_per_type := 'day'; l_per_num := p_per_num * 7; ELSIF (p_per_type IN ('year', 'month', 'day')) THEN l_per_type := p_per_type; l_per_num := p_per_num; ELSE . . .

DB2 SQL PL syntax: . . . IF (p_per_type = 'quarter') THEN SET l_per_type = 'month'; SET l_per_num = p_per_num * 3; ELSEIF (p_per_type = 'week') THEN SET l_per_type = 'day'; SET l_per_num = p_per_num * 7; ELSEIF (p_per_type IN ('year', 'month', 'day')) THEN SET l_per_type = p_per_type; SET l_per_num = p_per_num; ELSE . . .

Page 67: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

67

6.9.3 111BLOOP statement The behavior of Loop statement is exactly same in PL/pgSQL and SQL PL but you might want to change the way the label is defined when porting to DB2.

PL/pgSQL example: [ <<label>> ] LOOP statements END LOOP [ label ];

DB2 SQL PL syntax: [ label :] LOOP statements END LOOP [ label ];

6.9.4 112BRecords and cursors In routines, a cursor makes it possible to define a result set (a set of data rows) and perform complex logic on a row by row basis. By using the same mechanics, a routine can also define a result set and return it directly to the caller of the routine or to a client application.

A cursor can be viewed as a pointer to one row in a set of rows. The cursor references one row at a time, and can move to other rows of the result set as needed.

To use cursors in PL/pgSQL and SQL PL, you need to do the following:

1. Declare a cursor that defines a result set.

2. Open the cursor to establish the result set.

3. Fetch the data into local variables from the cursor, one row at a time. 4. Close the cursor when done

Both PL/pgSQL and SQL PL support the following statements to work with the cursors; DECLARE CURSOR, OPEN, FETCH, and CLOSE

A FOR loop can be used to iterate through the rows returned by the cursor. FOR statement automatically opens the cursor at the beginning of the loop and closes the cursor at the end of the loop.

In addition to cursors, PostgreSQL also supports a FOR loop to iterate through the result-set of a query, without having to declare a cursor explicitly.

Example: _row RECORD; FOR _row IN SELECT * FROM bomitem WHERE ((bomitem_parent_item_id=pItemid) AND (bomitem_rev_id=pRevid))

Page 68: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

68

LOOP RETURN NEXT _row; END LOOP;

6.9.5 113BWorking with DB2 cursors and result sets In SQL procedures, cursors can be used to do more than iterate through rows of a result set. They can also be used to return result sets to the calling program.

Result sets can be retrieved by SQL procedures (in the case of a nested procedure calls) or client applications programmed in C, Java, CLI, or .NET CLR languages.

To return a result set from an SQL procedure, you must:

1. Specify the DYNAMIC RESULT SETS clause in the CREATE 2. PROCEDURE statement

3. DECLARE the cursor using the WITH RETURN clause

4. Open the cursor in the SQL procedure

5. Keep the cursor open for the client application - do not close it

If the cursor is closed using the CLOSE statement prior to the return of the SQL procedure, the cursor result set will not be returned to the caller or client application. Multiple result sets can be returned from an SQL procedure by using multiple cursors.

To return multiple cursors the following must be done:

1. Specify the DYNAMIC RESULT SETS clause in the CREATE PROCEDURE statement. Specify the maximum possible number of result sets likely to be returned. The number of results sets actually returned must not exceed this number.

2. Declare cursors for each of the result sets to be returned that specify the WITH RETURN clause.

3. Open the cursors to be returned.

4. Keep the cursor open for the client application - do not close them. 5. One cursor is required per result set that is to be returned.

6. Keep the cursor open for the client application - do not close them.

7. One cursor is required per result set that is to be returned.

DB2 SQL PL Procedure syntax (with a dynamic result set): CREATE OR REPLACE PROCEDURE bomitem (IN pItemid INTEGER, IN pRevid INTEGER) LANGUAGE SQL DYNAMIC RESULT SETS 1 BEGIN DECLARE c1 CURSOR WITH RETURN TO CLIENT FOR SELECT * FROM PUBLIC.BOMITEM WHERE bomitem_parent_item_id=pItemid AND bomitem_rev_id=pRevid; OPEN c1;

Page 69: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

69

END

6.10 39BCondition Handling An exception is raised if an error occurs when executing an SQL statement in a routine. Let us look at how you can trap and handle exceptions in PL/pgSQL and SQL PL.

6.10.1 114BRAISE Statement In PL/pgSQL you can use RAISE statement to report and handle individual errors.

Syntax of RAISE statement: RAISE [ level ] 'format' [, expression [, ...]] [ USING option = expression [, ... ] ];

Where:

• LEVEL specifies the severity of error.

• Allowed levels are DEBUG, LOG, INFO, NOTICE, WARNING, and EXCEPTION.

• EXCEPTION is the default level.

• EXCEPTION raises an error which aborts the current transaction. • Other levels only generate messages of different priority levels.

• FORMAT is optional simple string literal.

• The format string specifies the error message text to be reported.

The format string can be followed by optional argument expressions to be inserted into the message.

Inside the format string, % is replaced by the string representation of the next optional argument's value.

USING followed by option = expression can be used to attach additional information to the error report. The allowed option keywords are MESSAGE, DETAIL, HINT, and ERRCODE, while each expression can be any string-valued expression.

Example1: RAISE RAISE 'Duplicate Employee: %', empid USING ERRCODE = '90001';

Example2: RAISE EXCEPTION CREATE FUNCTION basecurrid() RETURNS integer AS $$ DECLARE returnVal INTEGER; BEGIN SELECT curr_id INTO returnVal FROM curr_symbol WHERE curr_base = TRUE; IF NOT FOUND THEN

Page 70: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

70

RAISE EXCEPTION 'No base currency found'; END IF; RETURN returnVal; END; $$ LANGUAGE plpgsql;

6.10.2 115BEXCEPTION Statement Block An EXCEPTION statement block is used to handle one or more known and unknown errors in a routine.

Syntax: EXCEPTION WHEN condition [OR condition…] THEN Exception-handler WHEN condition [OR condition…] THEN Exception-handler … WHEN OTHERS THEN Exception-handler END;

Example: EXCEPTION WHEN undefined_object THEN RETURN 0; WHEN undefined_table OR invalid_schema_name THEN RETURN 0; WHEN OTHERS THEN RAISE EXCEPTION '% %', SQLSTATE, SQLERRM; END;

6.10.3 116BGET DIAGNOSTICS Statement DB2’s GET DIAGNOSTICS statement is used to obtain information about the previously executed SQL statement. The available options are ROW_COUNT, DB2_RETURN_STATUS, and EXCEPTION 1.

Syntax: GET DIAGNOSTICS sql-variable-name = ROW_COUNT | DB2_RETURN_STATUS GET DIAGNOSTICS EXCEPTION 1 sql-variable-name = message_text

Where:

• The SQL variable name identifies the variable that is the assignment target. If ROW_COUNT or DB2_RETURN_STATUS is specified, the variable must be an integer variable, and must not be a global variable. Otherwise, the variable must be CHAR or VARCHAR.

• ROW_COUNT identifies the number of rows associated with the previous SQL statement. If the previous SQL statement is a DELETE, INSERT, or UPDATE

Page 71: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

71

statement, ROW_COUNT identifies the number of rows that qualified for the operation. If the previous statement is a PREPARE statement, ROW_COUNT identifies the estimated number of result rows in the prepared statement.

• DB2_RETURN_STATUS identifies the status value returned from the procedure associated with the previously executed SQL statement, provided that the statement was a CALL statement invoking a procedure that returns a status. If the previous statement is not such a statement, then the value returned has no meaning and could be any integer.

• The message text identifies any error or warning message text returned from the previously executed SQL statement. The message text is returned in the language of the database server where the statement is processed. If the statement completed with an SQLCODE of zero, an empty string is returned for a VARCHAR variable or blanks are returned for a CHAR variable.

DB2 example: CREATE OR REPLACE PROCEDURE sqlprocg (IN deptnbr VARCHAR(3)) LANGUAGE SQL BEGIN DECLARE SQLSTATE CHAR(5); DECLARE rcount INTEGER; UPDATE CORPDATA.PROJECT SET PRSTAFF = PRSTAFF + 1.5 WHERE DEPTNO = deptnbr; GET DIAGNOSTICS rcount = ROW_COUNT; -- At this point, rcount contains the number of rows --- that were updated. ... END @

6.10.4 117BDECLARE HANDLER Statement In SQL PL, you can also use condition handlers for exception handling. There are three types of condition handlers: EXIT, CONTINUE, and UNDO.

DB2 syntax: DECLARE CONTINUE|EXIT|UNDO HANDLER FOR condition <statement or block> A CONTINUE handler will continue the execution of the statement that immediately follows the statement that raised the exception.

EXIT handler will execute the SQL PL statements in the handler. After that, the handler will skip the remaining statements in the current BEGIN-END block. Execution will continue with the next statement to be executed. If the statement that raised the exception is in the outer most procedure block, execution will continue in the routine that called the procedure or control is passed to the DB2 if this is the highest level routine.

UNDO handler also continues with execution at the end of the compound statement in which it was declared. Each executed statement will be rolled back in this compound statement.

Page 72: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

72

6.10.5 118BSIGNAL Statement DB2 will raise a condition automatically if an operation does not complete successfully. In contrast, the SIGNAL statement can be used to raise a condition manually.

The RESIGNAL Statement is useful in EXIT exception handlers. It lets you pass the exception encountered to the next higher program block. If that block has an exception handler, it can take action. If not, the exception is automatically passed up to all higher level program blocks – and commonly to DB2 when called from a main routine. Use RESIGNAL to catch an exception, take some action, and then pass the exception to DB2 to stop execution. DB2 will display the exception on the terminal window if the program was called from the Command Line Processor (CLP).

DB2 syntax: SIGNAL SQLSTATE sqlstate [SET MESSAGE_TEXT text ]

SQL PL example: CREATE OR REPLACE FUNCTION basecurrid() RETURNS integer BEGIN DECLARE returnVal INTEGER; DECLARE P_NOT_FOUND INTEGER DEFAULT 0; DECLARE SQLCODE INTEGER DEFAULT 0; DECLARE EXIT HANDLER FOR NOT FOUND BEGIN SIGNAL SQLSTATE 'SP001' SET MESSAGE_TEXT = 'No base currency found'; END; SELECT curr_id INTO returnVal FROM PUBLIC.curr_symbol WHERE curr_base = 1; RETURN returnVal; END

When porting to DB2: Use appropriate statement in SQL PL when porting the code used for error handling in PL/pgSQL.

PL/pgSQL allows the format string to be followed by optional argument expressions to be inserted into the message. Inside the format string, % is replaced by the string representation of the next optional argument's value. This is not allowed in SQL PL message text. The message text has to be simple text message without any expressions in the message.

A workaround is to build the message text before passing it to the SIGNAL statement.

PLpg/SQL example: IF (p_per_num <= 0) THEN

Page 73: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

73

RAISE EXCEPTION ''Invalid negative or zero period number %'', p_per_num; RETURN NULL; END IF;

SQL PL example: IF (p_per_num <= 0) THEN SET l_message_text = 'Invalid negative or zero period number ' || CAST(p_per_num AS VARCHAR); SIGNAL SQLSTATE '70000' SET MESSAGE_TEXT = l_message_text; RETURN NULL; END IF;

Consider using DBMS_OUTPUT.PUTLINE when porting RAISE NOTICE.

PLpg/SQL example: IF (p_start_date >= p_end_date) THEN RAISE NOTICE ''Start date % should be before end date %'', p_start_date, p_end_date; RETURN -5; END IF;

SQL PL example: IF (p_start_date >= p_end_date) THEN CALL DBMS_OUTPUT.PUT_LINE('Start date ' || p_start_date || ' should be before end date ' || p_end_date); RETURN -5; END IF;

6.11 40BUsing Dynamic SQL Dynamic SQL is used when the syntax of a statement is only known at runtime. The statements will build typically by concatenating variables and strings.

The privileges to execute Dynamic SQL will be checked at runtime. Make sure that the user calling the routine has required privileges to execute the statement. In both SQL PL and PL/pgSQL, you can use EXECUTE IMMEDIATE statement if a dynamic SQL is executed only once. PREPARE and EXECUTE statements are used if you want to execute a statement multiple times.

When porting to DB2: Dynamic values that are to be inserted into the constructed query require careful handling since they might themselves contain quote characters. When working with dynamic SQL statements, you will often have to handle escaping of single quotes.

In PL/pgSQL, expressions containing column or table identifiers are passed through quote_ident function before insertion in a dynamic query. Expressions containing values that should be literal strings in the dynamic SQL are passed through quote_literal function.

Page 74: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

74

These functions take the appropriate steps to return the input text enclosed in double or single quotes respectively, with any embedded special characters properly escaped.

Make sure, you make appropriate changes to the dynamic SQL statement that is constructed in a routine and remove any PostgreSQL dependencies.

PL/pgSQL Example: BEGIN ... SELECT orderseq_number, orderseq_table, orderseq_numcol INTO _number, _table, _numcol FROM orderseq WHERE (orderseq_name=psequence); ... EXECUTE 'SELECT ' || quote_ident(_numcol) || ' FROM ' || quote_ident(_table) || ' WHERE (' || quote_ident(_numcol) || '=' || quote_literal(_number) || ');' INTO _test; ... END;

DB2 SQL PL example: BEGIN DECLARE VAR1 VARCHAR(1000); DECLARE STMT1 STATEMENT; ... SELECT orderseq_number, orderseq_table, orderseq_numcol INTO pnumber, ptable, pnumcol FROM PUBLIC.orderseq WHERE (orderseq_name=psequence); ... SET VAR1 = 'SELECT '|| CHAR(pnumcol)||' FROM '|| CHAR(ptable) || ' WHERE (' || CHAR(pnumcol) || '=' ||CHAR(pnumber) || ');' PREPARE STMT1 FROM VAR1 ; EXECUTE STMT1 INTO PTEST; ... END

6.12 41BTriggers In PostgreSQL, a trigger is a specification to the database for the automatic execution of a function whenever certain type of operation is performed. The operation is considered an event that “triggers” the execution of additional procedural code.

The trigger specification is registered in the database using CREATE TRIGGER and contains no procedural logic. A trigger specification identifies a trigger function to be executed when the event has occurred. e.g.

CREATE TRIGGER cashrcpttrigger

Page 75: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

75

BEFORE INSERT OR UPDATE ON cashrcpt FOR EACH ROW EXECUTE PROCEDURE _cashrcpttrigger (); trigger function In DB2, a trigger is both the specification and procedural routine to be performed when the specific event occurs. However, using a trigger to CALL a stored procedure is a frequently used technique and can be used to emulate the PostgreSQL implementation. Both database recognize INSERT, UPDATE or DELETE operations as trigger events, Neither database supports the use of SELECT triggers.

6.12.1 119BFOR EACH ROW and FOR EACH STATEMENT Both DB2 and PostgreSQL offer both per-row triggers and per-statement triggers. With a per-row trigger, the trigger function is invoked once for each row that is affected by the statement that fired the trigger. In contrast, a per-statement trigger is invoked only once when an appropriate statement is executed, regardless of the number of rows affected by that statement.

It should be noted, in both databases a statement that affects zero rows will still result in the execution of any applicable per-statement triggers.

6.12.2 120BClassified as BEFORE or AFTER Both DB2 and PostgreSQL support two trigger classifications: before triggers and after triggers. Statement-level before triggers naturally fire before the statement starts to do anything, while statement-level after triggers fire at the very end of the statement. Row-level before triggers fire immediately before a particular row is operated on, while row-level after triggers fire at the end of the statement (but before any statement-level after triggers).

6.12.3 121BMultiple events on a single object PostgreSQL supports trigger specifications for multiple events INSERT or UPDATE: e.g.

CREATE TRIGGER cashrcpttrigger BEFORE INSERT OR UPDATE ON cashrcpt trigger executed on both operations FOR EACH ROW EXECUTE PROCEDURE _cashrcpttrigger ();

DB2 requires a separate trigger to be created for each type of operation regardless if the procedural logic is the same. For example, you cannot have a single trigger that activates for both UPDATE and INSERT events. You must create two separate triggers.

6.12.4 122BMultiple triggers for a single event type PostgreSQL supports more than one trigger being defined for the same event on the same relation (i.e. multiple INSERT triggers for the same table) and will fire each in alphabetical order by trigger name.

Page 76: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

76

In DB2, multiple triggers can be created on the same event and relation however the activation order is determined by which ones were created first as opposed to alphabetical order.

6.12.5 123BCascading triggers When a PostgreSQL trigger function executes SQL commands, these commands might fire triggers again. This is known as cascading triggers. There is no direct limitation on the number of cascade levels. It is possible for cascades to cause a recursive invocation of the same trigger; for example, an INSERT trigger might execute a command that inserts an additional row into the same table, causing the INSERT trigger to be fired again. It is the trigger programmer's responsibility to avoid infinite recursion in such scenarios.

DB2 protects against this scenario by supporting BEFORE triggers with an implicit no cascade. Also, BEFORE triggers have restrictions on the types of stored procedures it can execute. Thus DB2 will not encounter recursive processing of triggers.

When creating a BEFORE trigger which executes a stored procedure the procedure will need the inclusion of the keywords READS SQL DATA and contain no DML statement which modifies data. DB2’s BEFORE triggers cannot execute a stored procedure which contains a DML statement other than SELECT. This is to enforce a rule protecting against operations that might activate other triggers.

An AFTER trigger activates AFTER a row is inserted, updated, or deleted. AFTER triggers do allow INSERT, UPDATE, and DELETE statements. You can designate an AFTER trigger as FOR EACH ROW, meaning that the trigger should activate after every row is inserted, updated, or deleted. Or, you can designate the trigger as FOR EACH STATEMENT, which activates it after the triggering statement completes and all applicable rows have been processed.

6.12.6 124BAccess to transition data and values Each database has its own method for making the trigger input data available to the trigger function:

For PostgreSQL this input data includes the type of trigger event (e.g., INSERT, UPDATE or DELETE) as well as any arguments passed to the trigger function. For a row-level trigger, the input data also includes the NEW row for INSERT and UPDATE triggers, and the OLD row for UPDATE and DELETE triggers. Statement-level triggers do not currently have any way to examine the individual row(s) modified by the statement.

DB2 triggers can access both transition variables as well as complete data sets which are effected by the triggering operation. The REFERENCING clause specifies the correlation names for the transition variables and the table names for the transition tables. Correlation names identify a specific row in the set of rows affected by the triggering SQL operation. Table names identify the complete set of affected rows.

Each row affected by the triggering SQL operation is available to the triggered action by qualifying columns with correlation-names specified as follows: OLD AS correlation-name specifies a correlation name which identifies the row state prior to the triggering SQL operation.

Page 77: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

77

NEW AS correlation-name specifies a correlation name which identifies the row state as modified by the triggering SQL operation and by any SET statement in a BEFORE trigger that has already executed.

The complete set of rows affected by the triggering SQL operation is available to the triggered action by using a temporary table name specified as follows.

OLD TABLE AS identifier specifies a temporary table name which identifies the set of affected rows prior to the triggering SQL operation. NEW TABLE AS identifier specifies a temporary table name which identifies the affected rows as modified by the triggering SQL operation and by any SET statement in a BEFORE trigger that has already executed.

6.12.7 125BEnabling PostgreSQL triggers in DB2 When a PostgreSQL trigger function is defined, arguments can be specified for it. The purpose of including arguments in the trigger definition is to allow different triggers with similar requirements to call the same function. As an example, there could be a generalized trigger function that takes as its arguments two column names and puts the current user in one and the current time stamp in the other.

A properly written PostgreSQL trigger function would typically be independent of the specific table it is triggering on. So the same function could be used for INSERT events on any table with suitable columns, to automatically track creation of records in a transaction table for example. It could also be used to track last-update events if defined as an UPDATE trigger.

There are two recommended methods for converting PostgreSQL triggers to DB2:

1 – Emulate the architecture of the Postgres’ trigger implementation. This can be accomplished by creating only the specification as a DB2 trigger and placing all trigger function logic within a DB2 stored procedure. This maps two PostgreSQL objects directly to two DB2 objects. 2 - Consolidate the PostgreSQL trigger and trigger function into a single DB2 trigger.

The complexity of the PostgreSQL trigger functions logic should be considered before making a decision on which methodology to use for the conversion. While consolidating into a single database object would provide the most efficient and easiest scenario to manage, DB2 triggers support only a sub-set of the SQL PL commands available within a stored procedure and the complexity of the PostgreSQL trigger function may require the full support of DB2’s SQL PL programming language.

Converting the trigger function

PostgreSQL example: CREATE OR REPLACE FUNCTION _cashrcpttrigger() RETURNS trigger AS $BODY$ DECLARE _check BOOLEAN;

Page 78: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

78

_checkId INTEGER; _currId INTEGER; _bankCurrId INTEGER; BEGIN -- Checks -- Start with privileges IF (TG_OP = 'INSERT') THEN SELECT checkPrivilege('MaintainCashReceipts') INTO _check; IF NOT (_check) THEN RAISE EXCEPTION 'You do not have privileges to add new

Cash Receipts.'; END IF; ELSE SELECT checkPrivilege('MaintainCashReceipts') INTO _check; IF NOT (_check) THEN RAISE EXCEPTION 'You do not have privileges to alter a

Cash Receipt.'; END IF; END IF; -- Currency must be same as Bank Currency IF (TG_OP = 'INSERT') THEN _currId = COALESCE(NEW.cashrcpt_curr_id, basecurrid()); ELSE _currId = NEW.cashrcpt_curr_id; END IF; SELECT bankaccnt_curr_id INTO _bankCurrId FROM bankaccnt WHERE (bankaccnt_id=NEW.cashrcpt_bankaccnt_id); IF (_currId<>_bankCurrId) THEN RAISE EXCEPTION 'Currency supplied does not match Bank Currency.'; END IF; RETURN NEW; END; $BODY$ LANGUAGE 'plpgsql' VOLATILE COST 100;

DB2 syntax: CREATE OR REPLACE PROCEDURE cashrcpttrigger ( IN tg_op CHAR(6), IN new_cashrcpt_curr_id INTEGER, IN new_cashrcpt_bankaccnt_id INTEGER ) READS SQL DATA BEGIN DECLARE check BOOLEAN; DECLARE checkId INTEGER; DECLARE currId INTEGER; DECLARE bankCurrId INTEGER; -- Checks -- Start with privileges IF (TG_OP = 'INSERT') THEN SET check = public.checkPrivilege('MaintainCashReceipts'); IF (check != TRUE) THEN

Page 79: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

79

SIGNAL SQLSTATE '70000' SET MESSAGE_TEXT='You do not have privileges to add new Cash Receipts.'; END IF; ELSE SET check = public.checkPrivilege('MaintainCashReceipts'); IF (check != TRUE) THEN SIGNAL SQLSTATE '70000' SET MESSAGE_TEXT='You do not have privileges to alter a Cash Receipt.'; END IF; END IF; -- Currency must be same as Bank Currency IF (TG_OP = 'INSERT') THEN SET currId = COALESCE(new_cashrcpt_curr_id, basecurrid()); ELSE SET currId = new_cashrcpt_curr_id; END IF; SELECT bankaccnt_curr_id INTO bankCurrId FROM bankaccnt WHERE ( bankaccnt_id = new_cashrcpt_bankaccnt_id ); IF (currId <> bankCurrId) THEN SIGNAL SQLSTATE '70000' SET MESSAGE_TEXT='Currency supplied does not match Bank Currency.'; END IF; END@

Converting the trigger

Postgres example: CREATE TRIGGER cashrcpttrigger BEFORE INSERT OR UPDATE ON cashrcpt FOR EACH ROW EXECUTE PROCEDURE _cashrcpttrigger ();

DB2 syntax: CREATE TRIGGER cashrcpttrigger_i BEFORE INSERT ON cashrcpt REFERENCING NEW AS new FOR EACH ROW CALL public.cashrcpttrigger ('INSERT', new.cashrcpt_curr_id, new.cashrcpt_bankaccnt_id); CREATE or replace TRIGGER cashrcpttrigger_u BEFORE UPDATE ON cashrcpt REFERENCING NEW AS new FOR EACH ROW CALL public.cashrcpttrigger ('UPDATE', new.cashrcpt_curr_id, new.cashrcpt_bankaccnt_id);

Page 80: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

80

6.13 42BPostgreSQL Rules PostgreSQL supports a database rule system which allows the definition of alternative action to be performed when a data manipulation statement (DML) is processed against a specified table.

The PostgreSQL rule system could be more accurately described as a “query rewrite facility”. It interfaces with the database’s query optimization process; between the parser and the planner, and has the ability to transform a query prior to passing a modified version for planning and execution. Rules can be a very powerful tool since they can not only apply substitution, but include additional SQL statements for processing and thus providing a macro-expansion facility for SQL Processing.

From an enablement perspective, a PostgreSQL rule can be emulated by DB2 using a combination of triggers and stored procedures. There are some differences in the initiating event; PostgreSQL rules can be initiated by any DML statement (i.e. SELECT, INSERT, UPDATE, or DELETE) processed against a table. DB2 triggers can be initiated by an INSERT, UPDATE, or DELETE events with no support for a trigger based on a SELECT event.

Additionally, a PostgreSQL rule uses a specification of DO ALSO or DO INSTEAD which designates how the rule is to interact with the original query. A rule’s DO specification will be followed by one or more SQL commands or the keyword NOTHING as an instruction that no action is to take place. In DB2, the type of trigger; BEFORE, AFTER and INSTEAD OF determines how it processes with the original query and a sub-set of DB2’s SQL PL programming language provides the procedural processing capability.

PostgreSQL has support for a NOTIFY action, a simple form of an inter-process communication mechanism, which has no corresponding facility in DB2.

The following example demonstrates how the similarities between a PostgreSQL rule and a DB2 trigger can ease of conversion. In this case an update to a table causes the execution of an INSERT statement. By default, a PostgreSQL rule definition’s is DO ALSO thus a DB2 AFTER trigger would perform this procedure in an identical manner.

PostgreSQL example: CREATE RULE log_shoelace AS ON UPDATE TO shoelace_data WHERE NEW.sl_avail <> OLD.sl_avail DO INSERT INTO shoelace_log VALUES ( NEW.sl_name, NEW.sl_avail, current_user, current_timestamp );

DB2 syntax CREATE TRIGGER log_shoelace AFTER UPDATE ON shoelace_data REFERENCING NEW AS new OLD AS old FOR EACH ROW WHEN (NEW.sl_avail <> OLD.sl_avail) INSERT INTO SHOELACE_LOG VALUES (

Page 81: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

81

NEW.SL_NAME, NEW.SL_AVAIL, CURRENT_USER, CURRENT_TIMESTAMP ); A PostgreSQL INSTEAD rule can be converted easily to a DB2 INSTEAD OF trigger if applicable database object is a view. DB2 only supports the use of INSTEAD OF triggers on views. While PostgreSQL does not have this restriction, INSTEAD logic for rules was implemented to provide the ability to update complex views making all views “update-able”. This was the same rationale as DB2 so you may find most occurrences within your database to be capable of the conversion without significant change.

PostgreSQL example:

CREATE RULE shoelace_ins AS ON INSERT TO shoelace shoelace is a view DO INSTEAD INSERT INTO shoelace_data VALUES ( NEW.sl_name, NEW.sl_avail, NEW.sl_color, NEW.sl_len, NEW.sl_unit );

DB2 syntax: CREATE trigger shoelace_ins INSTEAD OF INSERT ON shoelace REFERENCING NEW AS new FOR EACH ROW INSERT INTO shoelace_data VALUES ( NEW.sl_name, NEW.sl_avail, NEW.sl_color, NEW.sl_len, NEW.sl_unit ); While there are similarities between the uses of a PostgreSQL rule and those of a DB2 trigger it is important to realize that a PostgreSQL rule is a unique object with some unique capabilities which are not supported by DB2.

Page 82: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

82

7. 6BBasic Security

There are many similarities between PostgreSQL and DB2’s Basic Security. This section examines the three primary security mechanisms of both databases while focusing on the differences between their implementations:

Authentication

• Process of validating a supplied user ID and password against a security facility • Confirming “you are who you say you are”

Authorization

• Determines the operations that users, roles or group authorities can perform and controls access to database objects

• Examples of authorities: SYSADM, DBADM, SECADM

Privileges

• Defines operations permitted on database objects

• Object security more granular than authorities

7.1 43BAuthentication There is no user authentication data managed DB2. Authentication of a user is completed using a security facility outside of the DB2 database. The security facility can be part of the operating system or a separate product. Any attempt to attach to the instance or connect to any of the instance’s databases will require the user ID identifies the user to the security facility. By supplying the correct password, information known only to the user and the security facility, the user's identity (corresponding to the user ID) is verified.

PostgreSQL database passwords are separate from operating system user passwords. The password for each database user is stored in the pg_authid system catalog. Passwords can be managed with the SQL commands HCREATE USERH and HALTER USER H, e.g., CREATE USER user-id WITH PASSWORD 'secret'. By default, that is, if no password has been set up, the stored password is null and password authentication will always fail for that user.

Both DB2 and PostgreSQL support a variety of authentication using similar methods; trusted authentication, password authentication, encrypted passwords, LDAP, Kerberos, GSS-API, SSPI, SSL plug-in and PAM authentication.

PostgreSQL supports an Identification-based authentication which DB2 does not support natively however can be configured using a combination of a authentications and authorizations.

Page 83: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

83

7.2 44BAuthorization As mentioned already, DB2 relies upon an authentication process external to the database. The user is authenticated to be “who he says he is” by an external sub-system and as a result no user security data such as the user’s password are in the database.

Once the user has passed through Authentication, the second component of basic security, Authorization, takes responsibility for managing access to specific database objects. Once connected to a DB2 database, users (identified by an authorization ID) can successfully execute operations only if they have the authority to perform the specified function. For example, to create a table, a user must be authorized to create tables; to alter a table, a user must be authorized to alter the table; and so forth.

PostgreSQL manages all database access permissions using the concept of roles. A role can be thought of as either a database user, or a group of database users, depending on how the role is set up (i.e. CREATE … LOGIN or NOLOGIN). A role having the LOGIN attribute can be thought of as a user. Roles without this attribute are useful for managing database privileges, but are not users in the usual sense of the word.

DB2 supports a concept of “Separation of Duties” for database authorities and divides the duties of database administrator and security administrator. This separation empowers the Security Administrator (SECADM) to the highest authorization for managing users and database access. The SECADM authority is required for all grants and revokes of authorities, roles and privileges.

7.3 45BPrivileges In both databases, roles can own database objects (for example, tables) and can assign privileges on those objects to other roles to control who has access to which objects. Furthermore, it is possible to grant membership in a role to another role, thus allowing the member role use of privileges assigned to the role it is a member.

In DB2, managing database privileges through the use of roles is the equivalent of PostgreSQL’s user security.

7.4 46BData Control Language (DCL)

7.4.1 126BCreating a RESTRICTIVE database in DB2 When the RESTRICTIVE option is used when creating a DB2 database the DB CFG parameter RESTRICT_ACCESS is set to YES and no privileges or authorities are automatically granted to PUBLIC.

DB2 syntax: CREATE DATABASE database-name RESTRICTIVE

Page 84: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

84

7.4.2 127BInstance administrative authority

PostgreSQL example: CREATE ROLE role-name SUPERUSER

DB2 syntax: Using the security management facility of the operating or 3rd party security system create the user id and group id (if necessary), assign the user to the group then update the instance configuration for SYSADM_GROUP to the group-name. UPDATE DBM CFG USING SYSADM_GROUP {group-name} All members of the group identified by SYSADM_GROUP parameter value will have the instance’s highest administrative privileges.

7.4.3 128BDatabase administrative authority

DB2 database administrative authority is granted to roles or users using the GRANT command.

PostgreSQL example: CREATE ROLE role-name SUPERUSER

DB2 syntax: CREATE ROLE dba GRANT DBADM ON DATABASE TO ROLE dba GRANT ROLE dba TO USER bob

7.4.4 129BCreating a new database user and granting user privileges

PostgreSQL example: CREATE ROLE { user-id | role-name } LOGIN NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE

DB2 equivalent syntax: CREATE ROLE { user-id | role-name }

GRANT CONNECT ON DATABASE TO ROLE { user-id | role-name }

GRANT DATAACCESS ON DATABASE TO ROLE { user-id | role-name }

GRANT ROLE { user-id | role-name } TO USER { user-id | role-name }

Page 85: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

85

8. 7BMigration Issues

This section lists known migration issues which cannot be identified as part of DDL, DML or SQL considerations. This allows a separate discussion of the issues when enabling an application from PostgreSQL to DB2.

For example, the issues surrounding creating a stored procedure are discussed in the DDL section, and the issues surrounding the stored procedure language are discussed in the DML section.

This section is provided as a “how to” guide when a simple solution is not available.

8.1 47BName identifiers Rules exist for the naming of all database objects, users, groups, files, and paths in both Postgres and DB2. Some of these rules are specific to the operating system platform.

On UNIX platforms, names are case-sensitive. For example, /data1 is not the same directory as /DATA1 or /Data1

On Windows® platforms, names are not case-sensitive. For example, \data1 is the same as \DATA1 and \Data1.

In DB2, all names can include the following characters:

− The letters A through Z, and a through z, as defined in the basic (7-bit) ASCII character set. When used in identifiers for objects created with SQL statements, lowercase characters “a” through “z” are converted to uppercase unless they are delimited with quotes (“)

− 0 through 9 − ! % ( ) { } . – � ~ _ (underscore) @, #, $, and space − \ (backslash)

A comparison of PostgreSQL and DB2 conventions results in a restriction; DB2 name identifies can not begin names with a number or with the underscore character.

8.2 48BDatabase name length All DB2 identifiers visible by the application have a name limit of 128 characters with the following exceptions:

• Database and database aliases are limited to 8 characters in length

• Buffer pools and table spaces are limited to 18 characters in length

• Index extensions, ADT transform groups, and type mappings are limited to 18.

Page 86: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

86

The only resolution is reduce the length of the PostgreSQL database object name to conform to DB2 naming standard lengths.

A database name should be the only identifier requiring conversion impacting the application. The other database objects bound by the 18 character limit are never referenced directly by SQL statements so shortening of these names has no functional impact on your migrated application.

8.3 49BColumn default derived from function Only built in functions can are supported as default values for column declarations. CREATE TABLE "PUBLIC"."ACCNT" ( “ACCNT_CURR_ID” INTEGER DEFAULT basecurrid() … );

-or- ALTER TABLE "PUBLIC"."ACCNT" ALTER COLUMN "ACCNT_CURR_ID" SET WITH DEFAULT basecurrid

Solution:

• The assignment of a default value returned by the PostgreSQL function will need to be encapsulated within a DB2 BEFORE on INSERT trigger. A BEFORE trigger can be used to manipulate a column’s value for the rows processed by an INSERT, UPDATE or DELETE statement.

8.4 50BTYPE declarations in functions and procedures DB2 9.7 does not support TYPE declarations inside functions and procedures. The only exception being TYPE <type> IS REF CURSOR. All other variable types will need variable types to be created outside of the routine.

8.5 51BSUBSTR restrictions Both DB2 and PostgreSQL SUBSTR function have operational equivalence, being passed a string, a starting position and number of characters to be extracted from string.

DB2’s SUBSTR function requires the value of <length> to be in the range of 0 to n, where n equals LENGTH_OF_<string> - <start> + 1. When exceeded, this limit will return an error.

PostgreSQL does not impose this restriction thus the references to this function may have specified a value that is greater than DB2’s upper limit.

PostgreSQL example:

Page 87: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

87

CREATE TABLE shoe_sizes ( sl_name character varying(30)[], sl_avail integer ); select substr(sl_name, 10,30) from shoelace_data;

-or- select substr(sl_name, 10,999) from shoelace_data;

DB2 syntax: CREATE TABLE shoe_sizes ( sl_name character varchar(30), sl_avail integer ); select substr(sl_name, 10,21) from shoelace_data;

8.6 52BDEFAULT parameters in functions DB2 9.7 does NOT support DEFAULT parameters on functions. If this functionality is needed it will be necessary to create a duplicate of the function and overload it with a version which supplies the default value or find all references to the function and call it passing the default value in cases where no value was being passed.

Functions that modify data

DB2 9.7 requires that you add the MODIFIES SQL DATA option when declaring a function that performs any INSERT, UPDATE or DELETE processing.

The only solution is to add the required syntax to the user defined function. CREATE FUNCTION DEPTEMPLOYEES (DEPTNO CHAR(3)) RETURNS TABLE (EMPNO CHAR(6), LASTNAME VARCHAR(15)) LANGUAGE SQL MODIFIES SQL DATA NO EXTERNAL ACTION DETERMINISTIC BEGIN ATOMIC INSERT INTO AUDIT VALUES (USER, ‘Table: EMPLOYEE Prd: DEPTNO = ' || DEPTNO); RETURN SELECT EMPNO, LASTNAME, FIRSTNME FROM EMPLOYEE WHERE EMPLOYEE.WORKDEPT = DEPTEMPLOYEES.DEPTNO; END

8.7 53BBoolean variables and IF statements DB2 9.7 does not support the use of a BOOLEAN variable as a boolean expression in a test condition with the SQL PL procedural language.

Length value must be reduced to DB2 limit

Page 88: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

88

The PostgreSQL syntax must be changed, from: IF v_firstColumn THEN

DB2’s supported syntax: IF (v_firstColumn = TRUE) THEN

8.8 54BINTERVAL data type In PostgreSQL interval values are written with syntax QUANTITY UNIT where quantity is a number and unit is microsecond, millisecond, second, minute, hour, day, week, month, year, decade, century, millennium, or abbreviations or plurals of these units (i.e. 2 MONTH).

There is no interval data type in DB2’s SQL PL. A workaround is to use two variables, one for quantity and one for unit.

PLpg/SQL example: CREATE OR REPLACE FUNCTION LIST_EMPLOYEES (INTERVAL) RETURNS RECORD LANGUAGE 'plpgsql' AS $$ DECLARE l_cutoff_time interval ALIAS for $1; l_emprec RECORD; BEGIN FOR l_emprec in (select empno, empname from employee where hiredate < current_date – l_cutoff_time) LOOP RETURN l_emprec; END LOOP; END; $$ ;

DB2 SQL PL syntax: CREATE OR REPLACE FUNCTION LIST_EMPLOYEES (l_cutoff_quantity SMALLINT, l_cutoff_unit VARCHAR(20)) RETURNS TABLE(empno INT, empname VARCHAR(30)) BEGIN DECLARE l_cutoff_date TIMESTAMP; IF (l_cutoff_unit = 'year') THEN SET l_cutoff_date = current_date - ((l_cutoff_quantity * 1) years); ELSEIF (l_cutoff_unit = 'month') THEN SET l_cutoff_date = current_date - ((l_cutoff_quantity * 1) months); ELSEIF (l_cutoff_time_unit = 'day') THEN SET l_cutoff_date = p_data_timestamp - ((l_cutoff_quantity * 1) days); END IF; RETURN select empno, empname

Page 89: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

89

from employee where hiredate < current_date – l_cutoff_time; END

8.9 55BUn-typed NULL values in a SELECT list The following PostgreSQL SQL statement will be returned an error by DB2:

PostgreSQL example: SELECT sl_name, NULL as sl_size FROM shoe_sizes SQL0418N A statement contains a use of an un-typed parameter marker or a null value that is not valid. SQLSTATE=42610

The reason for the error is the presence of a result column (sl_size) of a SELECT statement that is returning an un-typed NULL value expression. DB2 can not resolve the expression type of the NULL value to a data type from the SELECT list.

Solution:

• The un-typed NULL value must be explicitly cast to a valid DB2 data type. SELECT sl_name, CAST(NULL AS INTEGER) as sl_size FROM shoe_sizes

8.10 56BCombined action triggers DB2 9.7 does not support combined event triggers, i.e., triggers that are fired for more than one event, with events being INSERT, UPDATE and DELETE type of action. CREATE TRIGGER custtrigger BEFORE INSERT OR DELETE OR UPDATE ON custinfo FOR EACH ROW EXECUTE PROCEDURE _custtrigger();

Solution:

• Split the combined action trigger into separate triggers, one for each type of action. In this case, you will need to split the original trigger in two different triggers. One will have the AFTER INSERT clause and the other will have the AFTER UPDATE clause.

8.11 57BBEFORE triggers that modify the database DB2 9.7 does not allow BEFORE triggers to modify the database. That means BEFORE triggers can not execute DML operations such as INSERT, UPDATE or DELETE.

Solution: • Convert any BEFORE trigger which processes a DML statement to an AFTER trigger.

Comment out all insert, update and delete operations in the original BEFORE trigger

Page 90: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

90

and create a new AFTER trigger to execute all the operations which must be removed from the BEFORE trigger.

8.12 58BUsing a function’s expression as an index key Functional indexes are indexes created on the value returned by the function, rather than the value of a column. PostgreSQL will allow an index to be created using a built-in or user-defined function. DB2 does not support functional indexes however a solution can be engineered using the GENERATED ALWAYS option applied to a column’s definition.

PostgreSQL example: CREATE INDEX indx1 ON tab1(UPPER(COL1))

DB2 solution: SET INTEGRITY FOR tab1 OFF; ALTER TABLE tab1 ADD col2 GENERATED ALWAYS AS (UPPER(col1)); SET INTEGRITY FOR tab1 IMMEDIATE CHECKED FORCE GENERATED; CREATE INDEX INDX1 ON tab1(col2); When using this solution the application’s SQL does not need to changed. The DB2 SQL optimizer will compensate and choose the proper index for the generated index key.

8.13 59BLimitation on table row width Within a DB2 database, rows in a table cannot span more than one page. A table's row size is the sum of bytes required to represent all the columns in a table (not including LOB data). DB2’s maximum page size is 32 kilobytes. Therefore, maximum row size for any table must be within this 32 kilobyte limit.

Solutions (more than one may apply):

1. Reduce the table’s row size

Evaluate how the tables are used and the businesses reasons for having this size. Very often, the majority of these large tables could be reduced below the 32 K limit easily without a major impact on applications.

2. Relocate data elements

Use DB2’s XML or CLOB data type for column’s containing large character strings. The table’s required row width can be reduced by storing columns in alternate locations. In DB2, XML and large object data can designate a storage location in another table space other than the remaining data elements of the table.

3. Create a view to represent the two wide tables

Page 91: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

91

If the row width cannot be reduced under the 32,676 byte limit another possible solution is to physically split the table into two tables and provide the application with a unified view.

Solution:

Postgres DB2

Then unify the two tables using a view: CREATE VIEW wide_table AS SELECT wide_table1.c1, wide_table1 c2, wide_table2.c1, wide_table2.c2 FROM wide_table1, wide_table2 WHERE wide_table.pk = wide_table2.pk;

8.14 60BDisabling triggers There is no facility for disabling triggers in DB2. Without the ability to disable a trigger the only option in DB2 is to drop and re-create the trigger.

CREATE TABLE wide_table( pk INTEGER, c1 VARCHAR(20000), c2 VARCHAR(20000));

CREATE TABLE wide_table1( pk INTEGER, c1 VARCHAR(15000), c2 VARCHAR(15000));

CREATE TABLE wide_table2( pk INTEGER, c1 CLOB(20K), c2 CLOB(20K));

Page 92: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

92

9. 8BAdditional Resources

9.1 61BEducation and learning Porting to HDB2 Universal DatabaseH. The developerWorks DB2 Universal Database porting site gives you the information you need to port an application and its data from other database management systems to DB2 UDB.

Visit the HdeveloperWorks DB2 zone H to expand your DB2 skills

Stay current with HDeveloperWorks technical events and WebcastsH.

UDFs to ease migration HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0504greenstein/index.html U

Everything You Wanted to Know About DB2 Universal Database Processes HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/0304chong/0304chong.html U

Leverage MySQL skills to learn DB2 Express HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0602tham2/ U

DB2 Express-C, the developer-friendly alternative HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0602hutchison/ UH Log DB2 UDB stored procedure messages HU http://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0601khatri

Getting to know the DB2 UDB command line processor HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0503melnyk/ U

The IBM DB2 Universal Database for Linux, UNIX, and Windows Backup Utility HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0501zikopoulos/U

Lock avoidance in DB2 UDB V8 HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0509schuetz/U

Migrating to IBM database servers gets easier with the latest MTK release HUhttp://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0603geib/

Page 93: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

93

9.2 62BDownload products and technologies DB2 Express-C Absolutely Free Hhttp://www.ibm.com/developerworks/downloads/im/udbexp/?S_TACT=105AGX01&S_CMP=LP

Software Evaluation Kits on DVDs Hhttp://www.ibm.com/cgi-bin/software/track0.cgi?i=53018&c=74648&o=5&ef=T&cn=7817704

Featured product trials Hhttp://www.ibm.com/cgi-bin/software/track0.cgi?i=50023&c=74648&o=4&ef=T&cn=7817704

PostgreSQL JDBC Driver Hhttp://jdbc.postgresql.org/

IBM JDK 5.0 Hhttp://www-128.ibm.com/developerworks/java/jdk/

9.3 63BDiscussion groups and forums

Participate in DB2 discussion Groups

IBM DB2 Express-C Forum Hhttp://www-128.ibm.com/developerworks/forums/dw_forum.jsp?forum=805&cat=19

Participate in HdeveloperWorks blogsH and get involved in the developerWorks community.

9.4 64BReferences

9.4.1 130BPostBooks: An Open Source ERP Most of the PostgreSQL examples used in this document are from the database of a free open source ERP application called PostBooks. More information about this application can be found at: Hhttp://sourceforge.net/projects/postbooks/

9.4.2 131BPostgreSQL Documentation Porting Topics covered in this document are based on PostgreSQL version 8.4. Online documentation can be found at: Hhttp://www.postgresql.org/docs/

9.4.3 132BDB2 Documentation Porting Topics covered in this document are based on DB2 Express-C Edition for Linux, Unix, and Windows version 9.7. From time to time, we have also covered some advanced topics like table partitioning which is part of DB2 Enterprise Edition. DB2 Online

Page 94: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

94

documentation can be found at: Hhttp://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp

9.4.4 133BdeveloperWorks Articles We referred to the following two articles for the content in architectural overview and data type comparison chapters.

Leverage your PostgreSQL V8.1 skills to learn DB2, Version 8.2 Hhttp://www.ibm.com/developerworks/data/library/techarticle/dm-0603wasserman2/index.html

Migrate from MySQL or PostgreSQL to DB2 Express-C Hhttp://www.ibm.com/developerworks/data/library/techarticle/dm-0606khatri/

Complete coverage of DB2 Data Partitioning features is beyond the scope of this guide, the following developerWorks articles provide resources to learn about different DB2 data partitioning features and the best approach to implement each of them:

DB2 partitioning features Hhttp://www.ibm.com/developerworks/db2/library/techarticle/dm-0608mcinerney/

Introducing DB2 9, Part 2: Table partitioning in DB2 9 Hhttp://www.ibm.com/developerworks/db2/library/techarticle/dm-0605ahuja2/

Page 95: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

95

9BAppendix A - Using the IBM Data Movement Tool (IDMT)

There is a free tool offered by IBM to assist your enablement effort. The IBM Data Movement Tool (IDMT) is a simple tool that can extract database object definitions (DDL) and data from a variety of database management systems to a format which can be accepted by DB2 for Linux, UNIX, and Windows and DB2 for z/OS.

This tool can be downloaded from:

DB2 9.7: IBM Data Movement Tool Hhttp://www.ibm.com/developerworks/data/library/techarticle/dm-0906datamovement/ This tool is not supported by the IBM support organization. However, you can report bugs, issues, suggestions, and enhancement requests in the support HforumH.

Page 96: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

96

While IDMT does not fully support migrations from PostgreSQL it can still provide a significant assist with a migration. The utility will extract and produce a script of DDL converted to DB2 syntax for each table, index and sequence object.

Prior to deployment in a DB2 database the DDL scripts generated by IDMT should be reviewed for any conversion issues. Typically, DDL conversion issues can result from data type mapping or the use of native PostgreSQL functions in a table definition.

See the following examples:

Mapping TEXT to CLOB(2147483647) IDMT will map the PostgreSQL data type TEXT to the DB2 data type CLOB. If this is not acceptable it will be necessary to determine the required size for the column to contain the data and manually edit the db2tables.sql file prior to deployment of the DDL within the destination DB2 database.

TIMESTAMP data types with default of ‘now’ IDMT does not convert the PG/sql keyword ‘now’. It will be necessary to replace the reference with DB2’s CURRENT TIMESTAMP.

Extracted by IDMT: ALTER TABLE "PUBLIC"."BANKREC" ALTER COLUMN "BANKREC_CREATED" SET WITH DEFAULT 'now'

Manually edited for DB2: ALTER TABLE "PUBLIC"."BANKREC" ALTER COLUMN "BANKREC_CREATED" SET WITH DEFAULT CURRENT TIMESTAMP

Page 97: IBM DB2 9.7 PostgreSQL to DB2 porting guidepublic.dhe.ibm.com/software/.../PostgreSQL...Guide.pdf · 5 1. 0BIntroduction This document is a technical guide describing the process

97

© Copyright IBM Corporation 2009 All Rights Reserved. IBM, IBM (logo), and DB2 are trademarks or registered trademarks of International Business Machines Corporation in the United States, other countries, or both. Linux is a registered trademark of Linus Torvalds in the United States, other countries, or both. UNIX is a registered trademark of The Open Group in the United States, other countries, or both Windows is a trademark of Microsoft Corporation in the United States, other countries, or both. Other company, product, or service names may be trademarks or service marks of others. References in this publication to IBM products or services do not imply that IBM intends to make them available in all countries in which IBM operates. 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 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 measurement 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. The information in this publication is provided AS IS without warranty. Such information was obtained from publicly available sources, is current as of January 2009, and is subject to change. Any performance data included in the paper was obtained in the specific operating environment and is provided as an illustration. Performance in other operating environments may vary. More specific information about the capabilities of products described should be obtained from the suppliers of those products.