You are on page 1of 868

unisys

ClearPath Enterprise Servers

Enterprise Relational Database Server


for ClearPath OS 2200 SQL Programming
Reference Manual
Level 20R1

February 2015 7830 8160–027


NO WARRANTIES OF ANY NATURE ARE EXTENDED BY THIS DOCUMENT. Any product or related information
described herein is only furnished pursuant and subject to the terms and conditions of a duly executed agreement to
purchase or lease equipment or to license software. The only warranties made by Unisys, if any, with respect to the
products described in this document are set forth in such agreement. Unisys cannot accept any financial or other
responsibility that may be the result of your use of the information in this document or software material, including
direct, special, or consequential damages.

You should be very careful to ensure that the use of this information and/or software material complies with the
laws, rules, and regulations of the jurisdictions with respect to which it is used.

The information contained herein is subject to change without notice. Revisions may be issued to advise of such
changes and/or additions.

Notice to U.S. Government End Users: This is commercial computer software or hardware documentation developed
at private expense. Use, reproduction, or disclosure by the Government is subject to the terms of Unisys standard
commercial license for the products, and where applicable, the restricted/limited rights provisions of the contract
data rights clauses.

Unisys and ClearPath are registered trademarks of Unisys Corporation in the United States and other countries.
All other brands and products referenced in this document are acknowledged to be the trademarks or registered
trademarks of their respective holders.
Contents
Section 1. Introduction to Enterprise Relational Database
Server

1.1. Using This Manual .............................................................................. 1–2


1.2. Documentation Updates ................................................................... 1–3
1.3. Introduction to the Relational Database Model ..........................1–4
1.3.1. Structured Query Language (SQL) .......................................1–4
1.3.2. Sample Database ...................................................................... 1–5
1.3.3. Relational Calculator ................................................................1–6
1.3.4. Characteristics of Relational Tables.....................................1–6
1.3.5. Views ...........................................................................................1–8
1.3.6. Terminology ...............................................................................1–8
1.4. RDMS Environment .......................................................................... 1–10
1.5. RDMS Interfaces............................................................................... 1–12
1.6. Interface Tradeoffs .......................................................................... 1–14
1.6.1. Tradeoffs to Consider ........................................................... 1–14
1.6.2. Static ESQL Interface ............................................................. 1–16
1.6.3. Interactive Interface ............................................................... 1–17
1.6.4. Dynamic ESQL Interface ....................................................... 1–18
1.6.5. General Guidelines ................................................................. 1–19
1.7. SQL and RDMS Statements.......................................................... 1–20
1.7.1. Data Retrieval ......................................................................... 1–20
1.7.2. Deletes, Inserts, and Updates ............................................. 1–21
1.7.3. Locks ..........................................................................................1–22
1.7.4. Table Security ..........................................................................1–22
1.7.5. Table Definition ...................................................................... 1–23
1.7.6. View Definition ....................................................................... 1–23
1.7.7. Routines and Triggers .......................................................... 1–24
1.7.8. ESQL Variable Declarations ................................................. 1–24
1.7.9. Dynamic ESQL Statement Execution ............................... 1–25
1.7.10. UDS Work Sessions (Thread Control) .............................. 1–25
1.7.11. Checks and Inquiries ............................................................. 1–26

Section 2. SQL Fundamentals

2.1. Syntax Rules for SQL Statements ................................................ 2–2


2.2. Naming Conventions......................................................................... 2–3
2.2.1. Rules for Naming Entities ...................................................... 2–3
2.2.2. Referencing Tables, Views, and Versions ......................... 2–5
2.2.3. Referencing Columns ............................................................. 2–7
2.2.4. Referencing Functions and Procedures ............................ 2–8
2.2.5. Referencing Storage Areas................................................... 2–9
2.2.6. Rules for Naming Roles ....................................................... 2–10

7830 8160–027 iii


Contents

2.3. Literals ................................................................................................. 2–11


2.3.1. String Literals ........................................................................... 2–11
2.3.2. Numeric Literals ......................................................................2–12
2.3.3. Nulls........................................................................................... 2–14
2.3.4. Datetime Literals.................................................................... 2–15
2.3.5. Interval Literals ....................................................................... 2–18
2.4. Expressions ....................................................................................... 2–22
2.4.1. What Is an Expression?........................................................ 2–22
2.4.2. Boolean Expressions ............................................................ 2–23
2.4.3. Universal Quantifiers (SOME, ANY, ALL) ......................... 2–25
2.4.4. Bitwise Expressions ............................................................. 2–27
2.4.5. Order of Precedence for Operations ............................... 2–30
2.4.6. Evaluation and Rounding of Arithmetic
Expressions ........................................................................ 2–31
2.4.7. Arithmetic Result Types ...................................................... 2–35
2.4.8. Datetime Arithmetic Expressions ..................................... 2–36
2.4.9. String and Blob Expressions ............................................... 2–37
2.4.10. Built-In Functions ................................................................... 2–38
2.5. Expression Operands and Comparison Operators ................. 2–39
2.5.1. Null Value and IS NULL Operator ....................................... 2–41
2.5.2. DEFAULT value ....................................................................... 2–42
2.5.3. BETWEEN Operator .............................................................. 2–42
2.5.4. LIKE and NOT LIKE Operators ............................................ 2–43
2.5.5. IN Operator.............................................................................. 2–47
2.5.6. Aggregate Functions (AVG, SUM, MIN, MAX,
COUNT) ................................................................................ 2–48
2.5.7. Datetime Functions ............................................................... 2–51
2.5.8. USER Function ........................................................................ 2–55
2.5.9. Boolean Existential Function (EXISTS) .............................. 2–56
2.6. Sequences ......................................................................................... 2–57
2.7. Query Specification ......................................................................... 2–59
2.7.1. SELECT Statement Processing .......................................... 2–60
2.7.2. Referencing Views ................................................................ 2–67
2.7.3. Execution ..................................................................................2–71
2.7.4. Subqueries................................................................................2–71
2.7.5. Common Table Expressions ............................................... 2–79
2.8. RDMS Data Types ........................................................................... 2–80
2.8.1. Character Data Types ........................................................... 2–80
2.8.2. Numeric Data Types ............................................................. 2–82
2.8.3. Datetime Data Types ............................................................ 2–87
2.8.4. Binary Large Object Data Type .......................................... 2–89
2.9. Character Handling and Internationalization ............................. 2–93
2.9.1. Character Value Assignment Considerations ................. 2–93
2.9.2. Internationalization Considerations for
Character Data ................................................................... 2–98
2.9.3. Collating Sequence.............................................................. 2–107
2.9.4. Kanji Data ............................................................................... 2–108
2.10. Host Language Variables ............................................................. 2–109
2.10.1. Embedded Variables ............................................................ 2–110
2.10.2. Parameter Markers .............................................................. 2–111
2.10.3. Placeholder Variables........................................................... 2–111
2.10.4. Indicator Variables ................................................................2–114

iv 7830 8160–027
Contents

2.11. Embedded SQL (ESQL) ..................................................................2–118


2.11.1. Static ESQL .............................................................................2–119
2.11.2. Automatic Recompilation ...................................................2–119
2.11.3. Marking ESQL Statements for the Compiler ................ 2–120
2.11.4. Scope of ESQL Statements .............................................. 2–120
2.11.5. Resolving Cursor References .......................................... 2–122
2.11.6. Dynamic ESQL ...................................................................... 2–124
2.11.7. Dynamic ESQL Statement Set ......................................... 2–126
2.12. Using SQL in Module Programs................................................. 2–127

Section 3. Scalar Functions

3.1. Introduction to Scalar Functions ..................................................... 3–1


3.1.1. Aggregate and Scalar Functions ........................................... 3–1
3.1.2. Input to Scalar Functions ....................................................... 3–2
3.1.3. Rules ........................................................................................... 3–2
3.1.4. Where Functions Can Be Used ............................................ 3–3
3.1.5. Considerations for Routines and Triggers ........................ 3–4
3.1.6. Considerations for RDMS CHARACTER Data
Type........................................................................................ 3–4
3.1.7. Considerations for GET DESCRIPTION ............................... 3–8
3.1.8. Week of the Year .................................................................... 3–8
3.1.9. Julian Day ................................................................................... 3–9
3.1.10. Gregorian Dates ....................................................................... 3–9
3.2. Alphabetical Summary of Functions ........................................... 3–10
3.3. Character Functions That Return Character Values................ 3–24
3.3.1. active_version Function ....................................................... 3–24
3.3.2. active_schema and active_qualifier Functions ............... 3–24
3.3.3. concat Function ...................................................................... 3–25
3.3.4. concatrtrim Function ............................................................. 3–25
3.3.5. concatstrim Function ............................................................ 3–26
3.3.6. delesc Function ...................................................................... 3–27
3.3.7. initcap Function ...................................................................... 3–27
3.3.8. insert and stuff Functions ................................................... 3–28
3.3.9. insesc Function ...................................................................... 3–29
3.3.10. lcase and lower Functions................................................... 3–29
3.3.11. left Function ............................................................................ 3–30
3.3.12. lower Function ........................................................................ 3–30
3.3.13. lpad Function ........................................................................... 3–31
3.3.14. ltrim Function .......................................................................... 3–31
3.3.15. nspace Function ..................................................................... 3–32
3.3.16. repeat and replicate Functions .......................................... 3–32
3.3.17. replace Function..................................................................... 3–33
3.3.18. reverse Function .................................................................... 3–33
3.3.19. right Function ..........................................................................3–34
3.3.20. rpad Function .......................................................................... 3–35
3.3.21. rtrim Function ......................................................................... 3–36
3.3.22. soundex Function .................................................................. 3–36
3.3.23. space Function ....................................................................... 3–37
3.3.24. stuff Function.......................................................................... 3–37
3.3.25. substr and substring Functions ......................................... 3–37

7830 8160–027 v
Contents

3.3.26. ucase and upper Functions .................................................3–40


3.4. Character Functions That Return Numeric Values .................. 3–41
3.4.1. charindex, position, and posstr Functions ...................... 3–41
3.4.2. cursorstatus Function ........................................................... 3–42
3.4.3. char_length, character_length, length, and
datalength Functions ....................................................... 3–42
3.4.4. difference Function ...............................................................3–43
3.4.5. instr Function ..........................................................................3–44
3.4.6. isalnum Function .................................................................... 3–45
3.4.7. isalpha Function...................................................................... 3–45
3.4.8. iscntrl Function .......................................................................3–46
3.4.9. isdigit Function ....................................................................... 3–47
3.4.10. isgraph Function ..................................................................... 3–47
3.4.11. islower Function.....................................................................3–48
3.4.12. isprint Function .......................................................................3–49
3.4.13. ispunct Function .....................................................................3–49
3.4.14. isspace Function .................................................................... 3–50
3.4.15. isupper Function .................................................................... 3–51
3.4.16. isxdigit Function ..................................................................... 3–52
3.4.17. locate Function ....................................................................... 3–53
3.4.18. octet_length Function ........................................................... 3–54
3.4.19. patindex Function .................................................................. 3–54
3.5. Binary-to-Character/Character-to-Binary Conversion ............ 3–55
3.5.1. ascii Function .......................................................................... 3–55
3.5.2. char and chr Functions ......................................................... 3–55
3.6. Other Character Functions ............................................................ 3–56
3.6.1. coalesce and value Functions ............................................ 3–56
3.6.2. decode Function .................................................................... 3–57
3.6.3. ifnull and nvl Functions ......................................................... 3–58
3.6.4. nullif function .......................................................................... 3–58
3.7. Mathematical and Numerical Conversion Functions .............. 3–59
3.7.1. abs and absval Functions ..................................................... 3–59
3.7.2. acos Function .......................................................................... 3–59
3.7.3. asin Function ........................................................................... 3–60
3.7.4. atan Function .......................................................................... 3–60
3.7.5. atan2 Function ........................................................................ 3–60
3.7.6. ceil and ceiling Functions ..................................................... 3–61
3.7.7. cos Function ............................................................................ 3–61
3.7.8. cosh Function.......................................................................... 3–62
3.7.9. cot Function ............................................................................ 3–62
3.7.10. degree and degrees Functions .......................................... 3–62
3.7.11. exp Function ........................................................................... 3–63
3.7.12. floor Function .......................................................................... 3–63
3.7.13. hex Function ............................................................................3–64
3.7.14. integer Function .....................................................................3–64
3.7.15. ln Function ............................................................................... 3–65
3.7.16. log Function ............................................................................. 3–65
3.7.17. log10 Function ......................................................................... 3–66
3.7.18. mod Function .......................................................................... 3–66
3.7.19. octal Function ......................................................................... 3–66
3.7.20. pi Function ............................................................................... 3–67
3.7.21. power Function ...................................................................... 3–67

vi 7830 8160–027
Contents

3.7.22. radians Function ..................................................................... 3–68


3.7.23. rand Function .......................................................................... 3–69
3.7.24. real Function............................................................................ 3–69
3.7.25. round Function........................................................................ 3–70
3.7.26. sign Function ........................................................................... 3–71
3.7.27. sin Function ............................................................................. 3–71
3.7.28. sinh Function ........................................................................... 3–72
3.7.29. smallint Function .................................................................... 3–72
3.7.30. sqrt Function ........................................................................... 3–73
3.7.31. str Function ............................................................................. 3–73
3.7.32. tan Function ............................................................................. 3–75
3.7.33. tanh Function .......................................................................... 3–75
3.7.34. trunc and truncate Functions ............................................. 3–76
3.7.35. double Function ...................................................................... 3–77
3.8. Date, Time, and Timestamp Functions ...................................... 3–78
3.8.1. add_months Function ........................................................... 3–78
3.8.2. cast Function ........................................................................... 3–79
3.8.3. convert Function .................................................................... 3–85
3.8.4. curdate Function ....................................................................3–88
3.8.5. curtime Function ....................................................................3–88
3.8.6. date Function ..........................................................................3–89
3.8.7. dateadd Function ................................................................... 3–90
3.8.8. datediff Function .................................................................... 3–92
3.8.9. datename Function ................................................................ 3–93
3.8.10. datepart Function...................................................................3–94
3.8.11. day Function ............................................................................ 3–96
3.8.12. dayname Function ................................................................. 3–97
3.8.13. dayofmonth Function ............................................................ 3–97
3.8.14. dayofweek Function .............................................................3–98
3.8.15. dayofyear Function .............................................................. 3–100
3.8.16. days Function .........................................................................3–101
3.8.17. erdate_to_timestamp Function ........................................ 3–102
3.8.18. erdwtime_to_timestamp Function .................................. 3–102
3.8.19. ertdate_to_timestamp Function ...................................... 3–103
3.8.20. ertime_to_time Function .................................................... 3–103
3.8.21. extract Function ................................................................... 3–103
3.8.22. getdate and now Functions .............................................. 3–105
3.8.23. getutcdate ............................................................................. 3–106
3.8.24. hour Function ........................................................................ 3–106
3.8.25. julian_day Function .............................................................. 3–107
3.8.26. last_day Function ................................................................. 3–108
3.8.27. microsecond Function ........................................................ 3–109
3.8.28. midnight_seconds Function ...............................................3–110
3.8.29. minute Function .................................................................... 3–111
3.8.30. month Function ..................................................................... 3–112
3.8.31. monthname Function ...........................................................3–113
3.8.32. months_between Function ............................................... 3–114
3.8.33. new_time Function ...............................................................3–115
3.8.34. next_day Function ............................................................... 3–118
3.8.35. now Function .........................................................................3–119
3.8.36. quarter Function ....................................................................3–119
3.8.37. round Function...................................................................... 3–120

7830 8160–027 vii


Contents

3.8.38. second Function .................................................................... 3–121


3.8.39. strftime Function ................................................................. 3–122
3.8.40. strptime Function ................................................................ 3–125
3.8.41. time Function ........................................................................ 3–128
3.8.42. timestamp Function ............................................................ 3–129
3.8.43. timestampadd Function ..................................................... 3–130
3.8.44. timestampdiff Function ...................................................... 3–132
3.8.45. timestamp_format Function ............................................. 3–134
3.8.46. to_char Function................................................................... 3–134
3.8.47. to_date Function .................................................................. 3–138
3.8.48. to_timestamp Function ...................................................... 3–141
3.8.49. trunc Function ....................................................................... 3–142
3.8.50. varchar_format Function .................................................... 3–143
3.8.51. week Function ...................................................................... 3–143
3.8.52. year Function ........................................................................ 3–144
3.9. System Information Functions ................................................... 3–146
3.9.1. generated_run_id Function ................................................ 3–146
3.9.2. max_aor_updates Function ............................................... 3–146
3.9.3. permuted_id Function ......................................................... 3–147
3.9.4. program_type Function ...................................................... 3–150
3.9.5. run_id Function ..................................................................... 3–150
3.9.6. uds_slot Function ..................................................................3–151
3.9.7. unique_id Function................................................................3–151
3.9.8. user Function ........................................................................ 3–154
3.9.9. pages_updated Function.................................................... 3–154
3.9.10. rdms_thread_stat function ................................................ 3–155
3.9.11. verification_timestamp Function ..................................... 3–157
3.10. Concurrency Functions ................................................................ 3–158
3.10.1. partition_id Function............................................................ 3–158
3.10.2. identity_val_local Function ................................................. 3–160
3.10.3. generated_date_val_local,
generated_time_val_local, and
generated_timestamp_val_local Functions ...............3–161
3.11. BLOB Functions.............................................................................. 3–163
3.11.1. get_file Function................................................................... 3–163
3.11.2. lob_crc Function ................................................................... 3–164
3.11.3. lob_end_address Function ................................................. 3–164
3.11.4. lob_end_page Function ...................................................... 3–165
3.11.5. lob_file Function ................................................................... 3–165
3.11.6. lob_id Function...................................................................... 3–166
3.11.7. lob_id_crc Function .............................................................. 3–166
3.11.8. lob_start_address Function ............................................... 3–167
3.11.9. lob_start_page Function ..................................................... 3–167
3.11.10. put_file Function................................................................... 3–168

Section 4. Routines and Triggers

4.1. Routines ................................................................................................4–1


4.2. Triggers ................................................................................................ 4–3
4.2.1. Example—Multiple Invocations of the Same
Trigger ................................................................................... 4–3

viii 7830 8160–027


Contents

4.2.2. Example—Recursive Trigger Invocation ........................... 4–4


4.2.3. Example—Cascading Trigger Invocation........................... 4–6
4.3. Version Names ................................................................................... 4–9
4.3.1. Routines and Version Names ............................................... 4–9
4.3.2. Triggers and Version Names ................................................ 4–9
4.4. Creating, Executing, and Dropping Routines ............................ 4–11
4.5. Creating, Executing, and Dropping Triggers ............................. 4–12
4.5.1. How Triggers Are Invoked .................................................. 4–13
4.5.2. Types of Triggers .................................................................. 4–13
4.5.3. Order of Execution ................................................................ 4–13
4.5.4. Dropping Triggers .................................................................. 4–15
4.6. Parameters ........................................................................................ 4–16
4.7. Dynamic Result Sets....................................................................... 4–17
4.7.1. Requirements ......................................................................... 4–17
4.7.2. Result Set Cursors ................................................................ 4–17
4.7.3. Result Set Information ......................................................... 4–18
4.7.4. Example .................................................................................... 4–19
4.8. Stored Functions .............................................................................. 4–21
4.9. System Variables ............................................................................. 4–22
4.9.1. RDMSAUXINFO ...................................................................... 4–22
4.9.2. SQLSTATE................................................................................ 4–23
4.10. Error Checking .................................................................................. 4–26
4.11. Transactions, Commits, and Rollbacks ...................................... 4–27
4.12. Statements and Keywords ........................................................... 4–28
4.12.1. Compound Statements: BEGIN . . . END ..........................4–30
4.12.2. Resolving Cursor and Variable References ....................4–33
4.12.3. Resolving Table Alias and Correlation Names in
Triggers ............................................................................... 4–37
4.12.4. Create Variable: DECLARE .................................................. 4–40
4.12.5. Execute Conditionally: IF ...................................................... 4–41
4.12.6. Return Value from Stored Function: RETURN ................4–43
4.12.7. Assign Data Value to Parameter or Variable:
SET ....................................................................................... 4–44
4.12.8. Terminate Routine or Trigger Execution:
SIGNAL ............................................................................... 4–46
4.12.9. Execute Repeatedly Based on Condition:
WHILE ................................................................................. 4–48
4.13. Datetime and Interval Data Types...............................................4–50

Section 5. SQL Statements Introduction and Summary

5.1. Content and Format of Reference Information .......................... 5–1


5.2. Comments in SQL Statements ...................................................... 5–3
5.2.1. Hyphens ..................................................................................... 5–3
5.2.2. /* and */ Delimiters ................................................................. 5–4
5.3. Alphabetical Summary of SQL Statements ................................ 5–5

Section 6. SQL Statements ALLOCATE CURSOR Through


CREATE TABLE

6.1. ALLOCATE CURSOR ......................................................................... 6–2

7830 8160–027 ix
Contents

6.1.1. Syntax ......................................................................................... 6–2


6.1.2. Example ...................................................................................... 6–3
6.1.3. Rules and Guidelines .............................................................. 6–3
6.2. ALTER TABLE ...................................................................................... 6–4
6.2.1. RDMS Extended Syntax ......................................................... 6–4
6.2.2. Edit Specifications ................................................................... 6–5
6.2.3. Examples.................................................................................. 6–12
6.2.4. Rules and Guidelines ............................................................ 6–17
6.3. BEGIN DECLARE ............................................................................... 6–20
6.3.1. SQL 92 Syntax (Entry Level)................................................ 6–20
6.3.2. Example .................................................................................... 6–20
6.3.3. Rules and Guidelines ............................................................ 6–20
6.4. BEGIN THREAD ................................................................................ 6–21
6.4.1. RDMS Extended Syntax ....................................................... 6–21
6.4.2. Examples.................................................................................. 6–23
6.4.3. Rules and Guidelines ............................................................ 6–23
6.5. CALL .................................................................................................... 6–28
6.5.1. Syntax ....................................................................................... 6–28
6.5.2. Examples.................................................................................. 6–29
6.5.3. Rules and Guidelines ............................................................ 6–30
6.6. CLOSE ................................................................................................. 6–31
6.6.1. Syntax ....................................................................................... 6–31
6.6.2. Example .................................................................................... 6–31
6.6.3. Rules and Guidelines ............................................................ 6–31
6.7. COMMIT ............................................................................................. 6–33
6.7.1. Syntax ....................................................................................... 6–33
6.7.2. Example .................................................................................... 6–33
6.7.3. Rules and Guidelines ............................................................6–34
6.8. CREATE INDEX.................................................................................. 6–35
6.8.1. RDMS Extended Syntax ....................................................... 6–35
6.8.2. Examples.................................................................................. 6–37
6.8.3. Rules and Guidelines ............................................................ 6–38
6.9. CREATE ROLE ................................................................................... 6–41
6.9.1. Syntax ....................................................................................... 6–41
6.9.2. Examples.................................................................................. 6–41
6.9.3. Rules and Guidelines ............................................................ 6–41
6.10. CREATE SCHEMA ............................................................................ 6–42
6.10.1. SQL 92 Syntax (Entry Level)................................................ 6–42
6.10.2. Example ....................................................................................6–43
6.10.3. Rules and Guidelines ............................................................6–43
6.11. CREATE TABLE .................................................................................6–45
6.11.1. Syntax .......................................................................................6–45
6.11.2. Table-Specification Clause ..................................................6–48
6.11.3. Table-Storage-Area Clause .................................................6–48
6.11.4. Column-Definition Clause ....................................................6–49
6.11.5. Table-Constraint-Specification Clause ............................. 6–59
6.11.6. Index-Specification Clause .................................................. 6–61
6.11.7. Primary-Key-Specification Clause ..................................... 6–62
6.11.8. Foreign-Key-Specification Clause...................................... 6–63
6.11.9. Owner-Specification Clause ...............................................6–64
6.11.10. Access-Specification Clause ..............................................6–64
6.11.11. Partition-Primary-Key-Specification Clause ....................6–64

x 7830 8160–027
Contents

6.11.12. Partition-Index-Specification Clause ................................. 6–71


6.11.13. CREATE TABLE Examples ................................................... 6–72
6.11.14. Rules and Guidelines ............................................................ 6–79

Section 7. SQL Statements CREATE TRIGGER Through DROP


VIEW

7.1. CREATE TRIGGER .............................................................................. 7–2


7.1.1. Syntax ......................................................................................... 7–2
7.1.2. Rules for BEFORE and AFTER Triggers.............................. 7–6
7.1.3. Examples.................................................................................... 7–7
7.1.4. Rules and Guidelines ............................................................ 7–10
7.2. CREATE VIEW ....................................................................................7–12
7.2.1. Syntax ........................................................................................7–12
7.2.2. Example .................................................................................... 7–13
7.2.3. Rules and Guidelines ............................................................ 7–14
7.3. DEBUG ................................................................................................ 7–18
7.3.1. RDMS Extended Syntax ....................................................... 7–18
7.3.2. Examples.................................................................................. 7–20
7.3.3. Rules and Guidelines ............................................................ 7–20
7.3.4. DEBUG and the UDS Trace File ...........................................7–21
7.4. DECLARE CURSOR .......................................................................... 7–22
7.4.1. Syntax ....................................................................................... 7–22
7.4.2. Examples.................................................................................. 7–28
7.4.3. Rules and Guidelines ............................................................ 7–34
7.5. DELETE ............................................................................................... 7–43
7.5.1. Syntax ....................................................................................... 7–43
7.5.2. Examples..................................................................................7–44
7.5.3. Rules and Guidelines ............................................................ 7–45
7.6. DROP CURSOR ................................................................................. 7–48
7.6.1. RDMS Extended Syntax ....................................................... 7–48
7.6.2. Example .................................................................................... 7–48
7.6.3. Rules and Guidelines ............................................................ 7–48
7.7. DROP INDEX ..................................................................................... 7–49
7.7.1. RDMS Extended Syntax ....................................................... 7–49
7.7.2. Example .................................................................................... 7–49
7.7.3. Rules and Guidelines ............................................................ 7–49
7.8. DROP PROCEDURE/FUNCTION ................................................... 7–51
7.8.1. SQL Syntax .............................................................................. 7–51
7.8.2. Examples.................................................................................. 7–51
7.8.3. Rules and Guidelines ............................................................ 7–52
7.9. DROP ROLE ....................................................................................... 7–53
7.9.1. Syntax ....................................................................................... 7–53
7.9.2. Examples.................................................................................. 7–53
7.9.3. Rules and Guidelines ............................................................ 7–53
7.10. DROP TABLE ..................................................................................... 7–54
7.10.1. RDMS Extended Syntax ....................................................... 7–54
7.10.2. Example .................................................................................... 7–54
7.10.3. Rules and Guidelines ............................................................ 7–54
7.11. DROP TRIGGER ................................................................................ 7–57
7.11.1. Syntax ....................................................................................... 7–57

7830 8160–027 xi
Contents

7.11.2. Example .................................................................................... 7–57


7.11.3. Rules and Guidelines ............................................................ 7–57
7.12. DROP VIEW ....................................................................................... 7–58
7.12.1. RDMS Extended Syntax ....................................................... 7–58
7.12.2. Example .................................................................................... 7–58
7.12.3. Rules and Guidelines ............................................................ 7–58

Section 8. SQL Statements END DECLARE Through INSERT

8.1. END DECLARE .................................................................................... 8–2


8.1.1. SQL 92 Syntax (Entry Level).................................................. 8–2
8.1.2. Example ...................................................................................... 8–2
8.1.3. Rules and Guidelines .............................................................. 8–2
8.2. END THREAD ...................................................................................... 8–3
8.2.1. RDMS Extended Syntax ......................................................... 8–3
8.2.2. Examples.................................................................................... 8–3
8.2.3. Rules and Guidelines .............................................................. 8–3
8.3. EXECUTE .............................................................................................. 8–5
8.3.1. SQL 92 Syntax (Intermediate Level) ................................... 8–5
8.3.2. Example ...................................................................................... 8–5
8.3.3. Rules and Guidelines .............................................................. 8–5
8.4. EXECUTE IMMEDIATE ...................................................................... 8–7
8.4.1. SQL 92 Syntax (Intermediate Level) ................................... 8–7
8.4.2. Example ...................................................................................... 8–7
8.4.3. Rules and Guidelines .............................................................. 8–7
8.5. EXPLAIN ............................................................................................... 8–8
8.5.1. RDMS Extended Syntax ......................................................... 8–8
8.5.2. Examples.................................................................................... 8–8
8.5.3. Rules and Guidelines ............................................................ 8–18
8.6. FETCH ................................................................................................. 8–23
8.6.1. Syntax ....................................................................................... 8–23
8.6.2. Example .................................................................................... 8–25
8.6.3. Rules and Guidelines ............................................................ 8–27
8.7. FETCH NEXT n................................................................................... 8–30
8.7.1. RDMS Extended Syntax ....................................................... 8–30
8.7.2. Example .................................................................................... 8–30
8.7.3. Rules and Guidelines ............................................................ 8–31
8.8. FUNCTION.......................................................................................... 8–33
8.8.1. SQL Syntax .............................................................................. 8–33
8.8.2. Examples.................................................................................. 8–35
8.8.3. Rules and Guidelines ............................................................8–40
8.9. GET DESCRIPTION ...........................................................................8–43
8.9.1. RDMS Extended Syntax .......................................................8–43
8.9.2. Example ....................................................................................8–45
8.9.3. Rules and Guidelines ............................................................8–45
8.10. GETERROR......................................................................................... 8–47
8.10.1. RDMS Extended Syntax ....................................................... 8–47
8.10.2. Example .................................................................................... 8–47
8.10.3. Rules and Guidelines ............................................................8–48
8.11. GET PARAMETERS ..........................................................................8–49
8.11.1. RDMS Extended Syntax .......................................................8–49

xii 7830 8160–027


Contents

8.11.2. Example .................................................................................... 8–53


8.11.3. Rules and Guidelines ............................................................ 8–53
8.12. GET RESULTS CURSOR NAME.....................................................8–54
8.12.1. RDMS Extended Syntax .......................................................8–54
8.12.2. Example ....................................................................................8–54
8.12.3. Rules and Guidelines ............................................................8–54
8.13. GRANT ................................................................................................ 8–56
8.13.1. Syntax ....................................................................................... 8–56
8.13.2. Examples..................................................................................8–58
8.13.3. Rules and Guidelines ............................................................ 8–59
8.14. INSERT ................................................................................................ 8–61
8.14.1. Syntax ....................................................................................... 8–61
8.14.2. Examples.................................................................................. 8–62
8.14.3. Rules and Guidelines ............................................................8–64

Section 9. SQL Statements LEVEL Through SET STATISTICS

9.1. LEVEL .................................................................................................... 9–2


9.1.1. RDMS Extended Syntax ......................................................... 9–2
9.1.2. Example ...................................................................................... 9–2
9.2. LOCATE ................................................................................................ 9–3
9.2.1. Syntax ......................................................................................... 9–3
9.2.2. Example ...................................................................................... 9–4
9.2.3. Rules and Guidelines .............................................................. 9–4
9.3. LOCK ..................................................................................................... 9–6
9.3.1. RDMS Extended Syntax ......................................................... 9–6
9.3.2. Types of Locks ......................................................................... 9–8
9.3.3. Examples.................................................................................... 9–9
9.3.4. Rules and Guidelines .............................................................. 9–9
9.4. OPEN ................................................................................................... 9–12
9.4.1. Syntax ....................................................................................... 9–12
9.4.2. Examples.................................................................................. 9–13
9.4.3. Rules and Guidelines ............................................................ 9–14
9.5. PREPARE ............................................................................................ 9–17
9.5.1. SQL 92 Syntax (Intermediate Level) ................................. 9–17
9.5.2. Examples.................................................................................. 9–18
9.5.3. Rules and Guidelines ............................................................ 9–18
9.6. PROCEDURE...................................................................................... 9–20
9.6.1. SQL Syntax .............................................................................. 9–20
9.6.2. Examples.................................................................................. 9–22
9.6.3. Rules and Guidelines ............................................................ 9–26
9.7. REVOKE .............................................................................................. 9–29
9.7.1. SQL 92 Syntax (Intermediate Level) ................................. 9–29
9.7.2. Examples.................................................................................. 9–30
9.7.3. Rules and Guidelines ............................................................ 9–31
9.8. ROLLBACK .........................................................................................9–34
9.8.1. Syntax .......................................................................................9–34
9.8.2. Examples.................................................................................. 9–35
9.8.3. Rules and Guidelines ............................................................ 9–35
9.9. SELECT Multirow ............................................................................. 9–37
9.9.1. RDMS Extended Syntax ....................................................... 9–37

7830 8160–027 xiii


Contents

9.9.2. Example .................................................................................... 9–37


9.10. SELECT Single Row .........................................................................9–38
9.10.1. Syntax .......................................................................................9–38
9.10.2. Examples.................................................................................. 9–39
9.10.3. Rules and Guidelines ............................................................9–40
9.11. SET .................................................................................................... 9–42
9.11.1. Syntax ....................................................................................... 9–42
9.11.2. Example ....................................................................................9–43
9.11.3. Rules and Guidelines ............................................................9–43
9.12. SET AUXINFO ....................................................................................9–45
9.12.1. RDMS Extended Syntax .......................................................9–45
9.12.2. Example ....................................................................................9–45
9.12.3. Rules and Guidelines ............................................................9–45
9.12.4. Host Language Examples for Declaring Aux-
Info........................................................................................9–46
9.13. SET RESULT SET .............................................................................. 9–47
9.13.1. RDMS Extended Syntax ....................................................... 9–47
9.13.2. Examples.................................................................................. 9–47
9.13.3. Rules and Guidelines ............................................................ 9–47
9.14. SET SKIPGENERATED .....................................................................9–49
9.14.1. RDMS Extended Syntax .......................................................9–49
9.14.2. Example ....................................................................................9–49
9.14.3. Rules and Guidelines ............................................................ 9–50
9.15. SET STATISTICS ............................................................................... 9–51
9.15.1. RDMS Extended Syntax ....................................................... 9–51
9.15.2. Example .................................................................................... 9–51
9.15.3. Rules and Guidelines ............................................................ 9–51

Section 10. SQL Statements UNLOAD Through WHENEVER

10.1. UNLOAD ............................................................................................. 10–2


10.1.1. RDMS Extended Syntax ....................................................... 10–2
10.1.2. Examples.................................................................................. 10–7
10.1.3. Rules and Guidelines ........................................................... 10–11
10.2. UNLOCK ........................................................................................... 10–19
10.2.1. RDMS Extended Syntax ..................................................... 10–19
10.2.2. Example .................................................................................. 10–19
10.2.3. Rules and Guidelines .......................................................... 10–19
10.3. UPDATE ALL..................................................................................... 10–21
10.3.1. RDMS Extended Syntax ...................................................... 10–21
10.3.2. Example .................................................................................. 10–22
10.3.3. Rules and Guidelines .......................................................... 10–22
10.4. UPDATE Positioned ....................................................................... 10–25
10.4.1. Syntax ..................................................................................... 10–25
10.4.2. Example .................................................................................. 10–26
10.4.3. Rules and Guidelines .......................................................... 10–27
10.5. UPDATE Searched ......................................................................... 10–30
10.5.1. Syntax ..................................................................................... 10–30
10.5.2. Examples.................................................................................10–31
10.5.3. Rules and Guidelines .......................................................... 10–32
10.6. UPDATE SYNCHRONIZE............................................................... 10–34

xiv 7830 8160–027


Contents

10.6.1. RDMS Extended Syntax ..................................................... 10–34


10.6.2. Examples................................................................................ 10–35
10.6.3. Rules and Guidelines .......................................................... 10–37
10.7. UPDATE VALUES ........................................................................... 10–40
10.7.1. RDMS Extended Syntax ..................................................... 10–40
10.7.2. Example .................................................................................. 10–41
10.7.3. Rules and Guidelines .......................................................... 10–41
10.8. USE DEFAULT ................................................................................. 10–44
10.8.1. RDMS Extended Syntax ..................................................... 10–44
10.8.2. Examples................................................................................ 10–44
10.8.3. Rules and Guidelines .......................................................... 10–45
10.9. WHENEVER ..................................................................................... 10–47
10.9.1. SQL 92 Syntax (Entry Level).............................................. 10–47
10.9.2. Examples................................................................................ 10–47
10.9.3. Rules and Guidelines .......................................................... 10–48

Appendix A. Keywords

A.1. Reserved Words ................................................................................ A–2


A.2. Nonreserved Keywords .................................................................A–14

Appendix B. RDMS Error Handling

B.1. Obtaining Current Error Messages ............................................... B–1


B.2. Error Message Groups ..................................................................... B–2
B.3. Checking Error Statuses .................................................................. B–3
B.3.1. Error Message Text ................................................................ B–3
B.3.2. Errors and Rollbacks ...............................................................B–4
B.3.3. RDMS Statuses 6000 to 6999 ..............................................B–6
B.3.4. Resolving 6000 to 6999 Errors ............................................B–8
B.4. COMMIT and ROLLBACK Statement Errors ...............................B–9
B.5. SQLSTATE.......................................................................................... B–10
B.5.1. SQL 92 SQLSTATE Values ................................................... B–11
B.5.2. ODBC SQLSTATE Values and Errors ................................ B–14
B.6. Routine and Trigger Compilation Errors .................................... B–16

Appendix C. Error Handling in ESQL

C.1. Tools for ESQL Error Handling ....................................................... C–1


C.2. Altering Program Flow with the WHENEVER
Statement ....................................................................................... C–2
C.2.1. Example Using the WHENEVER Statement ...................... C–2
C.2.2. Scope of the WHENEVER Statement ................................. C–2
C.3. Using SQLCODE in an ESQL Program .......................................... C–3
C.3.1. Migrating UCOB Programs to ESQL Without
SQLCODE ..............................................................................C–4
C.3.2. Migrating to ESQL with SQLCODE......................................C–4
C.4. Using SQLSTATE in an ESQL Program ......................................... C–5

7830 8160–027 xv
Contents

C.5. Using the GETERROR Statement in ESQL .................................. C–6


C.6. Using UCOB RDMCA Variables ERROR-STATUS and
AUX-INFO ........................................................................................ C–7

Appendix D. Using RDMS with ASCII COBOL

D.1. SQL Statements in ASCII COBOL Programs .............................. D–1


D.2. Passing Data to RDMS .................................................................... D–4
D.3. Receiving Data from RDMS ........................................................... D–5
D.4. User Contingencies .......................................................................... D–6
D.5. Collecting ASCII COBOL Programs That Contain SQL
Statements .....................................................................................D–7
D.6. ASCII COBOL TIP Transactions ..................................................... D–8
D.7. Example ASCII COBOL Program ................................................... D–9
D.7.1. Data Handling ........................................................................... D–9
D.7.2. Source Code............................................................................ D–10
D.7.3. Output....................................................................................... D–12

Appendix E. Using RDMS with ASCII FORTRAN

E.1. SQL Statements in ASCII FORTRAN Programs .......................... E–1


E.2. Passing Data to RDMS ..................................................................... E–4
E.3. Receiving Data from RDMS ............................................................ E–5
E.4. Calling F$RDMR.................................................................................. E–6
E.5. User Contingencies ........................................................................... E–7
E.6. Collecting ASCII FORTRAN Programs That Contain
SQL Statements ............................................................................ E–8
E.7. ASCII FORTRAN TIP Transactions ................................................. E–9
E.8. Example FORTRAN Program ........................................................ E–10
E.8.1. Data Handling .......................................................................... E–10
E.8.2. Source Code............................................................................. E–11
E.8.3. Output....................................................................................... E–13

Appendix F. HVTIP Restrictions for ASCII COBOL and ASCII


FORTRAN Programs

Appendix G. Passing Many Variables to RDMS

Appendix H. Obtaining and Freeing Work Space for UCS


Programs

H.1. Acquiring Additional Work Space..................................................H–2


H.2. Freeing Work Space......................................................................... H–4
H.3. TIP and HVTIP Considerations ....................................................... H–5

Appendix I. Using BLOB Data

I.1. Creating LOB Storage Areas in UREP ........................................... I–2

xvi 7830 8160–027


Contents

I.2. Creating LOB Columns Without Specifying a Storage


Area ................................................................................................... I–3
I.3. Creating LOB Columns in LOB Storage Areas ............................ I–4
I.4. Limitations of the BLOB Data Type ............................................... I–6
I.5. Calculating Record Size and Page Size for Tables
with BLOB Data .............................................................................. I–7
I.6. Calculating BLOB Storage Area Sizes ........................................... I–8
I.6.1. Calculating Minimum File Size ............................................... I–8
I.6.2. Maximum File Size ................................................................... I–9
I.6.3. Calculating MAXIMUM-PAGES .............................................. I–9
I.6.4. Calculating Page Size ..............................................................I–10
I.6.5. Avoiding Addressing Errors .................................................. I–11
I.7. Backup and Recovery of BLOB Storage Areas ......................... I–12
I.8. Declaring Large Object Variables in UCS C .................................I–13
I.8.1. Declaring BLOB Values Larger than 64
Megabytes in UCS C ......................................................... I–14
I.8.2. Referencing BLOB Variables in UCS C ...............................I–16
I.8.3. Declaring and Using BLOB Pointer Variables in
UCS C ..................................................................................... I–17
I.8.4. BLOB Data in C++ ....................................................................I–18
I.9. Declaring Large-Object Variables in COBOL...............................I–19
I.9.1. Declaring BLOB Values Larger than 64
Megabytes in COBOL ....................................................... I–20
I.9.2. Referencing BLOB Variables in COBOL ............................ I–20
I.10. Example UCS C Program—Using Embedded SQL................... I–22
I.11. Example UCS C Program—Using Interactive SQL ................... I–27
I.12. Example UCS COBOL Program—Using Embedded
SQL .................................................................................................. I–34
I.13. Example UCS COBOL Program—Using Interactive
SQL .................................................................................................. I–41

Index ..................................................................................................... 1

7830 8160–027 xvii


Contents

xviii 7830 8160–027


Tables

1–1. SQL Statements: Data Retrieval ................................................................................ 1–20


1–2. SQL Statements: Deletes, Inserts, and Updates.................................................... 1–21
1–3. SQL Statements: Locks.................................................................................................1–22
1–4. SQL Statements: Table Security .................................................................................1–22
1–5. SQL Statements: Table Definition ............................................................................. 1–23
1–6. SQL Statements: View Definition .............................................................................. 1–23
1–7. SQL Statements: Routines and Triggers ................................................................. 1–24
1–8. SQL Statements: ESQL Variable Declarations ....................................................... 1–24
1–9. Dynamic ESQL Statement Execution ....................................................................... 1–25
1–10. SQL Statements: UDS Work Sessions (Thread Control) ..................................... 1–25
1–11. SQL Statements: Checks and Inquiries.................................................................... 1–26

2–1. Truth Table for Boolean Operations ......................................................................... 2–24


2–2. Bitwise Operation Result Types ................................................................................ 2–29
2–3. Operations and Order of Precedence ...................................................................... 2–30
2–4. Expression Evaluation .................................................................................................. 2–31
2–5. Arithmetic Operation Result Types .......................................................................... 2–35
2–6. Operands ......................................................................................................................... 2–39
2–7. Value Ranges for Exact Numeric Types .................................................................. 2–83
2–8. Value Ranges for Approximate Numeric Types .................................................... 2–84
2–9. Numeric Data Type Precision ..................................................................................... 2–85
2–10. Numeric Data Type Memory Usage ......................................................................... 2–85
2–11. Datetime Data Type Precision and Memory Usage ............................................. 2–88
2–12. Rules of Comparison .................................................................................................. 2–103
2–13. Values of Indicator Variables ..................................................................................... 2–115

3–1. Data Type of Result from CONCAT, CONCATRTRIM, CONCATSTRIM


and the Concatenation Operator ............................................................................ 3–6
3–2. Alphabetical Summary of Built-In Functions .......................................................... 3–10
3–3. Range of Values for Interval Types...........................................................................3–84

4–1. RDMSAUXINFO Values ................................................................................................ 4–22


4–2. Statements and Keywords Used Exclusively by Routines and
Triggers ....................................................................................................................... 4–28
4–3. Subset of Standard SQL Statements and RDMS Extended Syntax for
Routines and Triggers ............................................................................................. 4–29

5–1. SQL Statements Summary ........................................................................................... 5–5

7830 8160–027 xix


Tables

A–1. Reserved Words .............................................................................................................. A–2


A–2. RDMS Nonreserved Keywords ................................................................................. A–15

B–1. Error Statuses 6000 to 6999 ........................................................................................B–6


B–2. SQLSTATE Class and Subclass Values ..................................................................... B–11
B–3. ODBC Error Codes ......................................................................................................... B–14

D–1. Error Status and Auxiliary Information in ASCII COBOL ........................................D–2

E–1. Error Status and Auxiliary Information in ASCII FORTRAN ................................... E–2

H–1. DEBUG DUMP SIZES Invocation Techniques ...........................................................H–2


H–2. RSA$INIT Invocation Techniques ............................................................................... H–3
H–3. RSA$FREE invocation techniques .............................................................................. H–4

I–1. Creating and Referencing BLOB Variables in UCS C ..............................................I–15


I–2. Creating and Referencing BLOB Variables in COBOL ........................................... I–20

xx 7830 8160–027
Section 1
Introduction to Enterprise Relational
Database Server

Enterprise Relational Database Server was previously named Relational Data


Management System (RDMS), the relational database model of the Universal Data
System (UDS). Throughout this document, all references to RDMS or Enterprise
Relational Database Server refer to the same software product.

This manual mentions other Unisys products that have been renamed (for example,
MAPPER, now BIS or Business Information Server). Because experienced users of
these products are more familiar with the former product names, the former names
have been retained throughout this manual.

7830 8160–027 1–1


Using This Manual

1.1. Using This Manual


As a user of Relational Database Server, you use Structured Query Language (SQL) to
interact with RDMS databases. SQL is an industry-standard relational database
language defined by the American National Standards Institute, Inc. RDMS conforms to
standard SQL and provides some extensions to standard SQL.

This manual describes the RDMS implementation of standard and RDMS extended
SQL. It presents every available standard and RDMS extended SQL statement, clause,
and option in the form of syntax diagrams and descriptions. It also provides a sample
database and examples illustrating the use of SQL statements.

This manual is intended primarily for programmers and software system engineers
who use SQL to access RDMS databases. This includes, among others, database
administrators, programmers who use languages like COBOL and C to build and
maintain applications that interact with relational databases, and developers who
access SQL databases through an interface such as IPF SQL or MAPPER.

As a user of this manual, you should have a working knowledge of relational database
and SQL concepts and terminology, the operating system environment, and any
high-level programming languages you are using to interact with the database. You
should also be familiar with basic UDS Control, Repository for ClearPath OS 2200
(UREP), and Integrated Recovery Utility (IRU) operations.

Syntax Notation Conventions


The following conventions are used in syntax notation throughout this manual.

Syntax Element Description

Default values Default values, where applicable, are in bold type.


Optional Optional elements are enclosed in brackets [ ] . For example:
elements LOCK [ TABLE ]

Choices Vertical bars separate choices. For example:


SELECT [ ALL | DISTINCT ]

Choices for Two or more choices for required syntax elements are enclosed in
required braces { } . You must select one of the choices. For example:
elements { CLOSE | RELEASE [ CURSOR ] }

Variables Names of items you must supply (variables) are in italics. For
example:
cursor-name

Repeating Syntax elements that you can repeat are followed by ellipses. For
elements example:
[ column-name [ , column-name ] ... ]

Note: In illustrations of syntax, spaces before and after keywords are only for
readability.

You can find further information on syntax notation conventions for SQL statements in
Section 5.

1–2 7830 8160–027


Documentation Updates

1.2. Documentation Updates


This document contains all the information that was available at the time of
publication. Changes identified after release of this document are included in problem
list entry (PLE) 19055949. To obtain a copy of the PLE, contact your Unisys
representative or access the current PLE from the Unisys Product Support Website:

http://www.support.unisys.com/all/ple/19055949

Note: If you are not logged into the Product Support site, you will be asked to do
so.

7830 8160–027 1–3


Introduction to the Relational Database Model

1.3. Introduction to the Relational Database Model


This introduction describes the benefits of a relational database and gives more
information about SQL. It introduces the sample database used for examples in this
manual and describes the characteristics of relational tables. It explains the difference
between tables and views, and explains the terminology used for relational tables in
this manual. It describes the RDMS environment, the interpreter interface and other
interfaces, and ends with a summary list of SQL statements. RDMS is based on the
relational data model, which represents data in two-dimensional tables of rows and
columns.

A relational database has several advantages over a nonrelational database:

• It is easier to use and manage, as the database is a collection of tables.


• It increases the value of data by making it easier to develop information from the
data in different ways.
• It enables maximum use of data, as you can combine sets of data to create new
tables.
• It provides for easier access to data since you do not have to specify a structure
for accessing data. Instead, RDMS selects an optimal access path for each query.
• You can dynamically create and maintain databases using a set of relational
statements.
• Since data files are not owned by one program, several application programs can
access the same data file.
• You can change the database without having to change application programs.

1.3.1. Structured Query Language (SQL)


RDMS users use SQL statements to create and access RDMS databases. SQL is a
relational data management language. The American National Standards Institute
(ANSI) uses SQL as the official standard for relational database languages. SQL is
sometimes pronounced “sequel.”

SQL divorces the application program or end user from the physical and location
attributes of the data. Data manipulation commands are expressed in logical terms.
An SQL query declares an action to be applied to the data of interest. It makes no
difference where the data is located or how it is arranged. The data of interest is
identified only in logical terms, which includes the following:

• Identifying the table or tables involved in the action (retrieval or update).


Optionally, the names of the tables can be qualified by a schema name. A query
can involve one or more tables, and the tables specified generally can involve
multiple schemas.

1–4 7830 8160–027


Introduction to the Relational Database Model

• Identifying the rows to be selected from the tables. Rows are selected through
specifications that identify the rows of interest. The specifications include column
names whose associated value in the row can be compared or included in an
expression that is compared to other like expressions. Whether these statements
are true or false for a row determines whether the row is to be included in the
“set of interest.” Optionally, columns can be qualified by a table and schema.
• Identifying the columns on which the action (retrieval or update) is specified. The
specifications include column names whose associated value is to be presented
or included in an expression of a column or columns for presentation from the
rows in the tables selected. For update actions, column names are associated with
corresponding values for assignment to the columns of the selected row set. In all
cases, the column names can be qualified by a table and schema name.

1.3.2. Sample Database


Tables CUSTOMERS and HOUSES are examples of relational tables that a real estate
company might use. These tables and their data are used in examples throughout this
guide.

Table CUSTOMERS contains a customer identifier (CNO), the customer's name


(CNAME), the maximum price the customer can pay for a house (MAXPRICE), and the
location desired by each customer (DESIREDLOC).

CNO CNAME MAXPRICE DESIREDLOC

C101 Thompson 150000 Woodbury


C102 Owen 70000 New London
C103 Johnson 90000 Woodbury
C104 Jones 100000 Greenville
C105 Smith 120000 Westchester

Table HOUSES contains a house identifier (HNO), the location of the house
(LOCATION), the asking price (PRICE), and a brief description of each house on the
market (DESCRIPTION).

HNO LOCATION PRICE DESCRIPTION

H101 Woodbury 130000 2-bedroom condominium


H102 Woodbury 40000 Handyman's special
H103 Westchester 90000 Duplex
H104 Parkway Heights 85000 3-bedroom townhouse
H105 Turtle Creek 110000 4-bedroom house

7830 8160–027 1–5


Introduction to the Relational Database Model

1.3.3. Relational Calculator


RDMS has a powerful expression evaluation capability that includes many scalar
built-in functions. This capability is useful for application programs, even when no
database data is involved. The SQL SELECT statement always requires a table name;
RDMS provides the table RDMS.RDMS_DUMMY for this purpose.

The RDMS_DUMMY table is guaranteed to exist and contain exactly one record. The
record value is 1,NULL. You can use this table to construct SELECT statements that
return the values of RDMS built-in functions. For a SELECT statement that contains a
built-in function to return a record, the table in the FROM clause must contain exactly
one record (because there is no WHERE clause); otherwise RDMS returns a no-find or
cardinality violation error.

For example, to return the number of days until Christmas, issue the following
single-row SELECT statement:

SELECT current_date,datediff('Day',current_date,
datename('year',current_date)||'-12-25'),'shopping days'
FROM rdms.rdms_dummy

The statement returns a value like the following:

2005-01-07 352 shopping days

1.3.4. Characteristics of Relational Tables


A relational table, or relation, is a two-dimensional table with horizontal rows and
vertical columns. Each table has the following characteristics:

• Name
Each table has a name.
• Columns and rows
Each table has a specified number of named columns and any number of unnamed
rows. Each row contains different types of information about one thing. For
example, each row of table HOUSES contains information about one house.
• Data items
The intersection of a column and a row is a data item. The specific value of a data
item is a data value. The data items in one column must be of the same type. For
example, the column LOCATION in table HOUSES contains character data.

1–6 7830 8160–027


Introduction to the Relational Database Model

• Data types
Each column in a relational table is defined to hold a specific type of data. The
three basic types of data are character, numeric, and datetime. Numeric data can
be either exact or approximate. The following are characteristics of the RDMS
data types:
ᔭ Character data
Columns defined as character data are assumed to be standard ASCII
characters with an implicit binary ordering sequence. Columns can be defined
as belonging to a specific character set (for example, ISO 8859-1). Columns
can also be defined with a specific collation, or collating sequence (for
example, fr_FR.ISO8859-1); in such a case, this explicit collation is used for any
comparison, grouping, and ordering for the column.
ᔭ Exact numeric data types
Columns defined as exact NUMERIC data types hold precisely the value you
store in them. For example, if you store the value 10000 in a column defined as
an exact numeric type and then test to see whether that column is equal to
10000, the result is TRUE. The exact numeric data types are as follows:
DECIMAL
NUMERIC
INTEGER
SMALLINT
ᔭ Approximate numeric data types
On the other hand, columns defined as approximate numeric data types may
not pass such a test. Some approximate numeric data types can hold very
large numbers, however, much larger than the exact types. The approximate
numeric data types are as follows:
REAL
FLOAT
DOUBLE PRECISION
ᔭ Numeric ranges and precision
Numeric data types are characterized by their ranges and precision. Range
refers to how large a number they can store. Precision refers to how many
actual decimal places can be accurately recorded regardless of the range of
the number. For example, some approximate numeric data types can store a
number on the order of 10300, but can provide only about 18 decimal places of
precision. By carefully evaluating an application, you can determine which
numeric data types best suit your needs.
ᔭ Datetime data types
Columns defined as datetime data types can be classified as DATE, TIME, and
TIMESTAMP types. The DATE data type contains the year, month, and day.
The TIME data type contains the hour, minute, and second. The TIMESTAMP
data type contains the year, month, day, hour, minute, and second. The value
of each datetime field conforms to the valid value of calendar data.

7830 8160–027 1–7


Introduction to the Relational Database Model

You can also rearrange data and combine tables to suit your needs. How you structure
a query determines how the data is rearranged. RDMS supports three relational
operations:

• Restrictions
A restriction selects some or all rows from one or more tables.
• Projections
A projection selects some or all columns from one or more tables.
• Joins
A join combines columns from two or more tables.

1.3.5. Views
A relational view is similar to a relational table. The main difference is that a table
contains its own data and a view does not. Instead, a view represents the restriction,
projection, or join of one or more tables. A relational view is a virtual table that
provides a window into selected parts of the database.

You can use views to establish an uncomplicated look at portions of the database that
are logically independent from the underlying database structure. You can also use
views for security reasons by allowing other users to access only the rows and
columns of tables that are visible through the view.

The difference between a table and a view is transparent to users. Users access
views and tables in the same manner.

1.3.6. Terminology
From a data processing perspective, a table is roughly equivalent to a file where a row
corresponds to a record and a column corresponds to a field. Most users and the
literature, however, seldom use the terms file, record, and field. Preferred terms are
table, row, and column, which are the terms used in this manual.

The kinds of relational tables are as follows:

• Base tables
Base tables physically contain rows and columns of data.
• Global temporary tables
Global temporary tables are identical in structure to base tables, but their data is
local to the thread. When a thread first references the global temporary table, the
table has zero rows. When the thread ends, all records are removed from the
temporary table. Multiple users can use the same temporary table, with each user
having different data.

1–8 7830 8160–027


Introduction to the Relational Database Model

• Viewed tables, or views


Views do not physically contain data. Views can be considered “virtual tables” that
provide a window into the data of one or more underlying base or global
temporary tables.

The general term “table” can refer to a base table, a global temporary table, or a view.
The specific terms base table, global temporary table, and view are used in this guide
if a distinction is necessary.

7830 8160–027 1–9


RDMS Environment

1.4. RDMS Environment


The following Universal Data System (UDS) products provide relational data
management capabilities:

• UDS Control
• Relational Data Management System (RDMS), including the Relational Syntax
Analyzer (RSA), which is a component of RDMS
• Repository for ClearPath OS 2200 (UREP)

UDS Control, RDMS, and UREP work together in many ways to support database
activities.

Universal Data System Control (UDS Control)


UDS Control establishes a database session environment, including

• Thread control
• Application groups
• Error message handling
• Recovery options
• Concurrency control

Relational Data Management System (RDMS)


RDMS is the relational data manager for the database and it performs these functions,
as well as others:

• Parses, analyzes, and executes SQL statements.


• Converts data among the various types, as needed.
• Provides interfaces to its relational database.

All RDMS interfaces support basic relational operations including the retrieval,
insertion, deletion, and updating of data from within application programs. This
includes the ability to define, alter, and drop, and to assign security requirements to
the relational entities (tables) used to model the information. It also includes the ability
to define transaction boundaries, and thus allows for multiple operations to be treated
as one unit of work.

1–10 7830 8160–027


RDMS Environment

Repository for ClearPath OS 2200 (UREP)


UREP manages the repository, which is a metadatabase; that is, it is a database that
contains information about other databases. It stores the following information:

• Tables and views including the following (for example):


ᔭ Column names, data types, and sizes
ᔭ Key names and composition
ᔭ Foreign key relationships, as well as other constraints supported by SQL
• Database configuration (for example, D-bank sizes and number of thread
D-banks)

RDMS users do not have to know how specific data items are stored, and they do not
have to understand RDMS data.

RDMS also provides system tables that contain authorization and statistical
information concerning all tables defined within the application group. This information
is available to authorized users through any of the supported relational interfaces.

7830 8160–027 1–11


RDMS Interfaces

1.5. RDMS Interfaces


You can access RDMS databases through the interpreter interface by way of
third-generation programming languages or through the IPF SQL Interface, the
MAPPER Relational Interface (MRI), or the Open Distributed Transaction Processing
(Open/OLTP) interface. You can also access RDMS data by embedding SQL
statements in UCS COBOL and UCS C programs, through the Query Language
Processor (QLP), or through UCS FORTRAN with module programs.

Interpreter Interface
You can access RDMS through the interpreter interface, where RDMS interprets each
SQL statement each time it encounters the statement during the execution of a
program.

Application Programs
The following Unisys programming languages provide access to RDMS, by
incorporating SQL statements passed as arguments to RDMS on a procedure call:

• ASCII COBOL
• ASCII FORTRAN
• UCS COBOL
• UCS C
• UCS FORTRAN

IPF SQL Interface


The IPF SQL Interface provides interactive access to RDMS data. You can use most
SQL statements with this interface. By combining SQL statements with Interactive
Processing Facility (IPF) capabilities, you can work with data in many versatile ways.
For more information, see the RDMS and IPF SQL End Use Guide.

MAPPER Relational Interface (MRI)


MRI enables you to use the MAPPER system report generating capabilities to request
reports about RDMS databases. MRI lets you access RDMS special capabilities such
as handling large tables. RDMS provides fast access to data through the use of
primary keys and secondary indexes.

You can design MAPPER runs that use SQL statements directly from the MAPPER
system, or you can use MAPPER runs through MRI. For more information, see the
MRI Administration and User’s Guide.

Open Distributed Transaction Processing Software


The Open Distributed Transaction Processing software interface allows a site to
develop and use applications that distribute application program processing among
heterogeneous computer systems.

1–12 7830 8160–027


RDMS Interfaces

UniAccess Software
The UniAccess Transaction Client for OS 2200 and the UniAccess Transaction Server
for OS 2200 process requests from clients using Sybase Open Client software. The
UniAccess and Sybase software products use the Tabular Data Stream (TDS) protocol.

The UniAccess ODBC Server allows ODBC-compliant tools for the workstation to
access an RDMS database.

Embedded SQL
You can embed SQL statements in UCS COBOL and UCS C programs. Embedded
SQL (ESQL) has some features and considerations that differ from SQL when it is
interpreted during program execution. For details, see 2.11.

Query Language Processor (QLP)


You can access RDMS tables, manipulate data, and generate reports through QLP. For
more information, see the QLP End Use Guide Volume 1.

Module Programs
Module procedures enable UCS FORTRAN programs to access an RDMS database
(see 2.12).

Logic and Network Information Compiler (LINC)


LINC can store its data in RDMS tables and use SQL queries to access RDMS data.

LINC II users should refer to current LINC documentation.

7830 8160–027 1–13


Interface Tradeoffs

1.6. Interface Tradeoffs


The following describes the tradeoffs of the various types of interfaces to RDMS.
The interfaces to RDMS are of three types:

• Interactive
• Dynamic ESQL
• Static ESQL

IPF SQL, MRI, ODBC, and JDBC always use the interactive interface. UCS COBOL and
UCS C programs can use any of the types, exclusively or in combination.

HVTIP has a control program that calls subprograms. The BEGIN THREAD command is
performed in the control program, and the same thread is used by the subprograms.
Therefore, anything RDMS performs as part of the thread is available to the control
program and all subprograms.

After you perform a dynamic PREPARE, the prepared statement is available until a
COMMIT, or until ROLLBACK or END THREAD if the prepared statement is a
RETENTION CURSOR. Dynamic ESQL is therefore as effective in an HVTIP
environment as it is within the other environments, such as batch.

1.6.1. Tradeoffs to Consider


Tradeoffs must be considered in terms of ease of use, flexibility, and performance.
Which factor receives the most weight depends on the needs of the program's
execution environment.

Flexibility and Ease of Use


The ability to modify a statement at run-time adds flexibility but reduces ease of use.
In order of their ease of use, the interfaces are as follows:

1. Static ESQL (easiest to use)


2. Interactive
3. Dynamic ESQL

Flexibility and Performance


There are tradeoffs between flexibility and run-time performance. In order of
performance, the interfaces are as follows:

1. Interactive
2. Dynamic ESQL
3. Static ESQL that auto-recompiles
4. Static ESQL (fastest)

1–14 7830 8160–027


Interface Tradeoffs

Internal Processing
The following table shows the delegation of work between compile time and
execution time for the RDMS interface categories.

Interface Internal Execution-Time Processing

Interactive Parsing, binding of name references, internal RDMS structure


creation done for every execution of every statement
Dynamic ESQL Parsing, binding of name references done once on PREPARE
Internal RDMS structure creation done on every EXECUTE
Auto-Recompile Parsing done at program compilation time
ESQL Binding of name references and internal structure creation
done the first time executed in loop
Static ESQL Parsing, binding of name references done at program
compilation time
Internal structure creation done at first execution in loop

Bindings
There are three bindings that affect flexibility:

• Host language variables


• Syntax
• Table definition

The following table describes when these bindings occur.

Table
Host Definition
Language Table Must Exist at
Interface Variables Syntax Definition Compile Time

Interactive Execution Execution Execution No


Dynamic Compile Execution Execution No
ESQL
Auto- Compile Compile Execution Yes
Recompile
ESQL
Static ESQL Compile Compile Compile Yes

The binding of host language variables to an SQL statement specifies how many
variables there are, their data types, and the names or memory locations of all
variables. Execution-time binding to host language variables can be done only using
the interactive interface. The other interfaces fix these values during the compile of
the UCS COBOL or UCS C program. Host language variables (sometimes called
program variables) are described in 2.10.

7830 8160–027 1–15


Interface Tradeoffs

When syntax is bound, it is parsed and turned into an encoded format called the
RDMS command module. For example, the binding of the clause “WHERE col1 = 5”
fixes the fact that a column named COL1 is being referenced within the WHERE
clause. After binding, it is not possible to reference COL2 instead of COL1.

The result of the SQL CREATE and ALTER TABLE statements is an internal RDMS
encoded format of the table definition called the Relational Definition Table (RDT).
Within the RDT, each column and index is assigned a number. Binding to a table
definition causes the replacement of the symbolic column names with their
corresponding numbers. Access paths are selected from the currently existing
indexes and specified using the assigned number of the index. When binding is done
at execution time, the table definitions may differ for each execution. When binding is
done at compile time, the RDT used during execution must exactly match the RDT
used during the compile (the RDT timestamps must be identical). If the RDT
timestamp at compile time is not identical to the RDT timestamp at execution time,
auto-recompile is attempted.

The table definition must exist at compile time, in the application group for which the
program is being compiled, when static ESQL syntax is used. The table definition does
not have to exist at compile time when dynamic ESQL or interactive syntax is used.
This means that it is easier to transfer programs that use only the dynamic ESQL or
interactive interfaces to other run-time environments (application groups or systems)
than when static ESQL syntax is used.

1.6.2. Static ESQL Interface


If you consider only performance, static embedded SQL (static ESQL) provides the
best performance. Static ESQL is the only interface that includes the FETCH NEXT n
statement, which improves performance when multiple records are fetched from a
cursor. Static ESQL can also bypass some RDMS initialization; this ABINIT BYPASS is
supported only for static ESQL.

Static ESQL is the easiest and most explicit to use for these reasons:

1. You specify the COBOL or C variables directly as part of the syntax, rather than
specifying parameter markers as part of the syntax and then specifying the
variables elsewhere.
2. A single statement is necessary. With dynamic ESQL, you have to issue two
statements, PREPARE and EXECUTE.
3. You do not have to code strings within strings. Consider this example static ESQL
statement:
EXEC SQL DELETE FROM houses
WHERE hno = 'H101';

In dynamic ESQL, you must use adjacent quotes to send a quote to RDMS:

EXEC SQL PREPARE deltbl FROM 'DELETE FROM houses


WHERE hno = ''H101''';

For ease of use by an applications programmer, static ESQL is preferable.

1–16 7830 8160–027


Interface Tradeoffs

When you compile a program that contains static ESQL syntax, the tables used by that
program must be created before the program is compiled. If application programs
must be moved between application groups or systems without being recompiled and
without auto-recompiling, the database administrator’s job is much more complicated
than with the other interfaces. This is because all tables must be created or altered
using static ESQL CREATE TABLE or ALTER TABLE statements, and the object
modules for these programs must be maintained by the database administrator and
executed in the same order on the production system as they were executed on the
development system. For more information and procedures for porting ESQL or
module language programs, see the Relational Database Server for ClearPath
OS 2200 Administration Guide.

Instead of porting ESQL programs, you can recompile the programs that create the
tables, or create the tables using the interactive interface. This ensures that the RDT
timestamp is different between the development system and the production system.
Because the timestamps are different, all static ESQL statements are auto-recompiled
by RDMS as they are executed. The recompiled structure is retained until the thread
exits, so any statement only auto-recompiles once per thread. For optimal
performance, you may wish to recompile just those programs on the production
system that use a large amount of system resources. You cannot recompile programs
if there is no compiler on the production system; for security reasons, some sites do
not allow compilers on the production system. To find out which programs are being
auto-recompiled, use the SUDS AR keyin; see the Universal Data System
Administration and Support Reference Manual.

Static ESQL has some flexibility; like dynamic ESQL, it can respond to changes to the
table definition:

• If the table definition changes and a static ESQL program has not been recompiled,
RDMS attempts to rebind an SQL statement to the updated table definition. This
succeeds unless the SQL statement explicitly references a dropped column, or if a
SELECT * was performed. If the rebinding succeeds, the new section (the
structure that is the output of the RDMS optimizer) is saved as part of the thread.
If the same static ESQL statement is reexecuted by the program within a loop that
saved section is used; no auto-recompile is done.
• When the XREF feature is enabled, UREP contains cross-references between
tables and the programs that reference them.
• The UREP commands REPORT COBOL and REPORT C can create COPY elements
matching RDMS table definitions.

1.6.3. Interactive Interface


The interactive interface is the most flexible interface. A program that uses the
interactive interface can be compiled before the tables used by that program are
created. The interactive interface can be used to execute an arbitrary SQL statement
(that is, read in from a user or built up by the program).

7830 8160–027 1–17


Interface Tradeoffs

LOCATE and OPEN CURSOR are the only statements that pass actual program variable
values as parameters to RDMS. For other statements, such as the INSERT statement,
the Relational Syntax Analyzer (RSA) converts the value of a variable into a constant
before passing it to RDMS, so your program might just as well build up the SQL
statement without using program variables. If this is done, RSA does not have to
match the number of placeholder variables referenced in the statement with the
number of program variables supplied on the rsa() call. This makes coding easier.

If program variables are being passed, an arbitrary number can be passed to RSA
using the UCS C rsa_param function or the UCS COBOL RSA$PARAM procedure; see
Appendix H for more information. An interactive program can thus be made to
respond automatically to added or dropped columns.

Note: The interactive interface is proprietary to Unisys Corporation; a program that


uses it is not portable to other vendors' databases.

Example UCS C Statements


Less flexible:

rsa("insert into t1 values($p1, $p2, $p3);", error_code, &aux_info,


&var1, &var2, &var3);

More flexible:

rsa_param(&var1);
rsa_param(&var2);
rsa_param(&var3);
rsa("insert into t1 values($p1, $p2, $p3);", error_code, &aux_info);

Even more flexible:

strcpy(cmd_var, "insert into t1 values(");


strcpy(cmd_var, var1); or fscanf() to convert from binary to char
strcpy(cmd_var, " , ");
strcpy(cmd_var, var2);
strcpy(cmd_var, " , ");
strcpy(cmd_var, var3);
strcpy(cmd_var, ");");
rsa(cmd_var, error_code, &aux_info);

1.6.4. Dynamic ESQL Interface


A program that uses dynamic ESQL can be compiled before the tables used by that
program are created. Dynamic ESQL also allows arbitrary statements to be built up.

You can use the EXECUTE IMMEDIATE statement to issue some SQL statements
(such as INSERT, UPDATE, DELETE) in a manner similar to the interactive interface; that
is, you can build up the syntax including the program variable values as constants.
However, you cannot retrieve any data using EXECUTE IMMEDIATE; instead, you must
use PREPARE, ALLOCATE, OPEN, and FETCH.

1–18 7830 8160–027


Interface Tradeoffs

The OPEN and FETCH statements must have the same number of parameters, and
their data types must match the SELECT list. The EXECUTE statement must include a
USING clause with a one-to-one relationship between parameter markers and host
program variables. To respond to an added column without recompiling your program,
you must include multiple versions of the same EXECUTE statement, each with a
different number of parameters of different data types. Dynamic ESQL cannot
respond to added and dropped columns if program variable usage must be changed.
Because program variables are bound at compile time with dynamic ESQL, programs
cannot respond to added or deleted columns when those values must go through a
program variable (for example, when a SELECT * is performed).

1.6.5. General Guidelines


The following are some general guidelines to help weigh the tradeoffs involved in
using different RDMS interfaces:

• Use static ESQL when you know the syntax of the statement and you know that
table definition changes will not affect the syntax.
• When you do not know the syntax of the statement, use dynamic ESQL or the
interactive interface.
Choose dynamic ESQL for any of these reasons:
− Standards conformance is an issue.
− You want to be able to PREPARE a statement once and EXECUTE it multiple
times.
− Execution-time binding of program variables is not an issue.
Choose the interactive interface for any of these reasons:
− You do not want to deal with the complexity of separate PREPARE and
EXECUTE statements.
− You require execution-time binding for program variables.
− Your table definition changes regularly and the changes affect the syntax.
• Consider the “80/20 rule.” This rule suggests that only 20 percent of programs are
performance-critical. This could mean, for example, that you could allow 80
percent of your programs to auto-recompile, without noticing any performance
difference from a system on which all of the programs containing static SQL had
been recompiled.

7830 8160–027 1–19


SQL and RDMS Statements

1.7. SQL and RDMS Statements


The following tables summarize standard SQL statements and RDMS extended
statements, grouped according to their functions. If a statement is not available
through a specific interface, it is noted in the discussion for the individual statement.
See the subsection listed in the See column for detailed reference information about a
statement.

1.7.1. Data Retrieval


Table 1–1 describes the SQL statements used for data retrieval.

Table 1–1. SQL Statements: Data Retrieval

Statement Description See

ALLOCATE CURSOR Declares a cursor defined in a prepared 6.1


dynamic ESQL statement.
CLOSE Releases a cursor after data is accessed. 6.6
This is the inverse of the OPEN
statement.
DECLARE CURSOR Specifies the tables, columns, and rows 7.4
that make up the cursor being defined.
DROP CURSOR Removes a previously defined cursor 7.6
from RDMS internal tables. This is the
inverse of the DECLARE CURSOR
statement.
FETCH Retrieves a row of data from an opened 8.6
cursor. The first, last, current, prior, or
next row in the cursor can be retrieved
with one of the FETCH options.
FETCH NEXT n Retrieves multiple rows of data from an 8.7
opened cursor through ESQL.
GET DESCRIPTION Retrieves information about each cursor 8.9
column declared by the WITH
DESCRIPTION clause of the DECLARE
CURSOR statement.
GET RESULT SET Retrieves the name of the cursor that 8.12
CURSOR NAME RDMS created to describe the dynamic
result sets returned by a call to a stored
procedure.
LOCATE Specifies a row of a cursor as the current 9.2
row. Once the row is current, retrieve it
using the FETCH statement.

1–20 7830 8160–027


SQL and RDMS Statements

Table 1–1. SQL Statements: Data Retrieval

Statement Description See

OPEN Prepares rows in the cursor for retrieval. 9.4


Use an OPEN statement to specify values
for the variables specified in the DECLARE
CURSOR statement.
SELECT Multirow Fetches any number of rows from the 9.9
database that satisfies the query
specification (from IPF SQL Interface).
SELECT Single Row Fetches a single row from the database. 9.10
Use this statement instead of the
DECLARE CURSOR, OPEN, and FETCH
statements when requesting a single row.
If more than one row satisfies the query
specification, the SELECT statement
returns the first row when interpreted
and an error when embedded.
UNLOAD Dumps selected rows into a system data 10.1
format (SDF) file. This statement provides
for the transferring of RDMS data to other
processors.

1.7.2. Deletes, Inserts, and Updates


Table 1–2 describes the SQL statements used to delete, insert, and update rows of
tables.

Table 1–2. SQL Statements: Deletes, Inserts, and Updates

Statement Description See

DELETE Deletes one or more rows from a table. 7.5


INSERT Adds one or more rows to the table. 8.14
UPDATE ALL Changes the values of data items in all 10.3
existing rows of a table.
UPDATE Positioned Changes the values of data items within 10.4
the current row of a cursor.
UPDATE Searched Changes the values of data items in a 10.5
subset of the existing rows in a table.
UPDATE Changes the values of data items in a 10.6
SYNCHRONIZE specific existing row of a table or adds
the row if it does not exist.
UPDATE VALUES Changes the values of data items in 10.7
specific existing rows of a table.

7830 8160–027 1–21


SQL and RDMS Statements

1.7.3. Locks
Table 1–3 describes the SQL statements used for table locking.

Table 1–3. SQL Statements: Locks

Statement Description See

LOCK Specifies the type of lock to place on a 9.3


table. This statement overrides the
default locking protocol.
UNLOCK Releases the lock on a table specified by 10.2
a previous LOCK statement.

1.7.4. Table Security


Table 1–4 describes SQL statements that control how users can access the data in a
table.

Table 1–4. SQL Statements: Table Security

Statement Description See

CREATE ROLE Creates a role that provides a shortcut for 6.9


a large number of GRANT statements.
DROP ROLE Destroys a role and removes all privileges 7.9
granted to that role.
GRANT Controls how other users can use a table 8.13
or data.
REVOKE Removes user permission to access a 9.7
table's data.

1–22 7830 8160–027


SQL and RDMS Statements

1.7.5. Table Definition


Table 1–5 describes SQL statements that can be used to define the properties of a
table.

Table 1–5. SQL Statements: Table Definition

Statement Description See

ALTER TABLE Changes the format of a table. 6.2


CREATE INDEX Creates an index for a table. 6.8
CREATE SCHEMA Defines a schema name and establishes 6.10
ownership and qualifier default values for
any following definition statements.
CREATE TABLE Defines the characteristics of a table, 6.11
stores the definition in the repository and
stores the encoded form of the definition
(relation description table [RDT]) in the
RDT$FILE file.
DROP INDEX Eliminates an index for a table. 7.7
DROP TABLE Deletes a table definition from the 7.10
repository and removes the associated
RDT and any dependent VDTs from the
RDT$FILE file.

1.7.6. View Definition


Table 1–6 describes SQL statements to define and use views.

Table 1–6. SQL Statements: View Definition

Statement Description See

CREATE VIEW Defines the characteristics of a view, 7.2


stores the view definition in the
repository and stores the encoded form
of the definition (view definition table
[VDT]) in the RDT$FILE file.
DROP VIEW Deletes a view definition from the 7.12
repository and removes the associated
VDT and any dependent VDTs from the
RDT$FILE file.

7830 8160–027 1–23


SQL and RDMS Statements

1.7.7. Routines and Triggers


Table 1–7 describes SQL statements that define and invoke routines (stored
procedures, functions) and triggers.

Table 1–7. SQL Statements: Routines and Triggers

Statement Description See

CALL Invokes a previously defined stored 6.5


procedure.
CREATE TRIGGER Defines a trigger. 7.1
DROP PROCEDURE/ Removes a defined stored procedure or 7.8
FUNCTION function from the database.
DROP TRIGGER Removes a trigger from the database. 7.11
FUNCTION Defines a stored function. 8.8
GET PARAMETERS Retrieves information about the number 8.11
and type of parameters for a routine.
PROCEDURE Defines a stored procedure. 9.6
SET Invokes a previously defined stored 9.11
function and assigns values returned by
the function to a host program variable or
placeholder variable.

1.7.8. ESQL Variable Declarations


Table 1–8 describes SQL statements to declare variables for embedded SQL (ESQL).

Table 1–8. SQL Statements: ESQL Variable Declarations

Statement Description See

BEGIN DECLARE Precedes host program variable 6.3


declarations for variables to be embedded
in ESQL statements.
END DECLARE Marks the end of embedded variable 8.1
declarations.

1–24 7830 8160–027


SQL and RDMS Statements

1.7.9. Dynamic ESQL Statement Execution


Table 1–9 describes SQL statements to execute dynamic ESQL statements.

Table 1–9. Dynamic ESQL Statement Execution

Statement Description See

EXECUTE Executes a prepared SQL statement. 8.3


EXECUTE IMMEDIATE Prepares and executes an SQL statement. 8.4
PREPARE Prepares an SQL statement for later 9.5
execution.

1.7.10. UDS Work Sessions (Thread Control)


Table 1–10 describes SQL statements for thread control.

Table 1–10. SQL Statements: UDS Work Sessions (Thread Control)

Statement Description See

BEGIN THREAD Sets up a work session by registering a 6.4


thread with UDS Control.
COMMIT Writes all updates since the last thread 6.7
control statement to the database and
closes all opened cursors.
END THREAD Ends the work session, writes any updates 8.2
made to the database since the last step,
and closes all opened cursors.
ROLLBACK Terminates a recovery step and discards 9.8
any updates made to the database since
the last step.

7830 8160–027 1–25


SQL and RDMS Statements

1.7.11. Checks and Inquiries


Table 1–11 describes various SQL statements you can use for checks and inquiries.

Table 1–11. SQL Statements: Checks and Inquiries

Statement Description See

DEBUG Checks the syntax of SQL statements 7.3


without actually executing them. Also
dumps internal information for help in
evaluating problems.
EXPLAIN Directs RDMS to return information about 8.5
the access path it plans to take to find the
rows specified in a DECLARE CURSOR
statement. This information is retrieved with
the GETERROR statement.
GETERROR Places message text in program variables. 8.10
LEVEL Identifies the system number of RDMS and 9.1
RSA, one of its components.
SET RESULT SET Directs RDMS to create dynamic result sets 9.13
from a stored procedure call.
SET STATISTICS Directs RDMS to use or not use information 9.15
in the statistics on a table to determine the
access path.
USE DEFAULT Establishes a default qualifier or version 10.8
name for subsequent references to tables
or views.
WHENEVER Directs UCS COBOL and UCS C host 10.9
program flow of control when RDMS
returns an error on an SQL statement.

1–26 7830 8160–027


Section 2
SQL Fundamentals

This section presents concepts with which you must be familiar before proceeding to
the statement syntax presented in Sections 5 through 10.

This section contains the following topics:

• Syntax Rules for SQL Statements (2.1)


• Naming Conventions (2.2)
• Literals (2.3)
• Expressions (2.4)
• Expression Operands and Comparison Operators (2.5)
• Sequences (2.6)
• Query Specification (2.7)
• RDMS Data Types (2.8)
• Character Handling and Internationalization (2.9)
• Host Language Variables (2.10)
• Embedded SQL (ESQL) (2.11)
• Using SQL in Module Programs (2.12)

7830 8160–027 2–1


Syntax Rules for SQL Statements

2.1. Syntax Rules for SQL Statements


Follow these principles and guidelines when entering SQL statements:

• End SQL statements with a semicolon ( ; ) if you are working from either
 A third–generation programming language through the interpreter interface
 An MRI run
• RDMS accepts characters in the ASCII/ISO (International Standards Organization)
character set.
• Each SQL statement issued from a third–generation programming language (such
as COBOL, FORTRAN, or C) must be placed in one of the following:
 A separate procedure call statement, if used with the interpreter interface
 An EXEC SQL statement, if used with the ESQL interface (see 2.11)
• All statement characters are from the ASCII character set. You can use uppercase
and lowercase characters interchangeably. The exception is when the letters are
enclosed in double quotation marks ( “ ) or single quotation marks ( ‘ ).
• Fieldata characters are not supported. Any attempt to pass Fieldata characters
from a program to RDMS results in an abnormal error status.
• Two consecutive hyphens ( -- ) in an SQL statement signal a comment. The text
of a comment is for information only; the text is not part of the statement.
 In static ESQL (see 2.11.1), the comment ends at the end of the line.
 In dynamic ESQL (see 2.11.6) and in the interpreter interface, the comment
extends to the end of the string or parameter that contains the SQL
statement.
A comment can also be enclosed within the delimiters /* (beginning of comment)
and */ (end of comment). For example
EXEC SQL PREPARE rb FROM
'DELETE FROM sample_table /* remove all rows */';

For other examples of comments, see 5.2.

• Each SQL statement in a routine or trigger (see Section 4) must be terminated by a


semicolon. This includes compound statements (BEGIN ... END), conditional
statements (IF ... END IF) and loop statements (WHILE ... END WHILE).

2–2 7830 8160–027


Naming Conventions

2.2. Naming Conventions


You can specify names for the following SQL entities in SQL statements:

• Columns
• Constraints
• Correlation names
• Cursors
• Indexes and keys
• Qualifiers for tables, views, routines, and triggers
• Scalar functions
• Schemas
• Statements
• Role names
• Routines
• Tables
• Triggers
• Title names
• Variables
• Views

You can also specify the following entities unique to RDMS in SQL statements:

• Database storage areas


• Versions for tables and views

2.2.1. Rules for Naming Entities


Each name must follow these rules:

• A name cannot exceed 30 characters in length.


• A name can have any of the following characters:
0 1 2 3 4 5 6 7 8 9

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

a b c d e f g h i j k l m n o p q r s t u v w x y z

_ (underscore)
• A name must begin with a letter.

7830 8160–027 2–3


Naming Conventions

• A name can use either lowercase or uppercase letters; lowercase letters are
treated as though they were uppercase. For example, avg_pay is the same as
AVG_PAY.
• A name cannot be a reserved word. See Appendix A for a list of reserved words.
• You can specify kanji names (see Relational Database Server for ClearPath
OS 2200 Administration Guide).

To avoid all of these naming rules, you can enclose a name in double quotation marks
( " )(042). Names enclosed in quotation marks are called delimited identifiers.
Lowercase letters are not equivalent to uppercase letters in names enclosed in
quotation marks. For example, the name "ABC" is the same as the name ABC, but it is
not the same as "aBc" or "abc". Blanks are allowed in delimited identifiers except for
schemas, qualifiers, storage-areas, tables and versions.

A delimited identifier is limited to 30 bytes. Within a delimited identifier, two double


quotation marks in a row mean that one double quotation mark is part of the identifier
and the second one is not used. Avoid using the NUL character (000), Shift-Out (016)
and Shift-In (017) because such names may not be accepted by tools such as JDBC.

Examples of Valid Names


houses

customers

avg_pay

t1

"@#!"

"%RATE"

Examples of Invalid Names


hyphen-ated

dollar$sign

2table

this_is_too_long_to_be_a_legal_name

2–4 7830 8160–027


Naming Conventions

2.2.2. Referencing Tables, Views, and Versions


A table-specification identifies a table or view.

Format
[schema.]table-name[:version-name]

where:

schema
is the name of the schema containing the table. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information, see the Repository for
ClearPath OS 2200 Administration Guide.

table–name
is the name of the table or view in the database.

version–name
is the version of the data you want to reference. If you omit the version name,
RDMS uses the value you specified on the USE DEFAULT VERSION statement. If
you have not established a default version, RDMS uses the default version name
PRODUCTION.

Examples
The following is an example of an unqualified table name for table CUSTOMERS:

customers

The following table specification includes the qualifier REALESTATE and version-name
JACQUES for table HOUSES:

realestate.houses:jacques

Version Names
When you create a table, you state in which storage area the table is to be stored.
You can have many versions of a table. This means that you can have a single table
definition, but several different sets of data that fit that definition. For example, the
real estate information in tables CUSTOMERS and HOUSES can have one table
definition for houses, but also have a separate set of data for Minnesota, Wisconsin,
Illinois, and so on. Each such set of data is called a version of the table.

Each version of a table requires a storage area version. In turn, each storage area
version requires its own Exec or TIP file. You create Exec files with the @CAT
statement. You link Exec files with storage area versions using UREP.

7830 8160–027 2–5


Naming Conventions

For more information about storage areas and versions, see the Repository for
ClearPath OS 2200 Administration Guide.

The storage area version name is the same as the table version name. The only time
the storage area version name is not the same as the table version name is when the
table version name is PRODUCTION. The table version name PRODUCTION is
associated with the blank storage area version name.

Example
Suppose a large university makes computer time and services available to the many
student organizations on campus. Many organizations take advantage of this by
requesting rosters of their members. Naturally, the university also needs a master
student directory. One way to implement such a system is as follows:

1. Catalog a file.
For this example, name the file DBA*STUDENT–DATA.
2. Use UREP to link DBA*STUDENT–DATA with a storage area named ROSTER. For
the storage area version name, specify MASTER.
3. Also use UREP to specify a schema name. For this example, name the schema
UNIVERSITY.
4. Use the SQL CREATE TABLE statement to create a table named
UNIVERSITY.STUDENTS in ROSTER.
You cannot specify a version name with the CREATE TABLE statement.

You now have a base table named UNIVERSITY.STUDENTS:MASTER. You can populate
the table and use it as needed. (Assume that the primary key of
UNIVERSITY.STUDENTS is a student identification number and that each student
knows and uses this number frequently.)

Now suppose the debate club on campus wants to create a roster of its members.
The debate club just needs to provide you with a list of student identification numbers
of their members. You use the following procedure to create the debate club roster:

1. Catalog an Exec file (for example, DBA*DEBATERS).


2. Use UREP to link DBA*DEBATERS with schema UNIVERSITY and storage area
ROSTER. This time, specify the storage area version name as DEBATE.

You now have a version of the table named UNIVERSITY.STUDENTS:DEBATE. You can
use the student identification numbers the debate club gave you to retrieve rows from
UNIVERSITY.STUDENTS:MASTER to populate this new version. You can also create a
user–id for the debater's membership officer to use to maintain the table as students
join or leave the club.

Version names require some care in their use with the DECLARE CURSOR, GRANT,
OPEN, and REVOKE statements.

2–6 7830 8160–027


Naming Conventions

ESQL Considerations
The version name can be supplied by an embedded variable. The following table
specification, for example, cannot be resolved until the variable VERSION–VAR is
assigned a value and the ESQL statement containing this table specification is
executed:

houses::version-var

The first of the two colons serves as the separator between the table name and the
version name. The second colon is the embedded variable prefix.

2.2.3. Referencing Columns


Column references are required by many SQL statements. A column is identified by a
column-specification.

Format
[table-specification.]column-name

where:

table–specification
is the name of the table containing the column, as defined in 2.2.2.

column–name
is the name of the column.

Examples
The following are examples of column name specifications:

houses.price

customers.cno

realestate.houses:roger.location

x.location

hno

7830 8160–027 2–7


Naming Conventions

2.2.4. Referencing Functions and Procedures


RDMS supports several kinds of functions:

• Aggregate built-in functions (such as MIN, MAX, and AVG)


• Scalar built-in functions (such as upper, lower, and substring)
• Stored procedures and functions

You can reference stored procedures and functions as qualified names or as


unqualified names.

Using a Qualified Name


When you use a qualified name to reference a function, RDMS finds the stored
PROCEDURE or FUNCTION you have named. For example, the following statement
finds the function lower in the schema myschema:

SET var1 = myschema.lower(namevar)

Note that a function you create in a schema can have the same name as an RDMS
scalar built-in function. It cannot have the same name as an RDMS aggregate built-in
function, because the aggregate built-in function names are reserved words.

The following statement finds the procedure lower in the schema schema2 if it exists:

CALL schema2.lower(namevar)

Using an Unqualified Name


When you use an unqualified name to reference a function, RDMS must search for the
function to resolve its name. The name can be a scalar function, stored procedure, or
stored function. RDMS looks for the name in the following order:

1. In the set of scalar built-in functions.


2. In the default schema. If you have not established a default schema, using the USE
DEFAULT SCHEMA statement, RDMS uses the schema RDMS or the schema
whose name matches the current user, depending on the value of the UREP
configuration attribute RDMS-DEFAULT-QUALIFIER

Examples
USE DEFAULT SCHEMA global1

SET var1 = lower(namevar)

2–8 7830 8160–027


Naming Conventions

RDMS looks for the function lower as a scalar built-in function, finds it, and executes
it. If RDMS does not find the name as a scalar built-in function, it looks in the schema
RDMS or in the schema whose name matches the current user. If you want RDMS to
find the function lower in the schema global1, you must specify it as a qualified name:

SET var1 = global1.lower(namevar)

Alternatively, you can indicate the schema to search on a USE statement:

USE DEFAULT SCHEMA global1

SET var1 = proc1(namevar)

RDMS does not find proc1 as a scalar built-in function, so it looks in the default
schema global1. If RDMS finds it in global1, it executes the function.

2.2.5. Referencing Storage Areas


Storage area names are required by many SQL statements.

Format
[schema-name.]storage-area-name

where:

schema-name
is the name of the schema in which the storage area was created. If you omit the
schema name, RDMS uses the name of the schema on the table being created or
altered. If you omit a schema name on the table, RDMS uses the value you have
specified on the USE DEFAULT SCHEMA statement. If you have not established a
default schema name, RDMS uses the default schema name RDMS or the value of
the user ID of the current run, depending on the value of the UREP configuration
attribute RDMS-DEFAULT-QUALIFIER. For additional information, see the
Repository for ClearPath OS 2200 Administration Guide.

storage-area-name
is the name of the storage area to use.

Examples
The following statement creates the table HOUSES in the schema REALESTATE and
uses the storage area APPLEVALLEY in the schema REALESTATE.

CREATE TABLE realestate.houses IN realestate.applevalley

The following statement creates the table HOUSES in the schema RDMS and uses the
storage area MINNEAPOLIS in the schema RDMS. This example assumes the value of
the UREP configuration attribute RDMS-DEFAULT-QUALIFIER is set to RDMS.

CREATE TABLE houses IN minneapolis

7830 8160–027 2–9


Naming Conventions

The following statement creates the table HOUSES in the schema REALESTATE and
uses the storage area ROSEVILLE in the schema REALESTATE.

USE DEFAULT SCHEMA realestate


CREATE TABLE houses IN roseville

The following statement creates the table HOUSES in the schema TEST and uses the
storage area SHOREVIEW in the schema TEST. Note that because the schema name
was omitted from the storage area name, RDMS uses the table’s schema name.

USE DEFAULT SCHEMA realestate


CREATE TABLE test.houses IN shoreview

2.2.6. Rules for Naming Roles


Role names are used by role security. They are identifiers that are sometimes treated
as role-names and sometimes treated as user IDs.

A role name can consist of numbers between 1 and 29 ASCII (not UNICODE or KANJI),
characters from A-Z, 0-9, period, and hyphen. The best practice is to use an invalid
user ID as a role name (to do this, use a name between 13 and 29 characters). Do not
use the prefix "RDMS-", because it is used by RDMS predefined roles.

2–10 7830 8160–027


Literals

2.3. Literals
This subsection includes the following topics:

• String Literals (2.3.1)


• Numeric Literals (2.3.2)
• Nulls (2.3.3)
• Datetime Literals (2.3.4)
• Interval Literals (2.3.5)

2.3.1. String Literals


A string literal is a character sequence surrounded by string delimiters. Use single
quotation marks ( ' ) for string delimiters.

String delimiters are not part of the actual string. Within a string literal, two single
quotation marks in a row mean that one quotation mark is part of the string and the
second one is not used.

The character sequence in a string literal can include any character belonging to a
supported character set. For more information on supported character sets, see The
I18N Assistant.

RDMS considers all literals as RDMS_TEXT. For more information on character


sets, see 2.9.2.

Examples
The following example is a string literal that contains five characters: j, o, e, ', and s:

'joe''s'

The next example is the string literal “a1 at lloyd's”. The quotation marks are part of
the string, which is 15 characters long (including blanks).

'"a1 at lloyd''s"'

The final example shows the use of characters with diacritical marks:

‘Bonbons sind süß’

7830 8160–027 2–11


Literals

2.3.2. Numeric Literals


Numeric literals are either integers or real numbers. You can write them with or
without a leading sign.

Integer Literals
Integer literals are simply strings of up to 21 digits. This 21-digit limit does not include
the optional leading sign.

Examples
The following are examples of integer literals:

-9

481567890231457849201

Do not place a space between the leading sign (if present) and the first digit of an
integer literal. Similarly, do not place any spaces or commas between the digits of an
integer literal.

Real Literals
Real literals are strings of digits containing a decimal point. You can write them with or
without a leading sign. A literal of this form can contain no more than 21 digits. This
21-digit limit does not include the leading sign if used or decimal point if used.

Do not place a space between the leading sign (if present) and the first digit of a real
literal. Similarly, do not place any spaces or commas between the digits of a real
literal.

You can also express real literals in a form similar to scientific notation by employing
an exponentiation suffix. The suffix is the letter E (either uppercase or lowercase),
followed by an integer exponent. The integer exponent can have a leading sign, and
cannot exceed three digits in length.

When expressed in this way, the portion of the literal to the left of the E suffix is
called the mantissa. The portion to the right of the E suffix is the exponent. The
expression mantissaEexponent is read “mantissa times ten to the exponent power.”

The mantissa can have no more than 21 digits. This 21-digit limit does not include the
leading sign or decimal point.

The largest absolute value a real literal can have is 8.988465674311579551E+307.

The closest to zero a positive real literal can be is 2.781342323134001732E–309.

2–12 7830 8160–027


Literals

Examples—Zeros
The following are examples of zeros:

0.0

0.0e6

Examples—Valid Real Literals


Some examples of valid real literals are as follows:

9.0e0

+9.e-12

0.9e+1

.9e1

1223.487743e22

3.14159265

Alternate Based Integers


Alternate based integers are strings in the following form:

base'value'

where:

base
specifies the base of the value and is one of the following letters:

B Binary
O Octal
X Hexadecimal

You can use either uppercase or lowercase letters for B, O, or X.

value
is an unsigned integer value enclosed in single quotation marks. If the value is
negative, precede the B, O, or X with a minus sign. A plus sign for a positive value
is optional.

Alternate based literals can be used in INSERT, UPDATE, and SELECT statements; the
WHERE clause and DEFAULT clause; in arithmetic expressions, including BIF
arguments; and as a partitioned table column-upper-bound.

7830 8160–027 2–13


Literals

Maximum and allowed values are as follows.

Maximum
Literal Type Length of value Allowed Characters in value

Binary 72 characters Digits 0 and 1


Octal 24 characters Digits 0 through 7
Hexadecimal 17 characters Digits 0 through 9 and letters A through F
Uppercase and lowercase letters are
treated as equal.

Examples
b'010' Value of 2 decimal
o'127' Value of 87 decimal
x'123a' Value of 4666 decimal
x'Ab' Value of 171 decimal
x'aB' Value of 171 decimal
x'ab' Value of 171 decimal
-b'101' Value of -5 decimal
+O'123' Value of +83 decimal

2.3.3. Nulls
Occasionally, a particular data item may not yet have a value associated with it. In
table HOUSES, for example, a new entry may be created for a house for which no
price is yet established. Another example may be a customer who has no location
requirement. Even though columns exist for this information, the information is not yet
available, appropriate, or applicable. The application must take special steps to handle
“dummy” data in these data items.

To address these kinds of situations, SQL provides for “null” data. Nulls are
placeholders for unavailable or nonexistent data. As such, they have no value.

When you design tables, decide which columns you want to be able to hold nulls.
When you use the ALTER TABLE and CREATE TABLE statements, you can specify in
which columns to allow nulls to be stored.

To store nulls in rows using the INSERT and UPDATE statements, you can use either
the NULL keyword or indicator variables (see 2.10.4). Third-generation programming
languages retrieve nulls through indicator variables. For information about other ways
to retrieve nulls, see the RDMS and IPF SQL Interface End Use Guide and the
UNLOAD statement in this manual.

2–14 7830 8160–027


Literals

You can find the rules for how nulls behave in expressions, functions, comparisons,
query specifications, and as parameter values in the following subsections:

2.4 Expressions
2.4.10 Functions
2.5.1 IS NULL operations
2.7 Query specifications, specifically with the DISTINCT keyword and GROUP BY
clause
2.10.4 Indicator variables
3.3 Passing a null value as a parameter

2.3.4. Datetime Literals


Datetime literals follow the keyword DATE, TIME, or TIMESTAMP and are enclosed in
single quotation marks. Specify the entire literal syntax as part of the command text if
the datetime literals are providing datetime data values.

DATE Literal Format


DATE 'date-value'

where date–value is the absolute value of the date in the format

YYYY-MM-DD

or
DD.MM.YYYY

or
DDMONYYYY

where:

YYYY
is the year in the range 0001 to 9999.

MM
is the month in the range 01 to 12.

7830 8160–027 2–15


Literals

MON
MON is a 3 char ASCII representation of the month.

For example:

12Jan2012

10Dec1985

23Nov2000

DD
is the day in the range 01 to 31. The day is further constrained by the value of the
month and year, in accordance with the Gregorian calendar.

TIME Literal Format


TIME 'time-value'

where time–value is the absolute value of the time in the format

HH:MM:SS[.[FFFFFF]]

where:

HH
is the hour in the range 00 to 23.

MM
are the minutes in the range 00 to 59.

SS
are the seconds in the range 00 to 59.

FFFFFF
(optional) is the fractional portion (from 0 to 6 digits) of the seconds in the range
.000000 to .999999.

TIMESTAMP Literal Format


TIMESTAMP 'timestamp-value'

where timestamp–value is the absolute value of the timestamp, a combination of the


values in date–value and time–value:

YYYY-MM-DD HH:MM:SS[.[FFFFFF]]

Only one space is allowed between DD and HH.

2–16 7830 8160–027


Literals

Examples
The following examples are valid datetime literals:

DATE '1998-12-31'

TIME '23:12:56'

TIME '09:58:45.123456'

TIME '10:23:15.96'

TIMESTAMP '1998-12-31 23:59:59'

TIMESTAMP '1998-01-01 12:45:56.'

The following examples are valid date, time, and timestamp values:

1998-12-31

23:12:56

09:58:45.123456

10:23:15.96

1998-12-31 23:59:59

1998-01-01 12:45:56.

TIMESTAMP Literal FORMAT (DB2 Alternative)


The timestamp may also take the following form:

YYYY-MM-DD-HH.MM.SS[.[FFFFFF]]

This differs from the previous format in three character positions.

1. There is a '-' between the date and time fields


2. There is a '.' between the hour and minute fields
3. There is a '.' between the minute and second fields

The following examples are valid timestamp literals:

TIMESTAMP '1998-12-31-23.59.59'

TIMESTAMP '1998-12-31-23.59.59.'

TIMESTAMP '1998-12-31-23.59.59.123456'

TIMESTAMP '1998-12-31 23.59.59.123456'

7830 8160–027 2–17


Literals

TIMESTAMP '1998-12-31-23:59:59.123456'

'1998-12-31-23.59.59'

'1998-12-31-23.59.59.'

'1998-12-31-23.59.59.123456'

'1998-12-31 23.59.59.123456'

'1998-12-31-23:59:59.123456'

These additional timestamp variations may appear only in commands submitted to


RDMS.

RDMS does not generate this format when returning timestamp information.

In addition, the character separating the hour and minute fields must be the same as
the character separating the minute and second fields. Both must be either a '.' or a ':'.

If this alternative format is needed on output, you must use a combination of existing
functions to transform the current RDMS timestamp format to this new format. The
following is one of the several techniques that may accomplish this transformation.

SELECT clts ,' new format = '


,concat(left(to_char(clts,'IYYY-MM-DD-HH24.MI.SS.'),20)
,microsecond(clts ) )
FROM qt.t01

This results in
2006-06-06 06:06:06.123456 new format = 2006-06-06-
06.06.06.123456

2.3.5. Interval Literals


Use interval literals to specify year–month and day–time intervals.

Format
INTERVAL [ { + │ ─ } ] 'interval-value' interval-qualifier

where:

+ or –
is the unary sign (+ or Ä) indicating whether the interval value is positive or
negative. If the sign is omitted, + is assumed.

interval–value
is the value of the interval, preceded by an optional unary sign (+ or –). If the sign
is omitted, + is assumed.

2–18 7830 8160–027


Literals

Use the following delimiters:

• A hyphen ( - ) to separate the year from the month (YEAR–MONTH).


• A colon ( : ) to separate the hour from minutes, and minutes from seconds
• One space only to separate the day from the hour

interval–qualifier
specifies the datetime fields (YEAR, MONTH, DAY, HOUR, MINUTE, and SECOND)
to include in the interval–value. For more details about interval qualifiers, see 3.8.

The following table illustrates the correlation between interval values and
qualifiers.

Value Qualifier

[±]Y (lp) YEAR(ilfp)


[±]Y (lp)-M (nlp) YEAR(ilfp) TO MONTH
[±]M (lp) MONTH(ilfp)
[±]D (lp) DAY(ilfp) [TO DAY]
[±]D (lp) h (nlp) DAY(ilfp) TO HOUR
[±]D (lp) h (nlp):m (nlp) DAY(ilfp) TO MINUTE
[±]D (lp) h (nlp):m (nlp):s (nlp)[.[f (fsp)]] DAY(n) TO SECOND(ifsp)
[±]h (lp) HOUR(ilfp) [TO HOUR]
[±]h (lp):m (nlp) HOUR(ilfp) TO MINUTE
[±]h (lp):m (nlp):s (nlp)[.[f (fsp)]] HOUR(ilfp) TO
SECOND(ifsp)
[±]m (lp) MINUTE(ilfp) [TO
MINUTE]
[±]m (lp):s (nlp)[.[f (fsp)]] MINUTE(ilfp) TO
SECOND(ifsp)
[±]s (lp)[.[f (fsp)]] SECOND(ilfp,ifsp)

7830 8160–027 2–19


Literals

The representation of the interval values is as follows:

± Optional unary sign (+ or −).


Y,M,D Year, month, day. Must be unsigned integers.
h,m,s Hour, minute, seconds. Must be unsigned integers, except for
SECOND, which can contain a decimal point and fractional digits.
Lp Leading precision. Leading zeros are ignored. Interpreted value must
fit within the range 0 to 9(ilfp).
nlp Nonleading precision. The number of digits of the leading field
excluding leading zeros. Interpreted value must fit within the valid
range for the field of which it is a part.
fsp Fractional seconds precision. Least significant digits are truncated
when fsp exceeds ifsp. If fsp is less than ifsp, zeros are added to the
least significant digits. The valid range of values for the fractional part
of the SECOND field is between 0 and 9(ifsp).
ilfp Specified or implied interval leading field precision.
ifsp Specified or implied interval fractional seconds precision.

For the valid range of values for each interval data type field and the memory
requirements, see 3.8.

Valid Examples
The following examples are valid.

The first example subtracts 6 from YEAR and 10 from MONTH:

INTERVAL -'6-10' YEAR TO MONTH

The next example adds 123 to HOUR and adds 4 to MINUTE:

INTERVAL +'123:4' HOUR(4) TO MINUTE

The next example subtracts 72.99 seconds:

INTERVAL -'72.99' SECOND(4,6)

The next example adds 365 days and 20 hours:

INTERVAL '365 20' DAY(4) TO HOUR

The next example subtracts 6 from YEAR and 10 from MONTH:

INTERVAL '-6-10' YEAR TO MONTH

The final example adds 6 to YEAR and 10 to MONTH:

INTERVAL -'-6-10' YEAR TO MONTH

2–20 7830 8160–027


Literals

Invalid Examples
The following examples are invalid for the reasons indicated.

In this example, HOUR(2) TO MINUTE is assumed by default:

INTERVAL -'123:4' HOUR TO MINUTE

In this example, MINUTE must be between 0 and 59:

INTERVAL '11:60:00.000000' HOUR TO SECOND

7830 8160–027 2–21


Expressions

2.4. Expressions
This subsection includes the following topics:

• What is an expression?
• Boolean expressions
• Universal quantifiers
• Order of precedence for operations
• Evaluation and rounding of arithmetic expressions
• Arithmetic result types
• Datetime arithmetic expressions
• Built–in functions

2.4.1. What Is an Expression?


An expression is a sequence of names, constants, placeholder variables, parentheses,
and operators that states a value.

Examples
The following expression states the value of 2:

The following expression expresses a character string:

'ab'

The following expression is a column name that expresses the value in the column:

hno

The following expression evaluates to the value 77:

5 + .06 * 1200

The following expression contains a placeholder variable, $P1 (see 2.10.3):

5 + .06 * $p1

The following expression evaluates to FALSE:

6 = 8

The following expression contains a column name and an embedded host program
variable in ESQL:

price * :commission

2–22 7830 8160–027


Expressions

The following expression contains a column name and a dynamic ESQL variable
marker:

maxprice < ?

The following expression states a value for the date in column 1 (C1) that is before or
on 1 May 1994:

c1 <= DATE '1994-05-01'

The following expression evaluates to the time value 23:34:45.55 :

TIME '15:34:45.55' + INTERVAL '8:00' HOUR TO MINUTE

The following expression evaluates to the string ‘AlphaBeta’:

‘Alpha’ || ‘Beta’

The following expression converts a character string specified in an embedded host


program variable to a timestamp value:

CAST(:tstmp AS TIMESTAMP(6))

The following expression extracts the exact numeric value 10 from the MONTH field
of a DATE value:

EXTRACT(MONTH FROM DATE '1998-10-06')

For more information about datetime arithmetic expressions, see 2.4.8.

2.4.2. Boolean Expressions


A Boolean expression is an expression that results in a value of TRUE, FALSE, or
UNKNOWN. Use Boolean expressions to select the rows in a table for which the
Boolean expression is TRUE. This applies also to selective groups from a grouped
table (query specification with a GROUP BY clause).

A predicate is the simplest of all Boolean expressions. It consists of one of the


following types of operations, which results in a truth value of TRUE, FALSE, or
UNKNOWN. A common subcomponent of all predicates is a value expression, which
results in either a numeric, character, time, date, or timestamp value. Some examples
are columns, literals, arithmetic expressions, and built–in functions (see 2.4.10).

Predicates include the following:

• Two value expressions or a value expression followed by a subquery separated


by a comparison operator.
• Three value expressions sequentially separated by the BETWEEN and AND
operators. See section 2.5.3.

7830 8160–027 2–23


Expressions

• A value expression with character values followed by the LIKE or NOT LIKE
operator and a pattern-matching operation. See section 2.5.4.
• A value expression followed by the IS NULL or IS NOT NULL operator. See section
2.5.1.
• A value expression separated from either a list of values or a subquery by the IN
or NOT IN operator. See section 2.5.5.
• A subquery parameter embedded within the Boolean EXISTS function call (that is,
a Boolean existential function), to create more complex Boolean expressions
(see 2.5.9). Parentheses can be used to alter the precedence of arithmetic
operations in evaluating comparison operands, or to alter the precedence of
Boolean operations in evaluating the Boolean operands, or for both reasons.

Examples
The following two examples illustrate simple predicates:

a <= b

c = d

The next example illustrates the use of the BETWEEN operator:

a BETWEEN c AND d

If you are using a subquery as a comparison operand within a predicate, you express
the subquery as the right-side operand of the comparison operator, as in this example:

a <= (SELECT AVG(x) FROM t2)

For more complex Boolean expressions, use the NOT, AND, and OR operators, as in
the following two examples:

a <= b AND c = d

a = b OR NOT (c BETWEEN d AND e)

Refer to Table 2–1 to determine the value of Boolean operations.

Table 2–1. Truth Table for Boolean Operations

Then...X OR Y
If X is... And Y is... is... X AND Y is... NOT X is...

TRUE TRUE TRUE TRUE FALSE


TRUE UNKNOWN TRUE UNKNOWN FALSE
TRUE FALSE TRUE FALSE FALSE
FALSE TRUE TRUE FALSE TRUE
FALSE UNKNOWN UNKNOWN FALSE TRUE

2–24 7830 8160–027


Expressions

Table 2–1. Truth Table for Boolean Operations

Then...X OR Y
If X is... And Y is... is... X AND Y is... NOT X is...

FALSE FALSE FALSE FALSE TRUE


UNKNOWN TRUE TRUE UNKNOWN UNKNOWN
UNKNOWN UNKNOWN UNKNOWN UNKNOWN UNKNOWN
UNKNOWN FALSE UNKNOWN FALSE UNKNOWN

The number of predicates and logical operators together cannot exceed 511.

2.4.3. Universal Quantifiers (SOME, ANY, ALL)


RDMS supports the following universal quantifiers:

SOME
ANY
ALL

SOME and ANY are synonyms and therefore functionally equivalent.

Format
value-expression comparison-operator [ NOT ] { ANY | ALL | SOME } subquery

( value-expression { , value-expression } ) { = | <> | ^= | != } [ NOT ] { ANY | ALL |


SOME } subquery

where:

value–expression
is a numeric, character, or datetime value.

comparison-operator
is any one of the arithmetic comparison operators: =, <>, ^=, !=, >, <, >= or <= .

NOT
makes the result TRUE if no rows from the set value list or subquery match the
value expression.

subquery
is as described in 2.7.4.

When you use a universal quantifier, the operand on the right must be a subquery
(see 2.7.4).

7830 8160–027 2–25


Expressions

The following rules apply for ALL:

• If the subquery is empty, the result is TRUE.


• If the comparison is TRUE for every row in the subquery, the result is TRUE.
• If the comparison is FALSE for at least one row in the subquery, the result is
FALSE.
• If none of these conditions apply, the result is UNKNOWN.

The following rules apply for ANY or SOME:

• If the subquery is empty, the result is FALSE.


• If the comparison is FALSE for every row in the subquery, the result is FALSE.
• If the comparison is TRUE for at least one row in the subquery, the result is TRUE.
• If none of these conditions apply, the result is UNKNOWN.

Row comparison operates as follows:

• The number of items in the left-hand row operand is always equal to the number
of items in the right-hand row operand.
• row1 = row2 is TRUE if row1(i) = row2(i) is TRUE for all i.
• row1 =row2 is FALSE if NOT (row1(i) = row2(i)) is TRUE for some i.
• row1 <comp op> row2 is UNKNOWN if row1 <comp op> row2 is neither TRUE nor
FALSE.

Examples
The following example evaluates to TRUE whenever a customer's maximum price is
greater than or equal to the price of at least one house:

customers.maxprice >= ANY (SELECT price FROM houses)

The following example evaluates to TRUE whenever a customer’s maximum price is


greater than or equal to the price of every house:

customers.maxprice >= ALL (SELECT price FROM houses)

2–26 7830 8160–027


Expressions

2.4.4. Bitwise Expressions


RDMS supports three bitwise operators:

& Bitwise AND


| Bitwise inclusive or (OR)
^ Bitwise exclusive or (XOR)

AND
The binary operator bitwise AND ( & ) performs a bitwise AND operation that sets bits
in the result value. A bit in the result is set if and only if each of the corresponding bits
in the converted operands is set. That is, if both bits are 1 bits, the bit in the result is
set to 1. Otherwise, the bit in the result is set to 0.

OR
The binary operator bitwise OR ( | ) performs a bitwise inclusive OR operation that
sets bits in the result value. A bit in the result is set if and only if at least one of the
corresponding bits in the converted operands is set. That is, if one of the bits is a 1 bit,
the bit in the result is set to 1. If both bits are 0 bits, the result bit is set to 0.

XOR
The binary operator bitwise XOR ( ^ ) performs a bitwise exclusive OR operation that
sets bits in the result value. A bit in the result is set if and only if exactly one of the
corresponding bits in the converted operands is set. That is, if exactly one bit is a 1 bit,
the bit in the result is set to 1. If both bits are 1 bits, or if both bits are 0 bits, the result
bit is set to 0.

Examples
B'1001' & B'1100' = B'1000'

B'1001' | B'1100' = B'1101'

B'1001' ^ B'1100' = B'0101'

6 & 5 = 4 == B'110' & B'101' = B'100'

6 | 5 = 7 == B'110' | B'101' = B'111'

6 ^ 5 = 3 == B'110' ^ B'101' = B'011'

7830 8160–027 2–27


Expressions

Intermediate Formats
RDMS converts the operands to 72-bit long intermediate formats before performing
the bitwise operations, as follows.

RDMS Data Type Intermediate Processing Value Format

SMALLINT 18-bit fixed-point binary value, right-shifted to the


rightmost 18 bits of a 72-bit fixed point binary value
INTEGER or any 36-bit fixed-point binary value, right-shifted to the
alternate-based literal string rightmost 36 bits of a 72-bit fixed point binary value
with a value less than or equal
to 34359738367 and greater
than or equal to -34359738367
Any alternate-based literal 72-bit RDMS NUMERIC format* binary value used
string with a value greater with no conversion
than 34B or less than -34B
DECIMAL or any numeric ASCII numbers converted to the double-precision
literal internal representation for NUMERIC format* data
NUMERIC—11 or fewer digits 36-bit RDMS NUMERIC format* binary value,
precision right-shifted to the rightmost 36 bits of a 72-bit
fixed-point binary value
NUMERIC—12 or more digits 72-bit RDMS NUMERIC format* binary value used
precision with no conversion
REAL 36-bit single-precision floating-point binary value,
right-shifted to the rightmost 36 bits of a 72-bit
fixed-point binary value
FLOAT—Binary precision of 27 36-bit single-precision floating-point binary value,
or less right-shifted to the rightmost 36 bits of a 72-bit
fixed-point binary value
FLOAT—Binary precision of 72-bit double-precision floating-point binary value
28 or more used with no conversion
DOUBLE PRECISION 72-bit double-precision floating-point binary value
used with no conversion

* The RDMS NUMERIC format stores values as a binary integer (fixed-point) value, multiplying
the value by the declared number of decimal places (scale) to eliminate any fractional value.
For example, if the scale is 3, RDMS multiplies the value by 103 to convert the floating-point
number into a binary integer representation. So the fractional number 2.345 is multiplied by
1000 and stored in the database as the binary integer value 2345.

2–28 7830 8160–027


Expressions

Result Types
After performing the bitwise operations, RDMS converts the result value into the
resulting data type format. The resulting data types differ slightly from the arithmetic
result types (see Table 2–5); for bitwise operations, the resulting data types are as
shown in Table 2–2. To use the table, first find the code for the left operand in the
leftmost column and then the code for the right operand in the top row. The code for
the result of a bitwise operation between that pair of numeric types is found at the
intersection of the row and column you selected.

Table 2–2. Bitwise Operation Result Types

SI I DI D N R F DP

SI SI I DI D N R F DP
I I I DI D N R F DP
DI DI DI DI D N R F DP
D D D D D N R F DP
N N N N N N R F DP
R R R R R R R F DP
F F F F F F F F DP
DP DP DP DP DP DP DP DP DP

Legend:

D DECIMAL
DI Double precision INTEGER
DP DOUBLE PRECISION
F FLOAT
I INTEGER
N NUMERIC
R REAL
SI SMALLINT

7830 8160–027 2–29


Expressions

2.4.5. Order of Precedence for Operations


The action portion of an operation is the operator. The result of many expressions
depends on the operands associated with each operator.

Table 2–3 lists the operations and operators accepted by RDMS and their order of
precedence. You can use parentheses to change the order of precedence, if
necessary (see 2.4.6).

Table 2–3. Operations and Order of Precedence

Operation Operator Precedence

Arithmetic unary + − First

*/ Second

− Third

Contatenate (see || Second


concat Function,2.4.9)

Comparison { <> | ^= | != | < | > | <= | Fourth


>= | = }

[ SOME | ANY | ALL ]


BETWEEN

IS [ NOT ] NULL

[ NOT ] LIKE

[ NOT ] IN

Boolean Existential [ NOT ] EXISTS Fourth


Function

Boolean NOT Fifth

AND Sixth

OR Seventh

Note: All operators, except for IS [NOT] NULL (2.5.1) and [NOT] EXISTS (2.5.9)
must have an expression preceding and following them. A single expression must
precede IS [NOT] NULL. When one of the universal quantifiers—SOME, ANY, ALL
(2.4.3—is combined with a comparison operator as illustrated, a subquery (2.7.4)
must follow. A subquery can also follow IN and must follow EXISTS.

2–30 7830 8160–027


Expressions

2.4.6. Evaluation and Rounding of Arithmetic Expressions


When RDMS evaluates expressions, it first evaluates anything in parentheses. For
parentheses nested within parentheses, RDMS starts with the innermost set of
parentheses and works outward. Within one pair of parentheses, or if no parentheses
are present, RDMS follows the order of precedence shown in 2.4.5. If RDMS
encounters two or more operators of the same order of precedence in the same level
of parentheses, it evaluates them from left to right.

This order of evaluation lets you know which operands (or even “subexpressions”)
belong to each operator. It does not necessarily mean that RDMS performs the
operations in this order. RDMS may be able to optimize the calculation of an
expression by executing the operators in a different order. Write expressions,
therefore, that do not depend on RDMS to execute them in a particular order.

Table 2–4 illustrates how RDMS evaluates an expression with and without
parentheses.

Table 2–4. Expression Evaluation

Expression Without Parentheses Equivalent Expression with Parentheses

a + b * c + -d a + (b * c) + (-d)
a < b - c * d a < (b - (c * d))
a < b OR c >= -d (a < b) OR (c >= (-d))
NOT a < b OR c = d AND e > f (NOT (a < b)) OR ((c = d) AND (e > f))

Rounding
Rounding during the evaluation of arithmetic expressions occurs when the precision
of the result is less than the precision of either or both operands.

RDMS uses the following three algorithms to determine the size of the result during
the evaluation of arithmetic expressions. The parameters s, s1, and s2 denote the
sizes of the numbers (whole number part plus fractional number part). The parameters
f, f1, and f2 denote the sizes of the fractional portions of the numbers. The value of f
indicates the precision of the result.

Note: For DECIMAL items defined in an owned schema, the number of decimal
digits is one greater than the number of decimal digits in the original definition. This
is because of the difference in the semantics of this value between the SQL
standard and RDMS. For more information, see 2.8.2.

Sometimes, the fractional size of the multiplication or division result may be reduced
by more than two decimal digits due to the 21 digits size limitation of the MAX or MIN
function. For example, 4 digits to the right of the decimal point reduced to 0 digits. The
result will be more accurate using double precision floating point arithmetic than using
exact numeric arithmetic of the DECIMAL or NUMERIC data types.

7830 8160–027 2–31


Expressions

GET DESCRIPTION can help to identify this situation. You have lost accuracy if

• The type is decimal or numeric


• The size is 22
• At least one of the operands has digits to the right of the decimal point
• The Scale is less than the optimal size described in this section. A Scale of 1
generally indicates a loss of accuracy.

A loss of accuracy is most apparent when the arithmetic is performed as part of the
operand of the SUM aggregate function.

To force RDMS to use double precision floating point arithmetic, enclose one of the
operators of the multiplication or division in the double() BIF. For Example,

Change

SUM(a_numeric_14_2 * (1 - my_numeric_14_2_tax))

to

SUM(double(a_numeric_14_2) * (1 - my_numeric_14_2_tax))

Addition and Subtraction


The rounding algorithm for addition and subtraction is

f = MAX(f1,f2)
s = MIN (21,MAX (s1 ─ f1,s2 ─ f2) + k) + f
IF s > 21
THEN f = 21 + f ─ s
s = 21

where k = 1 on the first, tenth, and hundredth addition or subtraction in an expression,


and k = 0 for all others.

Multiplication
The rounding algorithm for multiplication is

f = f1 + f2
s = s1 - f1 + s2 - f2 + f
IF s > 21
THEN IF f > 0 and this is the last operation in the expression
THEN min-precision = 1
ELSE min-precision = 0
f = MAX( min-precision, 21 + f - s)
s = 21

2–32 7830 8160–027


Expressions

The rounding algorithm can be modified by setting the DSR parameter


rdms6r4-rounding to TRUE. Then RDMS uses the same rounding algorithm as its
versions 6r4 and lower, which is as follows:

f = f1 + f2
s = s1 - f1 + s2 - f2 + f
IF s > 21
THEN f = MAX(0, 21 + f - s)
s = 21

Division
The rounding algorithm for division is

f = 21 ─ MIN(21,s1 ─ f1 + f2)
s = 21

Example
Let item W be NUMERIC(7,3)
Let item X be NUMERIC(21,2)
Let item Y be NUMERIC(11,10)
Let item Z be NUMERIC(5,0)

The size of the resulting value and its fractional portion (the precision) of the result of
each of the following expressions is as follows.

Expression Size Fractional Portion

X + Y 21 1
W + Z + Z 9 3
Y * W 18 13
(Y/Z) + W 21 16

Note: In some cases, RDMS attempts various optimizations on arithmetic


expressions in an attempt to preserve precision whenever possible. The precision
actually computed may therefore be greater than the result of these algorithms.

The nature of the algorithm for division is to produce a maximum–sized result with
just enough space for the largest possible integer portion. All of the rest of the result
is devoted to the fractional portion. If the dividend has a large size and a small
fractional portion or the divisor has a large fractional portion, the resulting quotient
ends up with a small fractional portion. The quotient can thus "lose" a fair amount of
precision. If the quotient is used as an operand in subsequent operations in the same
arithmetic expression, this loss of precision is propagated. (Note that the result of the
SUM and AVG functions end up with large sizes but may have relatively small
fractional sizes.)

Addition and subtraction are the only arithmetic operations involved in datetime value
expressions; hence, RDMS does not perform rounding because it is not necessary.
For further details on arithmetic operations on datetime items, see 2.4.8.

7830 8160–027 2–33


Expressions

Rounding with Program Variables


RDMS rounds when the WHERE clause compares a program variable of type REAL or
type DOUBLE PRECISION to a column of type DECIMAL in a table. Rounding occurs
only if the two digits of the program variable beyond the precision of the column are
99 or 00.

Suppose, for example, that the precision and scale of a column are defined as
5 and 2 (5,2) and that the column contains a value of 38.42. If the program variable X is
compared to the column in a WHERE clause, RDMS considers X to be equal to the
value 38.42 only if X falls in the range

38.4199 <= x < 38.4201

If a program variable is compared with more than one column in a WHERE clause,
RDMS rounds it only once and uses the rounded value in all comparisons. If the
columns do not have the same precision, RDMS rounds the program variable to the
precision of the column with the least precision.

2–34 7830 8160–027


Expressions

2.4.7. Arithmetic Result Types


Arithmetic operations sometimes result in a numeric type different from one or both
of the operands. Refer to Table 2–5 to determine the numeric type of any arithmetic
operation. To use the table, first find the code for the left operand in the leftmost
column and then the code for the right operand in the top row. The code for the result
of an arithmetic operation between that pair of numeric types is found at the
intersection of the row and column you selected.

Table 2–5. Arithmetic Operation Result Types

SI I D N R F DP DT IV
SI D D D D R DP DP
I D D D D R DP DP
D D D D D R DP DP
N D D D N R DP DP
R R R R R R DP DP
F DP DP DP DP DP DP DP
DP DP DP DP DP DP DP DP
DT DT
IV DT

Legend:

D DECIMAL
DP DOUBLE PRECISION
DT Datetime (DATE, TIME, and TIMESTAMP)
F FLOAT
I INTEGER
IV INTERVAL
N NUMERIC
R REAL
SI SMALLINT

Scientific notation literals are of type DOUBLE PRECISION. All other numeric literals
are of type DECIMAL.

Note: As discussed above, comparison for equality where one operand is of type
REAL, FLOAT, or DOUBLE PRECISION can generate misleading results, because
these data types contain approximate values. See the discussion on approximate
numeric data types in 2.8.2.

7830 8160–027 2–35


Expressions

2.4.8. Datetime Arithmetic Expressions


Datetime arithmetic expressions let you specify arithmetic operations using datetime
items, with resulting datetime data types.

The following are valid arithmetic operations:

datetime-operand + [ { + │ - } ] interval-operand

datetime-operand - [ { + │ - } ] interval-operand

[ { + │ - } ] interval-operand + datetime-operand

where:

datetime–operand
is a datetime data type item. It can be a datetime function, a CAST function, a
column reference, or a datetime literal.

interval–operand
is an interval data type item. It can be an interval literal or a CAST function.

Follow these guidelines for datetime arithmetic expressions:

• You cannot define a column as an interval data type (see 3.8). The interval operand
can be an interval literal or a CAST function that specifies an interval data type as
the target.
• The interval operand cannot include a datetime field that is not contained in the
datetime operand. For example, CURRENT_TIME + INTERVAL '99' YEAR is an error.
• If either operand is null, the result of the arithmetic expression is null.
• The result of the arithmetic operation uses the same set of datetime fields as the
datetime operand, with the same precision and scale.

The arithmetic operation is evaluated in the following order:

1. The value of each datetime field of the interval operand is added to or subtracted
from the corresponding datetime field of the datetime operand. This can mean
carrying from or to the next significant datetime field.
 If the data type of the datetime operand is TIME, the HOUR field is divided by
24 and the remainder is kept. For example, the following expression results in
a time of 01:00:00:

TIME '23:30:00' + INTERVAL '1:30' HOUR TO MINUTE

 If the data type of the datetime operand is DATE and the data type of the
interval operand is a year–month interval, the DAY field of the result is the
same as the DAY field of the datetime operand.

2–36 7830 8160–027


Expressions

The following expression results in a date of 1998–01–01:

DATE '1996-07-01' + INTERVAL '1-6' YEAR TO MONTH

2. If, after the preceding step, any datetime field of the result is outside the
permissible range of values for the field or the result is invalid based on the
Gregorian calendar system, an error is returned. RDMS verifies the datetime value
after each arithmetic operation within a datetime arithmetic expression.

Examples
The following expressions state datetime values using arithmetic expressions:

time_column + INTERVAL - '12:00:00' HOUR TO SECOND

CAST(:var1 AS TIMESTAMP(6)) - CAST(:var2 AS INTERVAL SECOND)

The following expression evaluates to the DATE value DATE ‘1995–02–28’. The DAY
field value is carried to the MONTH field.

DATE '1995-01-29' + INTERVAL '30' DAY

The following expression results in the return of an error because of an invalid


datetime value: the nonexistent date value DATE '1995–02–29'. This value was
computed by adding 1 to the month. Note that the DAY field retains the same value as
the datetime operand.

DATE '1995-01-29' + INTERVAL '1' MONTH

2.4.9. String and Blob Expressions


The concatenation operator ( || ) enables you to concatenate character or BLOB data.

Format
string1 || string2

where string1 is either a character string type or a BLOB. If string1 is a character string
type, then string2 must also be a character string type. If string1 is a BLOB, then
string2 must also be a BLOB.

See Table 3–1 for allowed data type combinations and the result data type.

If string1 is a scalar built-in function, it can return a length of zero, which is interpreted
as a null string.

The result of the operation is a string or BLOB of string1 concatenated to string2. If


either string1 or string2 is NULL, the result is a null string.

The result is truncated if its length exceeds 28,616 bytes.

7830 8160–027 2–37


Expressions

2.4.10. Built-In Functions


Built–in functions enable you to retrieve summary information about a group of rows
(for example, the number of rows that satisfy the search criteria or the sum of values
in a particular column).

When used in a select list, built–in functions return summary information about the set
of rows selected.

For information on expression operands, see 2.5. For information on built–in functions,
see Section 3.

2–38 7830 8160–027


Expression Operands and Comparison Operators

2.5. Expression Operands and Comparison


Operators
An operand is the data that is acted upon by an operator (in other words, the data
upon which an operation is performed). Operands are allowed wherever an
expression is allowed. RDMS recognizes the operands listed in Table 2–6.

Table 2–6. Operands

Operand Description Examples

Aggregate function A function name (AVG, MAX, MIN, SUM, AVG(Price)


and COUNT) followed by an argument COUNT(*)
enclosed in parentheses. See 2.5.6.
Boolean existential Using EXISTS enables you to check for the EXISTS (SELECT * FROM
function existence of a row that meets a certain houses WHERE
condition. See 2.5.9. houses.location=
customers.desiredloc)
Built-in Function RDMS has extensive built-in functions. See upper (:cname)
Section 3.
CAST function The keyword CAST followed by an CAST(:var AS DATE)
argument and the target data type
specification enclosed in parentheses.
See 3.8.2.
Column specification The specification of a column in a table. X.Location
See 2.2.3. Hno
Datetime function The function names CURRENT_DATE, CURRENT_TIME
CURRENT_TIME, and
CURRENT_TIMESTAMP. See 2.5.7.
Datetime literal A datetime expression enclosed in DATE '1998-12-31'
apostrophes following the keyword DATE, TIME '10:47:53'
TIME, or TIMESTAMP. See 2.3.4
Dynamic ESQL A question mark ( ? ). See 2.11.6. ?
parameter marker
Embedded variable A colon ( : ) immediately followed by the :custname
name of a variable declared in a COBOL
program. See 2.10.1.
EXTRACT function The keyword EXTRACT followed by an EXTRACT (SECOND FROM
argument and the source field specification time_column)
enclosed in parentheses. See 3.8.17.
Interval literal An interval expression enclosed in INTERVAL -'12:00' HOUR
apostrophes with an optional unary sign TO MINUTE
following the keyword INTERVAL, followed
by an interval qualifier. See 2.3.5.

7830 8160–027 2–39


Expression Operands and Comparison Operators

Table 2–6. Operands

Operand Description Examples

NULL An RDMS keyword used to indicate the NULL


absence of a value. See 2.3.3. For
information on the IS NULL operator,
see 2.5.1.
Numeric literal A string of up to 21 digits, which can have a 578.4
decimal point and a leading sign (+ or -) and 0.9e+12
can optionally be followed by a suffix in 5.0338e2
the form e[+]integer or e-integer, where -123.3e5
integer can be from 1 to 3 digits. See 2.3.2. 3e-5
Placeholder variable A variable that has the form $Pn, where n $P4
is an unsigned integer. See 2.10.3.
RDMSAUXINFO Contains the auxiliary status information. RDMSAUXINFO
Only available in routines and triggers.
See 4.9.1.
Routine parameter The specification of a parameter name for par1
a routine. See Section 3.
SQL variable The specification of a variable name in a max_price
routine or trigger. See 4.12.4.
SQLSTATE Contains the SQLSTATE information. Only SQLSTATE
available in routines and triggers. See 4.9.2.
String literal A string of characters enclosed in single 'employee' 's'
quotation marks. Two single quotation
marks in a row represent an apostrophe
that is part of the string. See 2.3.1.
Subquery A query specification with a limited select (SELECT * FROM houses)
list enclosed in parentheses. See 2.7.4.
USER function When used in expressions, USER is USER
equivalent to a string literal containing the
user ID of the current run. See 2.5.8.

2–40 7830 8160–027


Expression Operands and Comparison Operators

2.5.1. Null Value and IS NULL Operator


If a data item does not yet have a value assigned to it, RDMS considers the value to be
NULL (see 2.3.3).

If you add, subtract, multiply, or divide by a null, the result is null. If you compare a
non-null (like the number 6) with a null, the result is UNKNOWN. It is neither TRUE nor
FALSE. Nulls are treated differently by GROUP BY clauses (see 2.7), functions
(see 2.4.9), and ORDER BY clauses (see 7.4.3).

For example, if a data item of column A has the character value 'X' and a data item of
column B is null, the values of the following expressions are as follows:

5 + b (NULL)

A = 'X' (TRUE)

A < 'R' (FALSE)

A < 'f' (TRUE)

a = B (UNKNOWN)

'xyz' > B (UNKNOWN)

For more information on how RDMS processes expressions that contain character
values, see 2.9.1.

To determine whether a data item is or is not null, you can use the IS NULL and
IS NOT NULL comparison operators.

You can determine the value in column X as follows.

If column X is ... Then X IS NULL is ... And X IS NOT NULL is ...

NULL TRUE FALSE


NOT NULL FALSE TRUE

7830 8160–027 2–41


Expression Operands and Comparison Operators

2.5.2. DEFAULT value


The keyword DEFAULT causes RDMS to use the default value for a column on an
INSERT or UPDATE statement. For example, suppose a column is defined as

mycol CHAR(20) DEFAULT ‘abcd’

Using DEFAULT on an INSERT statement causes RDMS to write ‘abcd’ to the column:

INSERT INTO mytable (mycol) VALUE (DEFAULT)

Alternatively, omitting the column name mycol from the insert column list also causes
RDMS to write the default value ‘abcd’ to the column.

If an existing column in a table has a value, including the value NULL, you can change it
to the default value using the DEFAULT keyword. For example,

UPDATE mytable SET mycol = DEFAULT

2.5.3. BETWEEN Operator


The BETWEEN operator, shorthand notation for a commonly used form of Boolean
expression, tests whether a value lies within a specified range.

The following two expressions, for example, are the same:

p BETWEEN q AND r

(p >= q AND p <= r)

2–42 7830 8160–027


Expression Operands and Comparison Operators

2.5.4. LIKE and NOT LIKE Operators


The LIKE and NOT LIKE operators allow you to specify a pattern–matching operation
on CHARACTER or NCHARACTER data in a Boolean expression. The test is whether a
character string matches a specified pattern, which can include wildcards. The pattern
search condition is evaluated as TRUE if the column value is matched by the
designated string pattern.

Format
character-expression [ NOT ] LIKE pattern-expression [ ESCAPE { string-constant-2 |
variable-specification-2 } ]

where:

character-expression
is a CHARACTER or NCHARACTER valued expression. This is typically
a CHARACTER or an NCHARACTER column but may also be a
character-valued scalar BIF (see section 3). The left operand is a column or a BIF,
not a name. The concatenation operator (||) is not allowed.

NOT
makes the result TRUE for each row in which the column specification does not
match the pattern.

pattern-expression
string-constant-1 | variable-specification-1 | pattern-scalar-BIF

string–constant–1
is a pattern enclosed in apostrophes.

variable–specification–1
is a data variable (see 2.10) that contains a pattern.

pattern-scalar-BIF
is a scalar built-in-function (see section 3) which returns a CHARACTER
or an NCHARACTER result. The argument or arguments of a pattern-scalar-BIF are
expressions whose operands are either literals or pattern-scalar-BIFs.
Consequently, you may not have a column-name as (part of) a pattern-scalar-BIF
argument.

ESCAPE
defines the escape character to use, and includes the wild card characters
themselves in search patterns.

string–constant–2
is a single character or NCHARACTER enclosed in apostrophes.

variable–specification–2
is a data variable (see 2.10) that contains a single character or NCHARACTER.

7830 8160–027 2–43


Expression Operands and Comparison Operators

Consider the following items when using LIKE:

• LIKE operands are strings.


• If a null for a column is encountered, the expression is evaluated as UNKNOWN.
• If the column–specification data type is CHARACTER, RDMS treats a pattern and
an escape character as character strings. If the data type is NCHARACTER, RDMS
treats a pattern and an escape character as NCHARACTER strings.
• If the column–specification data type is CHARACTER and includes a COLLATE
clause, RDMS returns an error.
• If the column-specification data type is BLOB, RDMS returns an error.
• Comparisons are case–sensitive.

The LIKE operator allows the specification of a pattern–matching operation on


CHARACTER or NCHARACTER data. “Character,” therefore, can mean either
CHARACTER or NCHARACTER data in the following description.

The percent sign (%) and underscore character ( _ ) have special meaning in the
pattern string for the LIKE operator. The % is used to match any number of characters.
The _ is used to match exactly one character. The % and _ characters are often
referred to as “wildcard” characters.

Consecutive percent signs (for example, %%, %%%) are equivalent to a single %
wildcard character. All redundant % wildcard characters are ignored.

Example
DECLARE c1 CURSOR SELECT veg FROM seed1 WHERE veg like 'br%%%li';

is evaluated as

DECLARE c1 CURSOR SELECT veg FROM seed1 WHERE veg like 'br%li';

broccoli

The percent sign is also a special character in IPF and must be preceded by an IPF
escape character in the IPF SQL Interface. For more information, see the RDMS and
IPF SQL Interface End Use Guide.

The processing of LIKE depends on the setting of the application configuration


parameter RDMS–SQL92–STANDARD–LIKE.

Setting Result

FALSE (default) Traditional: Ignore trailing blanks in column values and pattern
strings.
TRUE Standard: Use trailing blanks in column values and pattern strings in
match; pad column values with spaces to their full defined length
(that is, apply SQL 92 standard rules).

2–44 7830 8160–027


Expression Operands and Comparison Operators

Assuming that column C1 is defined as CHARACTER(4) and contains the 3–character


value ABC, the result is as follows. Examples using the equality operator ( = ) are
included for comparison. The symbol ∆ stands for a significant blank.

Example Traditional LIKE Standard LIKE

C1 LIKE TRUE TRUE


'ABC∆'
C1 LIKE FALSE TRUE
'ABC_'
C1 LIKE TRUE TRUE
'ABC%'
C1 LIKE 'A%' TRUE TRUE
C1 LIKE 'A%∆' TRUE TRUE
C1 LIKE TRUE FALSE
'A%∆∆'
C1 LIKE 'ABC' TRUE FALSE
C1 LIKE '%C' TRUE FALSE
C1 LIKE FALSE TRUE
'ABC%_'
C1='ABC' TRUE TRUE
C1='ABC∆' TRUE TRUE
C1='ABC∆∆' TRUE TRUE

Examples
The following example evaluates to TRUE if the string “3 Bed” appears anywhere in
column DESCRIPTION.

description LIKE '%3 Bed%'

The next example evaluates to TRUE if column CNAME begins with the letter J as in
“Jones” and “Johnson.”

cname LIKE 'J%'

The next example evaluates to TRUE if column CNAME begins with the letter “J” and
is exactly five characters long. “Jones” qualifies, but “Johnson” and “jones” do not.

cname LIKE 'J_ _ _ _'

The next example evaluates to TRUE if the value in column LOCATION is at least four
characters long and the fourth character from the right is b as in “Woodbury.”

location LIKE '%b_ _ _'

7830 8160–027 2–45


Expression Operands and Comparison Operators

The next example evaluates to TRUE if the string “mall” does not appear anywhere in
column DESCRIPTION. Rows with the word “Small” or “small” in column
DESCRIPTION are not selected.

description NOT LIKE '%mall%'

The next example illustrates a DECLARE CURSOR statement using LIKE with logical
operators from a UCS COBOL program using ESQL:

MOVE '%polis' TO city-name.


EXEC SQL
DECLARE c CURSOR
SELECT * FROM houses
WHERE description LIKE '%house%'
AND location LIKE :city-name
END-EXEC.
EXEC SQL OPEN c END-EXEC.

This sequence of statements declares a cursor that selects all rows from table
HOUSES with the word “house” anywhere in the description (thus eliminating
duplexes and condominiums) which are also located in a city ending with “polis” (such
as Minneapolis or Annapolis).

If % or _ is part of the data you are trying to find, use an escape character to indicate
that the following special character is not to be used as a wild card, but as a character
to be matched with itself.

Whenever the escape character appears in the pattern string, RDMS substitutes the
escape character and the character immediately following it with a literal
representation of the second character. For example, if the escape character is #,
RDMS treats the pattern string “RATE IS %#%” as “RATE IS %%” with the second %
representing a literal percent sign. In order for a column value to match this pattern
string, it must start with “RATE IS” and end with %. The escape character cannot
appear as the last character of the pattern string.

Example: LIKE pattern with Scalar BIF and Concatenation


The next example can be used to find rows in which the NAME column begins with
the first three characters of the string 'Jomandius':

cname LIKE CONCAT(LEFT('Jomandius', 2), '%')

Example: LIKE Operator with Escape Character


The following example uses the LIKE operator with an escape character—in this case,
the # character:

description LIKE '%9#% assumable%' ESCAPE '#'

This evaluates to TRUE if the string “9% assumable” appears anywhere in column
DESCRIPTION.

2–46 7830 8160–027


Expression Operands and Comparison Operators

2.5.5. IN Operator
The IN operator tests for membership in a set by allowing you to specify a set
operation in a Boolean expression.

Format 1
value-expression [ NOT ] IN { (set-value-list) │ subquery }

The operand is a single value expression for the following conditions:

• If the value expression is equal to at least one value in the set value list or
subquery, the result is TRUE.
• If the value expression is not equal to any value in the set value list or subquery,
the result is FALSE.
• If the subquery is empty, the result is FALSE.
• If none of these conditions apply, the result is UNKNOWN.

Format 2
(value-expression [, value-expression]...) [ NOT ] IN subquery

where:

value–expression
is a numeric, character, or datetime value.
NOT
A NOT IN B is equivalent to NOT(A IN B).
set–value–list
is a list of any combination of string literals, numeric constants, datetime literals,
CAST functions, variable specifications, the keyword USER, or the datetime
functions CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP, as long
as the list is composed of operands of compatible t`ypes.

Note: For compatibility, RDMS allows NULL in the set value list; however, the
use of null here is nonstandard and meaningless. IN(NULL) does not select
records because it is equivalent to =NULL, which is always FALSE.

subquery
is as described in 2.7.4.

7830 8160–027 2–47


Expression Operands and Comparison Operators

The operand is a list of value expressions for the following conditions:

• If the row defined by the list of value expressions is equal to a row returned from
the subquery, the result is TRUE.
• If the row defined by the list of value expressions is not equal to any row returned
from the subquery, the result is FALSE.
• If the row defined by the list of value expressions or subquery is empty, the result
is FALSE.
• If none of these conditions apply, the result is UNKNOWN.

Examples
The following example has an IN operator with a set value list:

location IN ('woodbury', 'westchester', 'turtle creek')

The next example has an IN operator with a subquery, where the Boolean expression
evaluates to TRUE for every customer where no available house exists in the
customer's desired location:

desiredloc NOT IN (SELECT location FROM houses)

The following example uses a table that has a four-column primary key. The IN clause
selects the records returned by the subquery.

(c_transaction_date, c_account_number, c_transaction_code, c_transaction_time) IN


(SELECT c_transaction_date, c_account_number, c_transaction_code,
c_transaction_time FROM mybank.today WHERE c_check_amount > 10000)

The following two examples are equivalent:

x NOT IN subquery

NOT x IN subquery

2.5.6. Aggregate Functions (AVG, SUM, MIN, MAX, COUNT)


Aggregate functions describe data as a whole rather than as a set of rows.

Format
{ AVG │ MAX │ MIN │ SUM }

{ ( [ ALL ] { column-specification │ arithmetic-expression } ) │

( DISTINCT column-specification) }|

COUNT { ( * ) │ ( [ DISTINCT ] column-specification) }

2–48 7830 8160–027


Expression Operands and Comparison Operators

You cannot nest aggregate functions. The size and scale of the result of aggregate
functions generally depends on the argument type of the function, as follows.

Function Argument Type Result Type

AVG SMALLINT DECIMAL(22,15)


INTEGER DECIMAL(22,10)
REAL REAL
FLOAT REAL or DOUBLE PRECISION**
DOUBLE PRECISION DOUBLE PRECISION
DECIMAL(n,s)* DECIMAL(22,22-n+s) [unowned
schema]
DECIMAL(21,21-n+s) [owned
schema]
NUMERIC(p,s) NUMERIC(21,MAX(s,10-p+s))
MAX Other than FLOAT Same as argument
FLOAT REAL or DOUBLE PRECISION**
MIN Other than FLOAT Same as argument
FLOAT REAL or DOUBLE PRECISION**
SUM SMALLINT DECIMAL(22,0)
INTEGER DECIMAL(22,0)
REAL DOUBLE PRECISION
SUM FLOAT DOUBLE PRECISION
DOUBLE PRECISION DOUBLE PRECISION
DECIMAL(n,s)* DECIMAL(22,s) [unowned
schema]
DECIMAL(21,s) [owned schema]
NUMERIC(p,s) NUMERIC(21,s)
COUNT Any INTEGER
* For DECIMAL columns defined in an owned schema, the number of decimal digits is
one greater than the number of decimal digits in the original definition. This is because
of the difference in the semantics of this value between the SQL standard and RDMS.
** REAL if argument precision is 27 bits or less; DOUBLE PRECISION if otherwise.

7830 8160–027 2–49


Expression Operands and Comparison Operators

Follow these guidelines when using aggregate functions:

• Aggregate functions are allowed only in a select list, a HAVING clause, or in a


WHERE clause of a subquery (see 2.7.4) only if the column specification in the
function specification is an outer reference (that is, if it is in the WHERE clause of a
subquery and if the subquery is contained entirely within the scope of an outer
query's HAVING clause).
• The result of AVG, SUM, and COUNT is a numeric value.
• When you use AVG and SUM and do not specify either DISTINCT or ALL, ALL is
assumed.
• If SUM or AVG is specified, column–specification cannot be of data type character
or datetime.
• AVG is the arithmetic average (mean).
• The arithmetic expression must include a column specification; however, you
cannot pass a column specification in a variable.
• The arithmetic expression cannot include a function.
• COUNT(*) returns the number of rows selected, including nulls.
• COUNT (DISTINCT column specification) returns the number of distinct values in a
specified column, not including nulls.
• DISTINCT and ALL are permitted for the MAX and MIN functions, but they have no
effect on the result of those functions.
• Nulls are ignored in the evaluation of AVG, MAX, MIN, and SUM. If all arguments
to one of these functions are null, the result is also null. The result of any of these
functions taken over an empty set is null.
• In some cases when RDMS statistics are used, for the AVG and SUM functions,
the resultant size is reduced when the result type is decimal or numeric (for
optimization purposes).
• If the data type of column–specification is CHARACTER and includes a COLLATE
clause, RDMS returns a value based on the specified collation rules. If no COLLATE
clause is present on the column definition, RDMS uses the ordering based on the
binary code for the character.
• If the column-specification data type is BLOB, RDMS returns an error.

Examples
The following example finds the average price of all houses in table HOUSES,
regardless of location, counts all houses available, and determines the number of
cities in which the houses are located:

SELECT AVG(price), COUNT(*), COUNT(DISTINCT location)


FROM houses

The result is

91000 5 4

2–50 7830 8160–027


Expression Operands and Comparison Operators

If you place the SELECT clause in a DECLARE CURSOR statement and follow it with
two FETCH NEXT statements, you get the preceding result on the first FETCH
statement and an end of cursor status on the second FETCH statement.

Since arithmetic expressions are allowed with AVG, MAX, MIN, and SUM, you can also
calculate the total of sales commissions of selected houses, as in the following
example:

SELECT SUM(price * 0.06)


FROM houses
WHERE location = 'woodbury'

The result is the gross commission that would be earned if all houses listed in
Woodbury were sold by agents of the company.

The next example finds the lowest and highest prices of all houses listed, and also
finds the midpoint of the price range of the houses listed:

SELECT MIN(price), MAX(price), (MAX(price) + MIN(price))/2


FROM houses

2.5.7. Datetime Functions


The datetime functions include CURRENT_DATE, CURRENT_TIME, and
CURRENT_TIMESTAMP. Datetime functions are allowed wherever an expression is
allowed, except in a check constraint clause. SYSDATE returns the value of
CURRENT_DATE. You may use SYSDATE as an alternate for CURRENT_DATE. You may
use SYSTIMESTAMP as an alternate for CURRENT_TIMESTAMP(6).

Format
CURRENT_DATE

SYSDATE

CURRENT_TIME [ (time-precision) ]

CURRENT_TIMESTAMP [ (timestamp-precision) ]

SYSTIMESTAMP

7830 8160–027 2–51


Expression Operands and Comparison Operators

where:

time–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the column after the decimal point. If omitted, 0 is assumed.

time–precision affects the returned value as follows.

time–precision Resulting Value

Not specified RDMS returns no precision digits.


Between 0 and 6 RDMS returns the specified number of precision digits.

timestamp–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the column after the decimal point. If timestamp-precision is omitted, 6 is
assumed.

timestamp–precision affects the returned value as follows.

timestamp–precision Resulting Value

Not specified RDMS returns 6 digits of precision.


Between 0 and 6 RDMS returns the specified number of precision digits.

2–52 7830 8160–027


Expression Operands and Comparison Operators

The following table summarizes the format of the values returned for datetime
functions.

Function Return Value Format

CURRENT_DATE ccyy–mm–dd
Example:
2006-03-05

SYSDATE ccyy-mm-dd
Example :
2006-03-05

CURRENT_TIME hh:mm:ss
Examples:
09:23:12

12:22:31.322983

CURRENT_TIMESTAMP ccyy-mm-dd hh:mm:ss


Examples:
2006-03-08 14:24:53

2006-12-31 23:59:59.999999

SYSTIMESTAMP ccyy-mm-dd hh:mm:ssssss


Example:
2006-12-31 23:59:59.999999

The interactions described below for columns also apply to the assignment of a value
in a routine or trigger using the FETCH, RETURN, SET, and SELECT statements.

If you are using CURRENT_TIME/SYSTIMESTAMP as a column value for an INSERT or


UPDATE statement, the interaction between time–precision on
CURRENT_TIME/SYSTIMESTAMP and time–precision on the column declaration is as
follows.

time–precision Resulting Column Value

Not specified RDMS zero–fills the seconds portion of the value up to


the precision specified in the column declaration.
time–precision less than RDMS returns the specified digits of precision on the
column's time–precision CURRENT_TIME request and zero–fills the column value
up to the precision specified in the column declaration.
time–precision greater RDMS truncates the specified digits of precision on the
than column's CURRENT_TIME request to the precision of the column
time-precision declaration.

7830 8160–027 2–53


Expression Operands and Comparison Operators

If you are using CURRENT_TIMESTAMP as a column value for an INSERT or UPDATE


statement, the interaction between timestamp–precision on CURRENT_TIMESTAMP
and timestamp–precision on the column declaration is as follows.

timestamp–precision Resulting Column Value

Not specified RDMS returns 6 digits of precision. If the column


is declared with fewer than 6 precision digits,
RDMS truncates the timestamp value.
timestamp–precision less than RDMS returns the specified digits of precision on
column's timestamp–precision the CURRENT_TIMESTAMP request and zero–fills
the column value up to the precision specified in
the column declaration.
timestamp–precision greater RDMS truncates the specified digits of precision
than column's on the CURRENT_TIMESTAMP request to the
timestamp-precision precision of the column declaration.

You can determine the size and scale of function call results from the following table.

Function Argument Type Result Type

CURRENT_DATE n/a CHARACTER(10)


SYSDATE CHARACTER(10)
CURRENT_TIME n/a CHARACTER(8–15)*
CURRENT_TIMESTAMP n/a CHARACTER(19–26)*
SYSTIMESTAMP CHARACTER(19–26)*
* The size depends on the number of fractional digits of the associated column. In a
select list, where there is no associated column, CURRENT_TIME has no fractional digits
and CURRENT_TIMESTAMP and SYSTIMESTAMP each have 6 fractional digits.

Examples
For this example, assume the following table definition:

CREATE TABLE s1.mortgages


(cno CHARACTER(4) NOT NULL PRIMARY KEY,
cname CHARACTER(28),
mort_amt DECIMAL(14,2),
orig_date DATE,
appr_time TIMESTAMP,
IN s1.a1)

The following query displays the origination date for all mortgages in the table whose
value is not equal to the date on which the query is executed:

SELECT orig_date FROM s1.mortgages


WHERE orig_date <> CURRENT_DATE

2–54 7830 8160–027


Expression Operands and Comparison Operators

Here are more stand-alone examples:

INSERT INTO t1 VALUES(123, CURRENT_DATE);

SELECT CURRENT_TIMESTAMP(4), hno, price FROM houses;

INSERT INTO t1 VALUES ($p1, CURRENT_TIME(2) );

INSERT INTO t1 VALUES (:name, SYSDATE)

2.5.8. USER Function


You use the USER keyword to represent the system identifier of the person executing
the program or TIP transaction. This identifier is either the batch, demand, MAPPER
system, or TIP user ID.

Format
USER

The size and scale of the function call result is as follows.

Function Argument Type Result Type

USER n/a CHARACTER(12)

You can use this keyword wherever a string literal or user ID is permitted, with one
exception: You cannot use USER in place of the user ID in a GRANT or REVOKE
statement. Its value is a 12-character, blank-filled, left-justified ASCII string. You can,
for example, use the USER keyword with the OWNER IS clause of the CREATE TABLE
statement.

You may also want to store the current user’s user ID in one column of a table so that
you can track people who made updates to each row; or you may want to provide
row level security on views.

Example
You can override the owner user ID of a table by making the user ID in a view USER to
allow users to see only data that pertains to them, as in the following example:

CREATE VIEW v1
AS SELECT * FROM employees
WHERE emp_userid=USER
WITH CHECK OPTION

7830 8160–027 2–55


Expression Operands and Comparison Operators

2.5.9. Boolean Existential Function (EXISTS)


You can check for the existence of a row that satisfies a condition by invoking the
Boolean existential function EXISTS, which uses as its input parameter any valid
subquery (see 2.7.4) and returns one of the two Boolean truth values, TRUE or FALSE.
The EXISTS functions always returns TRUE if the subquery returns at least one row. It
is TRUE if the subquery returns one or more rows; it is FALSE if the subquery returns
no rows.

Format
[ NOT ] EXISTS subquery

Example
The following example selects all customers whose maximum price equals or
exceeds $100,000 and for which a house is available in the customer's desired
location:

SELECT * FROM customers


WHERE maxprice >= 100000 AND
EXISTS (SELECT * FROM houses WHERE
houses.location=customers.desiredloc)

2–56 7830 8160–027


Sequences

2.6. Sequences
Primary key values can be input to the application, for example a social security
number, or can be generated by the application. If the value is generated it is often
generated as a sequence, either as a sequence of monotonically increasing values (for
example, the BIF unique_id()) , or as a sequence of non-repeating random values (for
example, the BIF permuted_id()). These sequence implementations have
disadvantages. It is not guaranteed when sequentially fetching records from the table,
and having just fetched record n, that all records smaller than n have been inserted.
This is often referred to as the concept of "order". Also, with monotonically increasing
sequences, records are inserted at the end of the table and the inserts are therefore
prone to queuing and deadlock.

RDMS implements several additional ways to generate sequences, referred to


generally as generated defaults. A generated default is part of the column definition,
and is an extension to the default clause. It directs RDMS to (optionally) evaluate the
default value and include that value within the record, as done for the default clause.

The following can be used as generated defaults: IDENTITY, partition_id(),


current_date, current_time, current_timestamp, getdate(), getutcdate(), and now().
Their comparative characteristics are shown in the following table.

Condition Identity Partition_id() current_date/current_time/


current_timestamp/getdate()/
getutcdate()/now()

Generated User specified The value is Reads the clock to determine


value start value, generated in the these values.
increment, and partition to the right
max value. Can of the last value
specify cycle. generated (by any
thread). When the
right-most partition is
reached, the value is
generated in partition
1. Reads partition and
generates the next
largest value.
Increment is always 1.
Ordered Yes No Yes
inserts
Dynamic Yes Yes Yes
preconditioni
ng allowed
Restriction Must be on the Must be on the Must be on the leading column
on position column which is column which is the of the primary key or index.
of column the single column single column primary
within index primary key. key.
Restriction Ascending only Ascending only Ascending only
on sort
direction

7830 8160–027 2–57


Sequences

Condition Identity Partition_id() current_date/current_time/


current_timestamp/getdate()/
getutcdate()/now()

Partitioned Table may not be Table must be Either partitioned or


table partitioned partitioned non-partitioned is fine
NULL values Requires NOT Requires NOT NULL. Requires NOT NULL. NOT
NULL. NOT NULL NOT NULL is implicit NULL is implicit when the
is implicit when when the column is column is specified in a
the column is specified in a GENERATED clause on
specified in a GENERATED clause CREATE TABLE.
GENERATED on CREATE TABLE.
clause on CREATE
TABLE.

Refer to "6.2 CREATE TABLE" for more information on syntax and usage examples of
generated defaults.

See the Relational Database Server for ClearPath OS 2200 Administration Guide for
more information on deciding the appropriate sequence method.

Dynamic preconditioning, in conjunction with 1-record per data page, reduces the
possibility of queuing and deadlock when generated defaults are used. Dynamic
preconditioning is done internally by RDMS as records are inserted into tables
containing a generated default (such as an identity column.) RDMS predicts the key
value of future inserts and creates (and internally commits) empty data pages on the
right-hand side of the B-tree to contain these records. This eliminates the need for
subsequent inserts to perform page splits, and therefore increases concurrency. See
the Relational Database Server for ClearPath OS 2200 Administration Guide for more
information.

2–58 7830 8160–027


Query Specification

2.7. Query Specification


This subsection includes the following topics:

• SELECT statement processing


• Views and aggregate operations
• Query execution
• Subqueries

Examples: Query Specification


The following example illustrates how RDMS resolves ambiguous column
specifications.

Consider the following tables:

• Table R1 with columns A, B, and C


• Table R2 with columns B, D, E, and F

The results of the following two query specifications are the same:

SELECT a, d, b, c
FROM r1, r2
WHERE b = r2.b

SELECT r1.a, r2.d, r1.b, r1.c


FROM r1, r2
WHERE r1.b = r2.b

The next example lists pairs of identically priced houses. It specifies X and Y as
correlation names for the single table HOUSES.

SELECT x.hno,y.hno
FROM houses x,houses y
WHERE x.price = y.price
AND NOT (x.hno = y.hno)

The second part of the Boolean expression, namely NOT (X.HNO = Y.HNO), ensures
that no house is paired with itself.

To get a list of the average price of houses in each town (LOCATION) where houses
are listed, you can use the following query specification:

SELECT location, AVG(price)


FROM houses
GROUP BY location

7830 8160–027 2–59


Query Specification

The following table illustrates the data selected from table HOUSES.

LOCATION AVG(Price)

Woodbury 85000
Westchester 90000
Parkway Heights 85000
Turtle Creek 110000

Note that the database has one row for each location except Woodbury.

To find the locations where the average price of a house is higher than $100,000, use
the following query specification:

SELECT location, AVG(price)


FROM houses
GROUP BY location
HAVING AVG(price) > 100000

This example selects one row when applied to table HOUSES:

Turtle Creek 110000

The following example shows a query that takes sales record rows for one
salesperson, groups them by price into groups of thousands of dollars, discards
groups that have fewer than eight sales (excluding the five thousand dollar group) and
returns the groups’ “rounded off” dollar amount and number of sales.

SELECT 1000 * TRUNC(price,-3), COUNT(*) FROM sales


WHERE salesperson = ‘Pat’
GROUP BY TRUNC(price, -3)
HAVING COUNT(*) >= 8 OR TRUNC(price, -3) = 5;

2.7.1. SELECT Statement Processing


The query specification is the part of the DECLARE CURSOR, CREATE VIEW, SELECT
Multirow, and UNLOAD statements that specifies

• The columns you want to retrieve.


• The table or tables from which the data is to be retrieved.
• The conditions the data must meet to be retrieved.

You can also use the query specification to specify how to group the data and
whether duplicate sets of data should be returned.

2–60 7830 8160–027


Query Specification

Syntax
query-specification
(with-clause)
SELECT [ ALL | DISTINCT ] {select-list | * }

FROM table-reference-list

[ WHERE Boolean-expression ]

[ GROUP BY group-by-item [, group-by-item]…]

[HAVING Boolean-expression ]

where:
with-clause
Defines one or more common table expressions. For restrictions and usage, see
2.7.5.

WITH cte

cte
query-name [ ( column-name [, column-name])] AS ( query-
expression-order-fetch )

ALL
directs RDMS to select all rows identified by the FROM, WHERE, GROUP BY, and
HAVING clauses. If neither ALL nor DISTINCT is used, ALL is assumed.

DISTINCT
directs RDMS to select only distinct rows. Nulls are considered equal for the
purpose of determining distinct rows.
If a column identified in select–list is defined with a COLLATE clause (see 2.9.3),
RDMS uses the rules in the named collation to determine whether values are
equal or not equal.

In some collations, for example, the following two values are considered equal:

Cæsar
Caesar

* (asterisk)
directs RDMS to select all columns of the tables listed in the FROM clause.

select–list
is a list of items in the form

{ select-expression [ [ AS ] title-name ] │ table-specification.* }

7830 8160–027 2–61


Query Specification

where:

select–expression
is a numeric, character, or datetime value expression, or column specification.

AS
is the keyword for the title name clause that refers to an item in select-list.
You can use this name to generate reports and descriptions, to simplify sort
descriptions in the ORDER BY clause, and to specify the group item in the
GROUP BY clause.

title–name
is any descriptive name you provide to replace a column name, to name a
column of a derived table, to identify a result of an arithmetic expression, to
identify a constant, or to identify the result of a function.

The name of the title appears in the description returned by the GET
DESCRIPTION statement, in the description section of the UNLOAD statement,
and in the column headings produced by the IPF SQL Interface for the SELECT
Multirow statement. For more information, see the RDMS and IPF SQL End
User Guide.

Separate each item in select-list with a comma.

table–specification.*
is a shorthand notation that specifies all columns of the table specified in the
order they were defined.

You may have up to 510 items in the SELECT clause whether specified explicitly by
select-expressions or implicitly by * or table-specification.* .

table–reference–list
consists of a list of table-references

table-reference [ , table-reference ] ...

The table reference list can include views.

You can include a maximum of 14 table references in the table reference list. Use
commas to separate entries in the table reference list.

where:
table-reference
identifies [or references] a table, view, joined table, query name, or derived
table.

table-primary | joined-table

table-primary
identifies [or references] a table, view, joined table, query name, or derived
table.

2–62 7830 8160–027


Query Specification

table-specification [[AS] correlation-name ]


| query-name [[AS] correlation-name ]
| derived-table [(derived-column-list)]
| ( joined-table )

table-specification
is as defined in 2.2.2.

You can have a column specification in select-list that identifies a column


in more than one table in the table reference list. This can occur if you use
the same name for one or more columns in more than one table when you
create them. It can also happen if you specify more than one version of
the same table. When you have an ambiguous column specification, RDMS
resolves it with the first table in the list that has a matching column name.
You can eliminate ambiguous column names by fully qualifying each
column specification.

query-name
is the name of a common table expression defined using a WITH clause.
See 2.7.5.

derived-column-list
is a list of column names. The number of column names must be the same
as the number of columns in the table or derived table. The derived
column name overrides the name of the column within the table or derived
table such that only the derived column name may be used to reference
the column.

derived-table
( query-expression-order-fetch )
A derived table is a conceptual table defined by a query.
The derived table query cannot reference tables listed in the FROM clause
in which it appears. It can reference tables in the FROM clauses of outer
nesting levels.
A derived table must have a correlation–name.
A cursor containing a derived table is nonscrollable.

correlation–name
is an alias for a table within the query specification. The most common use
for correlation names is to easily identify each instance of a table that is
joined to it.

joined-table
table-primary join-type JOIN table-primary join-condition

7830 8160–027 2–63


Query Specification

The following restriction applies:

Within a joined-table syntax, the first table name’s correlation-name


may not be NATURAL, FULL, CROSS, UNION, or JOIN. Note that these
keywords are acceptable as correlation-name if they are outside a
joined-table syntax, or if they are used as the correlation-name of the
second (right-hand side) table name of a joined-table.

join-type

{LEFT | RIGHT} [OUTER] | INNER

join-condition

ON Boolean-expression

restricts the rows selected for the join. The Boolean expression for
an outer join may not contain predicates with a subquery. All columns
referenced in the Boolean-expression must be columns of the
table-primaries referenced in the joined-table clause.

WHERE Boolean–expression

restricts the rows selected. Boolean expressions are defined in 2.4.2. The Boolean
expression specifies the criteria that a row must meet for inclusion. Indicator
variables (see 2.10.4) are not allowed in the WHERE clause.

GROUP BY group-by-item [ , group-by-item ] …

where group-by-item is

{ column-specification | scalar-bif-reference | correlation-name }


A column-specification identifies a column referenced (if only implicitly, as in
SELECT*) in the query’s select-list.

A scalar-bif-reference is a reference to a scalar built-in function. A column which is


referenced in a scalar-bif-reference in the GROUP BY clause may appear in the
select-list only in an identical scalar-bif-reference. For example, if your GROUP BY
clause is:
GROUP BY ABS(a + 2)

then you can have a SELECT clause like:


SELECT ABS(a + 2) or SELECT ABS(a + 2) - 4

but you cannot have a SELECT clause like:


SELECT a or SELECT ABS(a) or SELECT ABS(a+3)

Similarly, a column referenced in a GROUP BY scalar-bif-reference can appear in a


HAVING Boolean-expression only in an identical scalar-bif-reference.
A correlation-name in a GROUP BY clause must match a correlation-name in the
query’s FROM clause. The GROUP BY correlation-name represents the table
associated with the matching FROM clause correlation-name.

2–64 7830 8160–027


Query Specification

The GROUP BY clause describes how to separate rows into distinct groups. All
rows in which the set of values in the group-by-item list are equal form one group.
The GROUP BY clause instructs RDMS to construct one row for each group. Each
such row contains summary information about the group.
This clause is typically used to select a single row for each group. The select list
can contain any combination of group-by-items, literals, or aggregate functions.

If a group-by-item is a column which is defined with a COLLATE clause (see 2.9.3),


RDMS uses the rules in the named collation to determine how to group the data.

Nulls are considered equal when forming a group.

HAVING Boolean–expression

imposes search conditions on groups formed by the GROUP BY clause.

One grouped table row is formed for each group that satisfies the HAVING clause.
The Boolean expression in the HAVING clause can refer to any literal value,
aggregate function, group-by-item found in the GROUP BY clause, or if the
HAVING clause appears within a subquery, it can be an outer reference. See the
explanation of GROUP BY in this section for the restriction on HAVING if a
scalar-bif-reference is used in the GROUP BY clause.

For more information about built-in functions, see 2.4.10; for more information
about subqueries and outer references, see 2.7.4.

If you have a HAVING clause but no GROUP BY clause, all rows derived from the
FROM and WHERE clauses comprise a single group, and the resulting grouped
table consists of zero or one row.

Order of Rows
A query specification defines a set of rows but does not impose an order to those
rows. The rows retrieved from the sets of two very similar query specifications can
come out in very different orders. Unless you use the ORDER BY clause (in
statements where it is permitted), you should assume that the order of retrieval of
rows is arbitrary.

DISTINCT Keyword
The SQL 92 entry level syntax allows the use of the DISTINCT keyword only once in a
query specification. RDMS provides two extensions to this restriction:
• Duplicate DISTINCT keywords are allowed in the arguments of the MAX and MIN
functions. DISTINCT is essentially ignored for these functions, anyway.
• A query specification can have, at most, one function with DISTINCT if the “global”
DISTINCT (namely, SELECT DISTINCT) is used.

7830 8160–027 2–65


Query Specification

If a column identified in select-list is defined with a COLLATE clause (see 2.9.3),


RDMS uses the rules in the named collation to determine whether values are equal or
not equal. In some collations, for example, the following two values are considered
equal:
Cæsar
Caesar

Derived Table Restrictions


A derived table can neither reference a view nor be part of a view. If a derived table is
part of a SQL statement, then that SQL statement may not reference any views.

The derived table query cannot reference tables listed in the FROM clause. It can
reference tables in FROM clauses of outer nesting levels. For example, the query

SELECT * FROM a, (SELECT * FROM b WHERE b.c1 = a.c1) d_table

is not allowed because table a and derived table d_table are in the same FROM clause.
Therefore, d_table may not reference table a as it does in the WHERE clause.

On the other hand, the reference to table a in the following query’s innermost WHERE
clause is acceptable because table a is not listed in the same FROM clause that
d_table is listed.

SELECT * FROM a
WHERE EXISTS(SELECT * FROM (SELECT * FROM b WHERE b.c1 = a.c1)d_table)

A derived table may not contain another derived table. A derived table may not contain
a UNION or be declared within a UNION.

You can use OUTER/INNER join operation within a derived table but you cannot use it
for joining a derived table with the other tables. For example, the query

SELECT * FROM a, (SELECT c1 FROM b LEFT OUTER JOIN c ON b.c1 = c.c1)


d_table

is allowed. The following query

SELECT * FROM a, (SELECT c1 FROM b WHERE b.c1 = ‘abc’) d_table INNER


JOIN c ON d_table.c1 = c.c1

is not allowed. A derived table can be inner joined with other tables by using a comma
instead of the INNER JOIN keywords.

2–66 7830 8160–027


Query Specification

2.7.2. Referencing Views


Except in the special cases described here, you cannot declare a cursor or create a
view that contains an aggregate operation and a subordinate view (that is, a view
specified in the FROM clause) that also contains an aggregate operation. Nor can you
specify a query or define a view that joins a view with an aggregate operation to
another table or view. The following are aggregate operations:

• DISTINCT keyword in the select list


• GROUP BY clause
• HAVING clause
• Built-in aggregate functions:
 AVG
 MAX
 MIN
 SUM
 COUNT
GROUP BY, HAVING, and built-in aggregate functions together are referred to as
“grouping operations.”

Those special cases where RDMS allows you to specify a query or define a view with
a subordinate view or views that contain aggregate operations are as follows:

• A query specification can contain either the DISTINCT keyword in the select list or
a WHERE clause, or both, even if the query specification’s FROM clause
references a view with grouping operations, with the following limitations:
 The view must be the only table name in the query specification’s FROM
clause.
 The query specification cannot contain any grouping operations.
If a query specification contains the DISTINCT keyword in the select list, RDMS
replaces view column references in the select list with the underlying table
columns, expressions, and functions, and applies the DISTINCT operation to
the modified select list.
If a query specification contains the WHERE clause, RDMS appends the
WHERE clause conditions to the HAVING clause of the referenced view.
• A query specification with the DISTINCT keyword in the select list can reference
one or more views with the DISTINCT keyword in the select list, with the
following limitations:
 None of the referenced views can contain any grouping operations if the
query specification's FROM clause references multiple table names.
 The query specification cannot contain any grouping operations.

7830 8160–027 2–67


Query Specification

In this case, RDMS replaces view column references in the select list with the
underlying table columns, expressions, and functions, and applies the DISTINCT
operation to the modified select list. The referenced view can also contain the
DISTINCT keyword in the select list, even though it is redundant and ignored by
RDMS.
• Even if a query specification does not contain the DISTINCT keyword in the select
list, it can join views that contain the DISTINCT keyword in the select list, with the
following limitations:
 Each table name in the query specification’s FROM clause must identify a
view.
 Each referenced view must contain the DISTINCT keyword in the select list.
 None of the referenced views can contain grouping operations if the query
specification's FROM clause references multiple views.
 The query specification cannot contain any grouping operations.
In this case, RDMS first removes duplicates after considering all items specified in
the select lists of the referenced views, and then returns the values of the items
specified in the select lists of the queries and views.

Notes:
• You cannot specify a query or define a view that joins a view with grouping
operations to another table or view.
• You cannot specify a query or define a view that contains a grouping operation
along with a subordinate view that contains aggregate operations as well.
• You cannot include a column whose data type is BLOB in the
column-specification-list or Boolean-expression in the WHERE, GROUP BY, and
HAVING clauses.

Examples: Views with Aggregate Operations


Assume the view AGGVIEW with the following aggregate operations:

CREATE VIEW aggview (location, max_price, min_price)


AS SELECT location, MAX(price), MIN(price)
FROM houses
GROUP BY location

The following cursor declaration, for example, is invalid because both the cursor and
view contain aggregate operations:

DECLARE agg_on_agg CURSOR


SELECT location, AVG(max_price)
FROM aggview
GROUP BY location

2–68 7830 8160–027


Query Specification

This view definition is also invalid because both views contain aggregate operations:

CREATE VIEW aggregate (location, median_price)


AS SELECT location, (max_price + min_price) / 2
FROM aggview
GROUP BY location
HAVING MAX(min_price) > 100000

The following cursor definition is valid: the WHERE clause condition


MAX_PRICE > 2000 is evaluated after the grouping operation is performed for view
AGGVIEW; the DISTINCT keyword in the select list takes effect using the two column
values, LOCATION and MAX_PRICE:

DECLARE distinct_on_agg CURSOR


SELECT DISTINCT location, max_price
FROM aggview
WHERE max_price > 2000

Now suppose the following view with the DISTINCT keyword in the select list:

CREATE VIEW distview (location)


AS SELECT DISTINCT location
FROM houses

The following cursor definition is valid. Note the redundant DISTINCT keyword in view
DISTVIEW's select list; it is ignored by RDMS.

DECLARE dist_on_dist CURSOR


SELECT DISTINCT location
FROM distview

Now suppose another view with the DISTINCT keyword in the select list:

CREATE VIEW dist_desloc (desiredloc)


AS SELECT DISTINCT desiredloc
FROM customers

The following cursor is invalid because view DISTVIEW contains the DISTINCT
keyword in the select list but table CUSTOMERS is not a view:

DECLARE distview_with_table CURSOR


SELECT distview.location
FROM distview, customers
WHERE distview.location = customers.desiredloc

7830 8160–027 2–69


Query Specification

On the other hand, the following cursor is valid since both DISTVIEW and
DIST_DESLOC are views that contain the DISTINCT keyword in the select list:

• RDMS removes duplicates and considers the two items, DISTVIEW.LOCATION and
DIST_DESLOC.DESIREDLOC.
• View column DIST_DESLOC.DESIREDLOC is not specified in the cursor's select list,
but it is considered when removing duplicates since it is in the definition of view
DIST_DESLOC.
DECLARE distview_with_dist_desloc CURSOR
SELECT distview.location
FROM distview, dist_location
WHERE distview.location = dist_desloc.desiredloc

The following two queries are semantically identical. You may find the INNER JOIN
query easier to understand.

SELECT *
FROM houses, customers
WHERE location = desiredloc AND maxprice > 100000

SELECT *
FROM houses INNER JOIN customers ON location = desiredloc
WHERE maxprice > 100000

If you want to join these results with loan packages available for various ranges of
prices, you can change the query to

SELECT *
FROM houses INNER JOIN customers ON location = desiredloc
LEFT OUTER JOIN loans
ON price BETWEEN minprin AND maxprin
WHERE maxprice > 100000

Note that price, a column in table Houses, may be referenced in the second ON clause
because it is part of the JOIN clause (the second one). This JOIN clause includes a
subordinate JOIN clause (the first one) that in turn includes table Houses. You will not
be able to reference table Loans in the first ON clause because Loans is not one of the
tables listed in that JOIN clause.

2–70 7830 8160–027


Query Specification

2.7.3. Execution
The query specification specifies

• The table or tables from which to retrieve rows


• Which rows to use from the specified table or tables
• What grouping, if any, to perform, and which grouped rows to include
• Which columns to use from the specified rows

Execution proceeds as follows:

1. The FROM clause specifies the tables to be used. Think of the result of the FROM
clause as a new conceptual table that consists of all listed tables joined together.
(Remember that the result is conceptual only; it does not physically exist.)
2. If a WHERE clause is used, all rows not meeting its requirements are discarded
from the conceptual table created in step 1. If the WHERE clause contains a
subquery, the subquery is evaluated against each candidate row of the conceptual
table in this same order of steps. Depending on whether the requirements are
met, rows are included or discarded from the conceptual table.
3. If a GROUP BY clause is used, the grouped conceptual table is formed based on
the rows remaining after step 2. If no GROUP BY clause is used, a HAVING clause
yields zero or one row.
4. If a HAVING clause is used, all rows in the grouped table created in step 3 that do
not meet the requirements of the HAVING clause are discarded. If the HAVING
clause contains a subquery, the subquery is evaluated for each group of the
grouped table according to this same scheme, and this evaluation determines
what is to be included in or discarded from the grouped table.
5. The select list then determines which columns of the remaining rows are to be
used.

2.7.4. Subqueries
As illustrated in 2.4.2, a subquery consists of a query specification that can be used as
an operand of a Boolean expression.

Subqueries impose a simple recursive structure for using the results of one query to
help resolve the results of another query. This powerful single construct, however,
does introduce some subtle syntax differences between a query specification and a
subquery specification. It introduces, as well, some restrictions on how subqueries are
used and where they can appear.

Subqueries submitted from UCS (extended mode) programs can be nested up to 10


levels deep. Subqueries submitted from base mode programs, IPF SQL, and MRI can
be nested up to 8 levels deep. Since RDMS imposes a limit of 14 tables in any query,
the accumulation across all subqueries may further limit the number of nested
subqueries. The only further restriction for subqueries is the physical limitation of your
system memory and the application environment in which you are working.

7830 8160–027 2–71


Query Specification

Format
( SELECT [ ALL │ DISTINCT ] { * │ select-expression | select-list }
FROM table-reference-list
[ WHERE Boolean-expression ]
[ GROUP BY group-by-item [, group-by-item]...
[ HAVING Boolean-expression ] )
[ ORDER BY sort-specification-list ]
[ FETCH FIRST m ROWS ONLY ]

where group-by-item is

{ column-specification | scalar-bif-reference | correlation-name }

sort-specification-list
are the sort specifications, separated by commas, in the form

{ column-specification │ title-name │ unsigned-integer │


scalar-bif-reference }

[ COLLATE collation-name ]

[ ASCENDING │ DESCENDING ]

where:

column-specification or title-name
must reference columns contained in tables that are listed in the
FROM clause.

unsigned-integer
specifies the position of the element in select-list if one of the
columns to sort is not a column specification but an expression (such
as MAXPRICE * 1.1).

collation-name
is the collation to use for ordering the values. The collation here is
independent of the column definition. The column’s character set must
match the collation's character set. This clause applies only to columns
with data type CHARACTER.

ASCENDING (default) or DESCENDING (or abbreviation ASC or DESC)


sorts in ascending or descending order. For CHARACTER columns, the
column definition's implicit or explicit collation order is used unless
you override it with a COLLATE clause.

scalar-bif-reference
is a reference to a scalar built-in-function. A column must be
referenced in each scalar-bif-reference in the ORDER BY clause.

2–72 7830 8160–027


Query Specification

FETCH FIRST m ROWS ONLY


m specifies the maximum number of rows that can be retrieved. It must be
an unsigned integer >=1 and <= 34359738367. An attempt to fetch the m+1
row results in a no-find being returned.
In addition to controlling the maximum number of records that are returned,
RDMS uses the information to more efficiently execute the statement. To
improve readability, the keyword ROW may be used instead of ROWS (for
example, when m = 1).

You define a subquery specification just as you define a query specification, with the
following exceptions:

• If the subquery follows a comparison operator, only one select-expression can be


in the subquery’s SELECT clause. If the subquery follows a universal operator, the
IN operator, or an EXISTS, the subquery’s select-list can contain one or more
select-expressions, but the number of select-expressions must be equal to the
number of value-expressions on the left side of the universal operator.
WHERE (colA,colB) IN (SELECT colC,colD FROM t2 ...).

If a subquery is the argument of an EXISTS function (see 2.5.9), you can use an
asterisk ( * ) as in the following example:
WHERE EXISTS (SELECT * FROM t1...).

• A subquery specification is enclosed in parentheses.

• The FROM clause of a subquery may not contain a joined-table.

For a description of the syntax, see 2.7.

Subqueries can appear as part of a Boolean expression contained within the scope of
an outer query's or subquery’s WHERE clause or HAVING clause.

Examples
The following example is invalid because SELECT * is only allowed in the select list of
a subquery if the predicate is an EXISTS function:

SELECT * FROM customers


WHERE desiredloc = ANY (SELECT * FROM
houses WHERE price > 120000)

The preceding example can be corrected by specifying LOCATION in the select list of
the subquery:

SELECT * FROM customers


WHERE desiredloc = ANY (SELECT location
FROM houses WHERE price > 120000)

7830 8160–027 2–73


Query Specification

Scope of References
The name of a table specified within a query or subquery specification and its
associated column name or names are defined in the corresponding select expression
or expressions and can be referenced anywhere within the scope of the query
specification. Any subqueries, therefore, contained within the scope of a query
specification can reference these tables and columns as an outer reference.
References, however, within the outer query to tables and columns defined in inner
level subqueries are not allowed.

The scope of references for tables and columns defined within a query and its
subqueries can be modeled as in nested procedures, each defining global variables at
their own level of nesting. The innermost procedure can reference all variables
defined outward. The outermost procedure, however, can reference only those
variables defined within its own body. Variables defined within the nested subroutines
are not available to it.

Outer references are therefore allowed within subquery specifications. A subquery


outer reference implies a reference to a column belonging to a table defined
(specified) in an outer query or subquery. When outer references are used within a
subquery, the query referenced can be thought of as a correlated query. If no outer
references are used, the queries can be thought of as uncorrelated queries.

Example
The following example illustrates an outer reference within a subquery specification.
The retrieved rows represent houses whose price is affordable for all customers who
want to buy in that location:

SELECT * FROM houses


WHERE price <= ALL (SELECT maxprice FROM customers
WHERE houses.location = customers.desiredloc)

The next example is invalid because the outer query refers to a column in a table that
is defined (specified) in the inner subquery:

SELECT * FROM customers


WHERE houses.location = customers.desiredloc AND
customers.maxprice >= (SELECT price FROM houses)

2–74 7830 8160–027


Query Specification

Execution in Boolean Expressions


Whenever a subquery is incorporated as part of a Boolean expression within the
WHERE clause of a query or subquery, the subquery within the Boolean expression is
effectively executed as part of the Boolean expression evaluation. The evaluation is
made for each row of the resulting conceptual table defined by the outer query or
subquery.

Whenever a subquery is incorporated as part of a Boolean expression within the


HAVING clause of a query or subquery, the subquery within the Boolean expression is
effectively executed as part of the Boolean expression evaluation. The evaluation is
made for each group of the resulting grouped table defined by the outer query or
subquery.

Examples
In the following query specification, the subquery portion of the Boolean expression is
executed for each unique customer name with a customer number greater than C201:

SELECT cname FROM customers


WHERE cno > 'c201'
GROUP BY cname
HAVING MAX(maxprice) > ANY (SELECT price FROM houses)

In the following query specification, the subquery portion of the Boolean expression is
evaluated for each row of table CUSTOMER to see whether it is included in the
resulting query:

SELECT cname, cno FROM customers


WHERE maxprice <= ANY (SELECT price FROM houses)

Rules of Evaluation
Assume S represents the result of a subquery whose number of projected items is
equal to 1 and number of rows is at most equal to 1. X represents the result of an
(arithmetic) expression.

You want to compare the operands S and X using a comparison operator


( >, <, =, <=, >=, or <> ) but without a universal quantifier (see Table 2–3):

• If X evaluates to a null value or if the result of S is an empty set, the comparison


evaluates to UNKNOWN.
• If the result S is a null value, the comparison evaluates to UNKNOWN.
• Any other values for S or X follow the normal rules for comparisons.

Next, assume S represents the result of a subquery whose number of projected items
is equal to 1, the number of rows in the set S is not restricted by a WHERE clause, and
Si represents those values in the set S. X represents the result of an (arithmetic)
expression.

7830 8160–027 2–75


Query Specification

You want to compare the operands S and X using a comparison operator


(>, <, =, <=, >=, <>, ^=, or != ) and a universal quantifier (SOME, ANY, or ALL):

• The result of the comparison is implied to mean the singular value of X to be


compared to every value of the set S.
• If S is empty or if the comparison is TRUE for every value Si in S, the following
comparison evaluates to TRUE:
X comparison-operator ALL S

• If the comparison is FALSE for at least one value Si in S, the following comparison
evaluates to FALSE:
X comparison-operator ALL S

• If the comparison is TRUE for at least one value Si in S, the following comparison
evaluates to TRUE:
X comparison-operator { SOME │ ANY } S

• If S is empty or if the comparison is FALSE for every value Si in S, the following


comparison evaluates to FALSE:
X comparison-operator { SOME │ ANY } S

• If the following comparison is neither TRUE nor FALSE, it evaluates to UNKNOWN:


X comparison-operator { SOME │ ANY │ ALL }

For more information about universal quantifiers, see 2.4.3.

Finally, assume S represents the result of a subquery whose number of projected


items is equal to 1. X represents the result of an (arithmetic) expression.

You want to evaluate the operands S and X by the comparison operator IN:

• “X IN S” compares like “X=ANY S”.


• “X NOT IN S” means the same as “NOT (X IN S)”.

For more information about the IN operator, see 2.5.5.

2–76 7830 8160–027


Query Specification

Summary of Guidelines for Using Subqueries


Follow these guidelines when using subqueries:

• Only when a subquery is evaluated within the context of universal or existential


operators such as ALL, SOME, ANY, IN, and EXISTS can the number of projected
items of the resulting subquery be greater than 1 (more than one column).
• The following multicolumn IN syntax is now supported:
(col1, col2, ... coln) IN (SELECT pcol1, pcol2, ... pcoln FROM ...
WHERE ...).

In previous levels of RDMS, it was necessary to rewrite this construct by changing


the IN predicate to EXISTS and adding the columns in the column list preceding the
IN as correlated predicates within the subquery. The IN predicate is transformed
to
EXISTS (SELECT pcol1, pcol2, ... pcoln FROM ... WHERE pcol1 = col1
AND pcol2 = col2 AND ... pcoln = coln ...)

• When a subquery containing the FETCH FIRST m ROWS ONLY clause is specified
within the context of the existential operator EXISTS, the clause is ignored and the
value of m is set to 0.
- A way to rewrite such a query, as in the following example:
SELECT * FROM houses
WHERE price EXISTS (SELECT maxprice FROM customers
FETCH FIRST 20 ROWS ONLY)

becomes
SELECT * FROM HOUSES
WHERE price = ANY (SELECT maxprice FROM customers
FETCH FIRST 20 ROWS ONLY)

• When using a FETCH FIRST m ROWS ONLY clause in a subquery, it is


recommended that an order in which to sort the records is also specified as an
ORDER BY clause in the subquery. If no order is specified, the result of the query
may not be what is expected.
• A subquery can appear only within the containing query (outer query) immediately
following:
 One of the comparison operators (>, <, =, <=, >=, <>, ^=, or !=), as in the
following example:
SELECT * FROM houses
WHERE price <= (SELECT MIN (maxprice) FROM customers)

 The IN comparison operator, as in the following example:


SELECT * FROM houses
WHERE location IN (SELECT desiredloc FROM customers
WHERE cno < 'c201')

7830 8160–027 2–77


Query Specification

 A universal quantifier, as in the following example:


SELECT * FROM houses
WHERE maxprice > ALL (SELECT price FROM houses)

 The Boolean existential function EXISTS, as in the following example:


SELECT * FROM customers
WHERE EXISTS (SELECT * FROM houses
WHERE houses.location=customers.desiredloc)

A subquery cannot be the left operand of a comparison operator, or anywhere as


an operand in conjunction with the BETWEEN, IS LIKE, or IS NULL comparison
operators. Nor can a subquery appear anywhere as an operand within an
arithmetic expression.
• When a subquery is the right operand of a comparison operator
(>, <, =, <=, >=, <>, ^=, or !=) with no universal quantifier, the number of rows of
the resulting subquery cannot be greater than 1. If FETCH FIRST m ROWS ONLY is
specified as part of the subquery, the value of m must be 1. The subquery also
cannot contain a GROUP BY clause, a HAVING clause, or reference to a grouped
view.
• If a subquery makes an outer reference to a grouped query or grouped subquery
specification and it is referenced from the outer query’s HAVING clause, the
column referenced by the subquery must be a grouped column in the outer
specification or it must appear as a parameter to an aggregate function in the
outer specification.
In the following example, the subquery contains an outer reference to the
grouped column HOUSES.LOCATION:
SELECT location, description FROM houses
GROUP BY location, description
HAVING AVG(price) < SOME (SELECT maxprice
FROM customers WHERE
customers.desiredloc = houses.location)

• When an outer reference occurs within a subquery as a parameter to an


aggregate function (MIN, MAX, AVG, SUM, COUNT), two conditions must be met:
 The subquery must be contained within the scope of a HAVING clause
associated with the outer-referenced query specification.
 The outer reference used as an input parameter must appear as a singular
column input, not as part of an input (arithmetic) expression.
This means that subqueries can use aggregate functions within their WHERE
clause specifications, but only if both of these conditions are met.
• The select expression within a subquery must adhere to the following conditions:
 If the subquery contains a GROUP BY clause, each column referenced in the
expression must be one of the grouped columns in the subquery or it must be
specified as an input parameter to an aggregate function.

2–78 7830 8160–027


Query Specification

 If the subquery does not contain a GROUP BY clause and the set expression
does include an aggregate function, then each column referenced in the
expression must be specified as an input parameter to an aggregate function.
To illustrate this, the following subquery specification is invalid because C2 is
not part of an aggregate function:
(SELECT MIN(c1) + c2 FROM t1 WHERE...)

 If the subquery table specification list contains a grouped view, the select
expression cannot contain an aggregate function.

2.7.5. Common Table Expressions


A common table expression (CTE) effectively creates and populates a temporary table
that exists for the duration of the query. Once populated, the records in the CTE never
change. It is often used as a shortcut for writing a derived table. The CTE can be
referenced more than once within the query (this is different from derived tables
which may be evaluated independently, even if they are syntactically identical. The
underlying records in the database may have changed between these executions
causing the derived tables to return different results). CTEs are defined using the
WITH clause. Each query-name represents a common table expression.

A cursor that contains a CTE is nonscrollable.

The CTE however has the following restrictions:

• A SQL statement can contain only a single WITH clause which must be at the
beginning of the outer-most query-expression.
• A WITH clause may contain only one CTE.
• The WITH clause is allowed only in the following SQL statements: DECLARE
CURSOR, PREPARE of a cursor specification, SELECT multi-row and SELECT
single-row. You can UNLOAD from a cursor that contains a CTE.
• Column-names returned must be unique within the common table expression.
• At most 510 columns may be returned by a common table expression.
• A CTE may not include UNION, nor may a CTE be referenced within a UNION.
• A CTE may not be in a VIEW, nor may it reference any views, nor may the SQL
statement containing the CTE reference any views.

For example
DECLARE houselist CURSOR
WITH okhouses( okprice,oklocation ) AS
(SELECT maxprice,desiredloc FROM customers),
oksellers( okprice,oklocation ) AS
(SELECT price, location FROM houses )
SELECT 'buyers want ' ,okhouses.okprice ,
'sellers offer' ,oksellers.okprice
FROM okhouses ,
oksellers
WHERE okhouses.oklocation = oksellers.oklocation ;

7830 8160–027 2–79


RDMS Data Types

2.8. RDMS Data Types


RDMS supports two character and seven numeric data types, plus datetime and BLOB
data types.

Note: In this subsection, an “item” refers to a column in a table or view, as well as


to a routine parameter, SQL variable, stored function result, or a correlation-name-
qualified-item within a trigger.

2.8.1. Character Data Types


The format of the two character data types and their definition is as follows:

CHARACTER [ (size) ] [ CHARACTER SET character-set-specification ]

NCHARACTER [ (size) ]

where:

size
must be a positive integer unless omitted, in which case 1 is assumed.

CHARACTER data types contain ASCII or any other 9-bit data. NCHARACTER data
types contain 16-bit character data, such as kanji.

For CHARACTER, RDMS treats each byte as one character. Thus, size defines both
the number of bytes and the number of characters a column can hold.

For NCHARACTER, RDMS treats each pair of bytes as one character. Thus, size
defines the number of characters and one-half the number of bytes a column can
hold.

character-set-specification
(default RDMS_TEXT) identifies the character set for the values in the column, and
can be either a standard-character-set-name or an
implementation-defined-character-set-name, where:

standard–character–set–name
can be the name of any character set supported by the I18N service library,
including but not limited to the most heavily used character sets ASCII and
ISO8859-1.

implementation–defined–character–set–name
can be any of the following character set names: SQL_TEXT, RDMS_TEXT
(default), SQL_CHARACTER, ASCII_GRAPHIC, LATIN1, or ASCII_FULL.

You can use the abbreviations CHAR for CHARACTER and NCHAR for NCHARACTER.

For an explanation of the characters included in each character set, see The I18N
Assistant.

2–80 7830 8160–027


RDMS Data Types

Character set names must be installed on the system and must be legal values for the
CCS_NAME_TO_CCS_NUMBER service routine provided by the I18N service library to
be allowable at RDMS execution time. The I18N character sets installed on your
system determine the legal values. For further information, see The I18N Assistant.

If the name contains a hyphen, you must enclose it in quotation marks (for example,
“ISO8859-1”).

Character set names are case-sensitive in RDMS; therefore, they may have to be
enclosed in quotation marks. RDMS is not otherwise case-sensitive.

Examples
CHARACTER(20)

CHARACTER(12) CHARACTER SET LATIN1

CHARACTER(9) CHARACTER SET SQL_TEXT

CHARACTER(40) CHARACTER SET "ISO8859-1"

NCHARACTER(40)

If you use ASCII COBOL or ASCII FORTRAN programs to pass 16-bit kanji data, you
must split the kanji character into two 8-bit halves and pass each half as a separate
alphanumeric character. RDMS reassembles the data correctly on output as kanji. This
means that you need two ASCII COBOL or ASCII FORTRAN character positions to
store the information that is usually stored in one NCHARACTER position.

RDMS compresses all character strings when they are stored by removing all trailing
blanks from the string. RDMS compresses a string of all blanks to a single blank to
decrease storage requirements and to increase character manipulation speed.

When RDMS compares character strings, it adds blanks (ASCII character 040) to the
shorter string to make both strings the same length, unless an explicit collation is
specified (see 2.9.2).

When you request character data (for example, using the FETCH or SELECT
statements), RDMS finds the character string, expands it with blanks to its defined
length as specified in the table definition, and returns the requested data.

RDMS provides a synonym for a character column with a character set “UCS-2”. For
example, the following two column definitions are equivalent:

UNICODE (10)

CHARACTER(10) CHARACTER SET "UCS-2"

7830 8160–027 2–81


RDMS Data Types

2.8.2. Numeric Data Types


Several data types can hold numeric information. Numeric data types can be either
exact or approximate.

Exact Numeric Data Types


The definition formats of exact data types are as follows:

DECIMAL [ (decimal-digits-precision[,scale]) ]

NUMERIC [ (digits-precision[,scale]) ]

INTEGER

SMALLINT

where:

decimal–digits–precision
depends on whether it appears in an item definition in an unowned or an owned
schema. If the value is part of a definition in an owned schema, the system adds 1
to the value before storing the definition in the UREP metadatabase and file
RDT$FILE. This means that all subsequent reporting of the definition by the UREP
commands PROCESS TABLE REPORT and REPORT TABLE, the RDMS catalog, and
the GET DESCRIPTION and UNLOAD (WITH DESCRIPTION) statements indicate a
value one greater than the original definition. For a description of owned and
unowned schemas, see 6.10.

For unowned schemas, it is the number of digits in an item, including the leading
sign. This must be an integer between 2 and 22. If decimal-digits-precision is
omitted, 2 is assumed. Two examples follow:

• An item defined as DECIMAL(3) can contain integer values from –99 to +99,
inclusive. DECIMAL(3) is the same as DECIMAL(3,0).
• An item defined as DECIMAL(3,2) can contain values from –.99 to +.99.
DECIMAL(3,2) is the same as DECIMAL(3.0002) or DECIMAL(3,0002).

For owned schemas, it is the number of digits in an item, excluding the leading
sign. This must be an integer between 1 and 21. If decimal-digits-precision is
omitted, 1 is assumed. Two examples follow:

• An item defined as DECIMAL(3) can contain integer values from –999 to +999,
inclusive. DECIMAL(3) is the same as DECIMAL(3,0).
• An item defined as DECIMAL(3,2) can contain values from –9.99 to +9.99.
DECIMAL(3,2) is the same as DECIMAL(3.0002) or DECIMAL(3,0002).

2–82 7830 8160–027


RDMS Data Types

digits–precision
is the number of digits in the item, a positive integer up to 21. If digits-precision is
omitted, 11 is assumed.

scale
is a nonnegative integer that indicates the number of digits for the fractional
portion of the item. If scale is omitted, zero is assumed.

You can use a period instead of a comma between digits-precision or


decimal-digits-precision and scale.

You can use the abbreviations DEC for DECIMAL and INT for INTEGER.

Table 2–7 shows the largest and smallest values for exact numeric data types.

Table 2–7. Value Ranges for Exact Numeric Types

Type Maximum Minimum

DECIMAL and 999999999999999999999 –999999999999999999999


NUMERIC
INTEGER 34359738367 –34359738367
SMALLINT 131071 –131071

Approximate Numeric Data Types


The format of the approximate numeric data types and their definition is as follows:

REAL

FLOAT [ (binary-precision) ]

DOUBLE [ PRECISION ]

where binary–precision specifies the minimum binary precision in bits. It must be a


positive integer less than or equal to 60. The default value is 60.

Precision is as follows for approximate numeric data types:

• REAL—27 bits. You can store values of 8 and sometimes 9 digits of precision.
• FLOAT—At least the minimum specified in binary–precision. RDMS frequently
provides more precision than specified, up to a maximum of 60 bits. This means
that you can store any values of up to 18 digits of precision. You can actually store
some 19-digit values.
• DOUBLE PRECISION—60 bits. This means that you can store any values of up to
18 digits of precision. You can actually store some 19-digit values.

7830 8160–027 2–83


RDMS Data Types

Table 2–8 shows the largest- and smallest-magnitude positive and negative values
that can be used with approximate data types.

Table 2–8. Value Ranges for Approximate Numeric Types

Type Largest-Magnitude Values Smallest-Magnitude Values

REAL
Positive 1.70141182E+38 1.46936794E–39
Negative -1.70141182E+38 -1.46936794E–38
FLOAT
Positive 8.988465674311579551E+307 2.781342323134001732E–309
Negative -8.988465674311579551E+307 -2.781342323134001732E–309
DOUBLE PRECISION
Positive 8.988465674311579551E+307 2.781342323134001732E–309
Negative -8.988465674311579551E+307 -2.781342323134001732E–309

You can also store zero in the approximate numeric data type items.

Range, Precision, Exactness, and Memory Requirements


The primary characteristics of numeric data types are range, precision, exactness, and
memory requirements:

• Range refers to how far apart the maximum and minimum values are for a data
type. As you can see from the listed maxima and minima, SMALLINT has the
smallest range and DOUBLE PRECISION has the largest range. If you know the
range of values an item must store, you may be able to narrow the field of
appropriate numeric data types for that item.
• Precision refers to the number of significant digits that "fit" in the item.
Table 2–9 gives the number of digits and bits for each numeric data type. A plus
sign (+) indicates that, in some cases, an additional digit or bit of precision is
available. For instance, 10+ in the table means “at least 10, and in some cases 11.”

2–84 7830 8160–027


RDMS Data Types

Table 2–9. Numeric Data Type Precision

Digits of
Data Type Precision Bits of Precision

DECIMAL(22,s) [unowned schema] 21 69+


DECIMAL(21,s) [owned schema]
NUMERIC(21,s) 21 71
INTEGER 10+ 35
SMALLINT 5+ 17
REAL 8+ 27
FLOAT(60) 18+ 60
DOUBLE PRECISION 18+ 60

• Exactness is discussed in 2.4.7 and 2.8.2. Perhaps the most important aspect of
exactness is that comparisons between exact and approximate types may give
unpredictable results.
• Memory requirements vary by numeric data type. If mass storage or main
memory space is a concern for you, you may wish to consider the memory
implications of the numeric data types you use.
Table 2–10 illustrates the basic amount of memory used for each listed data type.
In addition to the space shown, additional space is used for each item to contain
information about the item.

Table 2–10. Numeric Data Type Memory Usage

Data Type Memory Usage

DECIMAL(n,s) n bytes
NUMERIC(p,s) 1 word if p <= 11;
2 words if p > 11
INTEGER 1 word
SMALLINT Half word (18 bits)
REAL 1 word
FLOAT(n) 1 or 2 words
DOUBLE PRECISION 2 words

7830 8160–027 2–85


RDMS Data Types

Notes:
• For DECIMAL items defined in an owned schema, the number of decimal digits
is one greater than the number of decimal digits in the original definition. This is
because of the difference in the semantics of this value between the SQL
standard and RDMS. For a description of owned and unowned schemas,
see 6.10.
• Arithmetic and comparison operations are faster on binary data types (INTEGER,
SMALLINT, REAL, FLOAT, and DOUBLE PRECISION) than on the other data
types.
• The evaluation of expressions that include different data types uses more
overhead than the evaluation of expressions in which all operands are the same
type.
• FLOAT(n) uses one word when n <= 27; otherwise, it uses two words.
• NUMERIC(11,s) handles the values from –34359738367 to 34359738367. Use
NUMERIC(12,s) to handle numbers outside this range.

Storing Numeric Data


The numeric data types allowed in tables, views, routines, and triggers are divided into
two classes, exact and approximate. Likewise, the numeric data you give to RDMS, as
a literal or a program variable passed from a program, is either exact or approximate in
nature. You need to know what happens when the receiving item in a table is of a
numeric data type different from the data being fed into it. What happens case by
case follows:

• Exact to approximate
If you store an exact value, like DECIMAL type value 10.357, into an approximate
item (for example, into a REAL item), some accuracy may be sacrificed.
Note: For DECIMAL items defined in an owned schema, the number of decimal
digits is one greater than the number of decimal digits in the original definition.
This is because of the difference in the semantics of this value between the
SQL standard and RDMS. For a description of owned and unowned schemas,
see 6.10 (CREATE SCHEMA).
• Larger exact into smaller exact
Suppose you try to store an exact value (say DECIMAL type value 12345.678) in an
exact data item that cannot accommodate it. If a value is stored in a SMALLINT or
INTEGER item, RDMS truncates the fractional portion.
If the receiving item can accommodate some, but not all of the fractional portion,
it is rounded if necessary to make it fit. For example, storing 12345.678 into a
DECIMAL(7,1) item leaves 12345.7 in the receiving item.
If the integer portion of the value does not fit the receiving item (for example,
trying to store 12345.678 into a DECIMAL(3) item) the system returns an error and
no value is stored. If this happens on an UPDATE statement, the old value remains
in the item. If it occurs on an INSERT statement, no row is created.

2–86 7830 8160–027


RDMS Data Types

• Approximate to exact
When you store an approximate value into an exact item, the value is converted,
maintaining as much accuracy as possible. Fractional portions of the converted
value can be rounded off to fit into DECIMAL or NUMERIC items. Fractional
portions are truncated to fit SMALLINT or INTEGER items.
For example, when you store 3.14159265 into a DECIMAL(4,2) item, the result is
3.14. Storing 1934.88 into an INTEGER item results in 1934.
• Larger approximate into smaller approximate
If the value to be stored is within the range of the receiving item, it is stored.
However, its precision can be reduced. But if the value to be stored exceeds the
range of the receiving item, the system returns an error and no value is stored. If
this happens on an UPDATE statement, the old value remains in the item. If it
occurs on an INSERT statement, no row is inserted.

2.8.3. Datetime Data Types


Datetime data types include DATE, TIME, and TIMESTAMP.

Format
The formats of datetime data types are

DATE

TIME [ (time-precision) ]

TIMESTAMP [ (timestamp-precision) ]

where:

time–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 0 is assumed.

timestamp–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 6 is assumed.

The largest and smallest values for datetime data types are as follows.

Type Maximum Minimum

DATE 9999–12–31 0001–01–01


TIME 23:59:59.999999 00:00:00.000000
TIMESTAMP 9999–12–31 23:59:59.999999 0001–01–01 00:00:00.000000

7830 8160–027 2–87


RDMS Data Types

Memory Requirements
Memory requirements for datetime data types vary depending on the precision
specified. Table 2–11 illustrates the memory required for each data type based on
precision.

Table 2–11. Datetime Data Type Precision and Memory Usage

Data Type Precision Memory Usage

DATE Not applicable 1 word


TIME 3 or fewer 1 word
TIME More than 3 2 words
TIMESTAMP 3 or fewer 2 words
TIMESTAMP More than 3 3 words

Storing and Retrieving Datetime Data


You can use datetime literals and functions in an SQL statement to store datetime
data values.
You can retrieve datetime data through program variables declared as CHARACTER
data in the host language.
The following can be converted into and compared against datetime data:

• SQL variables
• Literal strings
• Program variables that contain character strings in datetime format

Use the following guidelines to determine the length of the character buffer to contain
the datetime value:

• For DATE ('yyyy–mm–dd'), 10 ASCII characters or more, and DATE ('ddMonyyyy')


where Mon is a 3 char ASCII representation of the month (locale en_US)
• For TIME ('hh:mm:ss[.[ffffff] ]'), 8 ASCII characters or more with no fractional
second; or 8 ASCII characters plus the number of digits in the fractional portion +1
or more
• For TIMESTAMP ('yyyy–mm–dd hh:mm:ss[.[ffffff] ]'
or 'yyyy-mm-dd-hh.mm.ss[.[ffffff] ]'), 19 ASCII characters or more with no fractional
second; or 19 ASCII characters plus the number of digits in the fractional portion +1
or more

If you try to store datetime data 2006–08–12 through program variables, you can use
the CAST function as follows, where the variable vdate contains the string
DATE '2006–08–12':

EXEC SQL INSERT INTO mytable VALUES(CAST (:vdate AS DATE))

2–88 7830 8160–027


RDMS Data Types

The length of variable VDATE should be at least 16 ASCII characters. In the preceding
example, if VDATE contains the string 2004–08–12, the length of VDATE must be at
least 10 ASCII characters. You can also use the program variable directly, and RDMS
will implicitly cast the value (to DATE in this case). For example

EXEC SQL INSERT INTO mytable VALUES (:vdate)

For more information on storing and retrieving datetime data, see 3.8.

Time Zones
Current_timestamp, now(), and getdate() always return timestamps in local time.
Getutcdate() returns a timestamp in Coordinated Universal Time (UTC). Use the
new_time() function to convert between time zones.

There are boundary conditions to be aware of when seasonal time zone shifts are
made (this is called changing between standard time and day light savings time in the
United States).

With no time zone shift, timestamps are monotonically increasing. This is not true
during the seasonal time zone shift as shown below.

2.8.4. Binary Large Object Data Type


A binary large object (BLOB) is a data type whose contents and structure are defined
by the application that uses it. BLOBs can be relatively small (a few thousand bytes) to
very large (up to 4 gigabytes). BLOBs are used to store image data such as pictures,
fingerprints, and scanned documents. They are also used to store binary data such as
encrypted credit card numbers. Using a BLOB is the only way to insert binary data
from a JAVA program.

Format
BINARY LARGE OBJECT ( size ) [IN storage-area-name]

or

BINARY LARGE OBJECT ( size ) [IN (storage-area-name [,storage-area-


name]...)]

where:

size
is the maximum length for the BLOB, in bytes. The value can be in the range 1 to
4,294,967,296 (4G) bytes. The maximum length can be specified as a simple
integer representing the number of bytes or as an integer followed by one of the
following suffixes:
K Kilobytes (210 or 1,024 bytes)
M Megabytes (220 or 1,048,576 bytes)
G Gigabytes (230 or 1,073,741,824 bytes; 2G is interpreted as 231)

7830 8160–027 2–89


RDMS Data Types

IN
When the IN storage-area-name clause is not specified, RDMS stores the BLOB
value as part of the record. BLOBs stored as part of the record are always stored
as varying because the amount of BLOB storage is never padded to the maximum
size BLOB. The maximum size BLOB value that can be stored in a record is similar
to the maximum size character value that can be stored in a record, approximately
28,000 bytes. Refer to the Relational Database Server for ClearPath OS 2200
Administration Guide for more information on RDMS maximum sizes.
storage-area-name
is the name of the storage area associated with the BLOB column. A storage area
name must be a valid SQL name as defined in 2.2.4.

You can use the abbreviation BLOB for Binary Large Object.

Examples
BLOB(24)

BINARY LARGE OBJECT (254)

BLOB(3M) IN myschema.bstorage1

BLOB(20M) IN (blob_area1, blob_area2, blob_area3)

BLOB(1073741824) IN blob_area4

BLOB (1G) IN blob_area4

The previous two examples are equivalent.

The following considerations apply to BLOB columns that include an IN


storage-area-name clause:

• You can add a column with data type BLOB to a table only if the table has explicitly
defined storage areas. For example, an IN clause must immediately follow the
table’s name on the CREATE TABLE statement. If the IN clause is present, the
table is said to have an “explicitly defined storage area.” If the IN clause is not
present, RDMS creates a storage area in which to store data and indices for the
table and the table is said to have an “implicitly defined storage area.” You cannot
add a BLOB column to a table with an implicitly defined storage area.
• BLOB storage areas (storage areas with DATA-FORMAT RSM-LOB) cannot be
shared with table indices or shared with data from columns whose data type is
not BLOB.
• With the BLOB data type, you specify a storage area for each column’s data. The
storage area can be different for each BLOB column or multiple BLOB columns
can share the same storage area. If you share one storage area among multiple
BLOB columns, you must declare each column with exactly the same size.

2–90 7830 8160–027


RDMS Data Types

• You can also specify a list of storage areas on the column definition. If you include
more than one storage area, they form a storage area pool. RDMS uses the
storage area in the order you list them in the storage-area-specification list.
When the first storage area is full, RDMS stores the BLOBs in the second storage
area specified for the column, and so on. If you specify more than one storage
area, the storage area names must be enclosed in parentheses.
• You can specify up to 511 storage areas for each BLOB column.
• All BLOB storage areas must have a DATA-FORMAT of RSM-LOB.
• All BLOB storage areas must have DOMAIN UDS or USER-UDS (as is the case for
all other RDMS storage areas).
• Once storage areas have been added to a BLOB column, they cannot be removed
individually. You must use ALTER TABLE to DROP the column and ADD it again
with fewer (or different) storage areas.
• Note that a BLOB value must be able to fit entirely within one storage area. When
cataloging storage areas, you must ensure that the maximum size of the storage
area is larger than the maximum size of the BLOBs you want to store in the
storage area. RDMS does not split BLOB data across storage areas. RDMS
returns a storage area full error if the BLOB value does not all fit in a single
storage area.

The following considerations apply to all BLOB columns:

• The BLOB data type cannot be used in routines or triggers.

In the following example, the data for the column name and the index for the name
primary key are stored in the storage area s1.data_storage. The data for column
picture is stored in s1.lob_storage_1 and can overflow into the storage area
s1.lob_storage_4. The data for column thumb_print is stored in the storage area
s1.lob_storage_2. The data for column signature is stored in storage area
s1.lob_storage_3. The column sizes are each tailored to the size of the expected data
values.

CREATE TABLE s1.t1


IN s1.data_storage
( name CHAR(40) PRIMARY KEY,
picture BLOB(30K) IN (s1.lob_storage_1,s1.lob_storage_4),
thumb_print BLOB(2K) IN s1.lob_storage_2,
signature BLOB(500K) IN s1.lob_storage_3 DEFAULT NULL)

In the following example, the data for the column name and the index for the name
primary key are stored in the storage area s1.data_storage. The data for columns
thumb_print and index_finger are both stored in s1.lob_storage_1. For both columns
to be stored in the same storage area, the declared size of the columns must match.

7830 8160–027 2–91


RDMS Data Types

Additionally, the column resume is stored in s1.lob_storage_6 and may overflow into
s1.lob_storage_4. Because of the sizes of the LOB columns, each column typically
uses multiple data pages. RDMS allocates “column size” amount of space in the
storage area for each BLOB value. The size of the pages in the storage areas can be
adjusted to accommodate the different column sizes without incurring excessive
overhead of wasted space for each BLOB value.

CREATE TABLE s1.t1


IN s1.data_storage
( name CHAR(40) PRIMARY KEY,
thumb_printBLOB(5K) IN s1.lob_storage_1,
index_finger BLOB(5K) IN s1.lob_storage_1,
resume BLOB(60K) IN (s1.lob_storage_6,s1.lob_storage_4),
signature BLOB(500K) IN s1.lob_storage_3)

Other considerations for using BLOB columns are described in Appendix I.

2–92 7830 8160–027


Character Handling and Internationalization

2.9. Character Handling and Internationalization


This subsection includes the following topics:

• Character value assignment considerations


• Internationalization considerations for character data
• Collating sequence
• Kanji data

2.9.1. Character Value Assignment Considerations


This subsection describes how character set and collating sequence affect data value
assignments. The rules and guidelines in this section apply to columns of data type
CHARACTER and NCHARACTER. The UPDATE and INSERT statements are affected by
these rules and guidelines specifically where program variables and literal strings are

• Assigned to columns
• Compared with column values in a WHERE clause

In the following discussion

• The destination is the column or program variable receiving a value.


• The source is where the value originates.

The discussion applies to the following variations of CHARACTER columns defined by


the CREATE TABLE statement:

• CHARACTER with no CHARACTER SET clause and no COLLATE clause on the


column definition
• CHARACTER with the CHARACTER SET clause on the column definition. See 2.9.2.
• CHARACTER with the CHARACTER SET and COLLATE clauses on the column
definition. See 2.9.2 and 6.10.
• NCHARACTER

For the UCS COBOL programming language, the discussion depends on the following
variations of the definitions of the program variables:

• PIC X or PIC A with no USAGE clause


• PIC 9
• PIC X with USAGE IS DISP–I18N
• PIC X with USAGE IS BYTE–I18N
• PIC X with USAGE IS DISP–2

7830 8160–027 2–93


Character Handling and Internationalization

Column with Data Type CHARACTER


The following rules apply in two situations:

• A column defined with data type CHARACTER and no CHARACTER SET clause
specified. The column’s character set is implicitly RDMS_TEXT.
• A column defined with data type CHARACTER and CHARACTER SET RDMS_TEXT.

The data source can be any of the following:

• A string literal containing 7–bit, 8–bit, or 9–bit printable, graphic, or control


characters.
• A string literal containing multibyte characters. The application program or user
must manipulate the data in the destination correctly to ensure that the characters
are processed in the correct byte grouping.
• A null value.
• A column of data type CHARACTER, CHARACTER with the CHARACTER SET
clause, or CHARACTER with the CHARACTER SET and COLLATE clauses. Any 7-bit,
8-bit, or 9-bit printable, graphic, or control character can be stored in the
destination column. Multibyte characters can be stored in the column. The
application program or user must manipulate the data in the destination column
correctly to ensure that the characters are processed in the correct byte grouping.
• A literal string in a DEFAULT clause. The same rules apply as for a string literal.
• A program variable with CHARACTER data type (for example, char in UCS C, or
PIC X or PIC A in UCS COBOL).
• A UCS COBOL program variable declared as PIC X USAGE IS DISP–I18N.
• A UCS COBOL program variable declared as PIC X USAGE IS DISP–2. Multibyte
characters can be stored in the column. The application program or user must
manipulate the data in the destination column correctly to ensure that the
characters are processed in the correct byte grouping.
• The system function USER.

RDMS does not allow any of the following as a data source:

• A program variable with numeric data type (for example, int in UCS C or PIC 9 in
UCS COBOL)
• A column with data type NCHARACTER
• A UCS COBOL or UCS C variable with data type SQL TYPE IS BLOB
• A column of data type BLOB

2–94 7830 8160–027


Character Handling and Internationalization

Column with Data Type CHARACTER with CHARACTER SET Clause


If the destination is a column of data type CHARACTER with the CHARACTER SET
clause and the character set is not RDMS_TEXT, the following rules apply.

The data source can be any of the following:

• A string literal containing 7–bit, 8–bit, or 9–bit printable, graphic, or control


characters. The application program or user must ensure that the characters in the
string literal are members of the column's character set.
• A string literal containing multibyte characters. Since none of the character sets
supported for inclusion on the CHARACTER SET clause are multibyte character
sets, you should not use them. However, RDMS cannot currently determine if the
characters in a string literal are members of the column's character set. The
application program or user must manipulate the data in the destination correctly
to ensure that the characters are processed in the correct byte grouping.
• A null value.
• A column of data type CHARACTER with no CHARACTER SET clause. Since the
implied character set is RDMS_TEXT, RDMS does not enforce a match of character
sets.
• A column of data type CHARACTER with the CHARACTER SET clause, or
CHARACTER with the CHARACTER SET and COLLATE clauses. The character set
of the source must match the character set of the destination.
• A literal string in a DEFAULT clause. The same rules apply as for a string literal.
• A program variable with CHARACTER data type (for example, char in UCS C, or PIC
X, PIC X USAGE IS DISP–I18N, or PIC A in UCS COBOL). The variable can contain
any 7–bit, 8–bit, or 9–bit printable, graphic, or control character. It is up to the
application program to ensure that the characters in the variable are members of
the column's character set.
• The system function USER.

RDMS does not allow any of the following as a data source:

• A column of data type NCHARACTER, because the character sets cannot match
• A UCS COBOL program variable of data type PIC X USAGE IS BYTE–I18N, because
the source is a binary value, not a character value
• A UCS COBOL program variable of data type PIC X USAGE IS DISP–2, because the
character sets cannot match
• A UCS COBOL or UCS C variable with data type SQL TYPE IS BLOB
• A column of data type BLOB

7830 8160–027 2–95


Character Handling and Internationalization

Column with Data Type CHARACTER with CHARACTER SET


and COLLATE Clauses
If the destination is a column of data type CHARACTER with the CHARACTER SET and
COLLATE clauses, the data source can be any of the following:

• A string literal containing 7–bit, 8–bit, or 9–bit printable, graphic, or control


characters. The application program or user must ensure that the characters in
the string literal are members of the column’s character set.
• A string literal containing multibyte characters. Since none of the character sets
supported for inclusion on the CHARACTER SET clause are multibyte character
sets, you should not use them. However, RDMS cannot currently determine if the
characters in a string literal are members of the column’s character set. RDMS
uses the STRING_TRANSFORM service routine provided by the I18N service library
to create an ordering key from the user's value. This service routine processes
the characters as if they were 9–bit characters. Some of the multibyte characters
entered as a value may cause STRING_TRANSFORM to return an error status. The
application program or user must manipulate the data in the destination correctly
to ensure that the characters are processed in the correct byte grouping.
• A null value.
• A column of data type CHARACTER with no CHARACTER SET clause. Because the
implicit character set for the CHARACTER column is RDMS_TEXT, RDMS does not
enforce a match between the character sets in the two columns.
• A column of data type CHARACTER with the CHARACTER SET clause. The
character set of the source must match the character set of the destination.
• A column of data type CHARACTER with the CHARACTER SET and COLLATE
clauses. The character set of the source must match the character set of the
destination.
• A literal string in a DEFAULT clause. The same rules apply as for a string literal.
• A program variable with CHARACTER data type (for example, char in UCS C, or PIC
X, PIC X USAGE IS DISP–I18N, or PIC A in UCS COBOL). The variable can contain
any 7–bit, 8–bit, or 9–bit printable, graphic, or control character. It is up to the
application program to ensure that the characters in the variable are members of
the column's character set.
• The system function USER. If the USER value comes from a source other than the
run's program control table (PCT) (for example, if the value comes from ODBC),
some of the characters may not be valid in the column's collation.

RDMS does not allow any of the following as a data source:

• A column of data type NCHARACTER, because the character sets cannot match
• A UCS COBOL program variable of data type PIC X USAGE IS BYTE–I18N, because
the source is a binary value, not a character value
• A UCS COBOL program variable of data type PIC X USAGE IS DISP–2, because the
character sets cannot match

2–96 7830 8160–027


Character Handling and Internationalization

• A UCS COBOL or UCS C variable with data type SQL TYPE IS BLOB
• A column of data type BLOB

Column with Data Type NCHARACTER


If the destination is a column with the data type of NCHARACTER, the data source can
be any of the following:

• A column of data type CHARACTER.


• A string literal containing 7–bit, 8–bit, or 9–bit printable, graphic, or control
characters. The application program or user must ensure that the characters in the
string literal are members of the LETS–J character set.
• A string literal containing multibyte characters. The application program or user
must ensure that the characters in the string literal are members of the LETS–J
character set.
• A null value.
• A literal string in a DEFAULT clause. The same rules apply as for a string literal.
• A program variable with CHARACTER data type (for example, char in UCS C, or
PIC X, PIC X USAGE IS DISP–I18N, or PIC A in UCS COBOL). The variable can
contain any 7–bit, 8–bit, or 9–bit printable, graphic, or control character. It is up to
the application program to ensure that the characters in the variable are members
of the column's character set.
• A UCS COBOL program variable declared as PIC X USAGE IS DISP–2.
• The system function USER.

RDMS does not allow any of the following as a data source:

• A column of data type CHARACTER with the CHARACTER SET, or CHARACTER


with the CHARACTER SET and COLLATE clauses, because the character sets
cannot match
• A UCS COBOL program variable with data type PIC X USAGE IS BYTE–I18N,
because the source is a binary value, not a character value
• A UCS COBOL program variable with data type PIC X USAGE IS DISP–I18N,
because the character sets cannot match
• A UCS COBOL or UCS C variable with data type SQL TYPE IS BLOB
• A column of data type BLOB

Program Variable with Data Type CHARACTER


If the destination is a program variable with the data type of character (for example,
char in UCS C or PIC X, PIC X USAGE IS DISP–I18N, or PIC A in UCS COBOL), the RDMS
data source can be any data type.

If the column has a data type of BLOB, RDMS stores only the BLOB text. It does not
store the length information.

7830 8160–027 2–97


Character Handling and Internationalization

Program Variable with Data Type PIC X USAGE IS DISP-2


If the destination is a program variable with the data type of PIC X USAGE IS DISP–2,
the RDMS data source can be a column of data type CHARACTER, NCHARACTER, or
BLOB. If the column has a data type of BLOB, RDMS stores only the BLOB text. It
does not store the length information.

RDMS does not allow a column of data type CHARACTER with the CHARACTER SET,
or CHARACTER with the CHARACTER SET and COLLATE clauses as a data source.

Program Variable with Data Type PIC X USAGE IS BYTE-I18N


If the destination is a program variable with the data type of PIC X USAGE IS
BYTE-I18N, RDMS generates an error, unless the column data type is BLOB, because
the BYTE-I18N data type is a binary data type, not a character data type.

If the column has a data type of BLOB, RDMS stores only the BLOB text. It does not
store the length information.

2.9.2. Internationalization Considerations for Character Data


If you are dealing with the internationalization of character data you must consider,
among other things, character strings, collating sequences, expressions, and implicit
and explicit character sets and collation.

Character Strings
A character string data type is identified by the RDMS data type CHARACTER or
NCHARACTER. This discussion, however, applies only to data type CHARACTER,
whose attributes include

• The maximum length in characters


• The name of the character set
• The name of the collation

Every character stored in a column belongs to a character set. The character set is
either implicit or explicit. If you specify only CHARACTER for the data type, RDMS
implicitly assigns the character set RDMS_TEXT to the column. You can use the
CHARACTER SET clause with the CHARACTER data type to attach the name of a
specific character set to the values in a column.

Character set names can be names defined by national or international standards and
names defined by the OS 2200 system, both of which are available for use in RDMS.
Character set names defined by standards are referred to as “standard character set
names.” Those defined by the OS 2200 operating system are referred to as
“implementation–defined character set names.”

The implementation-defined character set name SQL_TEXT specifies the name of a


character set that can represent every character that is in an SQL keyword and all
other characters that are in character set names supported by RDMS.

2–98 7830 8160–027


Character Handling and Internationalization

RDMS uses the implementation–defined character set name RDMS_TEXT to identify


the character set name for all CHARACTER columns when no other character set is
specified. RDMS uses RDMS_TEXT to name the character set for data inserted in
RDMS databases prior to this release. All character string literals are considered
RDMS_TEXT.

Character Strings and Collating Sequences


A character string is a sequence of characters chosen from the same character set. A
character string has a length, which is the number of characters in the sequence.

All character strings of a given character set are mutually comparable only if they have
the same collating sequence.

A collating sequence, also known as a collation, is a set of rules determining


comparison of character strings in a particular character set.

Given a collating sequence, two character strings are identical if and only if they are
equal in accordance with the collation rules.

When character strings have explicit collating sequences, the comparison of two
character strings depends on the collating sequence used for the comparison. Since
RDMS always strips trailing spaces from character column values or literals before
transforming the data to an ordering key value, the shorter value is effectively
extended to the length of the longer value by concatenating binary zeros on the right.

COLLATE Clause
The COLLATE clause has two functions:

• On a column definition, it tells RDMS how to compare and order column values
and indexes.
• In an ORDER BY clause of a DECLARE CURSOR statement, it tells RDMS how to
collate (sort) the data after it is retrieved from the database.

SQL 92 Syntax
COLLATE collation-name

where collation–name can be either character–representation or


“character–representation”:
Character–representation is the name of the locale that describes the desired
collation. It can be any locale supported by the I18N service library and installed on
your system. Ask your system administrator which locales are installed on your
system.
If the name contains a hyphen or period, you must enclose it in quotation marks (for
example, “it_IT.8859–1”).
For more detailed information about locales and the processing rules defined for each
locale, see The I18N Assistant.

7830 8160–027 2–99


Character Handling and Internationalization

Collation names must be installed on the system and must be legal values for the
LOCALE_NAME_TO_LOCALE_NUMBER service routine provided by the I18N service
library to be allowable at RDMS definition or execution time. The locales installed on
your system determine the legal values. For more information, consult The I18N
Assistant.
Collation names are case–sensitive. RDMS treats names that are not enclosed in
quotation marks as if all characters in the name were uppercase characters.
Each collation has an implicit or explicit character set associated with it. The character
set must match the implicit or explicit character set of the related RDMS column or
program variable. For example, if a table contains a column with CHARACTER SET ABC
and COLLATE COLL1, then COLL1 must be associated with character set ABC. This
association is defined by the I18N service library and can be determined by reports
from UREP. For more information about creating I18N UREP reports, see The I18N
Assistant.

Examples
COLLATE C

COLLATE "it_IT.8859-1"

Handling Expressions
The introduction of internationalization (I18N) processing changes the way character
columns can be used in expressions. This processing applies to any expression with a
comparison operator: <, <=, =, <>, ^=, !=, >=, >, BETWEEN, IN, NOT NULL, and EXISTS.
Columns with a COLLATE clause are not allowed with the LIKE operator.

Processing
How RDMS processes character string literals and columns of data type CHARACTER
depends on both of the following:

• Whether the column definition contains an explicit CHARACTER SET specification.


If no CHARACTER SET clause was included in the column definition, the column is
said to have an implicit character set name.
• Whether the column definition contains an explicit COLLATE specification. If no
COLLATE clause was included in the column definition, the column is said to have
an implicit binary collation.

When values of unequal length that do not have explicit collating sequences are
compared, the shorter value is effectively extended to the length of the longer by
concatenation of spaces on the right. RDMS always uses the character with the octal
code of 040 (an ASCII space) for a column with an implicit binary collation.

2–100 7830 8160–027


Character Handling and Internationalization

Implicit Character Set (Implicit Collation)


RDMS assigns the column the character set name RDMS_TEXT if a column definition
has no explicit character set name, as in the first example, or if the character set
RDMS_TEXT is explicitly specified, as in the second example:

CREATE TABLE t1
(col1 CHAR(20))

CREATE TABLE t1
(col1 CHAR(20) CHARACTER SET RDMS_TEXT)

All data entered into RDMS databases before the introduction of I18N features has an
implicit character set name of RDMS_TEXT. The implicit ordering for the character set
name follows the binary codes for the character representations.

Existing data in a column may actually be encoded in any character set. The following
examples assume that the data actually in the column uses a LATIN1 or ISO 8859–1
character set. If the data actually in the column used an ISO 646 national variant, the
results may differ.

The binary character order for the ISO 8859–1 character set is as follows:

<space> ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F


GHIJKLMNOPQRSTUVWXYZ[\]^_'abcdefghijklm
nopqrstuvwxyz{|}~¡¢£¤¥¦§¨©ª«¬-®¯°±²³´µ¶·¸¹º»¼
½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞ
ßàáâ ãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ

For example, suppose columns COL1 and COL2 are defined as CHARACTER with no
explicit character set name and no explicit collation. If a data item of column COL1 has
the character value 'X' and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:

Expression Value

col1 = ‘x’ False (comparison is still case-sensitive)


col1 = ‘X’ True
col1 < ‘r’ False
col1 < ‘R’ False
col1 < ‘z’ True
col1 < ‘Z’ True
col1 < ‘Å’ True
col1 > ‘ß’ False
col1 BETWEEN ‘t’ and ‘Å’ True
col1 = col2 Unknown
‘abc’ < col2 Unknown

7830 8160–027 2–101


Character Handling and Internationalization

For information on how to attach a standard character set name or


implementation–defined character set name to a column defined as CHARACTER,
see 2.9.

Explicit Character Set (Implicit Collation)


RDMS assigns the specified character set name to the column if the column definition
has an explicit character set name, as in this example:

CREATE TABLE t1
(col1 CHAR(20) CHARACTER SET "ISO8859-1")

When a column is defined with an explicit character set name, other than RDMS_TEXT,
RDMS enforces that the values inserted into the column are encoded using that
character set.

For example, if column COL1 is as defined in the preceding example, then column
COL2 must also be defined with the clause CHARACTER SET “ISO8859–1” in the
expression:

INSERT INTO t1 (col1) SELECT col2 FROM t2

However, columns defined implicitly or explicitly with the character set name
RDMS_TEXT can be the source or destination for columns defined with any character
set name. In the preceding example, col2 could also be defined with the character set
name RDMS_TEXT. Likewise, CHARACTER columns with no explicit character set can
be the source or destination for columns defined with any character set name.

2–102 7830 8160–027


Character Handling and Internationalization

Table 2–12 summarizes the legal comparison combinations. The definitions in the first
column of the table are the first operand in a comparison expression. The definitions in
the top row of the table are the second operand in a comparison expression.

Table 2–12. Rules of Comparison

Operand 2 CHARACTER with no


CHARACTER SET or
Operand 1 RDMS_TEXT CHARACTER
SET (binary collation
implied) NCHARACTER (NCHAR)

CHARACTER with no CHARACTER Binary collation Binary comparison


SET or RDMS_TEXT CHARACTER
SET (binary collation implied)
NCHARACTER (NCHAR) Binary comparison Binary collation
Explicit CHARACTER SET (not Binary collation (exception ERROR: character set
RDMS_TEXT); no COLLATE clause to the rule) * names do not match
Explicit CHARACTER SET; explicit ERROR: collations do not ERROR: character set
COLLATE clause match * names do not match
CHARACTER with no CHARACTER Binary collation (exception ERROR: collations do not
SET or RDMS_TEXT CHARACTER to the rule) * match *
SET (binary collation implied)
NCHARACTER (NCHAR) ERROR: character set ERROR: character set
names do not match names do not match
Explicit CHARACTER SET (not Validate, then binary ERROR: collations do not
RDMS_TEXT); no COLLATE clause collation ** match
Explicit CHARACTER SET; explicit ERROR: collations do not Validate and proceed
COLLATE clause match accordingly **

* This case is allowed only when one operand is a string literal or a program variable. RDMS
uses the explicit collation of the other operand.
** Two columns can be compared only if their character sets match and their collations match.

For information on how to attach a standard character set name or


implementation–defined character set name to a column defined as CHARACTER,
see 2.9.

Explicit Collation (Explicit Character Set)


Columns can be defined with an explicit collation.

Example
CREATE TABLE t1
(col1 CHAR(20) CHARACTER SET "ISO8859-1" COLLATE "da_DK.8859-1")

RDMS uses I18N library service routines with the rules in the specified collation when
processing values in the column.

7830 8160–027 2–103


Character Handling and Internationalization

Example: Danish
The collation then follows the collation rules for the specified locale. For example,
"da_DK.8859–1" indicates the collation for the Danish language in Denmark. For more
details on specific locale definitions, see The I18N Assistant.

The following is the collation order for Danish:


<space> _ ¯- , ; : ! ¡ ? ¿ / . ´ ` ^ ¨ ~ · ¸ ' " « » ( ) [ ] { } § ¶ © ® @ ¤ ¢ $ £ ¥ * \& #
%+±÷×<=>¬|¦°µ0¼½¾1¹2²3³456789AaªÁáÀàÂâÃãBb
CcÇçDdÐðEeÉéÈèÊêËëFfGgHhIiÍíÌìÎîÏïJjKkLlMmNn
Ñ ñ O o º Ó ó Ò ò Ô ô Õ õ P p Q q R r S s ß T t Þ þ U u Ú ú Ù ù Ûû Ü ü V v W w
X x Y y Ý ý ÿ Z z Æ æ Ä ä Ø ø Ö ö Å AA å aa

Peculiar to the Danish collating scheme are the characters that collate after z. For
collating purposes, the characters “AA” are a synonym for Å and the characters “aa”
are a synonym for å.
Some of the characters in the character set do not occur in the Danish language. The
characters Ñ, and ñ, for example, do not appear in Danish. These characters belong to
the ISO 8859–1 character set, however, and must be accommodated in the
da_DK.8859–1 ordering scheme.

For example, suppose columns COL1 and COL2 are defined as having the ISO8859–1
character set name and da_DK.8859–1 collation. If a data item of column COL1 has the
character value “X” and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:

Expression Value

col1 = ‘x’ False (comparison is still case-sensitive)


col1 = ‘X’ True
col1 < ‘r’ False
col1 < ‘R’ False
col1 < ‘z’ True
col1 < ‘Z’ True
col1 < ‘Å’ False
col1 > ‘ß’ True
col1 BETWEEN ‘Å’ AND ‘t’ False
col1 = col2 Unknown
‘abc’ < col2 Unknown

2–104 7830 8160–027


Character Handling and Internationalization

Example: German
The collation follows the collation rules for the specified locale. For example,
“de_DE.8859–1” indicates the collation for the German language in Germany. For more
details on specific locale definitions, see The I18N Assistant.

The collation order for German is as follows:


<space> _ ¯- , ; : ! ¡ ? ¿ / . ´ ` ^ ¨ ~ · ¸ ' " « » ( ) [ ] { } § ¶ © ® @ ¤ ¢ $ £ ¥ * \
&#%+±÷×<=>¬|¦°µ0¼½¾1¹2²3³456789AaªÁáÀàÂâ
ÅåÄäÃãÆæBbCcÇçDdÐðEeÉéÈèÊêËëFfGgHhIiÍíÌì
ÎîÏïJjKkLlMmNnÑñOoºÓóÒòÔôÖöÕõØøPpQqRrSs
ßTtÞþUuÚúÙùÛûÜüVvWwXx YyÝýÿZz

Peculiar to the German collating scheme, the “sharp S” or Eszet collates as if it were
“ss”. So the words “Straße” and “Strasse” compare as equal.
Some of the characters in the character set do not occur in the German language. The
characters Ñ and ñ, for example, do not appear in German.
These characters belong to the ISO 8859–1 character set, however, and must be
accommodated in the de_DE.8859–1 ordering scheme.
For example, suppose columns COL1 and COL2 are defined as having the ISO8859–1
character set name and de_DE.8859–1 collation. If a data item of column COL1 has the
character value “X” and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:

Expression Value

col1 = ‘x’ False (comparison is still case-sensitive)


col1 = ‘X’ True
col1 < ‘r’ False
col1 < ‘R’ False
col1 < ‘z’ True
col1 < ‘Z’ True
col1 < ‘Å’ False
col1 > ‘ß’ True
col1 BETWEEN ‘Å’ AND ‘t’ False
col1 = col2 Unknown
‘abc’ < col2 Unknown

7830 8160–027 2–105


Character Handling and Internationalization

Example: Spanish
The collation follows the collation rules for the specified locale. For example,
“es_ES.8859–1” indicates the collation for the Spanish language in Spain. For more
details on specific locale definitions, see The I18N Assistant.

The collation order for Spanish is as follows:


<space> _ ¯- , ; : ! ¡ ? ¿ / . ´ ` ^ ¨ ~ · ¸ ' " « » ( ) [ ] { } § ¶ © ® @ ¤ ¢ $ £ ¥ * \
&#%+±÷×<=>¬|¦°µ0¼½¾1¹2²3³456789AaªÁáÀàÂâ
Å å Ä ä Ã ã Æ æ B b C c Ç ç CH ch D d Ð ð E e É é È è Ê ê Ë ë F f G g H h
I i Í í Ì ì Î î Ï ï J j K k L l LL ll M m N n Ñ ñ O o º Ó ó Ò ò Ô ô Ö ö Õ õ Ø ø P p Q q
RrSsßTtÞþUuÚúÙùÛûÜüVvWwXx YyÝýÿZz

Peculiar to the Spanish collating scheme, the characters CH and ch collate between
cz and da. Thus, the correct ordering of the words “chorizo,” “czar,” and “day,”
according to the Spanish collating scheme, is “czar,” followed by “chorizo,” followed
by “day.”

Similarly, the characters “LL” and “ll” collate between “lz” and “ma”. Thus, the correct
ordering of the words “llama,” “lyric,” and “man” is “lyric,” followed by “llama,”
followed by “man.”

Some of the characters in the character set do not occur in the Spanish language. The
characters Ø and ø do not appear in Spanish, for example.

These characters belong to the ISO 8859–1 character set, however, and must be
accommodated in the es_ES.8859-1 ordering scheme.

For example, suppose columns COL1 and COL2 are defined as having the ISO8859-1
character set name and es_ES.8859-1 collation. If a data item of column COL1 has the
character value “X” and a data item of column COL2 is NULL, the values of the
following expressions are as indicated:

Expression Value

col1 = ‘x’ False (comparison is still case-sensitive)


col1 = ‘X’ True
col1 < ‘r’ False
col1 < ‘R’ False
col1 < ‘z’ True
col1 < ‘Z’ True
col1 < ‘Å’ False
col1 > ‘ß’ True
col1 BETWEEN ‘Å’ AND ‘t’ False
col1 = col2 Unknown
‘abc’ < col2 Unknown

2–106 7830 8160–027


Character Handling and Internationalization

If a data item of column COL1 has the character value “Chorizo”, the values of the
following expressions are as indicated:

Expression Value

col1 = 'chorizo' False (comparison is still case-sensitive)


col1 = 'Chorizo' True
col1 < 'cz' False
col1 < 'CZ' False
col1 < 'd' True
col1 BETWEEN 'czar' AND 'day' True

2.9.3. Collating Sequence


For the data type CHARACTER, RDMS uses the collating sequence in the column
definition when comparing characters to determine the correct order required by

• Primary keys
• Secondary indexes
• GROUP BY clause
• ORDER BY clause
• Boolean expressions

For the data type NCHARACTER, values collate according to the binary sequence of
the characters.

The COLLATE clause on the column definition determines the collating order for
column values. For more information on the collating order for the supported locales,
consult The I18N Assistant.

If no COLLATE clause is included on the column definition, values collate according to


the binary value of the character. For the ISO 8859–1 character set (also called the
LATIN1 character set) the order of the characters is as follows:

<space> ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F


GHIJKLMNOPQRSTUVWXYZ[\]^_'abcdefghijklm
nopqrstuvwxyz{|}~¡¢£¤¥¦§¨©ª«¬-®¯°±²³´µ¶·¸¹º»¼
½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞ
ßàáâ ãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ

This character set supports the Danish, Dutch, English, Faroese, Finnish, French,
German, Icelandic, Irish, Italian, Norwegian, Portuguese, Spanish, and Swedish
languages.

US ASCII is a subset of the ISO 8859–1 character set and consists of the characters
space through tilde ( ~ ).

7830 8160–027 2–107


Character Handling and Internationalization

2.9.4. Kanji Data


In UCS COBOL, UCS C, and UCS FORTRAN programs, you store kanji data in columns
defined as NCHARACTER using kanji type host program variables or embedded
variables as arguments.

ASCII COBOL and ASCII FORTRAN, however, do not have kanji type variables. When
you use one of these languages to work with kanji data, use alphanumeric host
program variables to store the data. The interface routines for these languages
(ACOB$RDMR and F$RDMR) are not informed that kanji data is being passed.

RDMS treats the data as though it were ASCII data, but the kanji data remains intact.
Remember that NCHARACTER columns use two bytes to store one kanji character.
Host program variables must therefore be declared to be twice as long as the kanji
column to avoid truncation.

For more information on CHARACTER and NCHARACTER data types, and kanji data,
see 2.9.

2–108 7830 8160–027


Host Language Variables

2.10. Host Language Variables


In most database applications that use programming languages, you must pass
information between a program and RDMS. The mechanism and procedure you use
depend on the interface you choose.

A host program variable is any variable declared in a third–generation programming


language and used only in the context of the programming language. It is not part of
an SQL statement.

You can use a host program variable to

• Hold information you are passing to RDMS using (for example, an INSERT
statement).
• Receive information retrieved by RDMS (for example, using a FETCH statement).
• Contain information from an application that is to be compared with a value in an
RDMS table. This is typically included in the WHERE clause of a query
specification.

For example, in a real estate application, a program might prompt users for a desired
location. This location is stored in a host program variable. RDMS compares that value
with the location value of the rows in table HOUSES to determine whether to retrieve
a given row.

You need a host program variable for each column into which you are inserting values,
from which you are retrieving values, or with which you are comparing values.

Other terms with which you should be familiar are as follows:

• Embedded variable
ESQL syntactically handles comparisons between RDMS and program data and the
moving of data to or from RDMS differently from how the interpreter interface
handles them. You prefix the host program variable name with a colon ( : ) and
embed it in the command string. Such a variable is called an embedded variable.
Host program variable names must be ASCII characters; they cannot contain kanji
or katakana characters.
• Parameter marker
ESQL permits you to place parameter markers in the SQL command string being
prepared. These are called dynamic parameter markers.
• Placeholder variable
In the interpreter interface, you must pass the SQL command string to RDMS. If
you are moving values to or from RDMS, or if RDMS is comparing a value from a
program with a value in a table, you must place markers in the SQL command
string to hold a place for values. These markers are called placeholder variables.
The call to RDMS must have a host program variable for each placeholder variable.

7830 8160–027 2–109


Host Language Variables

• Indicator variable
An indicator variable is an embedded variable, parameter marker, or placeholder
variable that contains a null value, a nonnull valid value, or the defined size of a
CHARACTER column.

All variables in an SQL statement must be of the same type; that is, they must all be
embedded variables, parameter markers, or placeholder variables.

2.10.1. Embedded Variables


Use the following format to embed variables in a static ESQL statement:

:embedded-variable-name,...

where embedded–variable–name is the name or names of up to 510 host program


variables.

You can omit the colon if ambiguity is not a problem.

Declare embedded variables between the BEGIN DECLARE (see 6.3) and
END DECLARE (see 8.1) statements, both of which are optional.

Example
EXEC SQL FETCH c1 INTO :house, :cust END-EXEC.

You can use an embedded variable to specify a version name in a table specification of
an ESQL statement. Since a colon ( : ) is used to prefix both an embedded variable and
a version name in a table specification, you must use two colons to correctly identify
the variable as an embedded variable containing a version name.

Use the following format to pass a version name with embedded variables:

[ qualifier.]table-specification[::variable-name]

where variable–name is the name of an unqualified, unsubscripted character type host


program variable that contains the version name.

Examples
If a host program variable VERNAME has the value OUTSTATE, the following table
specification names table Q1.HOUSES:OUTSTATE:

q1.houses::vername

When you use an embedded variable to pass a version name in connection with a
DECLARE CURSOR statement, the value of the embedded variable is not passed to
RDMS until the cursor is opened.

2–110 7830 8160–027


Host Language Variables

In the next example, the opened cursor is based on HOUSES:V2:

MOVE 'v1' TO vername.


EXEC SQL DECLARE xyz CURSOR
SELECT * FROM houses::vername END-EXEC.

MOVE 'v2' TO vername.


EXEC SQL OPEN xyz END-EXEC.

When a version name is passed in an embedded variable, the rules for delimited
identifiers apply (see 2.2.1). In particular, lowercase letters are not equivalent to
uppercase characters.

2.10.2. Parameter Markers


Parameter markers in SQL statements being prepared by dynamic ESQL statements
hold the place of a value to be supplied later (in an EXECUTE statement) through a
program variable reference. You must pass one embedded program variable as a
parameter for each parameter marker you place in the SQL command string.

Parameter markers are represented by question marks ( ? ).

Although you can use more than one parameter marker in your code, you must rely on
the one–to–one correspondence of question mark to embedded program variable to
ensure which parameter marker is serving what purpose.

Example
EXEC SQL PREPARE del FROM
'DELETE customers WHERE cno = ?'
END-EXEC.
EXEC SQL EXECUTE del USING :cus-no END-EXEC.

2.10.3. Placeholder Variables


A placeholder variable is a place to hold values in a program that uses the interpreter
interface.

Placeholder variable names have a leading dollar sign and the letter P to distinguish
them from other names, as follows:

$Pinteger

where integer is greater than or equal to one and has no leading sign. The placeholder
variable name cannot contain blanks.

You must pass one host program variable as a parameter for each placeholder variable
you place in the SQL command string.

7830 8160–027 2–111


Host Language Variables

Examples
The following are valid placeholder variable names:

$p1

$p5

$p10

The following names are not valid:

$P

P1
$P(1)

$Pete

$P0

$ p2

$P 3

The integer portion of a placeholder variable name associates it with a host program
variable in the RDMS call.

The next example shows that placeholder variables are useful for changing parameter
values within a statement:

INSERT INTO houses VALUES ($p1, $p2, $p3, $p4)

where $P1, $P2, $P3, and $P4 are placeholders for variables passed from the program
to RDMS.

This statement inserts a row of data that contains all four item values into table
HOUSES.

One way to use this statement is in a loop that changes the values of the associated
application program variables. With each execution of the loop, RDMS stores a new
row in table HOUSES.

Names in Placeholder Variables


You can use placeholder variables to specify the names of tables, views, columns,
qualifiers, versions, and cursors in a statement. Pass names like you pass data (that is,
assign a value to a character type variable in the program and pass that variable to
RDMS with the statement containing the corresponding placeholder variable).

Note: You can use embedded variables to pass names only for versions.
See 2.10.1.

2–112 7830 8160–027


Host Language Variables

Since both names and data can be passed to RDMS as placeholders, RDMS follows
this rule to differentiate between the two. If the placeholder variable appears where
an expression can appear, RDMS considers it to be data, not a name; otherwise,
RDMS considers it a name.

Examples
In the following statement, RDMS considers $P1 and $P2 as data:

INSERT INTO houses VALUES ($p1,'X',152000,$p2)

In the next statement, RDMS considers $P1 and $P2 names because they appear
where only names can appear:

INSERT INTO $p1 COLUMNS ($p2='C106')


USE DEFAULT QUALIFIER $p1

If you attempt to pass a name where an expression can appear, RDMS may return an
error or invalid results.

Follow these additional guidelines for names in placeholder variables:

• A placeholder variable can be used only in place of a simple name. It cannot


contain a qualified name such as RDMS.HOUSES.
• A placeholder variable cannot be used to contain a name in the DECLARE CURSOR,
CREATE TABLE, CREATE INDEX, CREATE VIEW, ALTER TABLE, DROP TABLE,
DROP INDEX, OPEN, or SELECT statements.
This restriction is enforced in part to prevent the possibility of a program creating
an entity with an uninitialized variable passed as the entity name.

Placeholder Variables in Application Programs


You can use placeholder variables from UCS COBOL, UCS C, and UCS FORTRAN
programs, as well as from the IPF SQL Interface.

Example 1
The following UCS FORTRAN example illustrates the relationship of placeholder
variables to application program variables in an RDMS CALL statement:

lolim = 8000
hilim = 10000
CALL F$RDMR('DELETE houses WHERE price'//
$ 'BETWEEN $p1 AND $p2;',
$ errloc, auxinf, lolim, hilim)

In this example, the variable $P1 is a placeholder for the FORTRAN variable LOLIM.
This is in the first parameter after the error status and auxiliary information variables.
$P2 is a placeholder for HILIM, the second parameter after the error status and
auxiliary information variables.

7830 8160–027 2–113


Host Language Variables

The possible numbers in the placeholder variable names range from 1 to the number
of host program variables passed with the statement. For example, if four variables
are passed, the placeholders can be $P1, $P2, $P3, and $P4.

Example 2
The next example shows that placeholder variables can appear in any order and any
number of times:

INSERT INTO houses COLUMNS (hno = $P3, location = $p1, price = $p2,
description = $p1) ;

Columns LOCATION and DESCRIPTION are set to the same value.

Assume the preceding INSERT statement is stored in the FORTRAN character variable
CMD and followed by the statement

CALL F$RDMR(cmd, errloc, auxinf, var1, cost, idno):

The value of VAR1 goes into columns LOCATION and DESCRIPTION (through $P1). The
value of COST goes into column PRICE (through $P2). The value of IDNO goes into
column HNO (through $P3).

Example 3
The final example, which executes the same operation as the preceding example,
shows that you do not have to associate a placeholder variable with each host
program variable passed with a statement.

CALL F$RDMR ('INSERT INTO houses COLUMNS ' //


+ '(hno = $p4, location = $p1, price = $p2, ' //
+ 'description = $P1) ;' errloc,auxinf,
+ var1,cost,unused,idno)

2.10.4. Indicator Variables


You can use embedded variables, parameter markers, and placeholder variables in an
SQL statement for either of the following uses:

• Data variables, which hold values


• Indicator variables, which are flags that describe the contents of data variables
An indicator variable reveals whether the associated data variable has a null value,
a nonnull valid value, or was truncated.

You use data variables and indicator variables, except for parameter markers, in pairs
to access columns. See the last example for the use of parameter markers.

When using indicator variables to determine whether the retrieved CHARACTER


column is defined to be longer than the host program variable, RDMS truncates the
character string and retrieves only the maximum number of characters defined for the
host program variable.

2–114 7830 8160–027


Host Language Variables

The indicator variable returns the defined size of the column of the table whenever it
is greater than the defined size of the host program variable, even if the truncated
characters are nonsignificant trailing blanks.

The host program variable corresponding to an indicator placeholder variable or


embedded variable serving as an indicator variable must be signed numeric.

Table 2–13 illustrates what different values returned by indicator variables mean.

Table 2–13. Values of Indicator Variables

Value of
Indicator Signifies on INSERT/UPDATE Signifies on SELECT/FETCH

-1 The corresponding data variable has The database column has a null
a null value.* value.*
Other Negative The corresponding data variable has ---
Values a value.
Note: This is the way RDMS has
always worked, but it is contrary to
SQL 2003, which states that all
negative values signify NULL.
Zero The corresponding data variable has The corresponding data variable has
a value. a value.
1 The corresponding data variable has The database value is too long for
a value, except for UPDATE the corresponding data variable and
SYNCHRONIZE, in which case the is truncated.
UPDATE does not change the
existing values in the table.
Other Positive The corresponding data variable has ---
Values a value.

* In either case, the value of the data variable is undefined.

You must provide a null indicator variable for each column that allows nulls. RDMS
returns an error if a null without an indicator variable is retrieved.

To use variables in a list, separate the data variable (first of the pair) from the indicator
variable with the keyword INDICATOR or a blank:

data-variable [ [ INDICATOR ] indicator-variable ]

Example 1
The following two lines both link data variable $P1 and its indicator variable $P2:

$p1 $p2
$p1 INDICATOR $p2

7830 8160–027 2–115


Host Language Variables

The next two lines both link the embedded variables :DATAVAR and :INDICVAR as data
variable and indicator variable:

:DATAVAR :INDICVAR
:DATAVAR INDICATOR :INDICVAR

Example 2
The following UCS COBOL example inserts a row into table CUSTOMERS with a null in
column CNAME (the second column of the table):

MOVE -1 TO null-indic.
MOVE 'c109' TO cno.
MOVE 80000 TO max-price.
MOVE 'gotham' TO des-loc.
ENTER MASM 'ACOB$RDMR' USING
'INSERT INTO customers VALUES ($p1,$p2 $p3,$p4,$p5);',
error-code, aux-info, cno, cust-name,
null-indic, max-price, des-loc.

Example 3
The next UCS COBOL example illustrates the preceding example rewritten to use
ESQL:

MOVE -1 TO null-indic.
MOVE 'c109' TO cno.
MOVE 80000 TO max-price.
MOVE 'gotham' TO des-loc.
EXEC SQL INSERT INTO customers VALUES (:cno, :cust-name :null-indic,
:max-price, :des-loc) END-EXEC.

Example 4
The next UCS FORTRAN example illustrates the use of an indicator variable in a FETCH
statement:

CALL F$RDMR('FETCH NEXT c1 INTO $p1,$p2 $p3,$p4,$p5;',


+ errcod,aux,cno,cname,null,maxpri,
+ locat)
IF (NULL.LT.0)
PRINT *, 'CUSTOMER NAME IS NOT KNOWN.'

Example 5
In the next example, the cursor TWOCOL has two columns, CNAME and
DESIRED_LOC. The variables NAME and DESLOC are declared as eight characters
each. The cursor is positioned to retrieve the values “Owen” and “New London.” To
retrieve a row, enter the following:

CALL F$RDMR('FETCH NEXT twocol INTO $p1 $p2,$p3 $p4;',


+ errcod,auxinf,name,ind1,desloc,ind2)

2–116 7830 8160–027


Host Language Variables

The value of each of the program variables is as follows.

Variable Value Comments

name Owen
ind1 0 No truncation occurred even though the application
program variable is smaller than the column in the table
(28-character capacity).
desloc New Lond
ind2 40 RDMS truncated the data value because the length of
the returned character value exceeded the size of the
host program variable. (The column capacity is 40
characters.)

Example 6
To use indicator variables in conjunction with a dynamic ESQL statement, use a single
parameter marker for the value of each variable, and use a pair of embedded variables
in the USING clause of the corresponding EXECUTE statement, as in the following
example:

EXEC SQL PREPARE st1 FROM


'INSERT INTO customers VALUES ("C106",?,150000,"Woodbury")' END-EXEC.
EXEC SQL EXECUTE st1
USING :cust INDICATOR :indicvar END-EXEC.

7830 8160–027 2–117


Embedded SQL (ESQL)

2.11. Embedded SQL (ESQL)


RDMS supports SQL through the interpreter interface, where each SQL statement
calls RDMS before executing whether you use a compiled program (written in UCS
COBOL, for example) or an online tool like the IPF SQL Interface. When RDMS is
called, it examines and processes the statement and then executes it if it parses
correctly and has no other errors.

This powerful approach allows you to write programs that take very different
measures with the database depending on the circumstances they encounter. Since
each SQL statement must be interpreted each time it is executed, however, the
overhead in calling RDMS can be significant. This is particularly true in tight loops
where some statements have to be executed many times.

You can also embed SQL statements in UCS COBOL and UCS C programs, not as an
ENTER MASM interpreter interface call, but in a form very much like any other COBOL
or C statement. SQL statements embedded in this manner are compiled instead of
interpreted. This interface is called ESQL, which takes two forms: static and dynamic.
For a closer look at dynamic ESQL, see 2.11.6.

If the UCS COBOL or UCS C LEVEL/SQL FLAGGER is turned on, warnings of


nonconforming SQL language or of conforming SQL language that may be processed
in a nonconforming manner are returned during program compilation. You can identify
all SQL language occurrences that may have to be modified if an application is being
moved from a nonconforming to a conforming SQL processing environment.

Example
The following line is an example of a static ESQL statement:

EXEC SQL OPEN main_cursor END-EXEC.

For a summary of which SQL statements you can use with ESQL, see Section 5. For an
example ESQL program, see the COBOL Compiler Programming Reference Manual
Volume 1.

By compiling SQL statements, you avoid a great deal of overhead in RDMS when a
program encounters SQL statements during execution. This results in a significant
reduction in execution time.

Note the following considerations for static ESQL:

• Part of the processing during program compilation is a check with RDMS to


ensure that the SQL statement is valid. ESQL code must conform generally to the
database as it is defined during compilation.
This means, for example, that you cannot embed SQL code to retrieve data from a
table that is not yet created when the program that accesses the table is
compiled. A nonexisting table during compilation causes an error. You can use
dynamic ESQL to resolve fluid programming situations like this.
• The extra compilation processing can take more time. However, the execution of
static ESQL code usually takes considerably less time than interpreted code.

2–118 7830 8160–027


Embedded SQL (ESQL)

2.11.1. Static ESQL


To write and execute a static ESQL program, follow these steps:

1. Embed SQL statements in the UCS COBOL program.


2. Create the tables used by the program.
3. Compile the program. The compiler produces an object module containing the UCS
COBOL instructions and the SQL statements in a processed form ready for RDMS
to execute.
4. Link the program (if you want a statically linked program).
5. Execute the program.

When the program executes, each SQL statement in the object module is checked
during execution to ensure that it is not out of date. This prevents errors that would
otherwise occur if the database definition changed between the compilation and
execution of the program.

For details on porting a static ESQL program or module from one application group or
host to another, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

2.11.2. Automatic Recompilation


Programs compiled prior to RDMS level 9R2 must be recompiled in order for RDMS
automatic recompilation to invoke itself. Programs compiled at RDMS level 9R2 and
higher, however, attempt to recompile themselves internally and execute any static
ESQL statements that reference modified tables. If the static ESQL statements that
reference modified tables can execute without syntax changes to the UCS program,
the program executes without errors.

Error statuses and error messages appear whenever a static ESQL statement is not
compatible with the modified table.

Automatic recompilation during the execution of a program affects performance to


some extent. UCS COBOL and UCS C programs that contain static ESQL statements
continue to execute after certain kinds of modifications to tables are made. It is
recommended that these programs be recompiled for maximum performance.

The occurrence of RDMS automatic recompilation is noted in thread statistics so that


you can identify programs that contain statements dependent on automatic
recompilation. If you wish, you can recompile them to regain the full performance
benefits of static ESQL.

Whenever automatic recompilation occurs while executing static ESQL programs that
are compiled with default qualifiers and versions, the RDMS internal compilation
process uses compile time qualifiers and versions to create the execution instruction
set. For further details on qualifier and version names, see 2.2.1.

7830 8160–027 2–119


Embedded SQL (ESQL)

Statistical information can change, however, between compilation and execution time.
RDMS uses current statistical information if statistics is on (SET STATISTICS ON) and
automatic recompilation is performed. Therefore, if you use portable ESQL to launch
your application, the STATS$FILE may not contain valid statistics. For further
information on porting ESQL programs, refer to the Relational Database Server for
ClearPath OS 2200 Administration Guide.

To ensure that appropriate execution paths are selected, you should run statistics
whenever you make any changes to tables that are likely to invoke automatic
recompilation.

2.11.3. Marking ESQL Statements for the Compiler


So that the compiler can process the ESQL statements correctly, you must bracket
them with special COBOL code. Place EXEC SQL in front of the statement and
END-EXEC after it.

Example
EXEC SQL SQL-statement END-EXEC.

Embedded SQL statements in an ESQL UC program are bracketed with EXEC SQL and
the C statement's terminating semicolon.

Example
EXEC SQL SQL-statement ;

In either case, the ESQL statement cannot contain a semicolon. Do not break
EXEC SQL or END-EXEC across a line boundary. The SQL statement can span as many
lines as necessary.

2.11.4. Scope of ESQL Statements


Some SQL statements affect other statements within the same program. For
example, the SET STATISTICS ON statement instructs RDMS to use previously
acquired statistics to optimize the access paths it uses on queries. The USE DEFAULT
statement informs RDMS of the qualifier or version name to assume in subsequent
statements.

In the interpreted and dynamic ESQL environments, these statements affect the
statements that follow them in execution. This follows from the interpreted nature of
this type of SQL interaction with the database. But ESQL statements are compiled,
and they may be compiled in an order different from the order in which they are
executed.

Certain ESQL statements, however, affect statements that follow them in the source
code for the compilation unit in which they are found. If two statements are both
found in object module A, the one that appears first in the listing affects the other.

2–120 7830 8160–027


Embedded SQL (ESQL)

This gives rise to some important characteristics of certain static ESQL statements:

• A SET STATISTICS statement affects all other static ESQL statements that follow it
textually in the listing until superseded by another SET STATISTICS statement.
• Likewise, a USE DEFAULT statement affects all other static ESQL statements that
follow it textually in the listing until superseded by another similar USE DEFAULT
statement. For special considerations on the use of defaults in routines and
triggers, see Section 4, 8.6 (FETCH), and 9.4 (OPEN).
• A cursor declaration must appear in the source listing before any static ESQL
reference to it.
• A WHENEVER statement affects all other static ESQL statements that follow it
textually in the listing until superseded by another WHENEVER statement.
• A static ESQL DEBUG statement causes the compiler to print compile-time
information of all subsequent static ESQL statements until another static ESQL
DEBUG statement turns off the printing.

The static ESQL statements DECLARE CURSOR, DEBUG, SET STATISTICS, USE
DEFAULT, and WHENEVER are called compile-time statements because they are acted
upon by RDMS during program compilation. Even though the statements derived from
these statements may affect the execution of the program, the statements
themselves are not executed.

Example
This example illustrates the scope of compile–time ESQL statements. Assume you
have the following UCS COBOL program source code:

EXEC SQL WHENEVER SQLERROR GO TO error-para END-EXEC.


:
: (Intervening statements omitted.)
:
EXEC SQL DECLARE first CURSOR... .
:
EXEC SQL SET STATISTICS ON END-EXEC.
:
EXEC SQL DECLARE second CURSOR... .
:
EXEC SQL USE DEFAULT QUALIFIER success END-EXEC.
:
EXEC SQL DECLARE third CURSOR... .
:
EXEC SQL WHENEVER SQLERROR GO TO report-error END-EXEC.
EXEC SQL SET STATISTICS OFF END-EXEC.
:
EXEC SQL DECLARE fourth CURSOR... .:

7830 8160–027 2–121


Embedded SQL (ESQL)

Some characteristics of each DECLARE CURSOR statement, including the following,


can be charted:

• Where control goes in the program if an SQL statement returns an error


• Which default qualifier is used
• Whether table statistics are used in determining the access path of a cursor

The following table illustrates these characteristics for all four of the cursors in the
code fragment.

Error Handling
Cursor Name Paragraph Default Qualifier Statistics On/Off

First error-para RDMS Off


Second error-para RDMS On
Third error-para success On
Fourth report-error success Off

The values of these characteristics hold regardless of the order in which the DECLARE
CURSOR statements are encountered during program execution.

2.11.5. Resolving Cursor References


RDMS lets you declare a cursor in one object module (or compilation unit) and
reference it in another object module with another SQL statement. You can also have
ESQL and interpreter interface (ENTER MASM) cursors in the same program and have
references to ESQL cursors resolved by interpreter interface DECLARE CURSOR
statements, and vice versa.

Even though you cannot have ESQL DECLARE CURSOR statements with the same
cursor name in the same object module or two opened interpreter interface cursors
of the same name, you must establish certain guidelines for how duplicate cursor
names from the two interfaces or from different compilation units are resolved
(or bound):

To resolve cursor references in the OPEN statement:

• An ESQL OPEN statement must resolve to an ESQL ALLOCATE CURSOR or


DECLARE CURSOR statement in the same object module.
• An interpreter interface OPEN statement must resolve to an interpreter interface
DECLARE CURSOR statement.

2–122 7830 8160–027


Embedded SQL (ESQL)

Follow these guidelines to resolve cursor references in all other statements:

• Any cursor reference from a dynamic ESQL or interpreter interface statement is


resolved, first, from a like-named dynamic or interpreter interface cursor that was
opened previously in the execution stream. If such a cursor does not exist, it is
resolved from a currently opened, like–named static embedded DECLARE
CURSOR statement, provided that exactly one such cursor exists. If no such
cursor exists, or if more than one cursor exists, RDMS returns an error.
• Any cursor reference from a static embedded ESQL statement resolves to a
like-named static embedded DECLARE CURSOR statement in the same object
module, provided that such a declaration exists. If such a declaration exists and
the cursor is not opened, RDMS returns an error.
• A cursor reference from a static embedded ESQL statement resolves externally if
a like-named static embedded DECLARE CURSOR statement in the same object
module does not exist. A cursor reference from a static embedded ESQL
statement is resolved externally based on the following conditions:
 If a like-named interpreter interface cursor is opened, the cursor reference is
bound to it.
 If exactly one opened ESQL cursor from another object module exists, the
cursor reference is bound to it.
If neither of the preceding conditions applies, RDMS returns an error.

Example
This example illustrates these cursor resolution rules.

Assume subprogram OBJECT_MODULE_1 is executed before subprogram


OBJECT_MODULE_2. All statements, except the one marked “illegal,” are permitted.

OBJECT_MODULE_1

:
EXEC SQL DECLARE csr_3 CURSOR... .
EXEC SQL DECLARE csr_2 CURSOR... .
ENTER MASM 'ACOB$RDMR' 'DECLARE csr_1 CURSOR...',... .
EXEC SQL OPEN csr_2 END-EXEC.
ENTER MASM 'ACOB$RDMR' 'OPEN csr_3;',... . (Illegal; interpreter OPEN must
be matched by an interpreter
DECLARE)
ENTER MASM 'ACOB$RDMR' 'OPEN csr_1;',... .
ENTER MASM 'ACOB$RDMR' 'CLOSE csr_1;',... .
EXEC SQL OPEN csr_3 END-EXEC.

7830 8160–027 2–123


Embedded SQL (ESQL)

OBJECT_MODULE_2

:
EXEC SQL DECLARE csr_2 CURSOR... .
ENTER MASM 'ACOB$RDMR' 'OPEN csr_1;',... .
ENTER MASM 'ACOB$RDMR'
'UPDATE tbl SET c1 = 5 WHERE CURRENT OF csr_1;',... .
ENTER MASM 'ACOB$RDMR'
'UPDATE tbl SET c1 = 5 WHERE CURRENT OF csr_2;',... . (csr_2 opened in
OBJECT_MODULE_1
above)
EXEC SQL FETCH csr_3 INTO... .

2.11.6. Dynamic ESQL


A subset of ESQL statements allows UCS COBOL and UCS C programs to compose
and execute SQL statements without having to process them during compilation. This
subset is dynamic ESQL.

Suppose a program has a function in which an interactive user enters

• The name of a table to be updated


• The names of the columns to be updated
• The criteria for determining which rows to update

The program processes the data and creates an UPDATE statement in a host program
variable. You can have the program have RDMS compile and execute the statement,
either immediately or later when the program is executed.

Example
Suppose the SQL UPDATE statement is in variable update–stmt, which contains the
string:

UPDATE houses
SET price = 119000
WHERE hno = 'H101'

You prepare it first, giving it a statement name. Then you execute the prepared
statement to actually update the database:

EXEC SQL PREPARE prepped_update FROM :update-stmt END-EXEC.


EXEC SQL EXECUTE prepped_update END-EXEC.

The prepared statement can be executed any number of times, making it especially
useful in loops. You can replace the literals in the UPDATE statement with parameter
markers:

UPDATE houses
SET price = ?
WHERE hno = ?

2–124 7830 8160–027


Embedded SQL (ESQL)

Prepare it once and then, within a loop, have the program solicit the user for the new
price and house number. With these values in variables, execute the UPDATE
statement, passing the variables so that their values replace the parameter markers:

ACCEPT new-price.
ACCEPT house-number.
EXEC SQL EXECUTE prepped_update USING :new-price, :house-number END-
EXEC.

Whenever the statement is not formed until the program is executed and the
statement has to be executed only once, you can use the EXECUTE IMMEDIATE
statement, which performs essentially what PREPARE and EXECUTE statements
together perform.

In the preceding UPDATE statement, for example, which contains the literal values,
you can execute the following:

EXEC SQL EXECUTE IMMEDIATE :update-stmt END-EXEC.

7830 8160–027 2–125


Embedded SQL (ESQL)

2.11.7. Dynamic ESQL Statement Set


In EXECUTE IMMEDIATE Statements
Dynamic ESQL allows you to use the following SQL statements in the EXECUTE
IMMEDIATE statement:

DEBUG
DELETE
INSERT
LOCATE
LOCK
SET STATISTICS
UNLOCK
UPDATE
USE DEFAULT

In PREPARE Statements
Dynamic ESQL allows you to use the following SQL statements in the PREPARE
statement:

COMMIT
DELETE
INSERT
LOCATE
LOCK
ROLLBACK
SET STATISTICS
UNLOCK
UPDATE
USE DEFAULT

You can also use a cursor specification in the PREPARE statement.

For special considerations on the use of defaults in routines and triggers,


see Sections 4, 8.6 (FETCH) and 9.4 (OPEN).

2–126 7830 8160–027


Using SQL in Module Programs

2.12. Using SQL in Module Programs


Module procedures enable UCS FORTRAN programs to access an RDMS database.
Authorization to access the data is determined by individual modules, not by the user
ID of the user executing the module. This means that whoever has access to a
particular module also has access to the data it references.

Authorization to access the data is determined by the module authorization identifier


specified in the module. The module authorization identifier is used in the privilege
check for the schema being referenced in the database. The user represented by the
module authorization identifier must hold all necessary privileges for all SQL
operations contained in the module. The module authorization identifier is also used as
the default qualifier for all SQL statements within the module. Module authorization
identifiers that exceed 12 characters are truncated to 12 characters.

The use of module programs limits the method used to invoke RDMS, thus preventing
the mixing of requests from module and nonmodule programs in the same thread. It
further prevents the mixing of requests from different modules in the same thread.
The use of both a module language and another interface to access the database in
the same thread produces undefined results.

Other points to keep in mind when accessing RDMS from a module language
program:

• The module program must be the initial call to RDMS.


• Statements may come from only one module per thread; requests from outside
the module are not allowed.
• SQL statements attempting to access tables under a different qualifier or version
name must use the other qualifier or version name explicitly.
• The application administrator can restrict access to a particular module.

Most SQL statements that are allowed in ESQL are allowed in module programs. See
detailed information about the individual statements in Sections 5 through 10.

The following statements, however, are allowed in ESQL but are meaningless in a
module:

BEGIN DECLARE
END DECLARE
FETCH NEXT n (module languages do not allow arrays)
USE DEFAULT
WHENEVER

7830 8160–027 2–127


Using SQL in Module Programs

The following statements are not allowed in modules because they are not allowed in
ESQL:

DROP CURSOR
EXPLAIN
GET DESCRIPTION
LEVEL
SELECT Multirow

Module language source programs are processed by the SQL module language
preprocessor (SMLP). SMLP verifies that the source program follows all syntax rules
defined in the SQL standard for modules, except one. The one exception is that the
RSA component of RDMS verifies that the SQL statement specified in a module
procedure is allowed and uses acceptable syntax. In other words, SMLP does not
parse SQL statements beyond initial keywords. SMLP produces a separate UCS
COBOL subroutine for each module procedure.

Each subroutine contains a USE DEFAULT QUALIFIER statement as well as the SQL
statement from the specific module procedure. These statements are ESQL and thus
processed by RDMS during program compilation. The SMLP flags unacceptable
occurrences of DECLARE CURSOR statements.

If LEVEL/SQL FLAGGER is turned on, UCS FORTRAN returns warnings of


nonconforming SQL language or of conforming SQL language that may be processed
in a nonconforming manner during program compilation.

For examples of module programs, see the FORTRAN Compiler Programming


Reference Manual Volume 2.

2–128 7830 8160–027


Section 3
Scalar Functions

RDMS provides many predefined functions called built-in functions (sometimes called
BIFs or scalar functions) that can be called from an SQL statement. This section
describes the syntax and usage of these functions in detail.

The subsections of this section group functions by their general purposes, such as
functions that return character, numeric, or date and time results. Table 3–2 is an
alphabetical listing and summary of functions. This table also provides a reference to
the subsection that describes each function in detail.

3.1. Introduction to Scalar Functions


The upper function is a scalar function that returns a character value. For example, the
following SELECT statement uses the upper function to return the customer's name in
uppercase:

SELECT UPPER(cname)
FROM s1.customers

The following example inserts the customer's name and its corresponding Soundex
value into the table s1.customers from an embedded SQL program:

INSERT INTO s1.customers VALUES(:custno, :custname, soundex(:custname))

3.1.1. Aggregate and Scalar Functions


RDMS functions can be divided into two broad categories based on the number of
rows of data used by the function:

• An aggregate function operates on many rows of data. The aggregate functions


include min, max, avg, sum, and count.
• A scalar function operates on a single row of data. The scalar functions are
described in this section and include upper, lower, and substring.

7830 8160–027 3–1


Introduction to Scalar Functions

3.1.2. Input to Scalar Functions


The scalar functions take as input a collection of related data types, as follows:

• Specific data types include CHARACTER, INTEGER, or DOUBLE PRECISION. In the


cases where the argument is INTEGER, RDMS implicitly casts the actual data type
of the argument to INTEGER before performing the function. In the cases where
the argument is DOUBLE PRECISION, RDMS implicitly casts the actual data type of
the argument to DOUBLE PRECISION before performing the function. Some
precision may be lost in the casting process.
• <any numeric data type> includes SMALLINT, INTEGER, REAL, FLOAT, DOUBLE
PRECISION, DECIMAL, and NUMERIC.
• <any string data type> includes CHARACTER, CHARACTER with CHARACTER SET,
CHARACTER with CHARACTER SET and COLLATION, and NCHAR.

• <any string data type or blob> includes CHARACTER, CHARACTER with CHARACTER
SET, CHARACTER with CHARACTER SET and COLLATION, NCHAR, and BLOB.

• <time, date, or timestamp data type > includes TIME, DATE, or TIMESTAMP data
item, a TIME, DATE, or TIMESTAMP literal string, or a character string containing a
valid time, date, or timestamp value.
• <time or timestamp data type > includes TIME or TIMESTAMP data item, a TIME
or TIMESTAMP literal string, or a character string containing a valid time or
timestamp value.
• <date, or timestamp data type > includes DATE, or TIMESTAMP data item, a DATE
or TIMESTAMP literal string, or a character string containing a valid date or
timestamp value.

3.1.3. Rules
The following are some rules that affect the operations and usage of functions.

Result Length
The functions that return values with the data type CHARACTER or NCHAR are limited
to 28,616 bytes. The functions that return values with the data type BLOB are limited
to 4,294,967,296 bytes. If the length of the return value exceeds the limit, RDMS
truncates it and returns an error message. Additionally, intermediate results may not
exceed these limits either. For example, although the following expression returns
only 10 bytes, the intermediate result of the concat function cannot exceed these
limits:

substring(concat(column1,column2),1,10)

Result Data Type


The data type of the result is described with each function either as a specific data
type (for example, INTEGER) or as a variable data type (for example,
<data type of s1>).

3–2 7830 8160–027


Introduction to Scalar Functions

Parameters
A parameter for a function, indicated as length, precision, start, and so on, can be any
of the following:

• An integer literal
• The result from a function of which the result data type is SMALLINT or INTEGER
• A column, parameter, or SQL variable of which the data type is SMALLINT or
INTEGER
If the data type is a numeric data type but not INTEGER, RDMS implicitly casts the
data type to INTEGER. RDMS truncates any fractional part of a floating point value.

For example, the following returns the string ‘abc’:

left('abcdef',pi())

3.1.4. Where Functions Can Be Used


Functions can be used in the following contexts:

• SELECT list:
select function(a,b,c) from t1 where x=y

• SELECT list arithmetic expression:


select function(a,b,c)+9 from t1 where x=y

• WHERE clause Boolean expressions:


select x, y, z from t1 where function(a,b,c) = c1
select x, y, z from t1 where function1(a,b,c) = function2(a,b,c)

• WHERE clause arithmetic expression:


select x, y, z from t1 where function(a,b,c)+ x = y
• Value clauses:
update t1 set c2 = function(a,b,c) where c1=x

update t1 values (1, function(consvar,consvar), consvar) where x=y

insert into t1 values(consvar, soundex(consvar))

• HAVING clause:
select x, y, z from t1 where c1=5 having function(a,b,c) = c1

• Nested:
select concat(substring(ltrim(c1),1,5), substring(ltrim(c3),2,8))

• Constraints:
alter table t1
add c7:char(15)
add constraint con7 check(isalpha(c7)=1);

7830 8160–027 3–3


Introduction to Scalar Functions

where:

a, b, c
are data items that can be literals, constants, ESQL variables, placeholder
variables, column-specifications, the name of another function, an SQL variable, or
routine parameter.

x, y, z
are column-specifications or other values currently allowed in the given context.

consvar
is a literal, constant, ESQL variable, or placeholder variable (in other words,
anything except a column-specification).

Stated simply, scalar functions may appear only in context as an arithmetic


expression.

Scalar functions are not allowed in the following situations:

• A scalar function cannot appear as the value of a DEFAULT clause in a CREATE


TABLE, PROCEDURE, or FUNCTION statement.
• A scalar function cannot appear in a view.

3.1.5. Considerations for Routines and Triggers


Functions can appear in the following contexts related to routines or triggers:

• SET sqlvar = function(a, b, c)


• IF sqlvar < function(a, b, c) ...

• WHILE sqlparam <> function(a, b, c) ...

• CALL sproutine(p, function(a, b, c), q)

• SET sqlvar = spfunct(p, function(a, b, c), q)

3.1.6. Considerations for RDMS CHARACTER Data Type


The RDMS data type for storing characters is CHARACTER. It is a fixed sized data type.
The SQL standard includes the VARCHAR variable length data type for storing
characters.

The semantics of the two data types are different:

• The string “AA” stored in a VARCHAR(6) field varc is materialized as “AA”.


• The string “AA” stored in a CHARACTER(6) field chr is materialized as “AA∆∆∆∆”
(where ∆ is an ASCII space). Four trailing spaces are appended so that the value is
six characters long.

3–4 7830 8160–027


Introduction to Scalar Functions

The processing of the concat function and the | | operator are influenced by the data
type. The concat function uses the materialized lengths of its string arguments. If the
data type of a string argument is CHARACTER, trailing blanks are returned to make the
string the maximum length. For example

• concat(varc,'BB') returns the string 'AABB'

• concat(chr,'BB') returns the string 'AA∆∆∆∆BB' (where ∆ is an ASCII space).

RDMS provides two additional concat functions to emulate the semantics of the
VARCHAR data type:

• concatrtrim(chr, 'BB') is equivalent to concat(rtrim(chr),'BB') and returns


'AABB'.
• concatstrim(chr, 'BB') is equivalent to concat(concat(rtrim(chr), ' '),'BB')
and returns 'AA∆BB'.

The functions concat, concatrtrim, and concatstrim take any string type as input.

RDMS always generates results in columns. The RDMS optimizer figures out what the
column width should be to accommodate the longest value for the column. In the case
of functions such as space, nspace, substring, repeat, and others, one of the
arguments indicates the length of the result value:

• If the argument is a numeric literal, the RDMS optimizer uses it directly to


calculate the column width for the function result.
• If the argument is a variable (such as a host language variable, column name, or
SQL variable), the RDMS optimizer cannot know what the value for the variable
will be at run time, so the optimizer sets the column width to 28,616 bytes. At run
time, when RDMS knows the value for the variable, RDMS could change the
item’s descriptor to that value.

For most functions, this length does not include trailing blanks. However, GET
DESCRIPTION would return a column size different from the actual result generated at
run time.

In the data record generated for the function result, the length is correct. You can
demonstrate this by concatenating a short literal value on either side of the function
result. For example

CONCAT(CONCAT( 'xx', SPACE(var_name) ), 'yy')

If the value of var_name is 3 and ∆ represents one ASCII space, the result would be as
follows:

xx∆∆∆yy

This demonstrates that the SPACE function generated 3 ASCII space characters.

7830 8160–027 3–5


Introduction to Scalar Functions

Table 3–1 summarizes the allowed data type combinations and the return values.

Table 3–1. Data Type of Result from CONCAT, CONCATRTRIM, CONCATSTRIM


and the Concatenation Operator

Data Type of String 2

CHARACTER with CHARACTER with


CHARACTER CHARACTER SET
CHARACTER SET 1 and COLLATION 2 NCHAR BLOB

CHARACTER CHARACTER CHARACTER with CHARACTER with NCHAR BLOB


CHARACTER CHARACTER SET
SET 1 and COLLATION 2

CHARACTER with CHARACTER CHARACTER with CHARACTER with Not BLOB 3


CHARACTER with CHARACTER CHARACTER SET allowed
SET 1 CHARACTER SET 1 and COLLATION 2
Data Type of String 1

SET 1

CHARACTER with CHARACTER CHARACTER with CHARACTER with Not BLOB 3


CHARACTER SET with CHARACTER SET CHARACTER SET allowed
and COLLATION 2 CHARACTER and COLLATION 2 and COLLATION 2
SET and
COLLATION 2

NCHAR NCHAR Not allowed Not allowed NCHAR Not


allowed

BLOB BLOB BLOB 3 BLOB 3 Not BLOB


allowed

1. The CHARACTER SET for both strings must be the same or compatible. The COLLATION for both
strings must be the same or must be compatible. See 2.9 for more information.

2. The CHARACTER SET for both strings must be the same or compatible. The COLLATION for both
strings must be the same or must be compatible. See 2.9 for more information. The resulting
character set is the character set of the item with the collation clause.

3. The internal format of the I18N value is concatenated to the BLOB value. The character set and
collation information are both lost.

Trailing blanks in character string arguments are ignored by most functions when the
character string arguments are variables (host language variables, column names, SQL
variables) and are not ignored when the character string arguments are literals. The
exceptions are the right and concat functions, which do not ignore trailing blanks
when the character string arguments are either variables or literals.

3–6 7830 8160–027


Introduction to Scalar Functions

The following table shows examples of arguments that illustrate these rules. In these
examples, COL1 has the 8-character value 'MMNNOO∆∆' (where ∆ is an ASCII space).

Argument Result Comment

LPAD('MMNNOO∆',8, 'AA') 'MMNNOO∆∆∆' Blanks not ignored


LPAD(COL1,8, 'AA') 'AAMMNNOO∆∆' Blanks ignored
RIGHT('MMNNOO∆∆',4) 'OO∆∆' Blanks not ignored
RIGHT(COL1,4) 'OO∆∆' Blanks not ignored
SUBSTR('MMNNOO∆∆',-3,3) 'O∆∆' Blanks not ignored
SUBSTR(COL1,-3,3) 'NOO' Blanks ignored

RDMS does not differentiate between zero-length strings and NULL strings for column
references. For example, suppose the table SEED has a character (20) column called
VARIETY. You can set the value of the column to spaces using the UPDATE statement:

UPDATE seed set variety = '∆∆∆∆∆∆∆'

RDMS stores a single space into the column. You can check the length using the
length function:

SELECT length(variety) FROM seed

The length function returns 1.

If you use rtrim(variety), the resulting length is 0 (zero), because the rtrim function
removes all trailing blanks including the original blank.

SELECT length(rtrim(variety)) FROM seed

The length function returns 0.

You can concatenate other character strings onto the blank value for the column
variety. For example

SELECT concat(variety, 'hardy') FROM seed

The SELECT statement returns a blank followed by ‘hardy’.

For example, consider using the concat function along with the rtrim function:

SELECT concat(rtrim(variety), 'hardy') FROM seed

or

SELECT concatrtrim(variety, 'hardy') FROM seed

7830 8160–027 3–7


Introduction to Scalar Functions

Both SELECT statements return a NULL string. Because rtrim(variety) returns a


zero-length string, RDMS interprets it as a NULL string. Concatenating a NULL string
with anything results in a NULL string.

Note that this behavior of the concatrtrim function applies only in the case where
parameter 1 is a column reference. If it is the result of another function, RDMS uses
the function result with no alteration. For example

SELECT concatrtrim(upper(variety), 'hardy') FROM seed

The SELECT statement returns a blank followed by ‘hardy’.

If you want a different semantic handling for the single space situation, you can use
the ifnull function to return a default value. For example

SELECT concat(ifnull(rtrim(variety),'no variety∆'), 'hardy') FROM seed

The SELECT statement returns the string “no variety hardy”. Because rtrim(variety)
returns a zero-length (NULL) string, the ifnull function returns the alternate (parameter
2) value.

See the Relational Database Server for ClearPath OS 2200 Administration Guide for
more information on how international character values are stored internally in RDMS.

3.1.7. Considerations for GET DESCRIPTION


The GET DESCRIPTION statement returns the type and length information for SELECT
statement values containing functions, as it does for SELECT statement values that
contain arithmetic expressions.

3.1.8. Week of the Year


The functions round, trunc, strftime, and to_char can return the value “week of the
year” in which a date occurs. There are three meanings for week of the year:

• The first week of the year begins on the first day of the year. The second week of
the year begins after seven days. For example, if January 1 occurs on a Friday,
week 1 in the new year contains Friday, January 1 through Thursday, January 7.
Week 2 contains Friday, January 8 through Thursday, January 14.
See the to_char function format WW.
• The first day of the week is Sunday. The first week of the year begins on the first
Sunday of the year. All days in a new year preceding the first Sunday are
considered to be in week 0. For example, if January 1 occurs on a Friday, week 0 in
the new year contains Friday, January 1 and Saturday, January 2. Week 1 contains
Sunday, January 3 through Saturday, January 9.
In regions where the first day of the week is Monday, the calculation changes
accordingly. If January 1 occurs on a Friday, week 0 in the new year contains
Friday, January 1, Saturday, January 2, and Sunday, January 3. Week 1 contains
Monday, January 4 through Sunday, January 10.

3–8 7830 8160–027


Introduction to Scalar Functions

See also
− round and trunc function formats YYYY and WW
− strftime function formats %U and %W
− week function
• (ISO rule) The first day of the week is Monday. If the week containing January 1
has four or more days in the new year, then it is considered week 1. If it does not
contain at least four days, then it is week 53 of the previous year and the next
week is week 1.
For example, if January 1 occurs on a Friday, week 53 of the previous year
contains Friday, January 1, Saturday, January 2, and Sunday, January 3. Week 1 in
the new year contains Monday, January 4 through Sunday, January 10.
See also
− round and trunc function formats IYYY and IW
− strftime function format %V
− to_char function formats IYYYY and IW

3.1.9. Julian Day


When calculating the difference between two dates, it is useful to convert the date
into an elapsed number of days since some point in the past. The point in the past
which these functions use as day zero (0) is noon on January 1, 4713 B.C. This date is
derived by projecting the rules for the Julian calendar from today backwards into the
past. This anachronistic calendar is referred to as the Julian Proleptic Calendar. If you
take into account the convention that the year 1 A.D. is preceded by the year 1 B.C.,
the date is January 1, 4712 B.C. If you project the rules of the Gregorian calendar from
today backwards into the past, the date is November 24 of –4713, that is, 4713 years
before the year 1 A.D.

Astronomers have reconciled the differences in interpretation such that January 1,


2000 is defined to be Julian Date 2,451,545. RDMS uses this number as the reference
point from which it calculates the Julian Date number for other dates.

See the julian_day function and the to_date and to_char functions’ format J. See
alternate rules for establishing day zero (0) in the datediff function, datename function,
datepart function, and days function.

3.1.10. Gregorian Dates


The Gregorian calendar was adopted in parts of Europe in 1582. Great Britain and the
British Colonies adopted the Gregorian calendar in 1753. Hence, any date arithmetic
calculations which result in dates prior to the adoption of the Gregorian calendar does
not take into account the discontinuity in the calendar at the time of adoption. RDMS
does not flag these resulting dates as errors.

7830 8160–027 3–9


Alphabetical Summary of Functions

3.2. Alphabetical Summary of Functions


Table 3–2 is an alphabetical listing and summary of the RDMS built-in functions. The
"See" column gives a subsection reference for details about each function.

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

abs Returns the absolute value of the 3.7.1


argument (same as absval function)
absval Returns the absolute value of the 3.7.1
argument (same as abs function)
acos Returns the principal value of the arc 3.7.2
cosine of the argument
active_qualifier Returns a 30-character ASCII string 3.3.2
containing the value of the current
default schema (qualifier)
active_schema Returns a 30-character ASCII string 3.3.2
containing the value of the current
default schema (qualifier)
active_version Returns a 30-character ASCII string 3.3.1
containing the value of the current
default version.
add_months Returns a date or timestamp 3.8.1
incremented or decremented by a
specified number of months (see also
dateadd and timestampadd functions)
ascii Returns the ASCII code for the first 3.5.1
byte in string 1
asin Returns the principal value of the arc 3.7.3
sine of the argument
atan Returns the principal value of the arc 3.7.4
tangent of the argument
atan2 Returns the principal value of the arc 3.7.5
tangent of y/x
cast Returns a string whose data type is 3.8.2
changed to time, date, timestamp, or
interval
ceil Returns the smallest integer greater 3.7.6
than or equal to the argument (same
as ceiling function)
ceiling Returns the smallest integer greater 3.7.6
than or equal to the argument (same
as ceil function)

3–10 7830 8160–027


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

char Returns the character that has the 3.5.2


ASCII code value specified by n
(same as chr function)
char_length Returns the character length of string 3.4.3
1 ignoring any trailing spaces (same
as character_length, length, and
datalength functions)
See also the octet_length function.
character_length Returns the character length of string 3.4.3
1 ignoring any trailing spaces (same
as char_length, length, and datalength
functions)
See also the octet_length function.
charindex Returns the starting position of string 3.4.1
1 in string 2 (same as position and
posstr functions)
chr Returns the character that has the 3.5.2
ASCII code value specified by n
(same as char function)
coalesce Returns the value for the first non- 3.6.1
null expression (same as value
function)
concat Concatenates string 1 to string 2 3.3.3
(same as | | operator)
concatrtrim Concatenates string 1 with trailing 3.3.4
spaces removed to string 2
concatstrim Concatenates string 1 with all but one 3.3.5
trailing spaces removed to string 2
convert Returns the time, date, or timestamp 3.8.3
as ASCII characters in the specified
format according to the current locale
(see also to_date, strftime, and
datename functions)
cos Returns the cosine of the argument, 3.7.7
in radians
cosh Returns the hyperbolic cosine of the 3.7.8
argument, in radians
cot Returns the cotangent of the 3.7.9
argument, in radians
curdate Returns the current date (same as 3.8.4
current_date keyword function)

7830 8160–027 3–11


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

cursorstatus Returns the parameter attribute as 3.4.2


the type of cursor information
curtime Returns the current time (same as 3.8.5
current_time keyword function)
datalength Returns the character length of string 3.4.2
1 ignoring any trailing spaces (same
as character_length, length, and
char_length functions)
See also the octet_length function.
date Returns a date from a date or 3.8.6
timestamp
See also the strptime,
timestamp_format, to_date, and
to_timestamp functions.
dateadd Returns the date, time, or timestamp 3.8.7
with the specified date part
incremented by the given amount
See also the add_months function.
datediff Returns the distance between two 3.8.8
date, time, or timestamp values in a
specific granularity (see also
timestampdiff and months_between
functions)
datename Returns the specified portion of a 3.8.9
time, date, or timestamp as ASCII
characters according to the current
locale
See also the strftime, convert, and
to_date functions.
datepart Returns the specified portion of a 3.8.10
time, date, or timestamp as an
integer (see also strftime, datename,
and to_date functions)
day Returns the day of the month from a 3.8.11
date or timestamp
See also the dayofmonth function.
dayname Returns the day of the week as ASCII 3.8.12
characters (Sunday, Monday, and so
on according to the current locale)
dayofmonth Returns the day of the month from a 3.8.13
date or timestamp
See also the day function.

3–12 7830 8160–027


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

dayofweek Returns the day of the week for a 3.8.14


date or timestamp (Sunday = 1,
Monday = 2, and so on)
dayofyear Returns the day of the year for a date 3.8.15
or timestamp
days Returns the number of days between 3.8.16
January 1, 0001 and the date or
timestamp
decode Compares the value of string 1 3.6.2
against each compare item; if string 1
matches the i th compare item,
returns the corresponding i th value
item
degree Converts the argument angle from 3.7.10
radians to degrees (same as degrees
function)
degrees Converts the argument angle from 3.7.10
radians to degrees (same as degree
function)
delesc Deletes the kanji escape sequence 3.3.6
from the beginning and ending of an
NCHAR string
difference Returns an integer value that 3.4.4
indicates the soundex difference
between the two values
erdate_to_timestamp Transforms ER DATE$ format to 3.8.17
RDMS TIMESTAMP format with
precision 0
erdwtime_to_timestamp Transforms ER DWTIME$ or CALL 3.8.18
INSPECTIME$ format to TIMESTAMP
format with precision 3
ertdate_to_timestamp Transforms ER TDATE$ format to 3.8.19
RDMS TIMESTAMP format with
precision 0
ertime_to_time Transforms ER TIME$ format to 3.8.20
RDMS TIME format with precision 3
exp Returns ex, where e is the base of 3.7.11
the natural logarithms
extract Returns the specified portion of a 3.8.21
time, date, or timestamp value
floor Returns the largest integer less than 3.7.12
or equal to the argument

7830 8160–027 3–13


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

generated_date_val_local Generates a date value during an 3.10.3


INSERT into a column declared
GENERATED AS (datetime function).
Returns the last value inserted (or
generated in response to the insert)
into such a column.
generated_time_val_local Generates a time value during an 3.10.3
INSERT into a column declared
GENERATED AS (datetime function).
Returns the last value inserted (or
generated in response to the insert)
into such a column.
generated_timestamp_val Generates a timestamp value during 3.10.3
_local an INSERT into a column declared
GENERATED AS (datetime function).
Returns the last value inserted (or
generated in response to the insert)
into such a column.
generated_run_id Returns the generated run-id for the 3.9.1
current run
get_file Returns the contents of a file as a 3.11.1
BLOB
getdate Returns the current date and time as 3.8.22
a timestamp (same as now function
and current_timestamp keyword
function)
getutcdate Returns the current utc date and time 3.8.23
as a timestamp with 6 digits of
precision.
hex Returns the hexadecimal 3.7.13
representation of n as ASCII
characters
hour Returns the hour portion of a time or 3.8.24
timestamp
identity_val_local Returns the value RDMS used during 3.10.2
the last insert into any identity
column, or column GENERATED AS
(partition_id()), or GENERATED AS
(expression) where the expression
returns a numeric value
ifnull If expr 1 is NULL, returns expr 2; else 3.6.3
returns expr 1 (same as nvl function)

3–14 7830 8160–027


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

initcap Returns string 1 with the first letter of 3.3.7


each word in uppercase, all other
letters in lowercase
insert Inserts string 2 into string 1 (same as 3.3.8
stuff function)
insesc Inserts the kanji escape sequence at 3.3.9
the beginning and ending of an
NCHAR string
instr Searches string 1 for the m th 3.4.5
occurrence of string 2 starting at
character n in string 1
See also the locate and patindex
functions.
integer Returns the expression e1 cast to 3.7.14
data type INTEGER.
isalnum Returns 1 if the argument is 3.4.6
composed entirely of alphabetic and
numeric characters. Otherwise, 0 is
returned.
isalpha Returns 1 if the argument is 3.4.7
composed entirely of alphabetic
characters. Otherwise, 0 is returned.
iscntrl Returns 1 if the argument is 3.4.8
composed entirely of control
characters. Otherwise, 0 is returned.
isdigit Returns 1 if the argument is 3.4.9
composed entirely of numeric
characters. Otherwise, 0 is returned.
isgraph Returns 1 if the argument is 3.4.10
composed entirely of graphical
characters. Otherwise, 0 is returned.
islower Returns 1 if the argument is 3.4.11
composed entirely of lowercase
alphabetic characters. Otherwise, 0 is
returned.
isprint Returns 1 if the argument is 3.4.12
composed entirely of printable
characters. Otherwise, 0 is returned.
ispunct Returns 1 if the argument is 3.4.13
composed entirely of punctuation
characters. Otherwise, 0 is returned.

7830 8160–027 3–15


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

isspace Returns 1 if the argument is 3.4.14


composed entirely of white space
characters. Otherwise, 0 is returned.
isupper Returns 1 if the argument is 3.4.15
composed entirely of uppercase
alphabetic characters. Otherwise, 0 is
returned.
isxdigit Returns 1 if the argument is 3.4.16
composed entirely of hexadecimal
characters. Otherwise, 0 is returned.
julian_day Returns the number of days between 3.8.25
the beginning of the Julian calendar
and the given date or timestamp
last_day Returns the date or timestamp for 3.8.26
the last day of the month for the
given date or timestamp
lcase Returns string 1 with all letters in 3.3.10
lowercase (same as lower function)
left Returns the leftmost n characters 3.3.11
from string 1
length Returns the character length of string 3.4.2
1 ignoring any trailing spaces (same
as character_length, char_length, and
datalength functions)
See also the octet_length function.
ln Returns the natural logarithm of the 3.7.15
argument
lob_crc Recalculates and returns the cyclical 3.11.2
redundancy check (CRC) value for the
specified BLOB column
lob_end_address Returns the word address of the last 3.11.3
word containing specified BLOB data
lob_end_page Returns the data-page number for the 3.11.4
last page containing a specified BLOB
value.
lob_file Returns the name of the file 3.11.5
underlying the storage area that
contains a specified BLOB value
lob_id Returns the 24-byte lob_id as an octal 3.11.6
value

3–16 7830 8160–027


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

lob_id_crc Returns the cyclical redundancy 3.11.7


check (CRC) value from the lob_id for
the specified BLOB column
lob_start_address Returns the starting address for the 3.11.8
start of a specified BLOB value
lob_start_page Returns the data-page number for the 3.11.9
start of a specified BLOB value
locate Searches string 1 for string 2 starting 3.4.17
at character n in string 1
See also the instr and patindex
functions.
log With one argument, returns the 3.7.16
natural logarithm of the argument
With two arguments, returns the
logarithm, base b, of the argument
log10 Returns the logarithm, base 10, of the 3.7.17
argument
lower Returns string 1 with all letters in 3.3.12
lowercase (same as lcase function)
lpad Inserts string two characters to the 3.3.13
left of string 1
ltrim Removes characters from the left of 3.3.14
string 1
max_aor_updates Returns the MAXIMUM-AOR- 3.9.2
UPDATES value for the current
application group
microsecond Returns the fractional portion of a 3.8.27
time or timestamp to 6 decimal
places
midnight_seconds Returns the number of seconds 3.8.28
between a time or timestamp and the
previous midnight
minute Returns the minute portion of a time 3.8.29
or timestamp
mod Returns the remainder (modulus) of 3.7.18
m divided by n
month Returns the month portion of a date 3.8.30
or timestamp
monthname Returns the month in ASCII 3.8.31
characters (January, February, and so
on according to the current locale)

7830 8160–027 3–17


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

months_between Returns the number of months 3.8.32


between the two date or timestamp
values, as a double precision number
See also the datediff and
timestampdiff functions.
new_time Returns a time or timestamp 3.8.33
converted to a specific time zone
next_day Returns the first date or timestamp 3.8.34
following the given day of the week
and a date value.
now Returns the current date and time as 3.8.35
a timestamp (same as getdate
function and the current_timestamp
keyword function)
nspace Returns a string consisting of n kanji 3.3.15
spaces.
nullif Returns NULL if the value of expr1 3.6.4
matches the value of expr2,
otherwise returns the value of expr1
nvl If expr 1 is NULL, returns expr 2; else 3.6.3
returns expr 1 (same as ifnull
function)
octal Returns the octal representation of n 3.7.19
as ASCII characters
octet_length Returns the byte length of string 1 3.4.18
See also the character_length
function.
pages_updated Returns the number of pages (blocks) 3.9.9
updated in this step (in other words,
since the last COMMIT or
ROLLBACK).
partition_id May only be specified as the 3.10.1
generated default for a partitioned
table
patindex Searches string 1 for string 2; 3.4.19
supports wild card searches
See also the locate and instr
functions.

3–18 7830 8160–027


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

permuted_id Returns the value for the system 3.9.3


services function UNIQUE$ID,
permuted to counteract the
monotonically increasing nature from
repeated calls
pi Returns the value of pi as a 72 bit 3.7.20
floating point number
position Returns the starting position of string 3.4.1
1 in string 2 (same as charindex and
posstr functions)
posstr Returns the starting position of string 3.4.1
1 in string 2 (same as charindex and
position functions)
power Returns x raised to the power y (xy) 3.7.21
program_type Returns the program type (demand, 3.9.4
batch, and so on)
put_file Writes a data item value to a file 3.11.10
quarter Returns an integer from 1 to 4 3.8.36
representing the quarter of the year
in which the date or timestamp
occurs
radians Converts the argument angle from 3.7.22
degrees to radians
rand With no arguments, returns a random 3.7.23
double-precision floating point
number between 0 and 1
With one argument, returns a random
double precision floating point
number between 0 and 1, using the
argument as a “seed”
rdms_thread_stat Returns the value of a given RDMS 3.9.10
statistic. For example, the number of
INSERT statements, which is
displayed by the UDS STAT trace and
the UDSMON K-screen.
real Returns the expression e1 cast to 3.7.24
data type REAL.
repeat Returns string 1 repeated n times 3.3.16
(same as replicate function)
replace Returns string 1 with each occurrence 3.3.17
of string 2 replaced by string 3

7830 8160–027 3–19


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

replicate Returns string 1 repeated n times 3.3.16


(same as repeat function)
reverse Returns string 1 with the characters in 3.3.18
the reverse order
right Returns the rightmost n characters of 3.3.19
string 1
round Returns the time, date, or timestamp 3.7.25
rounded to the specified granularity; 3.8.37
rounds the numeric argument x in
such a way that its least significant
digit is n digits to the right (or if n is
negative, to the left) of the decimal
point
rpad Inserts string 2 characters to the right 3.3.20
of string 1
rtrim Removes characters from the right of 3.3.21
string 1
run_id Returns the original run-id for the 3.9.5
current run
second If the argument is a time or 3.8.38
timestamp, returns the second
portion of the time or timestamp
sign Returns +1 if the argument is 3.7.26
positive, -1 if the argument is
negative, and 0 if the argument is 0
sin Returns the sine of the argument, in 3.7.27
radians
sinh Returns the hyperbolic sine of the 3.7.28
argument, in radians
smallint Returns the expression e1 cast to 3.7.29
data type SMALLINT.
soundex Returns a character string containing 3.3.22
the phonetic representation of string
1
space Returns a string consisting of n ASCII 3.3.23
spaces
sqrt Returns the square root of the 3.7.30
argument
str Returns a numeric value converted to 3.7.31
ASCII characters

3–20 7830 8160–027


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

strftime Returns the time, date, or timestamp 3.8.39


as ASCII characters in the specified
format according to the current locale
See also the to_char, convert, and
datepart functions
strptime Returns a timestamp given a 3.8.40
character string containing a time,
date, or timestamp value and a
character string describing its format
according to the current locale
stuff Inserts string 2 into string 1 (same as 3.3.24
insert function)
substr Returns a portion of string 1 (same as 3.3.25
substring function)
substring Returns a portion of string 1 (same as 3.3.25
substr function)
tan Returns the tangent of the argument, 3.7.32
in radians
tanh Returns the hyperbolic tangent of the 3.7.33
argument, in radians
Time Returns the time portion of a time or 3.8.41
timestamp
timestamp Returns a timestamp created from 3.8.42
the supplied date and time values
timestampadd Increments a timestamp by a given 3.8.43
amount in a specific granularity
timestampdiff Returns the distance between two 3.8.44
timestamps in a specific granularity
See also the months_between and
datediff functions.
timestamp_format Returns a timestamp value given a 3.8.45
character string containing a date,
time, or timestamp value and a
character string describing its format
according to the current locale.
See also the date, to_date,
to_timestamp, and strptime
functions.

7830 8160–027 3–21


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

to_char Returns the time, date, or timestamp 3.8.46


as ASCII characters in the specified
format according to the current locale
See also the strftime and datepart
functions.
to_date Returns a timestamp value given a 3.8.47
character string containing a date,
time, or timestamp value and a
character string describing its format
according to the current locale.
See also the date, strptime,
timestamp_format, and to_timestamp
functions.
to_timestamp Returns a timestamp value given a 3.8.48
character string containing a date,
time, or timestamp value and a
character string describing its format
according to the current locale.
See also the date, strptime,
timestamp_format, and to_date
functions.
trunc Truncates the numeric argument x in 3.7.34
such a way that its least significant
digit is n digits to the right (or if n is
negative, to the left) of the decimal
point (same as truncate function)
Returns the time, date, or timestamp 3.8.45
truncated to the specified granularity
truncate Truncates the numeric argument x in 3.7.34
such a way that its least significant
digit is n digits to the right (or if n is
negative, to the left) of the decimal
point (same as trunc function)
ucase Returns string 1 with all letters in 3.3.26
uppercase (same as upper function)
uds_slot Returns the UDS slot number 3.9.6
assigned to the current transaction
unique_id Returns the value for the system 3.9.7
services function UNIQUE$ID
upper Returns string 1 with all letters in 3.3.26
uppercase (same as ucase function)
user Returns the user ID of the current 3.9.8
user

3–22 7830 8160–027


Alphabetical Summary of Functions

Table 3–2. Alphabetical Summary of Built-In Functions

Function Name Description See

value Returns the value for the first nonnull 3.6.1


expression (same as coalesce
function)
varchar_format Returns the time, date, or timestamp 3.8.50
as ASCII characters in the specified
format
See also the to_char and strftime
functions.
week Returns the week of the year for a 3.8.51
date or timestamp, from 1 to 53
year If the argument is a date or 3.8.52
timestamp, returns the year portion
of the date or timestamp.

7830 8160–027 3–23


Character Functions That Return Character Values

3.3. Character Functions That Return Character


Values
The following functions accept character data as parameters and return character data
as results.

3.3.1. active_version Function


Format
active_version( ) → Character

Purpose
Returns a 30-character ASCII string containing the value of the current default version.
This is most useful in triggers.

Example
active_version( )

returns
PRODUCTION

3.3.2. active_schema and active_qualifier Functions


Format
active_schema() → character
active_qualifier() → character

Purpose
Returns a 30-character ASCII string containing the value of the current default schema
(qualifier). The scalar functions, active_schema() and active_qualifier() are synonyms for
each other, and return the same value.

Example
active_schema()

returns

RDMS

3–24 7830 8160–027


Character Functions That Return Character Values

3.3.3. concat Function


Format
concat(<any string data type or blob> s1,
<any string data type or blob> s2) → <a string data type>

See Table 3–1 for allowed data type combinations and the result data type.

Purpose
If s1 is a scalar built-in function, it can return a length of zero which concat interprets
as a null string.

Returns s1 concatenated to s2. If either s1 or s2 is NULL, RDMS returns a null value.

The result is truncated if its length exceeds 28,616 bytes.

Example
Suppose cname is a 20-character column with the value 'Peter'; desiredloc is a
20-character column with the value 'Roseville'

SELECT CONCAT( CONCAT( cname ,


'desires to buy a house in '), desiredloc)FROM s1.customers
WHERE cno = 'C101'

returns the following:


Peter desires to buy a house in Roseville

3.3.4. concatrtrim Function


Format
concatrtrim(<any string data type or blob> s1,
<any string data type or blob> s2) →
<a string data type>

See Table 3–1 for allowed data type combinations and the result data type.

Purpose
Returns s1, with trailing spaces removed, concatenated to s2. This function is
equivalent to

concat(rtrim(s1), s2).

If either s1 or s2 is NULL, RDMS returns a null value. If s1 is a string literal, RDMS does
not remove any trailing spaces. The result is truncated if its length exceeds 28,616
bytes. If either s1 or s2 is a BLOB, RDMS uses concat() semantics.

7830 8160–027 3–25


Character Functions That Return Character Values

Example
Assume that cname is a 20-character column with the value ‘Peter’ and desiredloc is a
20-character column with the value ‘Roseville’:

SELECT CONCAT(rtrim(cname), CONCAT(‘ desires to buy a house in ‘,


desiredloc))

Note: The space before the word desires in the string literal returns the following:

Peter desires to buy a house in Roseville

3.3.5. concatstrim Function


Format
concatstrim(<any string data type or blob> s1,
<any string data type or blob> s2) →
<a string data type>

See Table 3–1 for allowed data type combinations and the result data type.

Purpose
Returns s1, with trailing spaces removed and a single space inserted, concatenated
to s2. This function is equivalent to the following:

concat(concat(rtrim(s1),' ' ), s2).

If either s1 or s2 is NULL, RDMS returns a null value. If s1 is a string literal, RDMS does
not remove any trailing spaces. The result is truncated if its length exceeds 28,616
bytes. If either s1 or s2 is a BLOB, RDMS uses concat() semantics.

Example
Suppose cname is a 20-character column with the value ‘Peter’ and desiredloc is a
20-character column with the value ‘Roseville’

SELECT CONCAT( CONCATSTRIM( cname ,


'desires to buy a house in '), desiredloc)
FROM s1.customers
WHERE cno = 'C101'

Note: No space before the word desires in the string literal returns the following:

Peter desires to buy a house in Roseville

3–26 7830 8160–027


Character Functions That Return Character Values

3.3.6. delesc Function


Format
delesc(<any string data type> s1) → <data type of s1>

Purpose
Returns a copy of the string s1, with all the kanji shift codes deleted. The delesc
function eliminates all the shift codes by moving the non-shift-code characters to the
left and padding to the right with blanks. If s1 is NULL, RDMS returns a null value.

RDMS assumes that s1 is a kanji string irrespective of the data type of s1.

The functions delesc and insesc are opposite functions.

Example
delesc(acolumn)

3.3.7. initcap Function


Format
initcap(Character s1) → Character

Purpose
Returns s1 with the first letter of each word in uppercase, all other letters in
lowercase. Words are delimited by space or by characters that are not alphanumeric.

RDMS uses the rules for uppercasing ASCII characters.

If s1 is NULL, RDMS returns a null value.

Example
initcap('minneapolis, minnesota')

returns the string


Minneapolis, Minnesota

7830 8160–027 3–27


Character Functions That Return Character Values

3.3.8. insert and stuff Functions


Format
insert(<any string data type> s1, Integer start, Integer length,
<any string data type> s2) → <data type of s1>

stuff(<any string data type> s1, Integer start, Integer length,


<any string data type> s2) → <data type of s1>

insert(blob s1, Integer start, Integer length,


<any string data type or blob> s2) → blob

stuff(blob s1, Integer start, Integer length,


<any string data type or blob> s2) → blob

Purpose
Returns a string where length characters have been deleted from s1 beginning at start
and where s2 has been inserted into s1 beginning at start.

If s1 is a BLOB, RDMS interprets length in bytes. If s1 is NCHAR or CHARACTER SET is


UCS-2, RDMS interprets length in double-bytes.

If start is less than or equal to 0 or is NULL, RDMS uses the value 1. If start is greater
than the length of s1 RDMS appends s2 to s1 and ignores any length value.

If length is less than or equal to 0 or is NULL, RDMS uses the value 0 and deletes no
characters. If start + length extends beyond the end of the s1, RDMS removes all
characters from s1 between start and the end of s1.

If s1 or s2 is NULL, RDMS returns a null value. The result is truncated if its length
exceeds 28,616 bytes.

Example
stuff( 'He rld', 3, 1, 'llo Wo')

returns
Hello World

3–28 7830 8160–027


Character Functions That Return Character Values

3.3.9. insesc Function


Format
insesc(<any string data type> s1) → <data type of s1>

Purpose
Returns a copy of s1 with the kanji shift codes added to the beginning and ending of
the value, if they are not already present. The shift codes are always fixed. The fixed
shift-out code is 0223 0360. The fixed shift-in code is 0223 0361. This is the same
convention used for kanji identifier names in RDMS. See the Relational Database
Server for ClearPath OS 2200 Administration Guide for more information.
RDMS assumes that s1 is a kanji string regardless of the data type of s1.
If s1 is NULL, RDMS returns a null value.
The functions insesc and delesc are opposite functions.

Example
insesc(acolumn)

3.3.10. lcase and lower Functions


Format
lcase(Character s1) → Character

lower(Character s1) → Character

Purpose
Returns s1 with all letters in lowercase.

RDMS uses the rules for lowercasing ASCII characters. If the argument references a
column defined using CHARACTER SET and COLLATION, RDMS uses the lowercasing
rules for the specified collation. This function does not support columns defined only
with CHARACTER SET.

If s1 is NULL, RDMS returns a null value.

Example
lcase('MR. JOHN SMITH')

returns
mr. john smith

7830 8160–027 3–29


Character Functions That Return Character Values

3.3.11. left Function


Format
left(<any string data type or blob> s1, Integer n) → <data type of s1>

left(<any numeric data type> n1, Integer n) → Character

Purpose
Returns the leftmost n characters from s1 or n1. If n is less than or equal to 0, RDMS
uses the value 0 and returns a null value. If n is greater than the length of s1, RDMS
returns all the characters in s1 and space-fills to the right.

If s1 is a BLOB, RDMS interprets n in bytes. If s1 is NCHAR or CHARACTER SET is


UCS-2, RDMS interprets n in double-bytes. If s1 is NULL, RDMS returns a null value.

If n1 is numeric, RDMS returns a character string. See the examples for handling of
positive, negative, and fractional values. See the substring function (3.3.25) for more
examples of handling numeric values.

If n is not an integer, the value of n is truncated to an integer. For example, 3.6 is


truncated to the integer value 3.

Examples
left( 'MR. JOHN SMITH', 3)

returns the string


MR.

left(12345, 3)

returns the character string


123

Note that positive values are not preceded by a plus sign. In a negative value, a leading
minus sign is a significant character.

left(-12345, 3)

returns the character string


-12

If the sign of the value is not important, use the abs function to eliminate the sign.

3.3.12. lower Function


See lcase function (3.3.10).

3–30 7830 8160–027


Character Functions That Return Character Values

3.3.13. lpad Function


Format
lpad(<any string data type> s1, Integer length
[ , Character s2 ] ) → <data type of s1>

Purpose
Returns s1, left-padded to length length with the sequence of characters in s2
replicated as many times as necessary. If s2 is not included or is NULL, RDMS uses an
ASCII space.

If s1 is longer than length, RDMS returns the leftmost length characters of s1. If s1 is
NCHAR or CHARACTER SET is UCS-2, RDMS interprets length in double-bytes. If s1 is
NULL, RDMS returns a null value. If length is less than or equal to 0, RDMS uses the
value 0. The result is truncated if its length exceeds 28,616 bytes.

Examples
lpad( 'Page 1', 15, '*.')

returns
*.*.*.*.*Page 1

lpad( 'Page 1', 6, '*.')

returns
Page 1

3.3.14. ltrim Function


Format
ltrim(<any string data type> s1 [ , <any string data type> set ] )
→ <data type of s1>

Purpose
Removes characters from the left of s1, with initial characters removed up to the first
character not in set. The value of set defaults to a single space.

If s1 is NCHAR or CHARACTER SET is UCS-2, RDMS interprets s1 in double-bytes. If s1


is NULL, RDMS returns a null value.

7830 8160–027 3–31


Character Functions That Return Character Values

Examples
ltrim('xyxXxyMr. Smith', 'xy')

returns
XxyMr. Smith

ltrim( ' Mr. Smith')

returns
Mr. Smith

3.3.15. nspace Function


Format
nspace(Integer n) → NCHAR

Purpose
Returns a string consisting of n kanji spaces (each space is encoded as the two-byte
string 040 040).

Also see the space function (3.3.23).

If n is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. If n is larger than 14,308, a string of 14,308 kanji spaces is returned.

Example
nspace(4)

3.3.16. repeat and replicate Functions


Format
repeat(<any string data type> s1, Integer n) → <data type of s1>

replicate(<any string data type> s1, Integer n) → <data type of s1>

Purpose
Returns a string consisting of n repetitions of the string s1.

If n is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. The result is truncated if its length exceeds 28,616 bytes.

3–32 7830 8160–027


Character Functions That Return Character Values

Examples
repeat('abc', 3)

returns
abcabcabc

replicate('abc', 3)

returns
abcabcabc

3.3.17. replace Function


Format
replace(<any string data type> s1, <any string data type> s2
[,Character s3 ] ) → <data type of s1>

Purpose
Returns s1 with every occurrence of s2 replaced with s3. If s3 is omitted or is NULL,
all occurrences of s2 are removed. If s1 or s2 is NULL, s1 is returned with no changes.
If s2 is not found, s1 is returned with no changes.

If s1, s2, or s3 is a COBOL variable, you may have to use the rtrim function to remove
trailing spaces. RDMS treats trailing spaces as significant characters. The result is
truncated if its length exceeds 28,616 bytes.

Example
replace( 'JACK and JUE', 'J', 'BL')

returns
BLACK and BLUE

3.3.18. reverse Function


Format
reverse(<any string data type> s1) → <data type of s1>

Purpose
Returns s1 with the characters in the reverse order. If s1 is NULL, RDMS returns a null
value.

Example
reverse('abcd')

returns
dcba

7830 8160–027 3–33


Character Functions That Return Character Values

3.3.19. right Function


Format
right(<any string data type or blob> s1, Integer n) → <data type of s1>

right(<any numeric data type> n1, Integer n) → Character

Purpose
Returns the rightmost n characters from s1 or n1. If n is less than or equal to 0 or is
NULL, RDMS uses the value 0 and returns a null value. If n is greater than the length of
s1, RDMS returns all the characters in s1 and pads the value with ASCII spaces to the
lesser of n or, if s1 is a column, to the size of the column.

If s1 is NCHAR or CHARACTER SET is UCS-2, RDMS interprets n in double-bytes.


Otherwise, RDMS interprets n in bytes. If s1 is NULL, RDMS returns a null value. The
result is truncated if its length exceeds 28,616 bytes.

If n1 is numeric, RDMS returns a character string. See the examples for handling of
positive, negative, and fractional values. See the substring function (3.3.25) for more
examples of handling numeric values.

If n is not an integer, the value of n is truncated to an integer. For example, 3.6 is


truncated to the integer value 3.

Example 1
right( 'MR. JOHN SMITH', 3)

returns
ITH

Example 2
Suppose column c1 is defined as CHARACTER(24) with the value ‘MR. JOHN SMITH’.
The CHARACTER data type in RDMS is fixed length.

right(c1,3)

returns
' ' (three ASCII spaces)

To get the equivalent of the processing from a CHARACTER VARYING column, you
must use
right(rtrim(c1),3)

which returns
ITH

3–34 7830 8160–027


Character Functions That Return Character Values

Example 3
right(12345, 3)

returns the character string


345

Note that a positive value is not preceded by a plus sign.

3.3.20. rpad Function


Format
rpad(<any string data type> s1, Integer length
[ , <any string data type> s2 ] ) → <data type of s1>

Purpose
Returns s1, right-padded to length length with the sequence of characters in s2
replicated as many times as necessary. If s2 is not included, RDMS uses an ASCII
space.

If s1 is longer than length, RDMS returns the leftmost length characters of s1.

If s1 is NCHAR or CHARACTER SET is UCS-2, RDMS interprets length in double-bytes.


If s1 is NULL, RDMS returns a null value.

If length is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. The result is truncated if its length exceeds 28,616 bytes.

Examples
rpad( 'MR. JOHN SMITH', 19, 'ab')

returns
MR. JOHN SMITHababa

rpad( 'MR. JOHN SMITH', 3, 'ab')

returns
MR.

7830 8160–027 3–35


Character Functions That Return Character Values

3.3.21. rtrim Function


Format
rtrim(<any string data type> s1 [ , <any string data type> set ] )
→ <data type of s1>

Purpose
Returns s1 with final characters removed after the last character not in set. The value
of set defaults to a single ASCII space.

If s1 is NULL, RDMS returns a null value.

Example
rtrim('Mr. SMITHyxXxy', 'xy')

returns
Mr. SMITHyxX

3.3.22. soundex Function


Format
soundex(Character s1) → Character

Purpose
Returns a character string of length 4 containing the phonetic representation of s1.
This function allows you to compare words that are spelled differently, but sound alike
in English. S1 must be ASCII characters. If s1 is NULL, RDMS returns a null value.

The phonetic representation is defined in The Art of Computer Programming, Volume


3: Sorting and Searching, by Donald E. Knuth.

There are substantial limitations with both soundex and differences due to the
oddities of English spelling. Soundex fails to match the names Klein and Cline and
considers the word Phone an exact match with Pen, but not Fan. For these reasons,
soundex-based functions should be used cautiously in applications.

Example
SELECT cname FROM customers where soundex(cname) = soundex('SMYTHE')

returns
Smith

soundex('draw')

returns
D600

3–36 7830 8160–027


Character Functions That Return Character Values

3.3.23. space Function


Format
space(Integer n) → Character

Purpose
Returns a string consisting of n ASCII spaces.

Also see the nspace function (3.3.15).

If n is less than or equal to 0 or is NULL, RDMS uses the value 0 and returns a null
value. If n is larger than 28,616, a string of 28,616 ASCII spaces is returned.

Example
space(4)

3.3.24. stuff Function


See insert function (3.3.8).

3.3.25. substr and substring Functions


Format
substr(<any string data type> s1, Integer start [ , Integer length ] )
→ <data type of s1>

substring(<any string data type> s1, Integer start [ , Integer length ] )


→ <data type of s1>

substr(blob s1, Integer start [ , Integer length ] ) → blob

substring(blob s1, Integer start [ , Integer length ] ) → blob

substr(<any numeric data type> n1, Integer start [ , Integer length ] )


→ Character

substring(<any numeric data type> n1, Integer start [ , Integer length ] )


→ Character

Purpose
Returns a portion of s1 or n1 beginning at character start for length characters. If start
is positive, RDMS counts from the left end of the string. If start is negative, RDMS
counts from the right end of the string. If start is 0, RDMS uses 1.

If length is omitted, RDMS returns all the characters from start to the end of s1. If the
value for length is less than or equal to 0 or is NULL, RDMS uses the value 0 and
returns a null value.

7830 8160–027 3–37


Character Functions That Return Character Values

If s1 is not a BLOB, RDMS pads the value with ASCII spaces to length if s1 is less than
length characters long. If s1 is NULL, RDMS returns a null value. The result is truncated
if its length exceeds 28,616 bytes.

If n1 is numeric, RDMS returns a character string. See the examples for handling of
positive, negative, and fractional values.

If start or length is not an integer, the value of start or length is truncated to an


integer. For example, 3.6 is truncated to the integer value 3.

Examples Using Character String Values


substr( 'abcdefg', 3, 2)

returns
cd

substr( 'abcdefg', -3, 2)

returns
ef

substring( 'abcdefg', -3, 5)

returns
efg∆∆

where ∆ is one ASCII space.

Examples Using Integer Values


substring(12345, 3, 2)

returns the character string


34

Note that positive values are not preceded by a plus sign.

substring(12, 3, 2)

returns two ASCII spaces.

In a negative numeric value, the leading minus sign is a significant character.

substring(-12345, 3, 2)

returns the character string


23

3–38 7830 8160–027


Character Functions That Return Character Values

If the sign of the value is not important, use the abs function to eliminate the sign.

substring(-12, 3, 2)

returns
2∆

where ∆ is one ASCII space.

Example Using a Constant


To compensate for variable-length values in a database, add to the values a constant
that is larger than any database value. Suppose that an integer column named col1
contains the values 1, 23, and 444:

substr(10000+col1, 3, 3)

returns
001
023
444

Examples Using Fractional Values


When you are working with an expression that contains a fraction, the length of the
value depends on the precision of the literal, column declaration, SQL variable
declaration, or expression result. Again, suppose that an integer column named col1
contains the values 1, 23, and 444. Adding a fractional value to the integer creates a
floating point value:

substr(col1+.04, 1, 7)

returns
1.04∆∆∆
23.04∆∆
444.04∆

where ∆ is one ASCII space.

The numeric literal .04 has a precision of 2. The numeric expression 1/20 produces an
internal result with precision 19.

substr(col1+1/20, 1, 7)

returns
1.05000
23.0500
444.050

7830 8160–027 3–39


Character Functions That Return Character Values

3.3.26. ucase and upper Functions


Format
ucase(Character s1) → Character

upper(Character s1) → Character

Purpose
Returns s1 with all the letters in uppercase.

RDMS uses the rules for uppercasing ASCII characters. If the argument references a
column defined using CHARACTER SET and COLLATION, RDMS uses the uppercasing
rules for the specified collation. This function does not support columns defined only
with CHARACTER SET.

If s1 is NULL, RDMS returns a null value.

Example
upper('mr. john smith')

returns
MR. JOHN SMITH

3–40 7830 8160–027


Character Functions That Return Numeric Values

3.4. Character Functions That Return Numeric


Values
The following functions accept character data as parameters and return numeric
results.

3.4.1. charindex, position, and posstr Functions


Format
charindex(<any string data type or blob> s1,
<any string data type or blob> s2) → Integer

position(<any string data type or blob> s2,


<any string data type or blob> s1) → Integer

posstr(<any string data type or blob> s2,


<any string data type or blob> s1) → Integer

Purpose
Returns the starting position of expression s1 in expression s2. These functions treat
wild card characters underscore (_) and percent (%) as normal characters. The
patindex function treats the wild card characters as wild card characters.

If s1 is not found in s2 the function returns a value of 0. If s1 or s2 is NULL, RDMS


returns 0.

Note that the parameter order of charindex is opposite from the other two functions.

Examples
charindex( 'world', 'hello world')

returns
7

position('hello world', 'world')

returns
7

posstr('hello world', 'world')

returns
7

7830 8160–027 3–41


Character Functions That Return Numeric Values

3.4.2. cursorstatus Function


Format
cursorstatus(character cur1 [, character attribute]) → Integer

Purpose
The parameter cur1 is the name of the cursor. Cursor names must be passed as upper
case strings, unless the cursor was declared as a delimited identifier in which case the
string can be of mixed case.
The parameter attribute is the type of cursor information to return.

If attribute is omitted, RDMS uses 'openstatus'.

If attribute = 'OPENSTATUS'

Returns -2 if the cursor name is ambiguous. It means that there is more than one
external embedded cursors of this name and there is no interactive cursor by the
same name.

Returns -1 if the cursor does not exist

Returns 0 if the cursor is declared but is closed.

Returns 1 if the cursor is open.

Example
cursorstatus('C1','openstatus')

returns

3.4.3. char_length, character_length, length, and datalength


Functions
Format
char_length(<any string data type or blob> s1) → Integer

character_length(<any string data type or blob> s1) → Integer

length(<any string data type or blob> s1) → Integer

datalength(<any string data type or blob> s1) → Integer

Purpose
Returns the length of the expression s1, in characters, ignoring any trailing spaces. If
s1 is data type BLOB, all characters, including trailing spaces are included in the
returned length.

3–42 7830 8160–027


Character Functions That Return Numeric Values

In addition, see the octet_length function, which returns the length in bytes rather than
in characters.

If s1 is NCHAR or CHARACTER SET is UCS-2, these functions return the number of


double-byte characters.

If s1 is NULL, RDMS returns 0.

Example
Suppose cname is a column with the value 'Peter':

char_length(cname)
length(cname)
datalength(cname)

returns
5

3.4.4. difference Function


Format
difference(Character s1, Character s2) → Integer

Purpose
Returns an integer value that indicates the soundex difference between the two
character strings. The values s1 and s2 must both have been created by the Soundex
function before calling difference.

If s1 or s2 is NULL, RDMS returns 0.

There are substantial limitations with soundex and difference due to the oddities of
English spelling. Soundex fails to match the names Klein and Cline and considers the
word Phone an exact match with Pen, but not Fan. For these reasons, Soundex-based
functions must be used cautiously in applications.

Example
difference(soundex('drew'), soundex('draw'))

returns
0

7830 8160–027 3–43


Character Functions That Return Numeric Values

3.4.5. instr Function


Format
instr(<any string data type or blob> s1,
<any string data type or blob> s2
[ , Integer start-position [ , Integer m ] ] ) → Integer

Purpose
RDMS searches s1 beginning at character start-position for the mth occurrence of s2
and returns the position of the character in s1 that is the first character of this
occurrence. This function treats wild card characters underscore ( _ ) and percent ( % )
as normal characters. The patindex function treats the wild card characters as wild
card characters.

If start-position is negative, RDMS counts and searches backward from the end of s1.
If start-position is 0, RDMS uses 1.

The value of m must be positive. If m is less than 1, RDMS uses 1.

The default values for start-position and m are both 1 meaning that RDMS starts from
the first character position in s1 for the first occurrence of s2.

The return value is relative to the beginning of s1 regardless of the value of


start-position. The data type of the return value is INTEGER.

If the search is unsuccessful, that is, if s1 does not appear m times after the
start-position character of s1, RDMS returns the value 0. If s1 or s2 is NULL, RDMS
returns 0.

The value of s2 must be 28,616 characters or less, even if s1 is of data type BLOB.

Examples
instr( 'CORPORATE FLOOR', 'OR', 3, 2)

returns
14

instr( 'CORPORATE FLOOR', 'OR', -3, 2)

returns
2

3–44 7830 8160–027


Character Functions That Return Numeric Values

3.4.6. isalnum Function


Format
isalnum( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of alphabetic and numeric characters. Otherwise,
0 is returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

Example
isalnum('Ab123')

returns
1

3.4.7. isalpha Function


Format
isalpha( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of alphabetic characters. Otherwise, 0 is returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

7830 8160–027 3–45


Character Functions That Return Numeric Values

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

Example
isalpha('AbCdZz')

returns
1

3.4.8. iscntrl Function


Format
iscntrl( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of control characters. Otherwise, 0 is returned.

For example, the control characters for the ASCII character set are 00 (NUL) through
037 (US) inclusive and 0177 (DEL).

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

Example
iscntrl('Ab123')

returns
0

3–46 7830 8160–027


Character Functions That Return Numeric Values

3.4.9. isdigit Function


Format
isdigit( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of numeric characters. Otherwise, 0 is returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

Example
isdigit('0123456789')

returns
1

3.4.10. isgraph Function


Format
isgraph( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of graphical characters. Otherwise, 0 is returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

7830 8160–027 3–47


Character Functions That Return Numeric Values

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

For the ASCII character set, the graphical characters are 041 ( ! ) through 0176 ( ~ )
inclusive. Note that 040 (space) is not included.

Example
isgraph('@processor,options')

returns
1

3.4.11. islower Function


Format
islower( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of lowercase alphabetic characters. Otherwise, 0
is returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

Example
islower('atoz')

returns
1

3–48 7830 8160–027


Character Functions That Return Numeric Values

3.4.12. isprint Function


Format
isprint( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of printable characters. Otherwise, 0 is returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

For the ASCII character set, the printable characters are 040 (space) through 0176 ( ~ )
inclusive. Note that 040 (space) is included.

Example
isprint('@processor,options')

returns
1

3.4.13. ispunct Function


Format
ispunct( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of punctuation characters. Otherwise, 0 is
returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

7830 8160–027 3–49


Character Functions That Return Numeric Values

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

The punctuation characters for the ASCII character set are as follows:

• 041 ( ! ) through 057 ( / )


• 072 ( : ) through 0100 ( @ )
• 0133 ( [ ) through 0140 ( ` )
• 0173 ( { ) through 0176 ( ~ )

Note that space, alphabetic characters, and numeric characters are not included.

Examples
ispunct('@@@@')

returns
1

ispunct('Hello world')

returns
0

3.4.14. isspace Function


Format
isspace( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of white space characters. Otherwise, 0 is
returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

3–50 7830 8160–027


Character Functions That Return Numeric Values

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

For the ASCII character set, the white space characters are as follows:

• 011 (FF)
• 012 (NL)
• 013 (CR)
• 014 (HT)
• 015 (VT)
• 040 (space)

Example
isspace(' ')

returns
1

3.4.15. isupper Function


Format
isupper( Character s1 ) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of uppercase alphabetic characters. Otherwise, 0
is returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

If s1 is a column, the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

7830 8160–027 3–51


Character Functions That Return Numeric Values

Example
isupper('ATOZ')

returns
1

3.4.16. isxdigit Function


Format
isxdigit( Character s1) → 0 (zero) or 1 (one)

Purpose
Returns 1 if s1 is composed entirely of hexadecimal characters. Otherwise, 0 is
returned.

The s1 argument cannot be a BLOB or NCHAR column.

If s1 is NULL, RDMS returns a null value.

If s1 is a column then the following rules apply:

• If the column includes neither a CHARACTER SET nor a COLLATION, RDMS uses
the rules for the ASCII character set.
• If the column includes a CHARACTER SET without a COLLATION, RDMS uses the
character rules for the current locale.
• If the column includes both a CHARACTER SET and a COLLATION, RDMS uses the
character rules in the specified locale.

Example
isxdigit('0123456789abcdefABCDEF')

returns
1

3–52 7830 8160–027


Character Functions That Return Numeric Values

3.4.17. locate Function


Format
locate(<any string data type or blob> s1,
<any string data type or blob> s2
[ , Integer start ] ) → Integer

Purpose
Returns the starting position of expression s2 in expression s1. This function treats
wild card characters underscore ( _ ) and percent ( % ) as normal characters. The
patindex function treats the wild card characters as wild card characters.

If start is negative, RDMS searches backward from the end of s1. If start is 0, RDMS
uses the value 1.

The default value for start-position is 1.

The return value is relative to the beginning of s1 regardless of the value of start.

If the search is unsuccessful, that is , if s1 does not appear after the start character of
s1, RDMS returns the value 0. If s1 or s2 is NULL, RDMS returns 0.

The value of s2 must be 28,616 characters or less, even if s1 is of data type BLOB. If
the value is more than 28,616 characters, it is truncated to 28,616 characters.

Examples
locate( 'CORPORATE FLOOR', 'OR', 3)

returns
5

locate( 'CORPORATE FLOOR', 'OR', -3)

returns
5

7830 8160–027 3–53


Character Functions That Return Numeric Values

3.4.18. octet_length Function


Format
octet_length(<any string data type or blob> s1) → Integer

Purpose
Returns the length of the expression s1, in bytes, ignoring any trailing spaces. If s1 is
data type BLOB, all characters, including trailing spaces are included in the returned
length.

If s1 is NULL, RDMS returns 0.

In addition, see the data_length function, which returns the length in characters rather
than in bytes.

Example
Suppose cname is a column with the value “Peter”:

octet_length(cname)

returns
5

3.4.19. patindex Function


Format
patindex( Character '%pattern%',
<any string data type or blob> s1) → Integer

Purpose
Returns the position of the first occurrence of pattern in s1. Pattern may include the
wild card characters underscore ( _ ) to indicate exactly one character and percent ( %
) to indicate zero or more characters.

If RDMS does not find pattern in s1, it returns the value 0. If pattern or s1 is NULL,
RDMS returns 0.

The return data type is INTEGER.

The patindex function is supported only for strings encoded in 7-bit or 8-bit character
sets, and for Unicode strings that convert to ISO-8859-1.

Example
patindex( 'w%rd', 'forward is the word')

returns
4

3–54 7830 8160–027


Binary-to-Character/Character-to-Binary Conversion

3.5. Binary-to-Character/Character-to-Binary
Conversion
The following functions perform conversions between character and binary data
formats.

3.5.1. ascii Function


Format
ascii(Character s1) → Integer

Purpose
Returns the ASCII code for the first byte in s1 as an integer value. If s1 is NULL, RDMS
returns a null value.

The ascii and char functions are opposite functions.

Example
ascii('A')

returns
65

3.5.2. char and chr Functions


Format
char(Integer n) → Character

chr(Integer n) → Character

Purpose
Returns the character that has the ASCII code value specified by n. The value of n
must be between 0 and 255; if it is not, RDMS returns an ASCII space.

If n is NULL, RDMS uses 0 and returns the ASCII character NUL.

The char and ascii functions are opposite functions.

Example
char(65)

returns
A

7830 8160–027 3–55


Other Character Functions

3.6. Other Character Functions


The following functions perform a variety of other operations using character data.

3.6.1. coalesce and value Functions


Format
coalesce(expr1, expr2, ... , expr200) → <data type of expr1>

value(expr1, expr2, ... , expr200) → <data type of expr1>

Purpose
Returns the value for the first nonnull expression. Up to 200 arguments can be
included.

The data type of the return value is the data type of expr1. None of the expr values
can have data type BLOB.

If all the expressions are null, RDMS returns NULL.

When necessary, RDMS uses today’s date for the default date value and uses
00:00:00 as the default time value (see example).

Example 1
This function can be used to correct for null values in an arithmetic expression.

SELECT empno, empname coalesce(salary,0) +


coalesce(commission, 0) AS totalpay
FROM employees

Example 2
The following example references a column with a data type of TIMESTAMP. Because
the replacement value has no date portion, RDMS uses today’s date.

SELECT coalesce(order_date, '12:00:00')

returns the timestamp value


2001-05-15 12:00:00

3–56 7830 8160–027


Other Character Functions

3.6.2. decode Function


Format
decode(s1, compare1, value1
[ , compare2, value2 ]
. . .
[ , compare99, value99 ]
, default) → <data type of value1>

Purpose
The decode function is similar to a series of nested IF-THEN-ELSE statements. The
expression s1 is compared to the compare1, compare2, and so forth, in sequence. If
s1 matches the i th compare item, RDMS returns the i th value. If s1 does not match
any of the compare values, RDMS returns the default value.

The data type of s1 cannot be FLOAT, REAL, or DOUBLE PRECISION.

The data type of each compare must match or be coercible to the data type of the
expression s1. See Table 2–12 for comparison rules for character data types. These
comparison rules also apply to coercibility. All numeric types are coercible. RDMS
uses a default year of 01-01-001 when coercing TIME to TIMESTAMP and a default
time of 00:00:00 when coercing DATE to TIMESTAMP. RDMS truncates the time value
when coercing TIMESTAMP to DATE and truncates the date value when coercing
TIMESTAMP to TIME.

The data type of each value and the default must match value1.

The data type of the return value is the data type of value1 (the third parameter). None
of the compare, value, or default values can have data type BLOB.

The maximum number of arguments is 200, allowing 99 pairs of comparison and


value.

Example
decode('abc', 'a', 1,
'b', 2,
'abc', 3,
'd', 4,
-1)

returns
3

7830 8160–027 3–57


Other Character Functions

3.6.3. ifnull and nvl Functions


Format
ifnull(expr1, expr2) → <data type of expr1>

nvl(expr1, expr2) → <data type of expr1>

Purpose
If the expression expr1 is NULL, RDMS returns the expression expr2, else RDMS
returns expr1. The arguments expr1 and expr2 can be any data type, but they must
match.

The data type of the return value is the data type of expr1.
Expressions with data type BLOB cannot be used with the ifnull and nvl functions.

Examples

SELECT ifnull(desiredloc, 'no location specified')

SELECT nvl(desiredloc, 'no location specified')

3.6.4. nullif function


Format
nullif(expr1, expr2) → <data type of expr1>

Purpose
If the value of expr1 matches the value of expr2, then NULL is returned. Otherwise,
the value of expr1 is returned. The expressions, expr1 and expr2, must not be the
keyword NULL. If the expressions resolve to a null value, the comparison results in an
unknown value. Because unknown is not the same as true, the value of expr1 is
returned.

The data type of expr1, and expr2 must not be FLOAT, REAL, DOUBLE PRECISION or
BLOB.

The data type of each compare must match or be coercible to the data type of the
expression expr1. See Table 2–12 for comparison rules for character data types. These
rules also apply to coercibility. All numeric types are coercible. RDMS uses a default
year of 01-01-0001 when coercing TIME to TIMESTAMP and a default time of 00:00:00
when coercing DATE to TIMESTAMP. RDMS truncates the time value when coercing
TIMESTAMP to DATE and truncates the date value when coercing TIMESTAMP to
TIME.

3–58 7830 8160–027


Mathematical and Numerical Conversion Functions

Example 1
SELECT nullif(1957,1957)

returns

NULL

Example 2
SELECT nullif('apple', 'orange')

returns

'apple'

3.7. Mathematical and Numerical Conversion


Functions
The following are the RDMS mathematical and numerical conversion functions.

3.7.1. abs and absval Functions


Format
abs(<any numeric data type>) → <same numeric data type>

absval(<any numeric data type>) → <same numeric data type>

Purpose
Returns the absolute value of the argument. If the argument is NULL, RDMS returns a
null value.

Example
abs(-15)

returns 15

3.7.2. acos Function


Format
acos(Double Precision) → Double Precision

Purpose
Returns the principal value of the arc cosine of the argument, between 0 and pi. RDMS
returns an error if the argument is not between –1 and 1. If the argument is NULL,
RDMS returns a null value.

7830 8160–027 3–59


Mathematical and Numerical Conversion Functions

Example
acos(0)

returns
1.5708

3.7.3. asin Function


Format
asin(Double Precision) → Double Precision

Purpose
Returns the principal value of the arc sine of the argument, between –pi/2 and pi/2.
RDMS returns an error if the argument is not between –1 and 1. If the argument is
NULL, RDMS returns a null value.

Example
asin(1)

returns
1.5708

3.7.4. atan Function


Format
atan(Double Precision) → Double Precision

Purpose
Returns the principal value of the arc tangent of the argument, between –pi/2 and pi/2.
If the argument is NULL, RDMS returns a null value.

Example
atan(1)

returns
.7854

3.7.5. atan2 Function


Format
atan2(Double Precision y, Double Precision x ) → Double Precision

Purpose
Returns the principal value of the arc tangent of y/x using the signs of both arguments
to determine the quadrant of the return value. The result is between –pi and pi.

3–60 7830 8160–027


Mathematical and Numerical Conversion Functions

RDMS returns an error if both arguments are 0. If an argument is NULL, RDMS returns
a null value.

Example
atan2(1,2)

returns
.4636

3.7.6. ceil and ceiling Functions


Format

ceil(<any numeric data type> x) → <same data type>

ceiling(<any numeric data type> x) → <same data type>

Purpose
Returns the smallest integer value greater than or equal to x. If the argument is NULL,
RDMS returns a null value.
There are two exceptions to the rule that the return type is the same type as the
argument type. If the argument type is either decimal or numeric, the return type is
double precision.
Example
ceiling(13.2)

returns
14

3.7.7. cos Function


Format
cos(Double Precision) → Double Precision

Purpose
Returns the cosine of the argument measured in radians. If the argument is NULL,
RDMS returns a null value.

Example
cos(180*3.1415/180)

returns
-1

7830 8160–027 3–61


Mathematical and Numerical Conversion Functions

3.7.8. cosh Function


Format
cosh(Double Precision) → Double Precision

Purpose
Returns the hyperbolic cosine of the argument measured in radians. If the argument is
NULL, RDMS returns a null value.

Example
cosh(0)

returns
1

3.7.9. cot Function


Format
cot(Double Precision) → Double Precision

Purpose
Returns the cotangent of the argument measured in radians. If the argument is NULL,
RDMS returns a null value.

Example
cot(1)

returns
.6421

3.7.10. degree and degrees Functions


Format
degree( Double Precision) → Double Precision

degrees( Double Precision) → Double Precision

Purpose
Converts the argument angle from radians to degrees. If the argument is NULL, RDMS
returns a null value.

Also see the radian function.

3–62 7830 8160–027


Mathematical and Numerical Conversion Functions

Example
degrees(1.5708)

returns
90

3.7.11. exp Function


Format
exp(Double Precision x) → Double Precision

Purpose
Returns ex, where e is the base of the natural logarithms. If the argument is NULL,
RDMS returns a null value.

Example
exp(4)

returns
54.59815

3.7.12. floor Function


Format
floor(<any numeric data type> x) → <same data type>

Purpose
Returns the largest integer less than or equal to x. If the argument is NULL, RDMS
returns a null value.

There are two exceptions to the rule that the return type is the same type as the
argument type. If the argument type is either decimal or numeric, the return type is
double precision.
Example
floor(15.8)

returns
15

7830 8160–027 3–63


Mathematical and Numerical Conversion Functions

3.7.13. hex Function


Format
hex(<any numeric data type> n) → Character

Purpose
Returns the hexadecimal representation of n as ASCII characters. RDMS displays the
one- or two-word OS 2200 representation of the binary value.

RDMS converts numeric literals and values of data type DECIMAL to NUMERIC and
displays the hexadecimal representation of the NUMERIC format.

Example
hex(2048)

returns
800

3.7.14. integer Function


Format
integer(<any string data type> e1) → Integer

integer(<any numeric data type> e1) → Integer

int(<any string data type> e1) → Integer

int(<any numeric data type> e1) → Integer

Purpose
Returns the expression e1 cast to data type INTEGER. If e1 results in a value larger
than can be represented by INTEGER, RDMS returns an overflow error but does not
roll back the thread. Any fractional part of e1 is truncated; for example, int(34.99)
returns 34.

Examples
integer('33')

returns
33

int(substr('abc123',4,2))

returns
12

3–64 7830 8160–027


Mathematical and Numerical Conversion Functions

3.7.15. ln Function
Format
ln(Double Precision) → Double Precision

Purpose
Returns the natural logarithm of the argument. The argument must be greater than 0.
If the argument is NULL, RDMS returns a null value.

Example
ln(95)

returns
4.55387

3.7.16. log Function


Format
log(Double Precision n) → Double Precision

log(Double Precision b, Double Precision n) → Double Precision

Purpose
This function has two formats:

• With one argument, returns the natural logarithm of n.


• With two arguments, returns the logarithm, base b, of n. The base b can be any
positive number other than 0 or 1, and n can be any positive number.

If n is NULL, RDMS uses 0. If b is NULL RDMS returns a null value.

Examples
log(95)

or
log(exp(1),95)

returns
4.55387

log(10,100)

returns
2

7830 8160–027 3–65


Mathematical and Numerical Conversion Functions

3.7.17. log10 Function


Format
log10(Double Precision) → Double Precision

Purpose
Returns the logarithm, base 10, of the argument. The value n can be any positive
number. If the argument is NULL, RDMS returns a null value.

Example
log10(100)

returns
2

3.7.18. mod Function


Format
mod(Integer m, Integer n) → Integer

Purpose
Returns the remainder (modulus) of the m divided by n. If m or n is NULL, RDMS
returns a null value. If n is zero, RDMS returns an error.

Example
mod(13,4)

returns
1

3.7.19. octal Function


Format
octal(<any numeric data type> n) → Character

Purpose
Returns the octal representation of n as ASCII characters. RDMS displays the one- or
two-word OS 2200 representation of the binary value.

RDMS converts numeric literals and values of data type DECIMAL to NUMERIC and
displays the octal representation of the NUMERIC format.

3–66 7830 8160–027


Mathematical and Numerical Conversion Functions

Example
octal(2048)

returns
4000

3.7.20. pi Function
Format
pi() → Double Precision

Purpose
Returns the value of pi as a 72-bit floating-point number.

Example
pi()

returns
3.1415926535897932

3.7.21. power Function


Format
power(<any numeric data type> x, <any numeric data type> y) →
Integer or Double Precision

Purpose
Returns x raised to the power y (xy). If either argument is NULL, RDMS returns a null
value.

The following chart summarizes the results of the power function based on the data
types of the arguments. If the result exceeds the maximum value for the INTEGER or
DOUBLE PRECISION data type, RDMS returns an error. The maximum value for an
INTEGER data type is 34,359,738,367. The maximum value for DOUBLE PRECISION is
8.988,465,674,311,579,549E+307.

power(0, 0) returns the value 1 as an integer.

7830 8160–027 3–67


Mathematical and Numerical Conversion Functions

Data Type of y

Decimal, precision > 0 Decimal, precision = 0


Numeric, precision > 0 Numeric, precision = 0
Real Smallint
Float Integer
Double precision

Decimal, precision > 0 Result is double precision. Some Result is double precision.
Numeric, precision > 0 precision may be lost because Some precision may be lost
Data Type of x

Real double precision is an because double precision is


Float approximate numeric data type. an approximate numeric
Double precision data type.
Decimal, precision = 0 Result is double precision. Some Result is integer.
Numeric, precision = 0 precision may be lost because
Smallint double precision is an
Integer approximate numeric data type.

Examples
power(2,8)

returns 256 as integer.

power(10,3)

returns 1000 as integer.

To allow a larger result value, ensure one of the arguments is not an integer:
power(10,3.0)

returns 1000 as double precision.

power(36,0.5)

returns 6 as double precision.

3.7.22. radians Function


Format
radians(Double Precision) → Double Precision

Purpose
Converts the argument angle from degrees to radians. If the argument is NULL, RDMS
returns a null value.

Also see the degree function.

3–68 7830 8160–027


Mathematical and Numerical Conversion Functions

Example
radians(90)

returns
1.5708

3.7.23. rand Function


Format
rand() → Double Precision

rand(Integer) → Double Precision

Purpose
Returns a random double-precision floating-point number between 0 and 1. The
optional argument is used as a “seed” to begin a new random number sequence.

If the argument is given and is NULL, RDMS returns a null value.

Example
rand()

returns
.3426

3.7.24. real Function


Format
real(<any string data type> e1) → Real

real(<any numeric data type> e1) → Real

Purpose
Returns the expression e1 cast to data type REAL. If e1 is not within the range of
single precision REAL, RDMS returns an overflow error but does not roll back the
thread.

7830 8160–027 3–69


Mathematical and Numerical Conversion Functions

Examples
real('33')

returns
33.0

real(substr('abc12.3',4,4))

returns
12.3

3.7.25. round Function


Format
round(Smallint x [ , Integer n ] ) → Smallint

round(Integer x [ , Integer n ] ) → Integer

round(Any other numeric data type x [ , Integer n ] ) → Double


Precision

Purpose
Rounds the argument x in such a way that its least significant digit is n digits to the
right of the decimal point (if n is omitted or is NULL, to 0 places; if n is negative, the
least significant digit is to the left of the decimal point).

Rounding to more than 18 significant digits may produce incorrect results.

If x is NULL, RDMS returns a null value.

Also see the truncate function (3.7.34).

Examples
round(873.625, 2)

returns 873.63 as double precision.

round(873.625, 1)

returns 873.6 as double precision.

round(873.625, 0)

or
round(873.625)

returns 874.0 as double precision.

3–70 7830 8160–027


Mathematical and Numerical Conversion Functions

round(873.625, -1)

returns 870.0 as double precision.

round(873.625, -2)

returns 900.0. as double precision.

3.7.26. sign Function


Format
sign(<any numeric data type>) → Integer

Purpose
Returns +1 if the argument is positive, -1 if the argument is negative, 0 if the argument
is 0. If the argument is NULL, RDMS returns a null value.

Example
sign(-233)

returns
-1

3.7.27. sin Function


Format
sin(Double Precision) → Double Precision

Purpose
Returns the sine of the argument, measured in radians. If the argument is NULL,
RDMS returns a null value.

Example
sin(30 * 3.14159 / 180)

returns
.5

7830 8160–027 3–71


Mathematical and Numerical Conversion Functions

3.7.28. sinh Function


Format
sinh(Double Precision) → Double Precision

Purpose
Returns the hyperbolic sine of the argument, measured in radians. If the argument is
NULL, RDMS returns a null value.
Example
sinh(1)

returns
1.175201

3.7.29. smallint Function


Format
smallint(<any string data type> e1) → Smallint

smallint(<any numeric data type> e1) → Smallint

Purpose
Returns the expression e1 cast to data type SMALLINT. If e1 results in a value larger
than can be represented by SMALLINT, RDMS returns an overflow error but does not
roll back the thread. Any fractional part of e1 is truncated; for example, smallint(34.99)
returns 34.

Examples
smallint('33')

returns
33

smallint(substr('abc12.3',4,4))

returns
12

3–72 7830 8160–027


Mathematical and Numerical Conversion Functions

3.7.30. sqrt Function


Format
sqrt(Double Precision) → Double Precision

Purpose
Returns the square root of the argument. It cannot be a negative value. If the
argument is NULL, RDMS returns a null value.

Example
sqrt(81)

returns
9

3.7.31. str Function


Format
str(<any numeric data type> n1 [, Integer length [ , Integer precision]] )
→ Character

Purpose

Returns the n1 argument converted to length ASCII characters, with precision


characters to the right of the decimal point.

If n1 is NULL, RDMS returns a null value.

The length, if specified gives the total number of characters, including a decimal point,
and '-' sign (RDMS omits the '+' if the value is positive). RDMS space fills on the left if
length is greater than the total number of digits returned. If the value after the
conversion does not fit within the length specified, RDMS returns asterisks (*****). If
length is omitted, is NULL, or is less than or equal to zero (0), RDMS uses the value 10.
If length is greater than 22, RDMS uses 22.

The precision refers to the number of characters to the right of the decimal point. If
precision is greater than 20, RDMS uses 20. If precision is omitted, RDMS uses 2 for
data types FLOAT, REAL, and DOUBLE PRECISION; and uses the precision of n1 for
other data types. If precision is NULL, or is less than or equal to zero (0), RDMS
returns no fractional digits and no decimal point. If precision is greater than length,
RDMS returns asterisks (*****). When n1 has more than precision fractional digits,
RDMS rounds the value to precision fractional digits. When n1 has less than precision
fractional digits, RDMS zero fills the digits to the right of the decimal point.

7830 8160–027 3–73


Mathematical and Numerical Conversion Functions

Examples
str (-3.456)

returns
-3.456

str ( +3.456, 12, 6)

returns
∆∆∆∆3.456000

where ∆ indicates an ASCII space. Note that RDMS zero-fills to the indicated precision.

str ( +765432.456, 5, 2)

returns
*****

because the number of digits is greater than 5.

str ( +3.45, 4, 1)

returns ∆3.5, where ∆ indicates an ASCII space. Note that the fractional value is
rounded up.

To counteract the rounding behavior, use the floor or ceiling function:

str ( floor(+3.45, 1), 4, 1)

returns
∆3.4

str ( ceiling(+3.11, 1), 4, 1)

returns
∆3.2

3–74 7830 8160–027


Mathematical and Numerical Conversion Functions

3.7.32. tan Function


Format
tan(Double Precision) → Double Precision

Purpose
Returns the tangent of the argument, measured in radians. If the argument is NULL,
RDMS returns a null value.

Example
tan(135 * 3.14159 / 180)

returns
-1

3.7.33. tanh Function


Format
tanh(Double Precision) → Double Precision

Purpose
Returns the hyperbolic tangent of the argument, measured in radians. If the argument
is NULL, RDMS returns a null value.

Example
tanh(.5)

returns
.462117

7830 8160–027 3–75


Mathematical and Numerical Conversion Functions

3.7.34. trunc and truncate Functions


Format
trunc(Smallint x [ , Integer n ] ) → Smallint

trunc(Integer x [ , Integer n ] ) → Integer

trunc(Double Precision x [ , Integer n ] ) → Double Precision

Purpose
Truncates the argument x in such a way that its least significant digit is n digits to the
right of the decimal point (if n is omitted or is NULL, to 0 places; if n is negative, to the
left of the decimal point).

If x is NULL, RDMS returns a null value.

Also see the round function (3.7.25).

Examples
truncate(873.627, 2)

returns 873.62 as double precision.

truncate(873.627, 1)

returns 873.6 as double precision.

truncate(873.627, 0)

or
truncate(873.627)

returns 873.0 as double precision.

truncate(873.627, -1)

returns 870.0 as double precision.

truncate(873.627, -2)

returns 800.0 as double precision.

3–76 7830 8160–027


Mathematical and Numerical Conversion Functions

3.7.35. double Function


Format
double(<any string data type> e1) -> DOUBLE PRECISION

double(<any numeric data type> e1) -> DOUBLE PRECISION

Purpose
Returns the expression e1 cast to data type DOUBLE PRECISION. If e1 is not within the
range of the double precision floating point value, RDMS returns an overflow error but
does not roll back the thread.

Examples
double('33')

returns

.33000000000000000E+002

double(substr('abc12.3',4,4))

returns

.12300000000000000E+002

7830 8160–027 3–77


Date, Time, and Timestamp Functions

3.8. Date, Time, and Timestamp Functions


The following functions perform operations that manipulate date values.

3.8.1. add_months Function


Format
add_months(<date or timestamp data type> d, Integer x ) → <data type of d>

Purpose
Returns d incremented or decremented by x months. If the resultant month has fewer
days than the month of d, the last day of the resultant month is returned. Any time
portion of d remains unchanged.

If d is NULL, RDMS returns a null value. If x is NULL, RDMS uses 0.

If d is a character string containing data in DATE, TIME, or TIMESTAMP format, the


add_months function returns a data type of TIMESTAMP with precision 6.

If d is a literal character string containing data in DATE, TIME, or TIMESTAMP format,


the add_months function converts the literal string into the corresponding type it
represents. For example

add_months('2001-01-08 13:13:13', 3)

returns
2001-04-08 13:13:13

add_months('2001-01-08', 3)

returns
2001-04-08

Example
add_months('2001-03-31', -1)

returns the date value


2001-02-28

3–78 7830 8160–027


Date, Time, and Timestamp Functions

3.8.2. cast Function


Format
cast (<any string data type> cast-operand AS Character cast-target) →
<any string data type>

Purpose
Returns the argument with its data type changed to the specified target data type. The
cast function instructs RDMS to convert a character string to a datetime or interval
data type. It allows for the specification of datetime and interval values in host
program variables in application programs.

cast–operand is the source operand of the data type conversion.

cast–target is the data type to which the value of the source operand is to be
converted.

Follow these guidelines when using the cast function:

• You can use the cast function wherever an expression is allowed.


• The operand can be a character string literal, a routine parameter, an SQL variable,
or a host program variable:
− The host program variable must be a character type (for example, PIC X type in
COBOL) and can be an embedded variable (static ESQL interface), a parameter
marker (dynamic ESQL interface), or a placeholder variable (interactive
interface).
− You can optionally specify an indicator variable for an embedded or
placeholder variable.
• The character string specified as or contained in the operand must be in the valid
form of a literal or a value of the data type specified as the target.
• The date, time, timestamp, or interval value is valid (as well as the datetime or
interval literal) for a source operand of the cast function. The following lines
illustrate datetime and interval literals, where the date, time, timestamp, and
interval values are part of the datetime or interval literal.

DATE'date-value'
TIME'time-value'
TIMESTAMP'timestamp-value'
INTERVAL[ ± ]'interval-value' interval-qualifier

This allows the use of the same program variables (for example, variables created
by the UREP command REPORT COBOL or REPORT C) to fetch from and insert
into a table.

• If the fractional part of the SECOND field in the source character string contains
more digits than the data type specified in the target, RDMS truncates the lower
fractional digits for both datetime and interval data types.

7830 8160–027 3–79


Date, Time, and Timestamp Functions

• The converted value must fit in the valid value range of the specified data type,
except for the fractional digits of the SECOND field; otherwise, RDMS returns an
error.
• You cannot use the cast function in the CREATE TABLE and ALTER TABLE
statements.
• You can use the cast function to pass datetime data from program variables. The
argument for the cast function must be a CHARACTER type string that contains a
datetime or interval literal or a date, time, timestamp, or interval value.
• The target must be a datetime or interval data type.
• The cast function cannot be used as an argument for other scalar functions.

Supported and Unsupported Conversions and Comparisons


RDMS supports the implicit conversion and comparison of string literals in the
following contexts:

• INSERT statement
Inserting a string literal into a numeric value
• UPDATE statement
Updating a numeric with a string literal
• WHERE clause
Expression comparing a string literal with a numeric
• SET statement
Setting a numeric from a string literal
• Stored procedures
Using a string literal as an argument to a numeric

The following are examples of supported implicit string literal to numeric conversion:

Select * FROM my_table WHERE numeric_column < '1234';

INSERT INTO my_table VALUES ($p1)

In the preceding examples, $p1 corresponds to a numeric column in my_table and also
to a character value that has been initialized to the value "1234" within a program.

RDMS does not support string literal to numeric conversions in the following contexts:

• String literal in an arithmetic expression


• String literal conversion in an argument of a built-in function

3–80 7830 8160–027


Date, Time, and Timestamp Functions

The following are examples of unsupported implicit string literal to numeric


conversion:

SELECT * FROM my_table WHERE int_column <= dec_column + '1234';

SELECT AVG('1234') FROM my_table;

Cast to Timestamp
You can cast a value to a timestamp data type.

Format
DATE

TIME [ (time-precision) ]

TIMESTAMP [ (timestamp-precision) ]

where:

time–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 0 is assumed.

timestamp–precision
represents the number of fractional digits, from 0 to 6, in the seconds portion of
the item after the decimal point. If omitted, 6 is assumed.

Example 1
Insert the date January 30, 1998, using a constant into column MYDATE of table
MYTABLE:

EXEC SQL INSERT INTO mytable COLUMNS (mydate=DATE'1998-01-30')

Insert the date, using a datetime value retrieved from column MYDATE of TABLE
mytable. Variable VDATE contains the string DATE ‘1998–01–30’. The length of the
buffer VDATE to contain the date string 1998–01–30 should be at least 10 ASCII
characters.

EXEC SQL SELECT mydate FROM mytable INTO :vdate


EXEC SQL INSERT INTO mytable COLUMNS (mydate CAST(:vdate AS DATE))

Example 2
The next example converts a time literal (for example, TIME ‘23:01:30.123’) or time
value (for example, 23:01:30.123) contained in the embedded character variable VAR to
a time value:

CAST( :var INDICATOR :var-ind AS TIME( 3 ) )

7830 8160–027 3–81


Date, Time, and Timestamp Functions

Example 3
The final example converts a character string literal to a timestamp value. The actual
value stored in the database is 1998–10–11 16:03:00.000000.

CAST('TIMESTAMP''1998-10-11 16:03:00''' AS TIMESTAMP(6))


CAST('1998-10-11 16:03:00.00' AS TIMESTAMP(6))

Cast to Interval
You can cast a value to an interval using the INTERVAL function.

Interval types include year-month and day-time intervals:

• Year-month intervals contain a YEAR or MONTH field, or both.


• Day-time intervals contain a contiguous subset of DAY, HOUR, MINUTE, and
SECOND fields.

Follow these guidelines when using interval types:

• You can use interval types as operands within a datetime arithmetic expression.
You cannot use them as the source operand of the cast, extract, avg, count, max,
min, and functions.
• You generate interval values with the cast function and interval literals.
• You cannot define a column of data type interval. You cannot specify an
expression that results in an interval value. It follows, then, that you cannot have
an expression that evaluates to an interval type in the select list of a query
specification, and you cannot have a comparison operand that evaluates to an
interval value.

As long as you follow these guidelines, you can use interval items anywhere in SQL
statements.

3–82 7830 8160–027


Date, Time, and Timestamp Functions

Format
INTERVAL interval-qualifier

The formats of interval–qualifier for year-month intervals are

YEAR [ (leading-field-precision) ]

YEAR [ (leading-field-precision) ] TO MONTH

MONTH [ (leading-field-precision) ]

The formats of interval–qualifier for day-time intervals are

DAY [ (leading-field-precision) ] [ TO DAY ]

DAY [ (leading-field-precision) ] TO HOUR


DAY [ (leading-field-precision) ] TO MINUTE

DAY [ (leading-field-precision) ] TO SECOND [ (fractional-precision) ]

HOUR [ (leading-field-precision) ] [ TO HOUR ]

HOUR [ (leading-field-precision) ] TO MINUTE

HOUR [ (leading-field-precision) ] TO SECOND [ (fractional-precision) ]

MINUTE [ (leading-field-precision) ] [ TO MINUTE ]

MINUTE [ (leading-field-precision) ] TO SECOND [ (fractional-precision) ]

SECOND [ (leading-field-precision [,fractional-precision])]

where:

leading–field–precision
is the number of digits allowed for the starting field of the interval. For the
SECOND field, it is the number of digits preceding the decimal point. Maximum is
4; default is 2.

fractional–precision
is the number of digits following the decimal point for the SECOND field.
Maximum is 6; default is 6.

7830 8160–027 3–83


Date, Time, and Timestamp Functions

Follow these guidelines when specifying interval types:

• Order datetime fields as follows: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND.
• If you have a starting and ending field separated by the word TO, all included
datetime fields based on the preceding order are affected by the interval
specified.
• If the starting and ending fields are identical, the ending field is ignored.

Table 3–3 illustrates the range of values allowed for each interval type.

Table 3–3. Range of Values for Interval Types

Type Range

YEAR 0 to 9999 (further constrained by the interval qualifier)


MONTH 0 to 11 (within year) *
DAY 0 to 9999 (further constrained by the interval qualifier)
HOUR 0 to 23 (within day) *
MINUTE 0 to 59 (within hour) *
SECOND 0 TO 59.999999 (within minute) *

* These fields can contain from 0 to 9999 (9999.999999 for SECOND), depending on the
specification of the interval qualifier, if they are specified as the starting field of an
interval type.

The amount of memory required by interval types is always 8 bytes, regardless of the
number or kinds of datetime fields involved.

Example 1
The following example converts a character string literal to an interval value. Note that
you can specify the sign in interval values.

CAST('INTERVAL-''123:45'' HOUR(3) TO MINUTE'


AS INTERVAL HOUR(3) TO MINUTE)
CAST ('-123:45' AS INTERVAL HOUR(3) TO MINUTE)

Example 2
The next example elicits an error because the sign is specified in front of the character
string. The cast function requires a character string in a source operand.

CAST(-'123:45' AS INTERVAL HOUR(3) TO MINUTE)

3–84 7830 8160–027


Date, Time, and Timestamp Functions

Example 3
The next example elicits an error because the source operand does not follow both
formats, for interval literal and interval value:

CAST('-''123:45'' HOUR(3) TO MINUTE' AS HOUR(3) TO MINUTE)


CAST('INTERVAL''123:45''' AS HOUR(3) TO MINUTE)

Example 4
The next example elicits an error because the string literal does not fit in the value
range permissible for the target data type:

CAST('INTERVAL -''999:00'' HOUR TO MINUTE'


AS INTERVAL HOUR(2) TO MINUTE)

Example 5
The final example extracts an exact numeric value from the HOUR field of the result of
a datetime arithmetic expression, with a result data type of NUMERIC(2):

EXTRACT( HOUR FROM ( time_column + CAST( :var AS INTERVAL HOUR TO MINUTE ) ) )

3.8.3. convert Function


Format
convert(<time, date or timestamp data type > d, Integer x ) → Character

Purpose
Returns d formatted according to the format x.

If you use formats 0, 8, 9, 100, 108, 109, 13, 113, 14, 114, 20, 120, 21, 121, 126, or 127 with
a date value, then RDMS uses the time 00:00:00.

If you use any format except 8, 108, 14 or 114 with a time value, then RDMS uses
today’s date.

If d is NULL, RDMS returns a null value. If x is NULL, RDMS uses 0.

If d has a precision of 3 or less, RDMS returns three fractional digits (milliseconds). If d


has a precision greater than 3, RDMS returns the number of fractional digits indicated
by the precision.

7830 8160–027 3–85


Date, Time, and Timestamp Functions

Years That Do Not Include a Century


For years that do not include a century, the allowed values for x are as follows.

Values for x
Year Without Century Format of Value in the Converted String

0 or 100 mon dd yyyy hh:miAM (or PM)


1 mm/dd/yy
2 yy.mm.dd
3 dd/mm/yy
4 dd.mm.yy
5 dd-mm-yy
6 dd mon yy
7 mon dd, yy
8 or 108 hh:mi:ss
9 or 109 mon dd, yyyy hh:mi:ss:mmmAM (or PM)
10 mm-dd-yy
11 yy/mm/dd
12 Yymmdd
13 or 113 dd mon yyyy hh:mi:ss:mmm(24h)
14 or 114 hh:mi:ss:mmm(24h)
20 or 120 yyyy-mm-dd hh:mi:ss (24h)
21 or 121 yyyy-mm-dd hh:mi:ss.mmm (24h)
126 ISO8601 yyyy-mm-ddThh:mi:ss.mmm (no spaces)
127 ISO8601 with time zone Z yyyy-mm-ddThh:mi:ss.mmmZ (no spaces)
80 mmddyy

3–86 7830 8160–027


Date, Time, and Timestamp Functions

Years That Include a Century


For years that include a century, the allowed values for x are as follows.

Values for x
Year with Century Format of Value in the Converted String

100 or 0 mon dd yyyy hh:miAM (or PM)


101 mm/dd/yyyy
102 yyyy.mm.dd
103 dd/mm/yyyy
104 dd.mm.yyyy
105 dd-mm-yyyy
106 dd mon yyyy
107 mon dd, yyyy
108 or 8 hh:mi:ss
109 or 9 mon dd, yyyy hh:mi:ss:mmmAM (or PM)
110 mm-dd-yyyy
111 yyyy/mm/dd
112 Yyyymmdd
13 or 113 dd mon yyyy hh:mi:ss:mmm(24h)
14 or 114 hh:mi:ss:mmm(24h)
20 or 120 yyyy-mm-dd hh:mi:ss(24h)
21 or 121 yyyy-mm-dd hh:mi:ss.mmm(24h)
126 ISO8601 yyyy-mm-ddThh:mi:ss.mmm (no spaces)
127 ISO8601 with time zone Z yyyy-mm-ddThh:mi:ss.mmmZ (no spaces)
180 mmddyyyy

Examples
convert('2001-02-21', 7)

returns the string


Feb 21, 01

convert('2001-02-21' , 107)

returns the string


Feb 21, 2001

7830 8160–027 3–87


Date, Time, and Timestamp Functions

convert('2004-10-27 13:22:38.1', 109)

returns the string (with three fractional digits)


Oct 27, 2004 01:22:38.100PM

convert('2004-10-27 13:22:38.32347', 109)

returns the string (with five fractional digits)


Oct 27, 2004 01:22:38.32347PM

3.8.4. curdate Function


Format
curdate( ) → Date

Purpose
Returns the current date in YYYY-MM-DD format

Example
If executed on the 12th of February 2002
curdate( )

returns the date string


2002-02-12

3.8.5. curtime Function


Format
curtime( ) → Time

Purpose

Returns the current time in HH:MM:SS format, with no partial seconds.

Example
If executed at 2:56:23 P.M.
curtime( )

returns the time string


14:56:23

3–88 7830 8160–027


Date, Time, and Timestamp Functions

3.8.6. date Function


Format
date(<character, date, or timestamp data type> d) → Date

Purpose
Converts d to a date value.

If d is NULL, RDMS returns a null string.

The argument d may be one of the following:

• A column with data type date or timestamp. If d is a time value, RDMS returns an
error.
• A valid date or timestamp literal value – see section 2.3.4.
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in one
of these formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− ddMonyyyy
− mm/dd/yyyy
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss

Additional processing rules:

• If d is a timestamp, the result is the date part of the timestamp.


• If d is a date, the result is that date.
• If d is a string, the result is the date that is represented by the string.
• If d is a time, RDMS returns an error.

See also strptime, to_date, to_timestamp, and timestamp_format functions which can
return values other than Date.

Examples
date('2011-09-23')

returns the date 2011-09-23

date(current_timestamp)

suppose the current_timestamp value is 2011-10-07 09:57:23, the function returns the
date 2011-10-07.

7830 8160–027 3–89


Date, Time, and Timestamp Functions

3.8.7. dateadd Function


Format
dateadd(Character datepart, Integer x,
<character, time, date, timestamp data type> d) →
data type of d>

Purpose
Returns the time, date, or timestamp value produced by adding the number x of parts
datepart to d. The next higher granularity is incremented if necessary to produce a
valid result.

If you use any time datepart for a DATE value, RDMS sets the time portion to
00:00:00. If you use any date datepart for a TIME value, RDMS sets the date portion to
0001-01-01.

If datepart or d is NULL, RDMS returns a null value. If x is NULL, RDMS uses 0.

If d is a character type containing data in DATE, TIME, or TIMESTAMP format, the


dateadd function returns a data type of TIMESTAMP with precision 6.

If d is a literal character string containing data in DATE, TIME, or TIMESTAMP format,


the dateadd function returns a DATE, TIME, or TIMESTAMP. For example

dateadd('second', 1, '2001-01-08 13:13:13')

returns
2001-01-08 13:13:14

dateadd('day', 1, '2001-01-08')

returns
2001-01-09

The values for datepart are not case-sensitive.

If d is a datetime literal (for example, DATE ‘2001-12-24’), dateadd returns the data type
of the datetime literal.

3–90 7830 8160–027


Date, Time, and Timestamp Functions

The allowed values for datepart and x are as follows.

datepart
datepart Abbreviation Valid Range of x

year yy Approximately –247 to +7999, to produce dates in


the range 1753 to 9999
quarter qq -63 to +63
month mm -255 to +255
dayofyear dy -65,535 to +65,535
day dd
weekday dw
week wk -9362 to +9362
hour hh -255 to +255
minute mi -255 to +255
second ss -999999 to +999999
millisecond ms -999999 to +999999

Examples
dateadd('day', 1, DATE '2001-01-31')

returns the date string


2001-02-01

dateadd('WEEKDAY', 2, '2001-01-31')

Because d is a literal character string, dateadd returns the date string


2001-02-02

dateadd('Day', -1, '2001-03-01 21:0 to8:33')

returns the timestamp string


2001-02-28 21:08:33

7830 8160–027 3–91


Date, Time, and Timestamp Functions

3.8.8. datediff Function


Format
datediff(Character datepart,
<time, date, or timestamp data type> d1,
<time, date, or timestamp data type> d2) → Integer

Purpose
Returns d2 minus d1 as measured by the specified datepart. If you use any time
datepart for a DATE value, RDMS sets the time portion to 00:00:00. If you use any
date datepart for a TIME value, RDMS sets the date portion to 01,01,0001.

RDMS does not include partial units. It rounds down to a whole number of units. For
example, if the datepart is 'day' and the difference is 2 days 3 hours, RDMS returns
the value 2 (days).

The values for datepart are not case-sensitive.

If datepart, d1, or d2 are NULL, RDMS returns a null value.

The allowed values for datepart are as follows.

datepart
datepart Abbreviation Valid Range Produced

Year yy Approximately –247 to +7999, to produce dates in


the range 1753 to 9999
Month mm -127 to +127
day dd -511 to +511
hour hh -511 to +511
minute mi -511 to +511
second ss -999999 to +999999
millisecond ms -999999 to +999999

Examples
datediff('Day', '2001-02-01', '2001-01-31')

returns
-1

datediff('MONTH', '2001-01-14', '2001-02-01')

3–92 7830 8160–027


Date, Time, and Timestamp Functions

Because the day value for d2 is not at least as large as the day value for d1, not an
entire month has passed. RDMS returns 0.

datediff('hour', '2001-01-31', '2001-02-01')

returns
24

3.8.9. datename Function


Format
datename(Character datepart,
<character, time, or timestamp data type> d) → Character

Purpose
Returns the specified datepart of d as a string, converted to a name (for example,
“January”) if appropriate. RDMS uses the day and month names from the current
locale.

If you use any time datepart for a DATE value, RDMS sets the time portion to
00:00:00. If you use any date datepart for a TIME value, RDMS sets the date portion to
0001-01-01.

The values for datepart are not case-sensitive.

If datepart or d is NULL, RDMS returns a null value.

The allowed values for datepart are as follows.

datepart datepart Abbreviation Valid Range Produced

year yy 1753–9999
quarter qq 1–4
month mm January, February, and so on
dayofyear dy 1–366
day dd 1–31
week wk 1–54 (Sunday as the first day of the week;
RDMS considers all days prior to the first
Sunday of the year to be in week 1)
weekday dw Sunday, Monday, and so on
hour hh 0–23
minute mi 0–59
second ss 0–59

7830 8160–027 3–93


Date, Time, and Timestamp Functions

Examples
datename('week', '2001-01-05')

returns 1 as an ASCII character.

datename('WEEKDAY', '2001-01-05')

returns
Friday

The following example sets the current locale to fr_FR.8859-1 using CIFSUT:
@CIFSUT
set LC ALL=fr_FR.8859-1
@eof

datename('month', '2001-01-05')

returns
janvier

3.8.10. datepart Function


Format
datepart(Character datepart,
<time, date, or timestamp data type> d) → Integer

Purpose
Returns the specified datepart of d as an integer.

If you use any time datepart for a DATE value, RDMS sets the time portion to
00:00:00. If you use any date datepart for a TIME value, RDMS sets the date portion to
0001-01-01.

The values for datepart are not case-sensitive.

If datepart or d is NULL, RDMS returns a null value.

3–94 7830 8160–027


Date, Time, and Timestamp Functions

The allowed values for datepart are as follows.

datepart datepart Abbreviation Valid Range Produced

Year yy 1753–9999
Quarter qq 1–4
Month mm 1–12
Dayofyear dy 1–366
Day dd 1–31
dateasnum dn Returns the date as a numeric value
CCYYMMDD. For example, January
5, 2006 is returned as 20,060,106.
Week wk 1–54
Weekday dw 1–7 (Sunday=1)
Hour Hh 0–23
Minute Mi 0–59
Second Ss 0–59

Examples
datepart('week', '2001-01-05')

returns
1

datepart('weekday', '2001-01-05')

returns
6

datepart('month', '2001-01-05')

returns
1

7830 8160–027 3–95


Date, Time, and Timestamp Functions

3.8.11. day Function


Format
day(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the day of the month portion of d as an integer.

If d is NULL, RDMS returns a null string.

The argument d may be one of the following:

• A column with data type date or timestamp. If d is a time value, RDMS returns an
error.
• A valid date or timestamp literal value – see section 2.3.4.
• Another BIF or Datetime Function (see section 2.5.7), which returns a date, or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in one
of these formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
− hh:mm:ss – if the value contains only a time value, RDMS returns an error.
Additional processing rules:

• If d is a timestamp, the result is the date part of the timestamp.


• If d is a date, the result is that date.
• If d is a string, the result is the date that is represented by the string.
• If d is a time, RDMS returns an error.

See also the dayofmonth function

Examples
day('2011-09-23')

returns 23

day(current_timestamp)

suppose the current_timestamp value is 2011-10-07 09:57:23, the function returns 7.

3–96 7830 8160–027


Date, Time, and Timestamp Functions

3.8.12. dayname Function


Format
dayname(<date or timestamp data type> d) → Character

Purpose
Returns the day portion of d as a character string (Sunday, Monday, and so on),
according to the current locale.

If d is NULL, RDMS returns a null value.

Example 1
dayname('2001-01-05')

returns
Friday

Example 2
This example sets the current locale to fr_FR.8859-1 using CIFSUT:
@CIFSUT
set LC ALL=fr_FR.8859-1
@eof

dayname('2001-01-05')

returns
vendredi

3.8.13. dayofmonth Function


Format
dayofmonth(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the day portion of d as an integer in the range 1–31.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.

7830 8160–027 3–97


Date, Time, and Timestamp Functions

• A character value or literal string containing a valid date or timestamp value in


one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, the result is the day part of the timestamp.


• If d is a date, the result is the day of that date.
• If d is a string, the result is the day that is represented by the string.
• If d is a time, RDMS returns an error.

See also the day function.

Example
dayofmonth('2001-01-05')

returns
5

3.8.14. dayofweek Function


Format
dayofweek(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the day portion of d as an integer in the range 1–7 (Sunday = 1).

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.

3–98 7830 8160–027


Date, Time, and Timestamp Functions

• A character value or literal string containing a valid date or timestamp value in


one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.
Example
dayofweek('2001-01-05')

returns
6

7830 8160–027 3–99


Date, Time, and Timestamp Functions

3.8.15. dayofyear Function


Format
dayofyear(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the day of the year in d as an integer in the range 1–366.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.
Example
dayofyear('2001-01-05')

returns
5

3–100 7830 8160–027


Date, Time, and Timestamp Functions

3.8.16. days Function


Format
days(<character, date, timestamp data type> d) → Integer

Purpose
Returns one more than the number of days between January 1, 0001 and the date d.
The function projects the rules for the Gregorian calendar to all dates in the past when
calculating an elapsed number of days.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.
Example
days('2001-02-21')

returns
730537

7830 8160–027 3–101


Date, Time, and Timestamp Functions

3.8.17. erdate_to_timestamp Function


Format
erdate_to_timestamp( <any data type except BLOB> s1 ) → Timestamp

Purpose
Interprets the contents of s1 as a two-word Fieldata-encoded ER DATE$ value and
returns an RDMS timestamp value with precision 0. For more information on the ER
DATE$ format, see the Executive Requests Programming Reference Manual.

If s1 is NULL, RDMS returns a null value. s1 cannot be a BLOB value.

Example
erdate_to_timestamp (o'606661656064616361616065')

returns the timestamp


2004-06-15 13:11:05

3.8.18. erdwtime_to_timestamp Function


Format
erdwtime_to_timestamp( ) → Timestamp

erdwtime_to_timestamp( <any data type except BLOB> s1 ) → Timestamp

Purpose
Interprets the contents of s1 as a two-word binary ER DWTIME$ value or CALL
INSPECTIME$ value and returns an RDMS timestamp with precision 3. For more
information on the ER DWTIME$ format, see the Executive Requests Programming
Reference Manual. For more information on INSPECTIME$ format, see the System
Services Programming Reference Manual.

If you omit s1, RDMS performs an ER DWTIME$ and uses that value.

If s1 is NULL, RDMS returns a null value. s1 cannot be a BLOB value.

Example
erdwtime_to_timestamp (o'000267016710111005663120')

returns the timestamp


2004-06-24 13:27:34.325

3–102 7830 8160–027


Date, Time, and Timestamp Functions

3.8.19. ertdate_to_timestamp Function


Format
ertdate_to_timestamp( <any data type except BLOB> s1 ) → Timestamp

Purpose
Interprets the contents of s1 as a one-word binary ER TDATE$ formatted value and
returns an RDMS timestamp with precision 0. For more information on the ER TDATE$
format, see the Executive Requests Programming Reference Manual.

If s1 is NULL, RDMS returns a null value. s1 cannot be a BLOB value.

Example
ertdate_to_timestamp (o'061750134551')

returns the timestamp


2004-06-15 13:11:05

3.8.20. ertime_to_time Function


Format
ertime_to_time( <any data type except BLOB> s1 ) → Time

Purpose
Interprets the contents of s1 as a one-word binary ER TIME$ formatted value and
returns an RDMS time with precision 3. For more information on the ER TIME$ format,
see the Executive Requests Programming Reference Manual.

If s1 is NULL, RDMS returns a null value. s1 cannot be a BLOB value.

Example
ertime_to_time (o'265041053')

returns the time


13:11:05.003

3.8.21. extract Function


Format
extract(Character extract-field FROM <date, time, or typestamp data type>
extract-source) → Integer

where:

extract–field
is the field to be extracted from the source operand.

7830 8160–027 3–103


Date, Time, and Timestamp Functions

extract–source
is the source operand, which must be a datetime data type of one of the following
items:

• A cast function
• An aggregate function
• A datetime system function (for example, CURRENT_DATE)
• A column reference
• A routine parameter or SQL variable
• A datetime literal
• A datetime value expression

Purpose
Returns the specified portion of a time, date, or timestamp value. The extract function
lets you extract a numeric value from a datetime item or value expression.

Follow these guidelines when using the EXTRACT function:

• You can use the EXTRACT function wherever an expression is allowed.


• Applicable field names for the extract field are YEAR, MONTH, DAY, HOUR,
MINUTE, and SECOND.
• The result of the EXTRACT function is the value of the numeric data type with the
same scale and precision as the extract source.
• The EXTRACT function cannot be used as an argument for other scalar functions.

Example 1
The following example extracts the exact numeric value of 01.224512 from the
SECOND field of a time literal, with a result data type of NUMERIC(8,6):

EXTRACT(SECOND FROM TIME '16:34:01.224512')

Example 2
The next example extracts an exact numeric value from the HOUR field of the result
of a datetime arithmetic expression, with a result data type of NUMERIC(2):

EXTRACT(HOUR FROM (time_column + CAST( :var AS INTERVAL HOUR TO


MINUTE)))

You can use the EXTRACT function to retrieve datetime data into a program variable
from RDMS. The EXTRACT function retrieves a datetime value field into a numeric
program variable.

3–104 7830 8160–027


Date, Time, and Timestamp Functions

Example 3
In the following example, assume that the variables myyear, mymonth, and myday are
declared in the user program of a data type compatible with the RDMS data type
NUMERIC. The following SQL statement retrieves a record from mytable:

EXEC SQL SELECT


EXTRACT(YEAR FROM mydate),
EXTRACT(MONTH FROM mydate),
EXTRACT(DAY FROM mydate)
FROM mytable
INTO :myyear,:mymonth,:myday

After this statement is executed, example values of myyear, mymonth, and myday are
2006, 1, and 30.

3.8.22. getdate and now Functions


Format
getdate( ) → Timestamp

now( ) → Timestamp

Purpose
Returns the current date and time as a timestamp with zero precision. This is similar
to the current_timestamp keyword function.

Example
If executed on February 21, 2007 at 1:20:24 in the afternoon
getdate( )

returns
2007-02-21 13:20:24

7830 8160–027 3–105


Date, Time, and Timestamp Functions

3.8.23. getutcdate
Format
getutcdate( ) → Timestamp

Purpose
Returns the current utc date and time as a timestamp with 6 digits of precision.

Example
select getutcdate() from rdms.rdms_dummy;

returns

2008-12-04 09:40:24.442281

3.8.24. hour Function


Format
hour(<character, time, or timestamp data type> d) → Integer

Purpose
Returns the hour portion of d as an integer.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss

3–106 7830 8160–027


Date, Time, and Timestamp Functions

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the time part of the timestamp.


• If d is a time, RDMS uses that time.
• If d is a string, RDMS uses the time that is represented by the string.
• If d is a date, RDMS returns an error.

Example
hour('2007-02-21 13:20:24')

returns
13

3.8.25. julian_day Function


Format
julian_day(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the number of days between the beginning of the Julian calendar and d.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

7830 8160–027 3–107


Date, Time, and Timestamp Functions

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.

Example
julian_day('2000-02-21 13:20:24')

returns
2451596

3.8.26. last_day Function


Format
last_day(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the last day of the month for the month in which d occurs.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another scalar or datetime function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

3–108 7830 8160–027


Date, Time, and Timestamp Functions

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.

Example
last_day('2000-02-21 13:20:24')

returns
29

3.8.27. microsecond Function


Format
microsecond(<character, time, or timestamp data type> d) → Integer

Purpose
Returns the fractional portion of d as microseconds. RDMS adjusts the precision of d
to 6 and returns the value, zero-filled if necessary, to 6 digits.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the time part of the timestamp.


• If d is a time, RDMS uses that time.
• If d is a string, RDMS uses the time that is represented by the string.
• If d is a date, RDMS returns an error.

7830 8160–027 3–109


Date, Time, and Timestamp Functions

Examples
microsecond('2000-02-21 13:20:24.3827')

returns
382700

microsecond('2000-02-21 13:20:24.0005')

returns
500

3.8.28. midnight_seconds Function


Format
midnight_seconds(<character, time, or timestamp data type> d) → Integer

Purpose
Returns the number of seconds between d and the previous midnight.
If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the time part of the timestamp.


• If d is a time, RDMS uses that time.
• If d is a string, RDMS uses the time that is represented by the string.
• If d is a date, RDMS returns an error.

3–110 7830 8160–027


Date, Time, and Timestamp Functions

Example
midnight_seconds('2000-02-21 13:20:24.3827')

returns
48024

3.8.29. minute Function


Format
minute(<character, time, or timestamp data type> d) → Integer

Purpose
Returns the minute portion of d as an integer.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the time part of the timestamp.


• If d is a time, RDMS uses that time.
• If d is a string, RDMS uses the time that is represented by the string.
• If d is a date, RDMS returns an error.

Example
minute('2000-02-21 13:20:24')

returns
20

7830 8160–027 3–111


Date, Time, and Timestamp Functions

3.8.30. month Function


Format
month(<character, date, timestamp data type> d) → Integer

Purpose
Returns the month portion of d as an integer.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.

Example
month('2001-02-21 13:20:24')

returns
2

3–112 7830 8160–027


Date, Time, and Timestamp Functions

3.8.31. monthname Function


Format
monthname(<character, date, timestamp data type> d)→Character

Purpose
Returns the month portion of d as a character string (January, February, and so on),
according to the current locale.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.

Examples
monthname('2001-01-05')

returns
January

7830 8160–027 3–113


Date, Time, and Timestamp Functions

The following example sets the current locale to fr_FR.8859-1 using CIFSUT:
@CIFSUT
set LC ALL=fr_FR.8859-1
@EOF

monthname('2001-01-05')

returns
janvier

3.8.32. months_between Function


Format
months_between(<character, date, timestamp data type> d1,
<character, date, timestamp data type> d2) → Double Precision

Purpose
Returns the number of months between d1 and d2. If both d1 and d2 have the same
day or if both are the last days of their respective months, RDMS returns an integer
result. Otherwise, the result will contain the fractional portion of a 31-day month and
also considers the time components in d1 and d2.

If d1 is later than d2, the result is positive; if d1 is earlier than d2, the result is negative.

If d1 or d2 is NULL, RDMS returns a null value.

The arguments d 1 and d2 may be one of the following:

• A column with data type, date or timestamp. If d1 or d2 is a time value, RDMS


returns an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

3–114 7830 8160–027


Date, Time, and Timestamp Functions

Additional processing rules are as follows:

• If d1 or d2 is a timestamp, RDMS uses the date part of the timestamp.


• If d1 or d2 is a date, RDMS uses that date.
• If d1 or d2 is a string, RDMS uses the date that is represented by the string.
• If d1 or d2 is a time, RDMS returns an error.

Example
months_between('2001-01-05', '2001-05-05')

returns
-.40000000000000000E+001

3.8.33. new_time Function


Format
new_time(<time, timestamp data type> d,
Character tz1, Character tz2) → <data type of d>

Purpose
Returns the time or timestamp in time zone tz2 when the time or timestamp for d are
in time zone tz1.

If d, tz1, or tz2 is NULL, RDMS returns a null value.

If d is a character type containing data in DATE, TIME, or TIMESTAMP format, the


new_time function returns a data type of TIMESTAMP with precision 6.

If d is a literal character string containing data in DATE, TIME, or TIMESTAMP format,


the new_time function returns data in DATE, TIME, or TIMESTAMP format. For
example

new_time('13:13:13', 'MST', 'JST')

returns
05:13:13

new_time('2001-01-08 13:13:13', 'MST', 'JST')

returns
2001-01-09 05:13:13

7830 8160–027 3–115


Date, Time, and Timestamp Functions

The valid values for tz1 and tz2 are defined in the following table.

Difference from Coordinated


String Time Zone Universal Time (UTC)

ADT Atlantic Daylight Time UTC - 3.0


AHDT Alaska-Hawaii Daylight Time UTC - 8.0
AHST Alaska-Hawaii Standard Time UTC - 9.0
AST Atlantic Standard Time UTC - 4.0
AT Azores Time UTC - 2.0
ACDT Australian Central Daylight Time UTC + 10.5
ACST Australian Central Standard Time UTC + 9.5
AEDT Australian Eastern Daylight Time UTC + 11.0
AEST Australian Eastern Standard Time UTC + 10.0
AWDT Australian Western Daylight Time UTC + 9.0
AWST Australian Western Standard Time, UTC + 8.0
BDST British Double Summer Time UTC + 2.0
BET Bering Standard Time UTC - 11
BST British Summer Time UTC + 1.0
BT Baghdad Time UTC + 3.0
CCT China Coast Time UTC + 8.0
CDT Central Daylight Time UTC - 5.0
CEST Central European Summer Time UTC + 2.0
CET Central European Time UTC + 1.0
CST Central Standard Time UTC - 6.0
EDT Eastern Daylight Time UTC - 4.0
EEST Eastern European Summer Time UTC + 3.0
EET Eastern European Time UTC + 2.0
EST Eastern Standard Time UTC - 5.0
GMT Greenwich Mean Time UTC + 0.0
GST Guam Standard Time UTC + 10.0
HDT Hawaii Daylight Time UTC - 9.0
HST Hawaii Standard Time UTC - 10.0
IDLE International Date Line East UTC + 12.0
IDLW International Date Line West UTC - 12.0
IST Indian Time UTC + 5.5

3–116 7830 8160–027


Date, Time, and Timestamp Functions

Difference from Coordinated


String Time Zone Universal Time (UTC)

IT Iran Time UTC + 3.5


JST Japan Standard Time UTC + 9.0
JT Java™ Time UTC + 7.5
MDT Mountain Daylight Time UTC - 6.0
MEST Middle European Summer Time UTC + 2.0
MET Middle European Time UTC + 1.0
MST Mountain Standard Time UTC - 7.0
MT Moluccas Time UTC + 8.5
NST Newfoundland Standard Time UTC - 3.5
NZS New Zealand Summer Time UTC + 13
NZT New Zealand Standard Time UTC + 12
PDT Pacific Daylight Time UTC - 7
PST Pacific Standard Time UTC - 8
SDT South Australia Daylight Time UTC + 10.5
SAT South Australia Standard Time UTC + 9.5
UTC Universal Coordinated Time UTC + 0.0
USZ3 USSR Zone 3 UTC + 4.0
USZ4 USSR Zone 4 UTC + 5.0
USZ5 USSR Zone 5 UTC + 6.0
USZ6 USSR Zone 6 UTC + 7.0
USZ10 USSR Zone 10 UTC + 11.0
WAT West Africa Time UTC - 1.0
WET Western European Time UTC + 0.0
WEST Western European Summer Time UTC + 1.0
YDT Yukon Daylight Time UTC - 8.0
YST Yukon Standard Time UTC - 9.0

Example

new_time('2001-02-21 13:20:24', 'PDT', 'EDT')

returns
2001-02-21 16:20:24

7830 8160–027 3–117


Date, Time, and Timestamp Functions

3.8.34. next_day Function


Format
next_day(<character, date, timestamp data type> d,
Character s1) → <data type of d>

Purpose
Returns the date of the first day named by s1 that is later than date d. The value s1
indicates a day of the week in the language of the current locale. The time component
of d is unchanged. The case of s1 is not important.

If d or s1 is NULL, RDMS returns a null value.

If d is a character type containing data in DATE, TIME, or TIMESTAMP format, the


next_day function returns a data type of TIMESTAMP with precision 6.

If d is a literal character string containing data in DATE, TIME, or TIMESTAMP format,


the next_day function returns data in DATE, TIME, or TIMESTAMP format. For
example

next_day('2001-01-08 13:13:13', 'MONDAY')

returns
2001-01-15 13:13:13

next_day('2001-01-08', 'MONDAY')

returns
2001-01-15

Examples
This example returns the timestamp for the first Thursday after February 20, 2001.
next_day('2001-02-20 13:20:24', 'thursday')

returns
2001-02-22 13:20:24

In this example, the date d is the same day of the week as s1. The function returns the
date of the Wednesday of the following week:
next_day('2001-03-14 13:20:24', 'wednesday')

returns
2001-03-21 13:20:24

3–118 7830 8160–027


Date, Time, and Timestamp Functions

3.8.35. now Function


See getdate function (3.8.21)

3.8.36. quarter Function


Format
quarter(<character, date, or timestamp data type> d) → Integer

Purpose
Returns an integer between 1 and 4 representing the quarter of the year in which d
occurs.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.

Example
quarter('2000-02-21 13:20:24')

returns
1

7830 8160–027 3–119


Date, Time, and Timestamp Functions

3.8.37. round Function


Format
round(<character, time, date, or timestamp data type> d
[ , Character s1 ] ) → Timestamp

Purpose
Rounds d to the unit specified by s1. If s1 is not specified or is NULL, RDMS uses 'dd'
which rounds d to the nearest day.

If you use a time rounding format for a date value, RDMS sets the time to 00:00:00. If
you use a date rounding format for a time value, RDMS sets the date portion to
today’s date.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date, time, or timestamp.


• A valid date, time, or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date,
time, or timestamp value.
• A character value or literal string containing a valid date, time, or timestamp
value in one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
− hh:mm:ss

The value for s1 is not case sensitive. The value for s1 can be any of the following
formats.

Format Rounding Unit

CC Century
YYYY, YEAR, YYY, YY, Y Year (rounds up on July 1)
IYYY, IY, I ISO year
Q Quarter (rounds up on the sixteenth day of the second
month of the quarter)

3–120 7830 8160–027


Date, Time, and Timestamp Functions

Format Rounding Unit

MONTH, MON, MM, RM Month (rounds up on the sixteenth day)


WW Same day of the week as the first day of the year
IW Same day of the week as the first day of the ISO year
W Same day of the week as the first day of the month
DDD, DD, J Day
DAY, DY, D Starting day of the week (Sunday).
HH, HH12, HH24 Hour
MI Minute

Example
This example rounds to the nearest month.
round('2001-02-20 13:20:24', 'mm')

returns
2001-03-01 00:00:00

3.8.38. second Function


Format
second(<character, time, timestamp data type> d)→Integer

Purpose
Returns the second portion of d as an integer.

If d is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
− ddMonyyyy

7830 8160–027 3–121


Date, Time, and Timestamp Functions

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the time part of the timestamp.


• If d is a time, RDMS uses that time.
• If d is a string, RDMS uses the time that is represented by the string.
• If d is a date, RDMS returns an error.

Examples
second('2000-02-21 13:20:24')

returns
24

second('2000-02-21 13:20:24.987')

returns
24

3.8.39. strftime Function


Format
strftime(<character, time, date, or timestamp data type>d
[ , Character s1 ]) → Character

Purpose
Converts d to a character string according to the conversion specification string in s1.
If you omit s1, RDMS uses the format ‘%D %T’. This function calls the I18NLIB routine
of the same name.

If you use a time formatting conversion for a date value, RDMS sets the time to
00:00:00. If you use a date formatting conversion for a time value, RDMS sets the
date portion to today’s date.

The formatting conversion specification values are case-sensitive.

If d or s1 is NULL, RDMS returns a null value.

The argument d may be one of the following:

• A column with data type, date, time, or timestamp.


• A valid date, time, or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date,
time, or timestamp value.

3–122 7830 8160–027


Date, Time, and Timestamp Functions

• A character value or literal string containing a valid time, date, or timestamp


value in one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
− hh:mm:ss

The following table defines the valid values for the conversion specification s1.

This conversion
specification … Is replaced by these characters for the current locale:

%a Weekday name, abbreviated


%A Weekday name, full
%b Month name, abbreviated
%B Month name, full
%c The default date/time representation for the current locale.
%C Century number. To get this number, the year is divided by 100 and truncated
to an integer as a decimal [00–99].
%d Day of month as decimal [01,31]
%D Equivalent to %m/%d/%y
%e Day of month as decimal [1,31]. A single digit is preceded by a space.
%F Equivalent to %Y-%m-%d (the ISO 8601-:2000 standard date format). This
option is available if you install I18NLIB level 1R3E or higher.
%g Replaced by the last 2 digits of the week-based year as a decimal number
[00-99]. See the year rules for %V and %W. This option is available if you install
I18NLIB level 1R3E or higher.
%G Replaced by the week-based year as a four-digit decimal number. See the year
rules for %V and %W. This option is available if you install I18NLIB level 1R3E or
higher.
%h Month name, abbreviated
%H Hour on 24-hour clock as decimal [00,23]
%I Hour on 12-hour clock as decimal [01,12]
%j Day of year as decimal [001,366]
%m Month as decimal [01,12]

7830 8160–027 3–123


Date, Time, and Timestamp Functions

This conversion
specification … Is replaced by these characters for the current locale:

%M Minute as decimal [00,59]


%n New line character (012)
%p Equivalent for ante meridiem (AM) and post meridiem (PM) (see examples)
%r Time in AM/PM notation; equivalent of %I:%M:%S%p
%R Time in 24-hour notation (%H%M)
%S Second as decimal [00,61]
%t Tab character (ASCII octal character 011)
%T Time (%H:%M:%S)
%u Weekday as decimal [1,7] with 1 representing Monday
%U Week number of the year as decimal [00,53] with Sunday as day 1
%V Week number of the year as decimal [01,53] with Monday as day 1. If the week
containing January 1 has four or more days in the new year, then it is
considered week 1. If it does not contain at least four days, then it is the last
week of the previous year (week 52 or week 53), and the next week is week 1.
This is the ISO rule for week calculation.
%w Weekday as decimal [0,6] with 0 representing Sunday
%W Week number of the year as decimal [00,53] with Monday as day 1. All days in a
new year preceding the first Sunday are considered to be in week 0.
%x Default date representation for the current locale
%X Default time representation for the current locale
%y Year without century as decimal [00,99]
%Y Year with century as decimal [0001–9999]
%Z Time zone name or abbreviation; no bytes if no time zone information exists
%% %

Example
strftime('2000-02-21 13:20:24',
'today is: %A, %B %d, %Y at %I:%M:%S %p')

returns
today is: Wednesday, February 21, 2001 at 1:20:24 PM

3–124 7830 8160–027


Date, Time, and Timestamp Functions

The following example sets the current locale to de_DE.8859-1 using CIFSUT:
@CIFSUT
set LC_ALL=de_DE.8859-1
@eof

strftime('2000-02-21 13:20:24',
'today iF073: %A, %B %d, %Y, at %H:%M:%S')

returns
today is: Montag, Februar 21, 2000 at 13:20:24

3.8.40. strptime Function


Format
strptime(<character, time, date, timestamp> s1, Character s2) →
Timestamp

Purpose
Returns a timestamp for the character string in s1, which has a format as defined by
the conversion specification in s2.

The strptime function calls the I18NLIB function of the same name. If I18NLIB is prior
to level 1R3E, the I18NLIB function follows the UNIX convention for dates. Any
two-digit date is 1900 + year.

If I18NLIB is level 1R3E or higher, the I18NLIB function follows the IEEE standard, as
follows:

• Any two-digit date between 00 and 68 inclusive is 2000 + year.


• Any two-digit date 69 or higher is 1900 + year.

If s1 or s2 is NULL, RDMS returns a null value.

The argument s1 may be one of the following:

• A column with data type, date, time, or timestamp.


• A valid date, time, or timestamp literal value (see section 2.3.4).
• Another scalar or datetime function (see section 2.5.7) which returns a date,
time, or timestamp value.

7830 8160–027 3–125


Date, Time, and Timestamp Functions

• A character value or literal string containing a valid date, time, or timestamp


value in one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
− hh:mm:ss

Additional processing rules are as follows:

• If s1 is a time, RDMS uses current date as the default date.


• If s1 is a date, RDMS uses 00:00:00 as the default time.

The following are the valid values for the conversion specification s2. Conversion
specifications cannot adjoin. ‘%H%M’ is illegal; ‘%H %M’ and ‘%H:%M’ are legal.

This conversion Specifies the replacement characters required, using the


specification … representation from the current locale:

%a; %A Day of the week; name may be full or abbreviated.


%b; %B; %h Month of the year; name may be full or abbreviated.
%c Date and time
%C Century number [00–99], leading zeros permitted.
%d; %e Day of month [01,31], leading zeros permitted
%D Date as %m/%d/%y
%H Hour on 24-hour clock [00,23], leading zeros permitted
%I Hour on 12-hour clock [01,12], leading zeros permitted
%j Day of year [1,366], leading zeros permitted
%m Number of month [01,12], leading zeros permitted
%M Minute [00,59], leading zeros permitted
%n; %t Any white space (one or more)
%p Equivalent for ante meridiem (AM) and post meridiem (PM)
%r Time in AM and PM notation, equivalent of %I:%M:%S%p (for example,
“12:23:56 AM”)
%R Time in 24-hour notation (%H%M)
%S Seconds [0,61], leading zeros permitted.

3–126 7830 8160–027


Date, Time, and Timestamp Functions

This conversion Specifies the replacement characters required, using the


specification … representation from the current locale:

%T Time as %H:%M:%S
%U Week number of the year as decimal [00,53] with Sunday as day 1, leading
zeros permitted
%w Weekday as decimal [0,6] with 0 representing Sunday, leading zeros
permitted
%W Week number of the year as decimal [00,53] with Monday as day 1, leading
zeros permitted
%x Date as described by the current locale's d_fmt conversion specification
%X Time as described by the current locale's t_fmt conversion specification

%y Year within the century [00,99], leading zeros permitted. This conversion
specification includes a century of 19 plus the specified year (see examples).
%Y Year, including century [0001,9999]
%% %

Examples
strptime('21.02.2001 :: 16:43:03', '%d.%m.%Y :: %H:%M:%S')

In this example, the string s1 has a date with segments separated by periods,
followed by two colons, followed by a time with colon separators. The format string
s2 has these characters plus the formatting information for the date and time
segments and returns the timestamp value
2001-02-21 16:43:03

With I18NLIB levels prior to level 1R3E, two-digit years are assumed to be in the
twentieth century, as in the following example.

strptime('21.02.01 :: 16:43:03', '%d.%m.%y :: %H:%M:%S')

returns
1901-02-21 16:43:03

With I18NLIB level 1R3E or higher, the following apply:

• Any two-digit date between 00 and 68 inclusive is 2000 + year.


• Any two-digit date 69 or higher is 1900 + year.

For example

strptime('21.02.01 :: 16:43:03' , '%d.%m.%y :: %H:%M:%S')

returns

7830 8160–027 3–127


Date, Time, and Timestamp Functions

2001-02-01 16:43:03

In the following example, the separators are the slash character ‘/’. Zeros are used
because there is no time information. Therefore,

strptime('12/4/07', '%m/%d/%y')

returns

2007-12-04 00:00:00

The following example sets the current locale to fr_FR.8859-1 using CIFSUT:

@CIFSUT
set LC_ALL=fr_FR.8859-1
@eof

strptime('21-Février-2011 13:20:24', '%d-%B-%Y %H:%M:%S')

returns the timestamp value

2011-02-21 13:20:24

3.8.41. time Function


Format
time(<character, time, or timestamp data type> d) → Time

Purpose
Returns the time portion of d as a Time value.

If d is NULL, RDMS returns a null string.

The argument d may be one of the following:

• A column with data type, time or timestamp. If d is a date value, RDMS returns
an error.
• A valid time or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a time or
timestamp value.
• A character value or literal string containing a valid time or timestamp value in
one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss

3–128 7830 8160–027


Date, Time, and Timestamp Functions

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the time part of the timestamp.


• If d is a time, RDMS uses that time.
• If d is a string, RDMS uses the time that is represented by the string.
• If d is a date, RDMS returns an error.
Example
time('2000-02-21 13:20:24')

returns
13:20:24

3.8.42. timestamp Function


Format
timestamp(<character, date, time, or timestamp data type> d,
<character, date, time, or timestamp data type> t) → Timestamp

Purpose
Returns a timestamp whose date value is taken from d and whose time value is taken
from t. The resulting timestamp has the same precision as t.

If d or t is NULL, RDMS returns a null value.

The arguments d and t may be one of the following:

• A column with data type, date, time, or timestamp.


• A valid date, time, or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date,
time, or timestamp value.
• A character value or literal string containing a valid date, time, or timestamp
value in one of the following formats:
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy hh:mm:ss
− hh:mm:ss
− yyyy-mm-dd
− mm/dd/yyyy
− ddMonyyyy

7830 8160–027 3–129


Date, Time, and Timestamp Functions

Additional processing rules are as follows:

• If s1 is a timestamp, RDMS uses the date part of the timestamp.


• If s1 is a time, RDMS returns an error.
• If s1 is a string, RDMS uses the date that is represented by the string.
• If s1 is a date, RDMS uses the date value.
• If s2 is a timestamp, RDMS uses the time part of the timestamp.
• If s2 is a time, RDMS uses the time value.
• If s2 is a string, RDMS uses the time that is represented by the string.
• If s2 is a date, RDMS returns an error.
Example
timestamp('2000-02-21 13:20:24', '16:40:39')

returns the timestamp value


2000-02-21 16:40:39.000000

3.8.43. timestampadd Function


Format
timestampadd(Character interval,
Integer x,
<character, time, date,
timestamp data type> t1) → Timestamp

Purpose
Returns the timestamp calculated by adding x intervals of type interval to t1.

If d, x, or t1 is NULL, RDMS returns a null value.

For timestampadd, SQL_TSI_FRAC_SECOND is interpreted as microseconds, following


the ODBC convention.

The following table explains the valid values for interval and x.

interval Valid Range of x

SQL_TSI_YEAR Approximately -247 to +7999 to produce dates in the


range 1753 to 9999
SQL_TSI_QUARTER -63 to +63
SQL_TSI_MONTH -255 to +255
SQL_TSI_DAY -65,535 to +65,535
SQL_TSI_WEEK -9362 to +9362
SQL_TSI_HOUR -255 to +255

3–130 7830 8160–027


Date, Time, and Timestamp Functions

interval Valid Range of x

SQL_TSI_MINUTE -255 to +255


SQL_TSI_SECOND -967659 to +967659
SQL_TSI_FRAC_SECOND -999999 to +999999

If t1 is a time value and interval specifies days, weeks, months, quarters, or years,
RDMS fills in the date portion of that timestamp with the current date before
calculating the difference between the timestamps.

If t1 is a date value and interval specifies fractional seconds, seconds, minutes, or


hours, RDMS fills in the time portion of that timestamp with 0 before calculating the
difference between the timestamps.

Example 1
timestampadd('SQL_TSI_DAY', 2, '2000-02-21 13:20:24')

returns the timestamp


2000-02-23 13:20:24.000000

Example 2
timestampadd('SQL_TSI_MINUTE', 5, '2000-02-21 23:58:24')

returns the timestamp


2000-02-22 00:03:24.000000

Example 3
timestampadd('SQL_TSI_SECOND', 86400, '2000-02-21 13:20:24')

returns the timestamp


2000-02-22 13:20:24.000000

Example 4
timestampadd('SQL_TSI_HOUR', -15, '2000-03-01 13:20:24')

returns the timestamp


2000-02-29 22:20:24.000000

Example 5
timestampadd('SQL_TSI_DAY', 12, '13:20:24')

Because there is only a time and no date, RDMS uses today. Assume that today is July
15, 2004 and returns the timestamp
2004-07-27 13:20:24.000000

7830 8160–027 3–131


Date, Time, and Timestamp Functions

Example 6
timestampadd('SQL_TSI_HOUR', -4, '2001-03-13')

Because there is only a date and no time, RDMS uses 00:00:00 and returns the
timestamp
2001-03-12 20:00:00.000000

Example 7
timestampadd('SQL_TSI_DAY', -365, '2000-02-21 13:20:24')

returns the timestamp


1999-02-21 13:20:24.000000

Example 8
timestampadd('SQL_TSI_QUARTER', 2, '2002-02-21 13:20:24')

returns the timestamp


2002-08-21 13:20:24.000000

3.8.44. timestampdiff Function


Format
timestampdiff(Character interval,
<time, date, or timestamp data type> t1,
<time, date, or timestamp data type> t2) → Integer

Purpose
Returns the integer number of intervals of type interval by which t2 is greater than t1.
The return value can be less than zero. RDMS truncates the result to the specified
interval.

If interval, t1, or t2 is NULL, RDMS returns a null value.

RDMS returns SQL_TSI_FRAC_SECOND as microseconds.

Valid values for interval are as follows:

SQL_TSI_FRAC_SECOND
SQL_TSI_SECOND
SQL_TSI_MINUTE
SQL_TSI_HOUR
SQL_TSI_DAY
SQL_TSI_WEEK
SQL_TSI_MONTH

3–132 7830 8160–027


Date, Time, and Timestamp Functions

SQL_TSI_QUARTER
SQL_TSI_YEAR

If either t1 or t2 is a time value and interval specifies days, weeks, months, quarters,
or years, RDMS fills in the date portion of that timestamp with the current date before
calculating the difference between the timestamps.

If either t1 or t2 is a date value and interval specifies fractional seconds, seconds,


minutes, or hours, RDMS fills in the time portion of that timestamp with 0 before
calculating the difference between the timestamps.

Example 1
timestampdiff('SQL_TSI_DAY', '2000-02-21 13:20:24', '2000-02-23 16:40:39')

Because the time of t2 is greater than the time of t1, timestampdiff returns 2.

Example 2
timestampdiff('SQL_TSI_DAY', '2000-02-21 13:20:24', '2000-02-23 08:14:22')

Because the time of t2 is not greater than the time of t1, timestampdiff returns 1.

Example 3
timestampdiff('SQL_TSI_DAY', '2000-02-23 16:40:39', '2000-02-21 09:20:24')

Because both values are timestamps, timestampdiff returns a whole number of days
as -2.

Example 4
timestampdiff('SQL_TSI_DAY', '2000-02-23', '2000-02-21')

returns a whole number of days as -2.

Example 5
timestampdiff('SQL_TSI_YEAR', '2000-02-21 13:20:24', '2002-01-01
16:40:39')

returns a whole number of years as 1.

Example 6
timestampdiff('SQL_TSI_HOUR', '2000-02-23 16:40:24', '2000-02-21
13:20:39')

returns
-51

7830 8160–027 3–133


Date, Time, and Timestamp Functions

3.8.45. timestamp_format Function


Format
timestamp_format(<character, date, time, or timestamp> s1 ,
[ Character s2 ] ) → Timestamp

Purpose
Converts the character string s1 to a timestamp value according to the format string in
s2. If you omit s2 or if it is NULL, RDMS uses the format 'MM/DD/YYYY HH24:MI:SS'.

If s1 is a date, time, or timestamp data type, RDMS ignores s2.

The maximum length for s1 is 80 bytes. The maximum length for s2 is 80 bytes.

The timestamp_format function uses the same arguments as the to_date function. It is
a synonym for the to_date function. See the to_date function for more information.

See also the date, to_date, to_timestamp, and strptime functions, which also convert
strings to time, date, and timestamp values.

Example
timestamp_format('21-02-2011 13:20:24', 'DD-MM-YYYY HH24:MI:SS')

returns a timestamp value: 2011-02-21 13:20:24.000000.

See to_date for additional examples.

3.8.46. to_char Function


Format
to_char(<time, date, or timestamp data type> d
[ , Character s1 ] ) → Character

Purpose
Converts d to a character string according to the formatting string in s1. If you omit s1
or if it is NULL, RDMS uses the format 'MM/DD/YY HH24:MI:SS'

If d is NULL, RDMS returns a null value.

The formatting element values DAY, DY, MON, MONTH, and RM, which generate
words, are case-sensitive. The other formatting elements, which generate numbers,
are not case-sensitive.

3–134 7830 8160–027


Date, Time, and Timestamp Functions

The argument d may be one of the following:

• A column with data type, date, time, or timestamp.


• A valid date, time, or timestamp literal value (see section 2.3.4).
• Another scalar or datetime function (see section 2.5.7) which returns a date,
time, or timestamp value.
• A character value or literal string containing a valid date, time, or timestamp
value in one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy
− hh:mm:ss

The following are the valid values for s1.

Formatting
Element Description of Returned Value

Punctuation All punctuation symbols reproduced in the resulting string.


(including spaces)
“text” All text in double quotes reproduced in the resulting string, without the
quotation marks.
AM Ante meridiem indicator, without periods.
A.M. Ante meridiem indicator, with periods.
CC Century portion of the date value (can have a spelling or ordinal suffix).
D Day of week (1–7), with Sunday as day 1.
day Name of the day padded to 9 characters. Case of the returned value is as
Day follows:
DAY day All letters in the day name are lowercase.
Day The first letter of the day name is uppercase and the rest of the
letters are lowercase.
DAY All letters of the day name are uppercase.
RDMS uses the name from the locale indicated by the LC_TIME environment
variable.
DD Day of month as decimal (00–31).
DDD Day of year as decimal (001–366).

7830 8160–027 3–135


Date, Time, and Timestamp Functions

Formatting
Element Description of Returned Value

dy Abbreviated name of the day. Case of the returned value is as follows:


Dy dy All letters in the day abbreviation are in lowercase.
DY Dy The first letter of the day abbreviation is in uppercase and the
rest of the letters are in lowercase.
DY All letters of the day abbreviation are uppercase.
RDMS uses the name from the locale indicated by the LC_TIME environment
variable.
FF [1..6] Fractional seconds; no radix character is printed (use the X format element
to add the radix character). Use the numbers 1 to 6 after FF to specify the
number of digits in the fractional second portion of the time value returned.
If you do not specify a digit, RDMS uses the precision specified in the time’s
declaration.
Examples
‘HH:MI:SS.FF’
‘SS.FF3’
IW Week of the year as decimal (01–52 or 01–53), based on the ISO standard.
IYY, IY, I Last three, two, or one digit of the year following the ISO year.
IYYY Four-digit year based on the ISO standard.
HH, HH12 Hour on 12-hour clock as decimal [01–12].
HH24 Hour on 24-hour clock as decimal [00–23].
J Julian day.
MI Minute as decimal [01–59].
MM Month as decimal [01–12].
mon Abbreviated name of the month. Case of the returned value is as follows:
Mon mon All letters in the month abbreviation are lowercase.
MON Mon The first letter of the month abbreviation is uppercase and the
rest of the letters are lowercase.
MON All letters of the month abbreviation are uppercase.
RDMS uses the name from the locale indicated by the LC_TIME environment
variable.
month Name of the month padded to 9 characters. Case of the returned value is as
Month follows:
MONTH month All letters in the month name are lowercase.
Month The first letter of the month name is uppercase and the rest of
the letters are lowercase.
MONTH All letters of the month name are uppercase.
RDMS uses the name from the locale indicated by the LC_TIME environment
variable.
PM Post meridiem indicator, without periods.
P.M. Post meridiem indicator, with periods.

3–136 7830 8160–027


Date, Time, and Timestamp Functions

Formatting
Element Description of Returned Value

Q Quarter of the year. For example, a date value in January through March
returns 1.
rm Month in Roman numerals. Case of the returned value is as follows:
Rm rm All letters in the month value are lowercase.
RM Rm The first letter of the month value is uppercase and the rest of
the letters are lowercase.
RM All letters of the month value are uppercase.
RR Last two digits of the year.
SS Second as decimal (00–59).
SSSSS Seconds past midnight.
WW Week of year (1–53). Week 1 starts on the first day of the year and continues
to the seventh day. Thus, the weeks do not necessarily start on Sunday
W Week of month (1–5). Weeks are defined as they are for the WW formatting
element.
X Radix character
RDMS uses the radix from the locale indicated by the LC_TIME environment
variable.
YYYY Four-digit year.
YYY, YY, Y Last three, two, or one digits of the year.

Example
To_char('2000-02-21 13:20:24', 'J "is:" Day, Month DD, YYYY "at"
HH12:MI:SS PM')

returns
2451596 is: Monday , February 21, 2000 at 1:20:24 PM

The following example sets the LC_TIME environment variable to the German locale.

@CIFSUT
set LC_ALL=de_DE.8859-1
@EOF

To_char('2000-02-21 13:20:24','J "ist:" Day, Month DD, YYYY"@"


HH24:MI:SS')

returns

2451596 ist: Montag, Februar 21, 2000@ 13:20:24

7830 8160–027 3–137


Date, Time, and Timestamp Functions

3.8.47. to_date Function


Format
to_date(<character, date, time, or timestamp> s1,
[ Character s2 ] ) → Timestamp

Purpose
Converts the character string s1 to a timestamp value according to the format string in
s2.

If s1 is NULL, RDMS returns a null string.

If you omit s2 or if it is NULL, RDMS uses the format 'MM/DD/YYYY HH24:MI:SS'.


RDMS always returns the timestamp with precision 6.

The maximum length for s1 is 80 bytes. The maximum length for s2 is 80 bytes.

The following are the valid formatting elements for s2.

Formatting Element Description

Punctuation All punctuation symbols mark the end of the previous token. The
dash ‘-‘ and forward slash ‘/’ format elements accept either a dash or
a forward slash in the corresponding character string s1. For example,
s2 containing ‘MM-DD-YYYY’ accepts the s1 string values ’10-23-2011’
and ‘10/23/2011’.
"text" RDMS skips all text in double quotes in s1 and s2
AM Ante meridiem indicator with or without periods. RDMS accepts AM
A.M. and PM in s1 and adjusts the time value accordingly.
CC Century – 2 digits

D Day of week (1-7)


Day The name of the day
DAY RDMS uses the name from the locale indicated by the LC_TIME
environment variable
DD Day of month (1-31)
DDD Day of year (1-366)
Dy Abbreviated name of the day
DY RDMS uses the name from the locale indicated by the LC_TIME
environment variable
FF Fractional seconds
HH Hour of the day (1-12)
HH12
HH24 Hour of the day (0-23)
IW Week of the year (1-52 or 1-53) based on the ISO 8601 standard

3–138 7830 8160–027


Date, Time, and Timestamp Functions

Formatting Element Description

IYY Last three, two, or one digit of the ISO year


IY
I
IYYY Four-digit year based on the ISO standard
J Julian day. The number of days since the beginning of the Julian
calendar. The number specified must be an integer.
MI Minute (0-59)
MM Month (1-12). January = 1, December = 12
mon Abbreviated name of the month
Mon RDMS uses the name from the locale indicated by the LC_TIME
MON environment variable

month The name of the month


Month RDMS uses the name from the locale indicated by the LC_TIME
MONTH environment variable

NNNNNN Microseconds (000000-999999)


PM Post meridiem indicator, with or without periods. RDMS accepts AM
P.M. and PM in s1 and adjusts the time value accordingly.

Q Quarter of the year. January through March = 1


RR Last two digits of the year. See discussion later for determining the
RRRR century. If you use RRRR format, RDMS expects a four-digit year and
does not alter the century portion.
SS Second (0-59)
SSSSS Seconds past midnight (0-86399).
WW Week of year (1-53). Week 1 starts on the first day of the year and
continues to the seventh day. Thus, the weeks do not necessarily
start on Sunday.
W Week of month (1-5). Weeks are defined as they are for the WW
formatting element.
X Radix character.
RDMS uses the radix from the locale indicated by the LC_TIME
environment variable
YYYY Four-digit year.
YYY Last three, two, or one digit of the year. RDMS uses the current year
YY to fill in the other digits to form a four-digit year.
Y

Leading zeroes may be specified for any numeric value – month, day, hour, minute,
second.

7830 8160–027 3–139


Date, Time, and Timestamp Functions

The RR format element can be used to change how a specification for a year is to be
interpreted.

Final two digits of Two-digit year in


current year s1 Implied first two digits of year

00-50 00-49 First two digits of current year


51-99 00-49 First two digits of current year + 1
00-50 50-99 First two digits of current year – 1
51-99 50-99 First two digits of current year

For example, if the current year is 2011, ‘86’ with format ‘RR’ means 1986; however, if
the current year is 2052, it means 2086.

RDMS uses the following default values when the format string s2 does not include a
format element:

Timestamp component Default

year Current year as four digits


century e.g., YY format Century from current date
month Current month as two digits
day 01 (first day of the month)
hour 00
minute 00
second 00
fractional seconds RDMS uses the digits included in the string. If no fractional
digits appear, the precision is 0.

A substring of s1 may include fewer than the maximum number of digits for that
component of the timestamp that is indicated by the corresponding format element.
RDMS defaults any missing digit to zero. For example, with a format string s2 of
‘YYYY-MM-DD HH24:MI:SS’ and s1 containing ‘999-3-9 5:6:7’, RDMS generates a
timestamp value of ‘0999-03-09 05:06:07’.

Examples
to_date('2000-02-21 13:20:24', 'YYYY-MM-DD HH24:MI:SS')

returns a timestamp value: 2000-02-21 13:20:24.000000

to_date('2000-02-21 ', 'YYYY-MM-DD')

returns a timestamp value: 2000-02-21 00:00:0.000000

to_date('2000-02-21 13:20:24', 'YYYY-MM-DD')

3–140 7830 8160–027


Date, Time, and Timestamp Functions

returns an error because the number of formatting elements in s2 does not match the
number of tokens in s1.'

@CIFSUT
SET LC_ALL=fr_FR.8859-1
@EOF

to_date('21-Février-2011 13:20:24', 'DD-MONTH-YYYY HH24:MI:SS')

returns the timestamp value

2011-02-21 13:20:24.000000

3.8.48. to_timestamp Function


Format
to_timestamp (<character, date, time, or timestamp> s1,
[ Character s2 ]) → Timestamp

Purpose
Converts the character string s1 to a timestamp value according to the format string in
s2. If you omit s2 or if it is NULL, RDMS uses the format 'MM/DD/YYYY HH24:MI:SS'.

The maximum length for s1 is 80 bytes. The maximum length for s2 is 80 bytes.

The to_timestamp function uses the same arguments as the to_date function. See the
to_date function for more information.

Some additional formatting rules apply for to_timestamp:


• If the input string s1 contains no date value, RDMS uses the current date.
• If the input string s1 contains no time value, RDMS uses the current time.

See also the date, strptime, timestamp, and timestamp_format, functions which also
create timestamp values.

Example
to_timestamp('21-02-2011 13:20:24', 'DD-MM-YYYY HH24:MI:SS')

returns a timestamp value: 2011-02-21 13:20:24.000000

See to_date for more examples.

7830 8160–027 3–141


Date, Time, and Timestamp Functions

3.8.49. trunc Function


Format
trunc(<time, date, or timestamp data type> d [ , Character s1 ] )
→ Timestamp

Purpose
Returns d truncated to the unit specified by s1. If s1 is not specified or is NULL, RDMS
uses ‘dd’, which truncates d to the nearest day.

If you use a time truncation format for a date value, RDMS sets the time to 00:00:00. If
you use a date truncation format for a time value, RDMS sets the date portion to
today’s date.

If d is NULL, RDMS returns a null value.

The value for s1 can be any of the following formats.

Format Truncation Unit

CC Century
YYYY, YEAR, YYY, YY, Y Year
IYYY, IY, I ISO year
Q Quarter
MONTH, MON, MM, RM Month
WW Same day of the week as the first day of the year
IW Same day of the week as the first day of the ISO year
W Same day of the week as the first day of the month
DDD, DD, J Day
Day, DY, D Starting day of the week (Sunday)
HH, HH12, HH24 Hour
MI Minute

Example 1
This example rounds to the nearest year.
trunc('2001-02-20 13:20:24', 'year')

returns
2001-01-01 00:00:00

3–142 7830 8160–027


Date, Time, and Timestamp Functions

Example 2
trunc('2001-03-14 13:20:24', 'mi')

returns
2001-03-14 13:20:00

Example 3
trunc('2001-03-18 13:20:24', 'CC')

returns
2000-01-01 00:00:00

3.8.50. varchar_format Function


Format
varchar_format(<character, date, time, or timestamp> d,
[ Character s1 ] ) → Character

Purpose
Converts the character string d to a character string according to the format string in
s1. If you omit s1 or if it is NULL, RDMS uses the format 'MM/DD/YY HH24:MI:SS'.

The maximum length for s1 is 80 bytes.

The varchar_format function uses the same arguments as the to_char function. It is a
synonym for the to_char function. See the to_char function for more information.

Example
varchar_format('2011-02-21 13:20:24', 'DD-MM-YYYY HH24:MI:SS')

returns a timestamp value: 2011-02-21 13:20:24

See to_char for more examples.

3.8.51. week Function


Format
week(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the week of the year in which d occurs, expressed as an integer between 1
and 53. Sunday is considered the first day of the week. Week 1 begins on January 1.

If d is NULL, RDMS returns a null value.

7830 8160–027 3–143


Date, Time, and Timestamp Functions

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, RDMS uses the date part of the timestamp.


• If d is a date, RDMS uses that date.
• If d is a string, RDMS uses the date that is represented by the string.
• If d is a time, RDMS returns an error.

Example
week('2001-02-20 13:20:24')

returns
8

3.8.52. year Function


Format
year(<character, date, or timestamp data type> d) → Integer

Purpose
Returns the year portion of d expressed as an integer between 1 and 9999.

If d is NULL, RDMS returns a null string.

3–144 7830 8160–027


Date, Time, and Timestamp Functions

The argument d may be one of the following:

• A column with data type, date or timestamp. If d is a time value, RDMS returns
an error.
• A valid date or timestamp literal value (see section 2.3.4).
• Another BIF or Datetime Function (see section 2.5.7) which returns a date or
timestamp value.
• A character value or literal string containing a valid date or timestamp value in
one of the following formats:
− yyyy-mm-dd
− yyyy-mm-dd hh:mm:ss
− mm/dd/yyyy
− mm/dd/yyyy hh:mm:ss
− dd.mm.yyyy
− dd.mm.yyyy hh:mm:ss
− ddMonyyyy

Additional processing rules are as follows:

• If d is a timestamp, the result is the date part of the timestamp.


• If d is a date, the result is that date.
• If d is a string, the result is the date that is represented by the string.
• If d is a time, RDMS returns an error.

Example
year('2001-02-20 13:20:24')

returns
2001

7830 8160–027 3–145


System Information Functions

3.9. System Information Functions


The following functions return information about the system and applications
environment.

3.9.1. generated_run_id Function


Format
generated_run_id() → Character

Purpose
Returns the generated run-id for the current run as six ASCII characters. The value
may include trailing spaces. See also the run_id function (3.9.5).

For more information on the run_id and generated run_id, see the Executive Control
Language (ECL) and FURPUR Reference Manual.

Example
generated_run_id()

returns, for example


3RBKA

3.9.2. max_aor_updates Function


Format
max_aor_updates() → Integer

Purpose
Returns the value for the MAXIMUM-AOR-UPDATES configuration parameter for the
current application group.

For more information on MAXIMUM-AOR-UPDATES, see the Repository for ClearPath


OS 2200 Administration Guide.

Example
max_aor_updates()

returns, for example


15

3–146 7830 8160–027


System Information Functions

3.9.3. permuted_id Function


Format
permuted_id( [ 'CURRENT' | 'NEXT' ] [ , Integer n [ , Integer p ] ] ) →

Numeric(21,0)

permuted_id( [ 'CURRENT' | 'NEXT' ] [ , Integer n [ , Integer p ] ] ) →

Integer

Purpose
Returns the value for the system services function UNIQUE$ID, permuted to
counteract the monotonically increasing nature from repeated calls. The identifier is
unique across hosts in a multihost environment. For more information on UNIQUE$ID,
see the System Services Programming Reference Manual.

If you include no parameters or the keyword parameter ‘NEXT’ (default), RDMS calls
the Exec to obtain the next unique identifier. If you include the keyword parameter
‘CURRENT’, RDMS returns the same value as the previous call to the permuted_id
function. If no current value exists, RDMS creates one and returns it. RDMS keeps the
current permuted_id value for the duration of the thread. An END THREAD statement
clears the current permuted_id value.

Note: The ‘CURRENT’ and ‘NEXT’ parameters are literal strings enclosed in single
quotation marks.

The parameter n indicates the number of bits to return to the caller. The default value
for n is 72. If you include n, RDMS truncates the UNIQUE$ID value to the specified
number of bits. The UNIQUE$ID value is a structured 72-bit value:

• The first 3 bits are set to zero to ensure a positive result of no more than 21 digits.
• The next 6 bits are a randomizing value to counteract the monotonically increasing
nature of the UNIQUE$ID values.
• The next 6 bits are the host-id, to guarantee uniqueness in a multihost
environment.
• The remaining 57 bits are a counter that is incremented by 1 each time UNIQUE$ID
is called.

If n is less than 72, RDMS truncates bits from the left, following the randomizing bits,
first reducing the number of bits that represent the host-id, then reducing the number
of bits in the counter itself. RDMS concatenates the 6 randomizing bits at the
beginning of the resulting value. The smallest value for n is 12 (6-bit randomizing value
followed by a 6-bit counter). RDMS changes any n greater than 72 to 72 and changes
any value less than 12 to 12.

If n is greater than 36 or if n is not a numeric literal, RDMS returns NUMERIC(21,0).

If n is 36 or less, RDMS returns INTEGER.

7830 8160–027 3–147


System Information Functions

The parameter p indicates the number of bits to permute. The default value for p is 6.
If you include p, it must equal 6, 9, or 12. Any other value causes RDMS to use the
value 6. When p is 12, the permuted_id is not guaranteed to be unique across hosts in
an XTC environment.

Also see 3.9.7 for information about the unique_id function. The values returned by the
unique_id function always increase in value and are unique across all hosts in a
multihost environment. The values returned by the permuted_id function are
permuted and unique across all hosts in a multihost environment. For operations that
perform many inserts, the permuted_id function helps to avoid sequential inserts onto
the same database data page.

Because the system call UNIQUE$ID uses ‘microseconds since January 1, 1900’ as a
seed value, the maximum number of unique values generated for each day for each
system is 86,400,000,000. If you use the permuted_id or unique_id functions to
generate unique values for RDMS tables, you must consider this upper bound. These
functions should generate no more than 86,400,000,000 values across all RDMS tables
for each day.

Example 1
permuted_id()

returns a unique identifier, permuted to disperse the values across the B-tree.

permuted_id('current')

returns the same identifier as the previous call to permuted_id().

Example 2
Three successive calls to permuted_id() could return the following example values:

203494027282781912946

277281003577620119411

351067979872458325876

Example 3
The following is an extended example to illustrate how the unique_id function could
be used in a database with two tables, a customer order table and an order line
number table.

3–148 7830 8160–027


System Information Functions

First, create the two tables.

CREATE table klb_udf.customer_order in klb_udf.custorder


columns are
order_number : numeric(21,0),
cust_name : char(50)
primary key index_0 is order_number;
commit;

CREATE table klb_udf.order_line in klb_udf.custorder


columns are
order_number : numeric(21,0),
line_number : integer,
item : char(50)
primary key index_0 is order_number, line_number;
commit;

Next, enter an order with three corresponding order lines:

insert into klb_udf.customer_order


values(permuted_id(), 'acme foods');
insert into klb_udf.order_line
values(permuted_id('current'), 1, 'washington apple');
insert into klb_udf.order_line
values(permuted_id('current'), 2, 'fuji apple');
insert into klb_udf.order_line
values(permuted_id('current'), 3, 'bosc pear');

Fetch the rows to show that the same order_number value is inserted into both tables.
Note that permuting the value sometimes sets the high bit of the word, which makes
the value print as a negative number.

declare c1 cursor for select * from klb_udf.customer_order;


fetch first 20 c1;

4615067738100807639 acme foods

declare c2 cursor for select * from klb_udf.order_line;


fetch first 20 c2;

4615067738100807639 1 washington apple


4615067738100807639 2 fuji apple
4615067738100807639 3 bosc pear

7830 8160–027 3–149


System Information Functions

3.9.4. program_type Function


Format
program_type() → Integer

Purpose
Returns the program type, as follows:

4 Demand
5 Deadline batch
6 Batch
9 Self-destroying transaction
10 Self-initializing transaction
11 Reentrant transaction
12 Online batch
13 High-Volume Transaction Processing (HVTIP)

For more information on program type, see the Executive Control Language (ECL)
and FURPUR Reference Manual.

Example
program_type()

returns, for example


4

3.9.5. run_id Function


Format
run_id() → Character

Purpose
Returns the original run-id for the current run as six ASCII characters. The value may
include trailing spaces. See also the generated_run_id function (3.9.1).

For more information on the run-id and generated run-id, see the Executive Control
Language (ECL) and FURPUR Reference Manual.

Example
run_id()

returns, for example


3RBK

3–150 7830 8160–027


System Information Functions

3.9.6. uds_slot Function


Format
uds_slot() → Integer

Purpose
Returns the UDS slot number assigned to the current transaction. The return value is
in the range between 1 and the value of the configuration parameter MAX-THREADS.

Example
uds_slot()

returns, for example


2

3.9.7. unique_id Function


Format
unique_id( ['CURRENT' | 'NEXT' ] [ , Integer n ] ] ) → Numeric(21,0)

unique_id( ['CURRENT' | 'NEXT' ] [ , Integer n ] ] ) → Integer

Purpose
Returns the value for the system services function UNIQUE$ID. The identifier is unique
across hosts in a multihost environment. For more information on UNIQUE$ID, see the
System Services Programming Reference Manual.

If you include no parameters or the keyword parameter ‘NEXT’, RDMS calls the Exec
to obtain the next unique identifier. If you include the keyword parameter ‘CURRENT’,
RDMS returns the same value as the previous call to the unique_id function. If no
current value exists, RDMS creates one and returns it. RDMS keeps the current
unique_id value for the duration of the thread. An END THREAD statement clears the
current unique_id value.

Note: The ‘CURRENT’ and ‘NEXT’ parameters are literal strings enclosed in single
quotation marks.

The parameter n indicates the number of bits to return to the caller. The default value
for n is 72. If you include n, RDMS truncates the UNIQUE$ID value to the specified
number of bits. The UNIQUE$ID value is a structured 72-bit value:

• The first 12 bits the host-id, to guarantee uniqueness in a multihost environment.


• The remaining 60 bits are a counter that is incremented by 1 each time UNIQUE$ID
is called.

If n is less than 72, RDMS truncates bits from the left, first reducing the number of bits
that represent the host-id, then reducing the number of bits in the counter itself.

7830 8160–027 3–151


System Information Functions

The smallest value for n is 1. RDMS reduces any n greater than 72 to 72 and changes
any value less than 1 to 1.

If n is greater than 36, or if n is not a numeric literal, RDMS returns NUMERIC(21,0). If n


is 36 or less, RDMS returns INTEGER.

See also 3.9.3 for information about the permuted_id function. The values returned by
the unique_id function always increase in value and are unique across all hosts in a
multihost environment. The values returned by the permuted_id function are
permuted and unique across all hosts in a multihost environment. For operations that
perform many inserts, the permuted_id function helps to avoid sequential inserts onto
the same database data page.

Because the system call UNIQUE$ID uses ‘milliseconds since January 1, 1900’ as a
seed value, the maximum number of unique values generated per day per system is
86,400,000. If you use the permuted_id or unique_id functions to generate unique
values for RDMS tables, you must consider this upper bound. These functions should
generate no more than 86,400,000 values across all RDMS tables per day.

Example 1
unique_id()

returns a unique identifier.

unique_id('current')

returns the same identifier as the previous call to the unique_id function.

Example 2
Three successive calls to the unique_id function could return the following example
values:

1156221661307940821
1156221661307940822
1156221661307940823

Example 3
The following is an extended example to illustrate how the unique_id function could
be used in a database with two tables, a customer order table and an order line
number table.

3–152 7830 8160–027


System Information Functions

First, create the two tables.

CREATE table klb_udf.customer_order in klb_udf.custorder


columns are
order_number : numeric(21,0),
cust_name : char(50)
primary key index_0 is order_number;
commit;
CREATE table klb_udf.order_line in klb_udf.custorder
columns are
order_number : numeric(21,0),
line_number : integer,
item : char(50)
primary key index_0 is order_number, line_number;
commit;

Next, enter an order with three corresponding order lines:

insert into klb_udf.customer_order


values(unique_id(), 'acme foods');
insert into klb_udf.order_line
values(unique_id('current'), 1, 'washington apple');
insert into klb_udf.order_line
values(unique_id('current'), 2, 'fuji apple');
insert into klb_udf.order_line
values(unique_id('current'), 3, 'bosc pear');

Fetch the rows to show the same order_number value is inserted into both tables:

declare c1 cursor for select * from klb_udf.customer_order;


fetch first 20 c1;

1156221661307940939 acme foods

declare c2 cursor for select * from klb_udf.order_line;


fetch first 20 c2;

1156221661307940939 1 washington apple


1156221661307940939 2 fuji apple
1156221661307940939 3 bosc pear

7830 8160–027 3–153


System Information Functions

3.9.8. user Function


Format
user() → Character

Purpose
Returns a 12-character ASCII string containing the user ID of the current user.
Example
user()

returns, for example:


5AVINASH

3.9.9. pages_updated Function


Format
pages_updated()→ Integer
pages_updated('STEP') → Integer
pages_updated('PRECONDTIME') → Integer
pages_updated('PRECONDALTER') → Integer
pages_updated('PRECONDNEW') → Integer

Purpose
Pages_updated() and pages_updated('STEP') returns the number of pages (blocks)
updated in this step since the last COMMIT or ROLLBACK. This includes pages
updated by RDMS, DMS, and SFS. This does not include any pages updated during
preconditioning. This is the same value as returned by RDMS in H1 of AUXINFO when
SET AUXINFO PAGE COUNT is specified.

Pages_updated('PRECONDTIME') returns the number of pages written during the last


preconditioning request within an active step, which means that this count is cleared
when the main step is committed.

Preconditioning occurs as part of INSERT processing when the table contains a


GENERATED DEFAULT (such as an IDENTITY column.)

Pages_updated('PRECONDALTER') Returns the total number of existing pages (for


example, allocation pages, pages from the free chain) updated during preconditioning
by this thread, unless preconditioning failed in which case it is the number of pages
that would have been updated.

Pages_updated('PRECONDNEW') Returns the total number of new pages created


during preconditioning by this thread, unless preconditioning failed in which case it the
number of pages that would have been updated.

See the statistic, displayed by the rdms_thread_stat scalar function,


no_preconditioning and no_preconditioning_failures to determine whether we are
doing preconditioning and whether it tried and failed.

3–154 7830 8160–027


System Information Functions

Examples
pages_updated()

returns

pages_updated('PRECONDTIME')

returns

42

3.9.10. rdms_thread_stat function


Format
rdms_thread_stat (Character(8) s ) → integer

Purpose
Returns the value of a given RDMS statistic (for example, number of INSERT
statements) that is displayed by the UDS STAT trace and the UDSMON K screen. The
parameter s is the abbreviation of the statistic. Refer to the ClearPath Enterprise
Servers Universal Data System Administration and Support Reference Manual for
more information on the abbreviations and the meaning of the statistic.

The abbreviations are not case sensitive, for example, ‘Insert’ is the same as ‘INSERT’.
Refer to the following screen capture for information on abbreviations that can be
referenced from the rdms_thread_stat function. If the document ClearPath Enterprise
Servers Universal Data System Administration and Support Reference Manual
includes a blank as part of the abbreviation, you must also include it. For example, in
'Decl Cur', include the blank in the value of s.

Examples
rdms_thread_stat ('Insert')

returns

7830 8160–027 3–155


System Information Functions

In the following example, note that there is a space between the ‘t’ and the ‘N’,
because that is the way it is described in the UDS AG.

rdms_thread_stat('Fet Next')

returns

75

<09:29:09> Thread Control Inform. Actv/Avail= Txn: 0/ 9, Other: 1/ 9


Slot Runid Gen,Org SOS Time From Seq Update Locks MsgId ScrB Status
--------------------------------------------------------------------------------
1 5JMP 5JMP *09:26:13 Demand 2 1 SOS Complete
Step 793388- 0, 11/06/22 Msg 0, Recy: DU Thrd:10041
File Reads (req/act) = 0/ 0, Writes (req/act) = 0/ 0
Retention Read/Write = 0/ 0, Aud Looks(Bef/Aft)= 0/ 0
SUPs: 0: 0: 0. 0 (Qd: 0: 0: 0. 0) Thrd start: 2011/06/22:09:26:13
Q Cnt: 0, 0, 0, 0, 0, 0, 0
-------------------------------- LDM Statistics --------------------------------
RDMS <ACTIVE>: 0=Exe Prep 0=PreFirst 0=Pre Cur 0=PreCond
0=Pre Fail 0=SP RSet 0=SP UpCnt 0=Repl Rec 0=Flashed
0=LocalIdx 0=BadFlash 0=AbByPass 0=FetShort 0=Cmd Mig
0=Sec Mig 0=ActBanks 0=TmpFilWr 0=Int Sort 0=EsortCal
0=I18NCall 0=Groups 0=PKUpdate 0=SIUpdate 0=SnapShot
0=SngleFet 0=MultiFet 0=NestedJn 0=Hash Jn 0=Merge Jn
0=Outer Jn 0=Trapeze 0=Brute 0=Indexed 0=Shadow
0=Pk Equal 0=Pk Range 0=Subquery 0=Trigger 0=Reused
0=Recomp 0=Fetched 0=Updated 0=Inserted 0=Deleted
0=Loaded 0=Unloaded 0=FkeyChk 0=Open 0=Fet 1st
0=Fet Next 0=Fet Last 0=Fet Pri 0=Fet Cur 0=Close
0=Locate 0=Decl Cur 0=Update 0=Insert 0=Delete
0=Lock 0=Unlock 1=Use 0=Cre Tbl 0=Put LOB
0=Drop Tbl 0=Drop Cur 0=AlterTbl 0=Cre View 0=DropView
0=CreIndex 0=DropIndx 0=Grant 0=Revoke 0=Select
0=Load 0=Unload 0=Agg Fet 0=Explains 0=RunStats
0=Set Flag 0=Prepare 0=Execute 0=Exec Imm 1=Level
0=Fet NxtN 0=Report 0=RegIndex 0=Cre Sch 0=Drop Sch
0=Rep Load 0=Reset 0=DropRout 0=Cre Trig 0=Signal
0=Set Var 0=Return 0=CallProc 0=CondStmt 0=Else
0=Cre Rout 0=End Rout 0=GetParam 0=Process 0=SyntaxE
0=BeginStm 0=End Stmt 0=Chg Part 0=Get LOB 0=Get Desc
0=Repl Aud 0=Fet Abs 0=Fet Rel 0=Cre Role 0=DropRole

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

3–156 7830 8160–027


System Information Functions

3.9.11. verification_timestamp Function


Format
verification_timestamp(Character schema name, Character table or view
name) → Numeric(21,0)

Purpose
Returns the value used by RDMS to verify that a COBOL or C program containing static ESQL
was compiled using the current table or view definition. This two-word value has zero for the
second word unless the table or view was last altered using the technique described in the
RDMS Administration Guide, section 6.11 Porting ESQL or Module Language Program. The case
of the schema name and table name must match the one used by RDMS; when you create table
s.t, you are actually creating table S.T.

Example:
octal(verification_timestamp('RDMS','ROLES'))

returns a value of the following form. The actual value depends on the time when the
RDMS system table RDMS.ROLES was created.

410616126310000000000000

7830 8160–027 3–157


Concurrency Functions

3.10. Concurrency Functions


The following functions return information related to concurrency based on columns
GENERATED AS IDENTITY/EXPRESSION.

3.10.1. partition_id Function


Format
partition_id() → numeric(21,0)

Purpose
The partition_id function can be specified only as the generated default for a
partitioned table. Partition_id has no parameters and has the following properties:

• Partition_id() must be GENERATED ALWAYS. You cannot use partition_id() as


part of GENERATED BY DEFAULT.
• The first insert into a table following table creation, table alteration, system
restart, app group restart, down of file, or short recover is into the first
(left-most) partition.
• Sequential inserts into a given version of a table are in different partitions.
RDMS generates the values based on round-robin algorithm among the
partitions.
• For a given partition p, the first record inserted into that partition is 1 (if this is
the left-most partition), or the value of partition(p-1).upper_bound+1 for the
other partitions.
• For a given partition p, the next value inserted into that partition is the value of
the partition’s last record +1.
• The value of the next value inserted might be affected if it is necessary to read
the B-tree control page to get the restart value. In a single-host environment,
the maximum number of values lost depends on the following:
− the data type specified for the column using partition_id.
− when specified as something other than DYNAMIC, 0, or 1.
− when the value of CACHE is specified by the user.
With CACHE DYNAMIC or CACHE 0, the maximum number of values lost per
partition for SMALLINT is 1, INTEGER and one-word NUMERIC is 100, and
two-word NUMERIC is 10,000.
In an XTC environment, unless CACHE is 1, the maximum number of values
lost is less than 100 per partition regardless of data type. For a single host or
XTC, when CACHE is 1, the maximum number of values lost is 1 per partition.
The next value is affected if the table definition is altered, the system is
restarted, the app group is restarted, a DOWN/UP of the file is done, or
following a DELETE ALL.
• The last value inserted into a column GENERATED ALWAYS AS
(partition_id()),or GENERATED AS IDENTITY is returned by the scalar function
identity_val_local().

3–158 7830 8160–027


Concurrency Functions

• RDMS uses a round-robin algorithm to find the next partition_id value. Once
the maximum value for a particular partition is used the partition is marked full.
RDMS then looks for values in other partitions. For example, using the
following partition definition, after RDMS generates key values 1001 to 2555
and inserts the associated records into partition P2 it marks the partition as
full. The next key value is taken from the next ‘not’ full partition. If RDMS uses
P3, it looks for the next available value in P3. This means there is no “CYCLE”
capability within a partition, only across the set of partitions. RDMS returns a
'partition full' error when there are no more values available in any of the
partitions.

Suppose we have a partitioned table that has 3 partitions: P1 <= 1000, P2 <= 2555, P3
<= 3000. The sequence of inserts is as shown in the following table.

P1 <= 1000 P2 <= 2555 P3 <= 3000


1 1001 2556
2 1002 2557
3 1003 2558

Suppose, the following is done: DELETE WHERE BETWEEN 1001 and 1003. The
following values are left.

P1 <= 1000 P2 <= 2555 P3 <= 3000


1 2556
2 2557
3 2558

The next sequence of inserts is as shown in the following table.

P1 <= 1000 P2 <= 2555 P3 <= 3000


1 2556
2 2557
3 2558
4 1004 2559

Suppose you delete record 1004, then the sequence is as follows.

P1 <= 1000 P2 <= 2555 P3 <= 3000


1 2556
2 2557
3 2558
4 2559

7830 8160–027 3–159


Concurrency Functions

Suppose you down and up the file containing partition P2. The down causes the file to
be freed from UDS. When the file is next referenced, RDMS detects that this is the
first reference to the file since it was downed, short recovered, or copied from
another system. Therefore, RDMS reads the B-tree control page to get the restart
sequence for this partition. The restart value includes the increment used to
determine the restart value.

For example, if the data type specified for the column using partition_id is integer, then
an increment value of 100 is used. The restart value is incremented from the start
value + increment. The values from 1000 to 1100 are ‘lost’.

P1 <= 1000 P2 <= 2555 P3 <= 3000


1 2556
2 2557
3 2558
4 2559

The sequence of inserts is then as shown in the following table.

P1 <= 1000 P2 <= 2555 P3 <= 3000


1 1101 2556
2 2557
3 2558
4 2559
5 2560

3.10.2. identity_val_local Function


Format
identity_val_local()→ numeric(21,0)

Purpose
When a user inserts a record into a table with a generated default, RDMS assigns a
value to that column. The identity_val_local() scalar function returns the value RDMS
used during the last insert into any identity column, column GENERATED AS
(partition_id()), or GENERATED AS (expression) where the expression returns a
numeric value. This scalar function returns either the RDMS internally generated value
for the column or the user specified value for the column (when the user specifies the
value.) If this previous insert was INSERT…SELECT, the value of identity_val_local is
the value assigned to the last record inserted. The value of this scalar function is not
affected by either COMMIT or ROLLBACK.

3–160 7830 8160–027


Concurrency Functions

Suppose you are inserting records into multiple tables that are related to each other
by foreign keys, and that the primary key of the foreign key owner table is an identity
column. You need the value of the identity column in order to include that value on the
insert of the member table record. To do this use the identity_val_local() function in the
VALUES clause of the member table INSERT, as follows.

INSERT into the owner table


INSERT into member table VALUES(...identity_val_local(),...)

If the first INSERT statement terminated in error, the result of identity_val_local() is


unpredictable. Its value depends on where within processing RDMS detected the
error. Its value may be undefined, some previous value, or the value the inserted
record would have included had the INSERT succeeded.

RDMS keeps the last generated numeric value (for example, INTEGER, SMALLINT,
NUMERIC and the like) as a NUMERIC(21,0) value internally – and keeps it
independently of any DATE, TIME, or TIMESTAMP value. (See "Section 3.10.3,
generated_date_val_local".)

If no inserts have been done that trigger the GENERATED AS mechanism, RDMS
returns the value 0.

Example:

identity_val_local()

3.10.3. generated_date_val_local, generated_time_val_local, and


generated_timestamp_val_local Functions
Format
generated_date_val_local()→ date

generated_time_val_local()→ time(6)

generated_timestamp_val_local( ) → timestamp(6)

Purpose
RDMS might generate a date, time, or timestamp value during an INSERT into a
column declared GENERATED AS (datetime function.) These functions return the last
value inserted or generated in response to the insert into such a column. The value of
the function is not affected by either COMMIT or ROLLBACK.

RDMS keeps the last generated DATE, TIME, or TIMESTAMP value as a TIMESTAMP(6)
value internally and keeps it independent of the identity_val_local() numeric value.

7830 8160–027 3–161


Concurrency Functions

The precision returned as the time or timestamp value is always 6. This might be more
precision than the time or timestamp column in which it was stored. If you insert the
value into another table of the same data type and precision, RDMS implicitly rounds
the value to the proper precision in the same manner RDMS rounded the value during
the original insert. Use the CAST function to round the precision for use by the
application program.

Suppose you are inserting records into multiple tables that are related to each other
by foreign keys, and that the primary key of the foreign key owner table is an identity
column. You need the value of the identity column to include that value on the insert
of the member table record. To do this, use one of these functions in the VALUES
clause of the member table INSERT, as follows.

INSERT into the owner table


INSERT into member table VALUES(...identity_date_val_local(),...)

If the first INSERT statement terminated in error, the result of identity_date_val_local()


is unpredictable. Its value depends on where RDMS detected the error during
processing. Its value might be undefined, some previous value, or the value the
inserted record would have included had the INSERT succeeded.

UPDATE and INSERT…SELECT might affect multiple records. However, the value of
the current_date, current_time, and current_timestamp is the same for all records
affected by a given SQL statement.

If no inserts that trigger the GENERATED AS mechanism have been done, then RDMS
returns the following values:

date: 0001-01-01
time: 00:00:00.000000
timestamp: 0001-01-01 00:00:00.000000

The scalar functions, curtime(), getdate(), now(), and curdate() when executed as part
of an INSERT or UPDATE statement, always cause the value returned by the
generated_nnn_val_local() scalar functions to be updated.

Example:
generated_timestamp_val_local()

3–162 7830 8160–027


BLOB Functions

3.11. BLOB Functions


The following functions return information to identify and verify BLOB data.

3.11.1. get_file Function


Format
get_file( <any string data type> path ) → Blob

Purpose
Returns the contents of the file specified by path as a BLOB. The path must be a valid
CIFS path name. Internally, RDMS does a CIFS open(), stat(), read(), and close() of the
file.

See the CIFS for ClearPath OS 2200 User, Programmer, and Administrator
Reference Manual for more information about CIFS.

Note: The value returned by the get_file function may contain a final line
terminator character. The presence and value of this character depends on the
program that was used to create the file.

If path is NULL, RDMS returns a null value. If the specified file itself is empty, RDMS
returns a null value. If the file does not exist or RDMS receives an I/O error, RDMS
issues an error and terminates processing of the command containing the get_file
function.

The function get_file may not be used in a SELECT statement or within a WHERE or
HAVING clause.

The target of a get_file function in an INSERT or UPDATE statement can be a column


defined as BLOB, CHARACTER, NCHARACTER, or CHARACTER with a CHARACTER
SET clause. The target of a get_file function in a SET statement within an RDMS
routine or trigger can be a variable defined as CHARACTER or NCHARACTER.

Examples
In the following example, the get_file function reads a file from the local OS 2200
system and returns the contents of the pdf file as a BLOB.

get_file('/os2200/jmp/jmp/DocBox.pdf')

Other file sources are possible, using different forms of the path parameter:

• The following example reads from a different OS 2200 system on the LAN:

get_file('//RS929.nx.unisys.com/os2200/qual/fn/DocBox.pdf')

• The following example reads from a server on the LAN:

get_file('//SERVER1/bifproj/designs/getfilebif.doc')

7830 8160–027 3–163


BLOB Functions

• The following example reads from the C drive of a PC on the LAN:

get_file('//RON1-PC.nx.us.unisys.com/C$/ronpic.jpg')

If access to a remote system requires a separate user ID and password, include that
information in the path parameter. For example

get_file('//myuid:mypwd@RS929.us.unisys.com/os2200/qual/filename/bl01.d
oc')

3.11.2. lob_crc Function


Format
lob_crc( Blob ) → Numeric(21,0)

Purpose
Recalculates and returns the cyclical redundancy check (CRC) value for the BLOB
column specified by Blob. The CRC value is essentially a checksum on the BLOB value.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

Examples
lob_crc (emp_picture)

returns
570732582784159490468

This function can be used with the lob_id_crc function in a SELECT statement to help
detect storage area corruption. For example

SELECT primary_key FROM t1 WHERE lob_id_crc(emp_pic) NE


lob_crc(emp_pic)

This example returns the primary key values for the BLOBs whose CRC values stored
in the lob_id do not match the newly-calculated CRC value for the BLOB stored in the
database.

3.11.3. lob_end_address Function


Format
lob_end_address( Blob ) → Integer

Purpose
Returns the word address of the last word containing the BLOB data. It is the starting
address + lob_length - 1.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

3–164 7830 8160–027


BLOB Functions

Example
lob_end_address (emp_picture)

returns
28195

3.11.4. lob_end_page Function


Format
lob_end_page( Blob ) → Integer

Purpose
Returns the data-page number for the last page containing the BLOB value.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

Example
lob_end_page(emp_picture)

returns
179

3.11.5. lob_file Function


Format
lob_file( Blob ) → Character(26)

Purpose
Returns the name of the file underlying the storage area that contains this BLOB value.
The function returns either the Exec file name (qualifier*file) or the TIP file number as
a 26-character ASCII value, left-justified and space-filled.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

Example
lob_file(emp_picture)

returns
APP014*SET1-SA1

7830 8160–027 3–165


BLOB Functions

3.11.6. lob_id Function


Format
lob_id( Blob ) → Character(77)

Purpose
Returns the 24-byte lob_id as an octal value. The lob_id identifies this BLOB value.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

Example
lob_id(emp_picture)

returns
060000000002 000001000001 000000013554 000000000005 542461440461
440461462477

3.11.7. lob_id_crc Function


Format
lob_id_crc( Blob ) → Numeric(21,0)

Purpose
Returns the cyclical redundancy check (CRC) value from the lob_id for the BLOB
column specified by Blob. The CRC value is essentially a checksum on the BLOB value.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

Examples
lob_id_crc(emp_picture)

returns
626487201579747463753

This function can be used with the lob_crc function in a SELECT statement to help
detect storage area corruption. For example

SELECT primary_key FROM t1 WHERE lob_id_crc(emp_pic) NE


lob_crc(emp_pic)

This example returns the primary key values for the BLOBs whose CRC values stored
in the lob_id do not match the newly-calculated CRC value for the BLOB stored in the
database.

3–166 7830 8160–027


BLOB Functions

3.11.8. lob_start_address Function


Format
lob_start_address( Blob ) → Integer

Purpose
Returns the starting address (sector address, from 0) for the start of the BLOB value.
Note that the BLOB header appears one data-page before this starting sector address.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

Example
lob_start_address(emp_picture)

returns
2348

3.11.9. lob_start_page Function


Format
lob_start_page( Blob ) → Integer

Purpose
Returns the data-page number for the start of the BLOB value. Note that the BLOB
header appears one data-page before this page.

The Blob argument must be a BLOB column. It cannot be the result of another built-in
function.

Examples
lob_start_page(emp_picture)

returns
54

7830 8160–027 3–167


BLOB Functions

3.11.10. put_file Function


Format
put_file( <any data type> s1, <any string data type> path ) →

the four-character string 'OK'

Purpose
Writes the specified data item s1 to the file identified by path and returns the string
‘OK ’ (two spaces after ‘OK’). The path name must be a valid CIFS path name.
Internally, RDMS calls the CIFS creat(), write(), and close() functions.

See the CIFS for ClearPath OS 2200 User, Programmer, and Administrator
Reference Manual for more information about CIFS.

Note: A put_file function that has completed successfully cannot be undone, even
if the thread of which it is a part is rolled back.

If the file does not exist, RDMS creates the file. If the file exists, RDMS overwrites the
file. RDMS assigns permissions as follows: owner (read, write), group(read),
other(read).

If s1 is NULL, RDMS returns a null value and does not write anything to the file.

If path is NULL, RDMS returns a null value. If RDMS receives an I/O error, RDMS
issues an error and terminates processing of the command containing the get_file
function.

RDMS does not perform any data type conversion when writing s1 to the file. As a
result, some output values may not translate to environments other than OS 2200. For
example, integer or floating point numbers can be written to the output file as binary
values, but they would not be converted to equivalent integer or floating-point values
if the file is transferred to a different operating system environment.

Examples
In the following example, the get_file function writes the contents of the BLOB
column to the specified file and returns the status string 'OK'.

put_file(blob_col1, '/os2200/jmp/jmp/DocBox.pdf')

The following example concatenates the character columns, writes them to the
specified file, and returns the status string 'OK'.

put_file(rtrim(char_column1) || rtrim(char_column2),

'/os2200/jmp/jmp/description.txt')

3–168 7830 8160–027


BLOB Functions

In the preceding examples, the put_file function writes to the local OS 2200 system.
Other file destinations are possible, using different forms of the path parameter:

• The following example writes to a different OS 2200 system on the LAN:

put_file('//RS929.nx.unisys.com/os2200/qual/fn/bl01.doc')

• The following example writes to a server on the LAN:

put_file('//SERVER1/Groups/Test/pic2.jpg')

• The following example writes to the C drive of a PC on the LAN:

put_file('//PC1-nx.us.unisys.com/C$/prog.exe')

If access to a remote system requires a separate user ID and password, include that
information in the path parameter. For example

put_file('//myuid:mypwd@RS929.nx.unisys.com/os2200/qual/fn/bl01.doc')

7830 8160–027 3–169


BLOB Functions

3–170 7830 8160–027


Section 4
Routines and Triggers

This section describes how to create routines and triggers for RDMS databases.
These are the topics contained in this section:

• Routines (4.1)
• Triggers (4.2)
• Version Names (4.3)
• Creating, Executing, and Dropping Routines (4.4)
• Creating, Executing, and Dropping Triggers (4.5)
• Parameters (4.6)
• Dynamic Result Sets (4.7)
• Stored Functions (4.8)
• System Variables (4.9)
• Error Checking (4.10)
• Transactions, Commits, and Rollbacks (4.11)
• Statements and Keywords (4.12)
• Datetime and Interval Data Types (4.13)

4.1. Routines
A routine is an executable database object that exists independently of a table. It can
be called from a client or host application.

Note: In this reference manual, terminology is as follows:


• The term “routine” means “SQL routine” and refers to stored procedures and
stored functions.
• The term “stored procedure” is often used alone and includes stored functions.
The term “stored function” is used only when stored functions are specifically
indicated.

7830 8160–027 4–1


Routines

Routines can

• Contain individual execution statements


• Control execution within the routine itself
• Pass parameters in and out of the procedure
• Return open cursors as dynamic result sets
• Declare local variables

Routines offer many advantages, compared to executing large and complex SQL
queries from a client or host application:

• Faster execution
After their first execution, frequently used routines are resident in memory. After
compilation, they do not need to be reparsed, reoptimized, and recompiled.
• Reduced network traffic
Routines can consist of hundreds of individual statements but can be executed
with a single statement, allowing you to reduce the size of the call from the client
to the server.
• Modular programming
Routines allow you to break your work activities into smaller, more manageable
pieces.
• Reduced operator error
There is less information to pass.
• Enforced consistency
Problems associated with ad hoc data modifications are eliminated when users
access tables only through your routines.
• Automated complex or sensitive transactions
You can guarantee data integrity on certain tables by requiring all interaction with
those tables only through routines.

Routines improve overall system performance because multiple statements can be


executed with a single call to RDMS. Storing routines where they are to be used
reduces network traffic.

Whenever a routine is created, RDMS compiles, optimizes, and stores it. The first time
a routine is executed, RDMS reads it into cache memory from the database. Once the
routine resides in memory, it is easy and fast to locate and execute for future
execution during periods of heavy use.

SQL routines execute synchronously and atomically:

• Synchronous means that the client program waits while the routine executes.
• Atomic means that all statements invoked in the execution path of a routine are
guaranteed to succeed or fail as a unit.

4–2 7830 8160–027


Triggers

4.2. Triggers
A trigger is a specialized application created by users, but executed by RDMS.
Triggers are similar in many respects to routines. Triggers are used to specify the
processing action that RDMS is to take whenever a predetermined event (the deletion,
insertion, and/or update of information) occurs for a specific table. The processing
action that occurs may include any RDMS statements allowed within a routine
definition. The activation of a trigger may in turn cause the activation of other triggers.
Unlike routines, triggers are implicitly activated by RDMS and are not activated
through explicit reference from a user application.

Triggers can replace the execution of large and complex SQL queries and manual
processes in providing

• A straightforward method of enforcing business rules


• Expanded data constraint enforcement capability
• Detection of exceptional conditions
• Audit trail capabilities
• Data replication
• Enforcement of referential integrity

Triggers execute synchronously and atomically.

• Synchronous means that the client program waits while the trigger executes.
• Atomic means that all statements invoked in the execution path of the trigger are
guaranteed to succeed or fail as a unit. Note that if the trigger fails, the triggering
SQL statement also fails.

Some examples of trigger creation and invocation follow.

4.2.1. Example—Multiple Invocations of the Same Trigger


The procedure, update_col3, updates col3 of table t1 for each row that has a primary
key matching the input parameter, new_key, and a positive integer value of 1 to n from
the input parameter incount.

PROCEDURE update_col3 (IN new_key INTEGER, IN incount INTEGER,


IN value CHAR(10))
BEGIN
DECLARE update_count INTEGER;
SET update_count = incount;
WHILE update_count > 0 DO
UPDATE t1 SET (col3 = value)
WHERE key_col1 = new_key AND key_col2 = update_count;
SET update_count = update_count - 1;
END WHILE;
END;

7830 8160–027 4–3


Triggers

The trigger, trig2, updates the row in table t2 which has the same key as an updated
row in table t1.

CREATE TRIGGER Trig2 AFTER UPDATE ON t1


REFERENCING NEW ROW AS new_row
FOR EACH ROW
BEGIN
UPDATE t2 SET (col3 = new_row.col3)
WHERE key_col1 = new_row.key_col1 AND key_col2 = new_row.key_col2;
END;

When the user invokes the update_col3 procedure, the following events are initiated:

1. CALL update_col3(1000, 3, ‘new-value’);


2. The UPDATE t1… in the procedure is executed with a key_col2 value of 3.
a. Trig2 is invoked and UPDATE t2… is executed.
b. Control is returned to procedure update_col3.
3. The UPDATE t1… in the procedure is executed with a key_col2 value of 2.
a. Trig2 is invoked and UPDATE t2… is executed.
b. Control is returned to procedure update_col3.
4. The UPDATE t1… in the procedure is executed with a key_col2 value of 1.
a. Trig2 is invoked and UPDATE t2… is executed.
b. Control is returned to procedure update_col3.

The execution of procedure update_col3 is completed (update_count = 0) and control


is returned to the user.

4.2.2. Example—Recursive Trigger Invocation


Either avoid or carefully control recursion when creating triggers. The potential for an
endless processing loop is introduced if a trigger can be re-invoked before its
processing has been completed (whether due to statements within its own trigger
body or due to statements within one or more triggers that it causes to be invoked).
If recursive processing is desired and endless (or lengthy) loops can be avoided, it is
supported by RDMS. However, RDMS does impose a limit on the depth of trigger
nesting that can occur when a database modification statement is encountered.

4–4 7830 8160–027


Triggers

The following example shows how recursive trigger processing could be used to
replace the procedure shown in the preceding example (multiple invocations of the
same trigger) (the declaration of trig2 is removed from this example to simplify the
presentation):

CREATE TRIGGER Trig3 AFTER UPDATE ON t1


REFERENCING NEW ROW AS new_row
FOR EACH ROW
BEGIN
DECLARE update_count INTEGER;
SET update_count = new_row.key_col2 - 1;
IF update_count > 0 THEN
UPDATE t1 SET (col3 = new_row.col3)
WHERE key_col1 = new_row.key_col1 AND key_col2 = update_count;
END IF;
END;

When the user issues an UPDATE of table t1 the following events are initiated:

1. UPDATE t1 SET ( col_3 = ‘new-value’ WHERE key_col1 = 1000 AND key_col2 = 3;


2. Trig3 is invoked and an UPDATE t1… is executed with a key_col2 value of 3. (Call
1)
3. Trig3 is invoked and UPDATE t1… is executed with a key_col2 value of 2. (Call 2)
4. Trig3 is invoked and since key_col2 has a value of 1, no UPDATE statement is
executed. (Call 3).
5. Control is returned to Trig3 (Call 2).
6. Control is returned to Trig3 (Call 1).
7. Control is returned to the user’s UPDATE command.

The execution of the UPDATE command is complete and control is returned to the
user.

7830 8160–027 4–5


Triggers

4.2.3. Example—Cascading Trigger Invocation


An application environment contains five tables: orders_received, inventory,
shipments, vendors, and reorder_stock. As customer orders are received, a new row
is entered into the orders_received table for each product ordered. A request for
shipment is made by inserting a row into the shipments table for each product
ordered. The inventory on hand for each product is also updated each time a customer
order is received. When the inventory on hand falls to below zero, a reorder request
is entered into the reorder_stock table. The shipments table is processed every three
days, and all orders for a particular customer are combined and shipped. The inventory
table is processed every day and needed stock is reordered. There is only one vendor
for any particular product. The tables have the following characteristics:

• Orders_received table has a primary key of customer_number


• Inventory table has a primary key of product_code
• Shipments table has a primary key of customer_info
• Reorder_stock table has a primary key of product_code
• Vendors table has a primary key of vendor_name

Orders Shipments Reorder


Received Inventory Stock Vendors

Inventory and
shipments Reorder

Row triggers can be used to assist in accomplishing some of the tasks noted above.
The trigger definitions follow.

CREATE TRIGGER inventory_and_shipments AFTER INSERT ON orders_received


REFERENCING NEW ROW AS new_row
FOR EACH ROW
BEGIN
DECLARE cust_info (CHAR(10);
DECLARE code CHAR(10);
DECLARE quantity INTEGER;
SET cust_info = new_row.customer_info;
SET code = new_row.product_ordered;
SET quantity = new_row.quantity_ordered;
UPDATE inventory SET (product_count = product_count - quantity)
WHERE product_code = code;
INSERT INTO shipments (customer_info, order_date, product_code,
quantity_to_ship) VALUES(cust_info, CURRENT_DATE, code,
quantity);
END;

4–6 7830 8160–027


Triggers

CREATE TRIGGER reorder AFTER UPDATE ON inventory


REFERENCING OLD ROW AS old_row
NEW ROW AS new_row
FOR EACH ROW
BEGIN
DECLARE quantity INTEGER;
DECLARE code CHAR(10);
SET code = new_row.product_code;
SET quantity = new_row.product_count;
IF quantity < 0
THEN
BEGIN
DECLARE vendor CHAR(20);
DECLARE vendor_location CHAR(100);
SET quantity = - (quantity);
SELECT vendor_name, vendor_address INTO vendor, vendor_location
FROM
vendors WHERE product_code = code;

INSERT INTO reorder_stock (product_code, product_quantity,


vendor_name,
vendor_address) VALUES (code, quantity, vendor,
vendor_location);
END;
END IF;
END;

Processing a customer order results in the following events:

• The person who takes the customer's order generates an INSERT command
similar to the following:

INSERT INTO orders_received (customer_info, product_code,


quantity_ordered)

• The INSERT INTO the orders_received table causes the inventory_and_shipments


trigger to be invoked, which results in an update of the inventory table and an
INSERT into the shipments table.
• The inventory table UPDATE command causes the reorder trigger to be invoked
which may result in a SELECT from the vendors table and an INSERT into the
reorder_stock table.

7830 8160–027 4–7


Triggers

The actual execution order of these events is as follows:

1. The user executes an INSERT command into the orders_received table, and then
the inventory_and_shipments trigger is invoked.
2. An UPDATE command of the inventory table occurs, after which the reorder
trigger is invoked.
3. If product_quantity is less than zero
a. The SELECT from the vendors table is performed.
b. The INSERT into the reorder_stock table is performed.
4. Control is returned to the inventory_and_shipments trigger.
5. INSERT into the shipments table occurs. Control is returned to the user upon
completion of the INSERT.
6. The next user request is processed.

4–8 7830 8160–027


Version Names

4.3. Version Names


This subsection describes the use of version names with routines and triggers.

4.3.1. Routines and Version Names


Routines do not have versions. The version names refer only to tables and views
specified within a routine. If any statement within a routine specifies a table or view
without a version name, the version is not determined at routine definition time.
Instead, it is determined from the current default version name at the time the routine
statement is executed, regardless of the interface.

A static ESQL USE DEFAULT statement is effective only at compile time and therefore
has no effect in a routine. You can use a USE DEFAULT VERSION statement from the
interpreter interface or dynamic ESQL to change the current default version name at
execution time.

4.3.2. Triggers and Version Names


A trigger is always associated with a specific table definition, referred to as the target
table of the trigger, and never with a specific table version. When a trigger is invoked,
all table references within the trigger, which do not specify an explicit version name,
are resolved using the default version name which is in effect when the trigger is
invoked.

Note, however, that the default version may be changed when a trigger is invoked. If a
trigger is invoked by a data modification statement that includes an explicit table
version reference, then the default version name is changed to that of the table
version specified on the data modification statement. This new default table version is
in effect for the duration of the trigger invocation, including all nested trigger
references that may occur. This rule is applied at each level of nested trigger
invocation, that is, if a trigger contains a data modification statement that includes a
table version and that data modification statement causes another trigger to be
invoked, then the default version is changed to this newly specified table version. In
this manner, the default version may be set and reset several times during the
processing of a trigger invocation. The default version that was in effect prior to the
initial trigger invocation is restored upon completion of the execution of the trigger.

Because table versions are resolved using the default version name, undesirable side
effects may occur if the data modification command references a specific table
version or the trigger contains explicit table version references.

7830 8160–027 4–9


Version Names

For example, consider the following trigger definition:

CREATE TRIGGER archive_t1 AFTER DELETE ON t1


REFERENCING OLD ROW AS old
FOR EACH ROW
BEGIN
DECLARE oldkey CHAR(20);
DECLARE oldcol1 INTEGER;
DECLARE oldcol2 INTEGER;
DECLARE oldcol3 INTEGER;
DECLARE oldcol4 INTEGER;
SET oldkey = old.key;
SET oldcol1 = old.col1;
SET oldcol2 = old.col2;
SET oldcol3 = old.col3;
SET oldcol4 = old.col4;
INSERT INTO t1:archive (key, col1, col2, col3, col4)
VALUES (oldkey, oldcol1, oldcol2, oldcol3, oldcol4);
END;

The intent of this trigger is to preserve a copy of t1 record occurrences in an archive


whenever one is deleted from the production version. At the time the trigger is
activated, if the default version is ‘production’, as the row is deleted from
t1:production, an identical row is inserted into t1:archive. Assume that this is the
desired result.

If a user has issued a USE DEFAULT VERSION ARCHIVE command, however, a row is
deleted from t1:archive and immediately reinserted into t1:archive. This is not the
desired result. Similarly, when explicit versions are used, if the DELETE command
contains a version (for example, DELETE FROM t1:production WHERE …), the desired
result is achieved. If the DELETE command contains an explicit version reference to
‘archive’ (or any table version of t1 other than ‘production’), however, the desired
result is not achieved.

The built-in-function active_version is provided to resolve the problems discussed


above. For more information about the active_version function, see 3.3.1.

4–10 7830 8160–027


Creating, Executing, and Dropping Routines

4.4. Creating, Executing, and Dropping Routines


To create a routine, you give it a unique name, and then write the sequence of SQL
and other control statements you want to include.

Example

PROCEDURE house_schema.update_house_price( )
BEGIN
UPDATE houses SET price=20000 WHERE price < 20000;
END;

For details on creating procedures, see 8.8 (FUNCTION statement) and 9.6
(PROCEDURE statement).

To execute a routine from a host application, you use the CALL statement:

CALL house_schema.update_house_price( );

For details on executing routines, see 6.5 (CALL statement) and 9.11 (SET statement).

To drop a routine, you use the DROP PROCEDURE/FUNCTION statement:

DROP PROCEDURE house_schema.update_house_price RESTRICT;

For details on dropping routines, see 7.8.

7830 8160–027 4–11


Creating, Executing, and Dropping Triggers

4.5. Creating, Executing, and Dropping Triggers


Because triggers are such a powerful database tool, users should exercise care in
their deployment. One point to consider is that commands such as ALTER TABLE,
CREATE INDEX, DROP INDEX, CREATE TRIGGER, DROP TRIGGER, and in some cases
REVOKE, are possible only if the object table is not being referenced by another user.
Once any user executes a trigger, then every table referenced by that trigger (not just
the target table) is considered to be referenced. Any definitional commands against
any such table must wait for an END THREAD command from all referencing users.

To create a trigger

• Give the trigger a unique name.


• Determine the table with which the trigger is associated.
• Determine the timing of the trigger activation.
• Determine the event that will activate the trigger.
• Specify the SQL and control statements that are to be executed.

Example

CREATE TRIGGER replicate_data


AFTER INSERT ON t1
REFERENCING NEW ROW as new
FOR EACH ROW
BEGIN
DECLARE newkey CHAR(20);
DECLARE newcol1 INTEGER;
DECLARE newcol2 INTEGER;
DECLARE newcol3 INTEGER;
DECLARE newcol4 INTEGER;
SET newkey = new.key;
SET newcol1 = new.col1;
SET newcol2 = new.col2;
SET newcol3 = new.col3;
SET newcol4 = new.col4;
INSERT INTO t1_shadow (key, col1, col2, col3, col4)
VALUES (newkey, newcol1, newcol2, newcol3, newcol4);
END;

For details on creating triggers, see 7.1 (CREATE TRIGGER).

4–12 7830 8160–027


Creating, Executing, and Dropping Triggers

4.5.1. How Triggers Are Invoked


Triggers, unlike RDMS routines, are not invoked explicitly by the user. Triggers are
invoked by RDMS when the triggering conditions are met. The exceptions to this rule
are that triggers are not executed when mechanisms other than RDMS are used to
modify database files and when the RDMUTL LOAD command is executed. The
triggering criterion is always a DELETE, INSERT, or UPDATE statement.

The user that causes a trigger to be invoked does not need to have the privileges
necessary to perform the actions that a trigger requires. The user who created the
trigger is responsible for the actions of the trigger, regardless of who invokes it.

4.5.2. Types of Triggers


RDMS recognizes 12 types of triggers. The trigger types are formed from
combinations of the following:

• One of the triggering command types DELETE, INSERT, or UPDATE


• Either BEFORE or AFTER
• Either STATEMENT or ROW

For example

BEFORE DELETE STATEMENT

AFTER INSERT ROW

4.5.3. Order of Execution


If both STATEMENT and ROW triggers are created for the same data modification
statement (DELETE, INSERT, or UPDATE) on the same target table, the order of
execution is as described in the following.

The DELETE statement has the following process steps:

1. From the subject table, candidate rows are read and the old transition table is
created.
2. For each row in the old transition table, every ROW level BEFORE trigger is
executed once. After all ROW level BEFORE triggers are executed, every
STATEMENT level BEFORE trigger is executed once.
3. The database modification is performed.
4. The constraints are verified.
5. AFTER triggers are executed. For each row in the old transition table, every ROW
level AFTER trigger is executed once. After all ROW level AFTER triggers are
executed, every STATEMENT level AFTER trigger is executed once.

7830 8160–027 4–13


Creating, Executing, and Dropping Triggers

The INSERT statement has the following process steps:

1. For the subject table, the new transition table is created.


2. BEFORE triggers are executed. For each row in the new transition table, every
ROW level BEFORE trigger is executed once. ROW level BEFORE triggers can
modify the new row (which resides in the new transition table), by assigning new
value(s) to the item(s) in NEW ROW. After all ROW level BEFORE triggers are
executed, every STATEMENT level BEFORE trigger is executed once.
3. The database modification is performed.
4. The constraints are verified.
5. AFTER triggers are executed. For each row in the new transition table, every ROW
level AFTER trigger is executed once. After all ROW level AFTER triggers are
executed, every STATEMENT level AFTER trigger is executed once.

The UPDATE statement has the following process steps:

1. From the subject table, candidate rows are read and the old transition table is
created.
2. For each candidate row, a new row is created. The set of new rows is the new
transition table.
3. BEFORE triggers are executed. For each correspondence of an old row and its
new row, every ROW level BEFORE trigger is executed once. ROW level BEFORE
triggers can modify the new row (which resides in the new transition table), by
assigning new value(s) to the item(s) in NEW ROW. After all ROW level BEFORE
triggers are executed, every STATEMENT level BEFORE trigger is executed once.
4. The database modification is performed.
5. The constraints are verified.
6. AFTER triggers are executed. For each correspondence of an old row and its new
row, every ROW level AFTER trigger is executed once. After all ROW level AFTER
triggers are executed, every STATEMENT level AFTER trigger is executed once.

One or more of each type of trigger may be associated with a table. If more than one
trigger of a specific type is associated with a table, then the execution order of those
triggers is based on the timestamp of the definition of the triggers. The order of
execution is from the earliest definition timestamp to the latest. For two or more
triggers of the same type for a given table, which have the same definition timestamp,
the order of execution is unspecified.

Although there is a prescribed order to the execution of triggers of the same type for
a given table, care should be taken in creating such triggers. If a trigger is dropped and
re-created its definition timestamp will change, thus affecting its execution order. If
the order of execution of the triggers is important, then each of the triggers would
have to be dropped and re-created in the desired order. Alternatively, the triggers
could be combined, where possible, into one trigger to ensure the desired effect.

4–14 7830 8160–027


Creating, Executing, and Dropping Triggers

The SQL-procedure-statement(s) within an AFTER trigger can include DELETE, INSERT,


and UPDATE statements. This means that a trigger can cause other triggers to be
executed. Such triggers are referred to as cascading triggers. If the
SQL-procedure-statement(s) within an AFTER trigger cause that same trigger to be
executed again, the trigger is referred to as a recursive trigger.

RDMS limits the combined nesting depth of any combination of routine and trigger
invocations to 98 levels of nesting and terminates processing if that nesting depth
limit is exceeded.

Assuming that no errors occur, RDMS processes each statement in the trigger body
according to the rules of execution for an RDMS routine. If one of those statements
causes another trigger to be invoked, then each statement in that new trigger is
executed according to the same rules. Each nested trigger that is activated is
completely processed before control is returned to the trigger at the next higher
nesting level. This process continues until each statement in each of the triggers in a
string of cascading and/or recursive triggers is executed.

4.5.4. Dropping Triggers


To drop a trigger, use the SQL DROP TRIGGER statement. For example

DROP TRIGGER replicate_data;

For details on dropping triggers, see 7.10.

7830 8160–027 4–15


Parameters

4.6. Parameters
Routines can accept parameters to improve their usefulness and flexibility.

Note: Parameters cannot be used with triggers.

Examples

PROCEDURE house_schema.select_houses
(IN max_price NUMERIC, OUT how_many NUMERIC)
BEGIN
SELECT COUNT(*) INTO how_many FROM houses
WHERE price < max_price;
END;

To execute a routine from a host application, you use the CALL statement and pass
host variables as parameters:

CALL house_schema.select_houses($p1, $p2);

$P1 and $P2 are placeholder variables for the parameters.

If you want to pass a null value as an input or output parameter, you must use an
indicator variable just as you do when you pass a null value for a host program variable
(see 2.10.4). RDMS returns an error if a null is passed without an indicator variable.

With $P3 and $P4 as indicator variables for the parameters, the preceding example is
written as follows:

CALL house_schema.select_houses($p1 $p3, $p2 $p4);

To execute a routine from a routine or trigger, use the CALL statement and pass SQL
variables, parameters from the invoking routine, literals, arithmetic expressions,
datetime expressions, datetime system functions, or the NULL keyword as
parameters. (See 8.8 for more information on parameter values and nested
procedures.)

CALL house_schema.select_houses(local_sql_var1, local_sql_var2);

Note: When you assign a value to an OUT or INOUT parameter using the SET
statement (9.11), the FETCH statement (8.6), or the SELECT Single Row statement
(9.10), the data types (including precision and length, if applicable) of the source and
target must be compatible. If they are not compatible, exceptions, truncations,
conversions, and so forth are raised in a manner consistent with normal RDMS
handling of value assignments to columns. For further information on data type
compatibility of numeric, datetime, and character data, see the following:
• 2.7.1 (character data types)
• 2.7.2 (numeric data types)
• 2.7.3 (datetime data types)
For details on procedures, see 9.6 (PROCEDURE); for details on the CALL statement,
see 6.5.

4–16 7830 8160–027


Dynamic Result Sets

4.7. Dynamic Result Sets


Dynamic result sets are a way to return multiple rows of data from a stored
procedure. They can greatly enhance the usefulness of stored procedures.

A result set is like a cursor that is left open at the end of a stored procedure
execution. Normally such cursors are closed during the cleanup phase of stored
procedure processing. By declaring cursors WITH RETURN, you can access these
cursors after the stored procedure has concluded.

4.7.1. Requirements
This feature is not available for all types of cursors. You are only allowed to specify
WITH RETURN for cursors that also have the attributes FOR READ ONLY and FOR
RETENTION (or WITH HOLD, which is synonymous with FOR RETENTION).

These requirements also apply:

• The cursor must be declared in the outermost block of the stored procedure.
• The cursor must have been opened during the stored procedure.
• The cursor must be left open when the procedure concludes.
• You must inform RDMS that you want to receive the result sets before you call a
stored procedure. You use the statement SET RESULT SETS ON for this purpose;
you only need to issue this statement once per thread.
• The stored procedure must be defined with the DYNAMIC RESULT SETS clause.

4.7.2. Result Set Cursors


Because a stored procedure may return multiple cursors, the order of which may not
be predictable, RDMS creates and opens a cursor on a temporary table that contains
records that describe each of the returning cursors. This cursor is called a result set
cursor. The result set cursor and the returning cursors are available until closed
explicitly, implicitly by an END THREAD, or when the same stored procedure is
executed again.

Because you may want to process result sets from different procedures at the same
time, RDMS generates a unique result set cursor name for each stored procedure
execution that returns result sets. The result set cursor name can generally be
anticipated, as can the names of the return cursors. The result set cursor name
consists of the characters “RS” followed by the number of procedure executions that
have returned result sets since the start of the thread. For the first procedure invoked,
the result set cursor name is RS1.

The individual return cursor names take the result set cursor name as a prefix; they
append an underscore and the original cursor name from the procedure definition (for
example, RS1_C1). If the original cursor name is lengthy and cannot support the prefix
without exceeding the 30-character maximum, it is replaced with the line number
within the procedure at which it was declared (for example, RS1_7).

7830 8160–027 4–17


Dynamic Result Sets

4.7.3. Result Set Information


RDMS returns information about result sets in a temporary table for which RDMS
creates a cursor. Use the GET RESULT CURSOR NAME statement to obtain the name
that RDMS generated for the cursor. The GET RESULT CURSOR NAME statement
must immediately follow the procedure call.

The temporary table contains the following columns.

Column Name Type Description

1 line_number INTEGER The line_number identifies the line


in the stored procedure at which
the return cursor or database
update statement occurred.
2 update_count INTEGER When SET RESULT SET UPDATE
COUNT is ON, the update_count
tells how many rows were
updated by the SQL statement on
the indicated line.
When SET RESULT SET UPDATE
COUNT is OFF, or when the
statement is a cursor declaration,
update_count is set to –1.
See 9.13 for more information on
the SET RESULT SET UPDATE
COUNT statement.
3 return_cursor_name CHARACTER(30) This is the name that RDMS
generated for the dynamic result
set cursor. If the statement on the
indicated line is a database update
statement rather than a cursor
declaration, the
return_cursor_name is NULL.
4 routine_schema_name CHARACTER(30) This is the schema name of the
invoked stored procedure.
5 routine_name CHARACTER(30) This is the name of the invoked
stored procedure.

4–18 7830 8160–027


Dynamic Result Sets

4.7.4. Example
This example uses the following procedure. Clauses in bold type are the required
result set syntax. The procedure either returns a result set of two cursors (r1 and r2),
or just one (r2), depending on the value of the input parameter how_many.

PROCEDURE s.returns_1_or_2
(IN how_many INTEGER)
DYNAMIC RESULT SETS 2
BEGIN
DECLARE r1 CURSOR WITH HOLD WITH RETURN FOR SELECT * FROM farmer.seed
ORDER BY price FOR READ ONLY;
DECLARE r2 CURSOR WITH HOLD WITH RETURN FOR SELECT *
FROM rdms.seed FOR READ ONLY;
OPEN r2; r1 was declared first, so it will be the first result set
(if it is still open when the procedure ends), regardless
of order opened.
OPEN r1;
IF how_many < 2
THEN CLOSE r1;
END IF;
END;

You set up to call the procedure as follows:

SET RESULT SET ON;

RDMS returns OK. When RESULT SET CURSOR is OFF, RDMS drops the cursors
created by the stored procedure when the stored procedure completes
execution.

CALL S.RETURNS_1_OR_2(2);

RDMS returns SQLSTATE 0100C and error status 6022 (both statuses indicate
dynamic result sets returned).
AUXINFO = 2, indicating that two result set cursors were returned.

GET RESULTS CURSOR NAME INTO $P1;

RDMS returns a cursor name in $P1 (for this example, assume that RDMS returned
RS1 as the cursor name).
AUXINFO = 2, indicating that the results cursor has two records.

7830 8160–027 4–19


Dynamic Result Sets

The results cursor RS1 has the following values.

line_ update_ return_cursor_ schema_


number count name name routine_name

5 -1 RS1_R1 S RETURNS_1_OR_2
7 -1 RS1_R2 S RETURNS_1_OR_2
FETCH NEXT RS1 INTO ...;

This statement returns RS1_R1.


Now you can obtain the description of the first result set cursor.

cname = 'RS1_R1';

GET DESCRIPTION FOR CURSOR $P1 INTO ...

Use cname to correspond to $P1.


Then fetch from the first result set.

REPEAT UNTIL no-find DO

FETCH NEXT $P1 INTO ...

DROP CURSOR RS1_R1;

This frees resources. The DROP statement is optional.

FETCH NEXT RS1 INTO ...;

This returns ‘RS1_R2‘ as the result set cursor name.


Now get the description of the second result set cursor.

cname = 'RS1_R2';

GET DESCRIPTION FOR CURSOR $P1 INTO ...

Use cname to correspond to $P1.


Then fetch from the second result set.

REPEAT UNTIL no_find DO

FETCH NEXT cname INTO ...

DROP CURSOR RS1;

The results cursor is dropped.


This implicitly drops RS1_R2, because it has not been explicitly dropped.

4–20 7830 8160–027


Stored Functions

4.8. Stored Functions


Stored functions are routines that pass a value back to the caller directly by use of the
RETURN statement.

Examples
FUNCTION house_schema.select_houses2(IN max_price NUMERIC) RETURNS
NUMERIC
BEGIN
DECLARE how_many NUMERIC;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

To execute a stored function from a host application, you use the nonstandard SET
statement to indicate a variable to use for the return value and pass host variables as
parameters:

SET $p2 = house_schema.select_houses2($p1);

If the function result can be a null value, the executing statement must be as follows:

SET $p2 $p3 = house_schema.select_houses2($p1);

where $P3 is the indicator variable for the function result.

To execute a stored function from a routine or trigger, you use the SET statement to
indicate an SQL variable or an INOUT or OUT parameter of the invoking routine to use
for the return value and to pass SQL variables, parameters from the invoking routine,
literals, arithmetic expressions, datetime expressions, datetime system functions, or
the NULL keyword as parameters. (See 8.8 for more information on parameter values
and nested function invocations.)

SET local_sql_var1 = house_schema.select_houses(local_sql_var2);

For details on functions, see 8.8 (FUNCTION); for details on the nonstandard SET
statement, see 9.11.

7830 8160–027 4–21


System Variables

4.9. System Variables


Two system variables, RDMSAUXINFO and SQLSTATE, are provided for use in the
body of a routine or trigger.

4.9.1. RDMSAUXINFO
The system variable RDMSAUXINFO provides auxiliary information for use in routines
and triggers. RDMSAUXINFO is an RDMS keyword.

Table 4–1 shows the value that RDMSAUXINFO contains upon successful completion
of execution of the following statements.

Table 4–1. RDMSAUXINFO Values

Statement … RDMSAUXINFO contains:

DELETE The number of deleted rows, or zero if no rows were deleted.


INSERT The number of inserted rows, or zero if no rows were
inserted.
LOCATE 0 The specified row exists.
1 The specified row does not exist.
UPDATE Positioned The number of updated rows, or zero if no rows were
updated.
UPDATE Searched The number of updated rows, or zero if no rows were
updated.

RDMSAUXINFO is not updated for any other statements.

The value of RDMSAUXINFO is zero when a routine is invoked. The value of


RDMSAUXINFO is updated upon completion of the execution of any of the statements
specified in the RDMSAUXINFO Values table. RDMSAUXINFO retains the value of its
latest update until the completion of the execution of another statement for which
RDMSAUXINFO is maintained.

The use of RDMSAUXINFO is restricted to being the source of a SET statement, a


RETURN value for a stored function, or part of a Boolean expression in an IF
statement, ELSEIF clause, or WHILE statement in the body of a routine or trigger
definition. For example, the following statements are allowed:

IF RDMSAUXINFO = 0

SET declared_var1 = RDMSAUXINFO;

or if used in a function:

RETURN RDMSAUXINFO;

4–22 7830 8160–027


System Variables

The following statements are not allowed, however:

SELECT col1 INTO RDMSAUXINFO FROM table1 WHERE key_col = value;

SET RDMSAUXINFO = 2;

INSERT INTO table1 VALUES (RDMSAUXINFO);

RDMSAUXINFO is defined as an INTEGER. When it is used as the source of a SET


statement, the target SQL variable or parameter must have a compatible type. When it
is used as a RETURN value for a stored function, the stored function must be defined
with a RETURN clause that includes a compatible type attribute. When it is used in a
conditional statement, it must be compared with an integer constant or an SQL
variable or parameter declared with a compatible type.

Example
The following example creates a procedure that increases the price of houses with a
specified value (cost) by a specified amount (increment) and returns the number of
houses affected (no_units).

PROCEDURE price_increase (IN cost INTEGER, IN increment INTEGER, OUT


no_units INTEGER)
BEGIN
UPDATE houses SET price = price + increment WHERE price = cost;
SET no_units = RDMSAUXINFO;
END;

4.9.2. SQLSTATE
The system variable SQLSTATE provides the SQLSTATE status information (see B.5)
for use in routines and triggers. The status information available is as follows:

Status Description
00000 Successful completion
01XXX Warning
02000 No data

All other status values cause an immediate termination of the routine or trigger
invocation.

7830 8160–027 4–23


System Variables

The statements for which SQLSTATE status information is updated are as follows:

CALL
CLOSE CURSOR
DELETE Positioned
DELETE Searched
FETCH
INSERT
LOCATE
OPEN CURSOR
SELECT
SET (referred to as ASSIGNMENT in the SQL 99 standard), if the source of the set
statement is a stored function
UPDATE Positioned
UPDATE Searched

The value of SQLSTATE is ‘00000’ when a routine is invoked. The value of SQLSTATE
is updated

• Upon completion of the execution of a statement which accesses the database


• Upon completion of a statement which invokes a nested routine

The use of SQLSTATE is restricted to being the source of a SET statement, a RETURN
value for a stored function, or part of a Boolean expression in an IF statement, ELSEIF
clause, or WHILE statement in the body of a routine definition. For example, the
following statements are allowed:

IF SQLSTATE = ’02000’

SET declared_var1 = SQLSTATE;

or (if used in a function)

RETURN SQLSTATE;

The following statements are not allowed, however:

SELECT col1 INTO SQLSTATE FROM table1 WHERE key_col = value;

SET SQLSTATE = ’00000’;

INSERT INTO table1 VALUES (SQLSTATE);

4–24 7830 8160–027


System Variables

SQLSTATE is defined as CHARACTER(5), a 2-character class value followed by a


3-character (subclass) value. When it is used as the source of a SET statement, the
target SQL variable or parameter must have a type of CHARACTER(5 (or greater)).
When it is used as a RETURN value for a stored function, the FUNCTION must be
defined with a RETURNS CHARACTER(5 (or greater)) attribute. When it is used in a
conditional statement, it must be compared with a literal or an SQL variable or
parameter declared with a type of CHARACTER.

Example
The following example creates a function which deletes a specified house
(house_code) if it exists in the database. The function returns a value of either
DELETED or NOT FOUND.

FUNCTION obsolete_listing (IN house_code INTEGER) RETURNS CHARACTER(10)


BEGIN
DECLARE result CHARACTER(10) DEFAULT ’DELETED’;
DECLARE code INTEGER;
SELECT hno INTO code FROM houses WHERE hno = house_code;
IF SQLSTATE = ’00000’
THEN DELETE FROM houses WHERE hno = house_code;
ELSE SET result = ’NOT FOUND’;
END IF;
RETURN result;
END;

7830 8160–027 4–25


Error Checking

4.10. Error Checking


A CALL statement invokes a routine and is an element of the SQL language. A
program that calls a routine can therefore use familiar coding practices to check for
errors, warnings, or messages after a routine is called.
RDMS deals with SQLSTATE, SQLCODE, the WHENEVER statement, the AUX-INFO
variable, and the ERROR-STATUS variable (depending on the SQL interface used) in its
usual manner.
If an error occurs in an SQL routine, the function result (if there is one) and any INOUT
and OUT parameters are not updated.

4–26 7830 8160–027


Transactions, Commits, and Rollbacks

4.11. Transactions, Commits, and Rollbacks


Routines and triggers execute in the context of the issuing transaction and are
committed or rolled back as a part of the thread. Routines and triggers do not support
transaction control statements such as BEGIN THREAD, COMMIT, ROLLBACK, or
OMIT THREAD. Application programs invoking routines and triggers are responsible
for issues, such as Two-Phase Commit, that coordinate updates to multiple databases
within the same transaction.

Errors that occur in the execution of a routine or trigger and cause an immediate
return also cause a rollback. If an error does occur sometime during trigger execution,
the name of the trigger (or each active trigger in the case of cascading triggers) are
incorporated into the issued error messages.

Example
In the following segment of code, all the INSERT statements are rolled back even
though the actual failure does not occur until the third INSERT statement (because it is
identical to the second INSERT statement):
.
.
.
PROCEDURE house_schema.insert_errors( )
BEGIN
INSERT INTO houses VALUES('IE01','Wes',99000,'Dp');
INSERT INTO houses VALUES('IE02','Wes',99000,'Dp');
INSERT INTO houses VALUES('IE02','Wes',99000,'Dp');
INSERT INTO houses VALUES('IE03','Wes',99000,'Dp');
END;
.
.
.

7830 8160–027 4–27


Statements and Keywords

4.12. Statements and Keywords


The body of a routine or trigger consists of the following types of statements:

• Standard SQL statements and keywords used exclusively by routines and triggers
(see Table 4–2). Note that RDMSAUXINFO is a nonstandard RDMS extension.
• A subset of standard SQL statements and RDMS extended syntax (see Table 4–3).
Note that the following are nonstandard RDMS extensions:
− DECLARE cursor-name CURSOR [ FOR ] query-expression (optional FOR)
− DECLARE cursor-name CURSOR FOR RANDOM ACCESS...
− DECLARE cursor-name CURSOR FOR DIRECT ACCESS...
− FETCH CURRENT
− LOCATE

Table 4–2 lists and describes statements and keywords that are used only in routines
and triggers.

Table 4–2. Statements and Keywords Used Exclusively by


Routines and Triggers

Statement Description See

RDMSAUXINFO System variable that returns the auxiliary 4.9.1


status information.
SQLSTATE System variable that returns the SQLSTATE 4.9.2
status.
BEGIN ... END Keywords that define the start and end of 4.12.1
compound statements within a routine or
trigger.
DECLARE Defines a variable to be used within a 4.12.4
compound statement.
IF ... END IF The IF statement uses these keywords to 4.12.5
define the start and end of branching within a
routine or trigger.
RETURN Returns the value to which a stored function 4.12.6
has been evaluated.
SET Assigns a value to a parameter or variable 4.12.7
within routine.

4–28 7830 8160–027


Statements and Keywords

Table 4–2. Statements and Keywords Used Exclusively by


Routines and Triggers

Statement Description See

SIGNAL Signal an exception condition from within a 4.12.8


routine or trigger and issue a user-specified
error message or issue a message from
within a routine or trigger and continue
execution.
WHILE ... END WHILE The WHILE statement uses these keywords 4.12.9
to define the start and end of looping within a
routine or trigger.

Table 4–3 lists and describes the subset of standard SQL statements available for
RDMS routines and triggers, as well as RDMS extensions.

Table 4–3. Subset of Standard SQL Statements and RDMS Extended


Syntax for Routines and Triggers

Statement Description See

CALL Invokes a stored procedure. 6.5


CLOSE CURSOR Releases an open cursor. 6.6
DECLARE CURSOR Defines a data set for later retrieval from the 7.4
database.
DELETE Deletes one or more rows from a table, or the 7.5
current row in the cursor.
FETCH Retrieves one row from a cursor. 8.6
FETCH CURRENT Retrieves the current row in the cursor. 8.6
INSERT Adds one or more rows to the table. 8.14
LOCATE Positions the pointer in a cursor. No data is 9.2
retrieved.
OPEN CURSOR Activates a cursor. 9.4
SELECT Single Row Fetches a row from the database. If more than 9.10
one row satisfies the query specification, the
SELECT statement returns an error.
SET Invokes a stored function. 9.11
UPDATE Positioned Changes the content of columns in the current 10.4
row of a cursor.
UPDATE Searched Changes the values of data items in a subset of 10.5
the existing rows in a table.

7830 8160–027 4–29


Statements and Keywords

4.12.1. Compound Statements: BEGIN . . . END


The BEGIN and END statements mark the starting and ending points of a list of
statements and keywords.

Typically, compound statements appear in two instances within a routine or trigger:

• Immediately following the FUNCTION, PROCEDURE, or CREATE TRIGGER


statement, so that more than one of the allowed statements from either Table 4–2
or Table 4–3 can be used
• If a group of statements requires additional, locally defined variables or cursors

Format

BEGIN

[declare-statement-list]

[declare-cursor-list]

compound-statement-list

END

where:

declare-statement-list
is one or more variable declaration statements (see 4.12.4). All variable
declarations must occur before any executable statement in the compound
statement. Variable declarations are optional. Any variables declared within a
compound statement can only be referenced within the compound statement.
They are local to the compound statement and are not visible to statements
outside the compound statement.

declare-cursor-list
is one or more cursor declaration statements (see 7.4). All cursor declarations
must occur after all variable declarations and before any executable statement in a
compound statement. Cursor declarations are optional. No two cursor names may
be the same within the same BEGIN statement. Any cursors declared within a
compound statement are local to that compound statement and are not visible to
statements outside the compound statement or outside of the routine. Note that
statements in an inner compound statement can reference cursors in an outer
compound statement. See 4.12.2 for a discussion of cursor name referencing
rules. Statements in an outer compound statement cannot reference cursors in an
inner compound statement. When execution control processes the END
statement of a compound statement, all cursor declarations within that compound
statement are automatically dropped. There is a limit of 16 cursor declarations
within a routine or trigger.

compound-statement-list
is one or more standard SQL statements (see 4.12). These statements must follow
all declaration statements.

4–30 7830 8160–027


Statements and Keywords

Example 1
The following example creates a stored function with more than one statement. The
list of statements must therefore be part of a compound statement.

FUNCTION house_schema.select_houses3(IN salary NUMERIC) RETURNS NUMERIC


BEGIN
DECLARE how_many NUMERIC;
DECLARE max_price NUMERIC DEFAULT 50000;
IF salary > 20000 THEN
SET max_price = 2 * salary;
END IF;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

Note the use of semicolons ( ; ). No semicolon follows BEGIN, but a semicolon


follows END.

Example 2
The following example illustrates compound statements nested in a stored procedure:

PROCEDURE house_schema.select_houses4()
BEGIN
DECLARE a INTEGER;
DECLARE b INTEGER;
DECLARE c INTEGER;
.
.
.
BEGIN
DECLARE m NUMERIC;
SET m = a;
END;
BEGIN
DECLARE x NUMERIC;
SET x = b;
END;
END;

Note: Variables in an inner compound statement can reference variables in an


outer compound statement. Variables in an outer compound statement, however,
cannot reference variables in an inner compound statement.

7830 8160–027 4–31


Statements and Keywords

Example 3
The following example shows how a cursor and cursor manipulation statements might
be used in a routine or trigger.

Note: The records are sorted by the account_id, sequence_num, scheduled_date,


and scheduled_time.

This procedure searches scheduled deposit/withdrawal transaction records that need


to be processed by the specified date and time for the specified account-id. Check
whether the balance is sufficient to complete the transaction. If it is, then the
scheduled transaction is completed by inserting a history record in the completed
transactions table and updating the status of the schedule record to “completed.”

When the balance in the account is insufficient, the record status is marked
“insufficient balance” and the next record is processed. The insufficient balance
records are handled separately.

The resulting balance is returned after all the scheduled transactions are processed.

Note: Any SQL error, other than a no-find condition, is expected to automatically
terminate the execution of this procedure.

PROCEDURE Banking_System.Process_Scheduled_Transactions
( IN p_account_id INTEGER,
IN p_transaction_date DATE,
IN p_transaction_time TIME(6),
INOUT p_result_balance NUMERIC(15,2),
OUT p_return_status CHARACTER(30)
)

BEGIN
DECLARE v_sequence_number INTEGER DEFAULT 0;
DECLARE v_amount NUMERIC(15,2);
DECLARE v_record_status CHARACTER(30);
DECLARE v_record_comment CHARACTER(80);
DECLARE c1 CURSOR
FOR SELECT amount, record_status, record_comment
FROM scheduled_transactions
WHERE account_id = p_account_id
AND scheduled_date <= p_transaction_date
AND scheduled_time <= p_transaction_time
AND record_status = ’scheduled’
FOR UPDATE OF record_status;

IF p_account_id >= 0 AND


p_transaction_date >= TIMESTAMP’1964-01-01’ AND
p_transaction_time IS NOT NULL
THEN
SET p_return_status = ’OK’;
OPEN c1;
FETCH NEXT FROM c1

4–32 7830 8160–027


Statements and Keywords

INTO v_amount, v_record_status, v_record_comment;


WHILE SQLSTATE = ’00000’
DO
IF p_result_balance + v_amount >= 0
THEN
SET p_result_balance = p_result_balance + v_amount;
SET v_sequence_number = v_sequence_number + 1;
INSERT INTO completed_transactions
VALUES (p_account_id, p_transaction_date,
p_transaction_time, v_sequence_number,
v_amount, p_result_balance, v_record_comment);
SET v_record_status = ’completed’;
ELSE
SET v_record_status = ’insufficient balance’;
SET p_return_status = ’insufficient balance’;
END IF;
UPDATE scheduled_transactions
SET record_status = v_record_status
WHERE CURRENT OF c1;
FETCH NEXT FROM c1
INTO v_amount, v_record_status, v_record_comment;
END WHILE;
CLOSE c1;
ELSE
SET p_return_status = ’parameter error’;
END IF;
END;

4.12.2. Resolving Cursor and Variable References


During routine or trigger compilation, cursor and variable specification is resolved to
the cursor or variable with the innermost scope. Thus, a cursor defined in an inner
compound statement takes precedence over a like-named cursor defined in an outer
compound statement. Similarly, an SQL variable defined in an inner compound
statement takes precedence over a like-named SQL variable defined in an outer
compound statement or a like-named parameter.

In some SQL statements in a routine or trigger (for example, in the UPDATE Searched
change-specification-list; see 10.5), the value-specification (see 10.3) can specify a
column name in a table, a parameter, or an SQL variable. In this case, the SQL
statement (for example, UPDATE) is deemed to have the innermost scope; the scope
of the table name in the table specification is the entire SQL statement. Thus, a
column reference takes precedence over a reference to an SQL parameter or SQL
variable.

7830 8160–027 4–33


Statements and Keywords

Example 1
(Also see the notes that follow the example.)

PROCEDURE house_schema.ref (OUT a INTEGER)


BEGIN
DECLARE b INTEGER;
.
.
.
SET a=b; (Note 1)
.
.
.
BEGIN
DECLARE price NUMERIC;
DECLARE a INTEGER;
DECLARE b INTEGER;
.
.
.
SET a=b; (Note 2)
.
.
.
INSERT INTO houses
VALUES('H299','Roseville',price,'3-bedroom house'); (Note 3)
.
.
.

UPDATE houses
SET price=price-1000 (Note 4)
WHERE hno='H299';
.
.
.
END;
.
.
.
END;

4–34 7830 8160–027


Statements and Keywords

Notes on Example 1:
1. The SET statement resolves a to the SQL parameter a, and b to the SQL
variable b, defined in the same compound statement, without ambiguity.
2. The SET statement resolves a and b to the SQL variables a and b defined in the
same compound statement. The SQL parameter a and the SQL variable b
defined at the outer level are not visible at this nesting level.
3. The INSERT statement does not allow column references in the value list;
therefore, it resolves to the SQL variable price without ambiguity.
4. The UPDATE statement does allow column references in the change
specification list, and table references are considered first. Therefore, it
resolves to the column named PRICE in table HOUSES.

7830 8160–027 4–35


Statements and Keywords

Example 2
(Also see the notes that follow the example.)

PROCEDURE house_schema.cur_ref (OUT a integer) (Note 1)


BEGIN (Level 1)
DECLARE sqlvar1a INT;
DECLARE curs1a CURSOR FOR...;
DECLARE curs1b CURSOR FOR ...;
.
.
.
OPEN curs1a; (Note 2)
FETCH curs1a INTO ...;
.
.
.
BEGIN (Level 2)
DECLARE sqlvar2a INT;
DECLARE curs1a CURSOR FOR ...;
DECLARE curs2a CURSOR FOR ...;
.
.
.
OPEN curs1a; (Note 3)
.
.
.
BEGIN (Level 3)
FETCH curs1a INTO ...; (Note 4)
OPEN curs2a;
FETCH curs2a INTO ...;
OPEN curs1b;
FETCH curs1b INTO ...;
END; (Level 3)
.
.
.
END; (Level 2) (Note 5)
.
.
.
FETCH curs1a INTO ...; (Note 6)
.
.
.
END; (Level 1) (Note 7)

4–36 7830 8160–027


Statements and Keywords

Notes on Example 2:
1. Any cursors declared in the thread that invokes this routine are not visible
within the routine.
2. The OPEN statement opens the cursor declared at Level 1, which is declared in
the same compound statement in which the OPEN appears.
3. The OPEN statement opens the cursor declared at Level 2. Although there is a
curs1a cursor declared in Level 1, the curs1a cursor declared in Level 2 takes
precedence, because it is in the same compound statement as the OPEN.
4. The FETCH is from the curs1a cursor declared and opened at Level 2, because
there is no curs1a cursor declared in the same compound statement as the
FETCH, and the Level 2 curs1a cursor is at the next outer level of nesting.
5. The END of the BEGIN block at Level 2 causes the cursors declared at this level
(curs1a and curs2a) to be closed.
6. The FETCH is from the curs1a cursor declared and opened at Level 1, because
that curs1a cursor is declared at the same level in which the FETCH appears.
7. At this point in the execution, all cursors declared within the routine have been
closed and effectively dropped by RDMS. They are not visible to the thread that
invoked this routine

4.12.3. Resolving Table Alias and Correlation Names in Triggers


During trigger compilation a table or item reference in an SQL statement is resolved to
the table or item with innermost scope.

Example

SELECT cola, colb, itema, . . . FROM tbl1, tbl2


WHERE colc = cold AND colx = itemb . . . .

The specification of tbl1 and tbl2 in the FROM clause means that their table names and
all their column names are made available to the name resolution of this statement;
that is, these definitions are of innermost scope. Therefore, any reference within this
statement is resolved to a tbl1 or tbl2 column name first.

If this statement exists in a trigger where (for example) the new table alias is defined
as tbl2, then the definition of the new table must be selected rather than any possible
table default-qualifier.tbl2 that may exist; that is, the new table has innermost scope.

When a table is named in an SQL statement (for example, in the FROM clause of a
SELECT statement), RDMS first attempts to satisfy the reference using any table alias
names. If the relation name matches either the old or new table alias name, then all old
or new table references in that statement are resolved just as if they were references
to a normal base table or view. Unqualified column names may also be resolved to a
column in the old or new table. If the alias table name is specified first in the
statement, its columns take precedence over any other table columns; otherwise, its
precedence depends on the user-specified order in the FROM clause of the specific
referencing statement.

7830 8160–027 4–37


Statements and Keywords

Note that the subject table and its columns can only be referenced explicitly in the
statements of a trigger (that is, where a table specification is permitted in SQL
statements). Also, if an old or new table alias name is identical to the subject table
name (for example, target_table), an unqualified reference to target_table is always
resolved to the old or new table alias.

Within a trigger, for any item reference that is not satisfied by the table columns
defined in the current statement, there is an attempt to resolve the reference to an
SQL variable or to a row correlation name reference.

SQL variables are always considered of a more local scope than a row correlation
name reference which belongs to the outermost level of the trigger. The precedence
of old and new row references depends on the user-specified order of their definition
in the REFERENCING phrase of the CREATE TRIGGER statement.

Example
This example presents an example for resolving names in triggers. This example
trigger operates on the target table HOUSES which has the columns HNO, LOCATION,
PRICE and DESCRIPTION.

(Also see the notes that follow the example.)

CREATE TRIGGER sch1.trigsample


AFTER UPDATE ON sch2.houses
REFERENCING
OLD ROW AS old_house
NEW ROW AS new_house
OLD TABLE AS old_table
NEW TABLE AS new_table
FOR EACH ROW
BEGIN
DECLARE new_house_price INTEGER;
.
.
DECLARE curs1 CURSOR
FOR SELECT hno, price
FROM new_table WHERE location = 'Minnetonka'; (Note 1)
.
.
UPDATE sch2.houses
SET price = price - 10000
WHERE location = new_house.location (Note 2)
.
.
IF old_house.price > new_house.price THEN
INSERT INTO changes
VALUES (hno, price, new_house_price); (Note 3)
.
.
BEGIN
DECLARE description CHAR (20);

4–38 7830 8160–027


Statements and Keywords

DECLARE max_new_price integer;


.
.
IF new_house.description < > old_house.description (Note 4)
THEN
SET description = 'UPDATED'; (Note 5)
.
.

IF location = 'Brainerd' THEN (Note 6)


.
.

SELECT MAX(new_price) INTO max_new_price FROM changes


WHERE EXISTS
(SELECT * FROM customers
WHERE customers.maxprice >= new_price
AND customers.desiredloc = location); (Note 7)
.
.
END;
.
.
END;

Notes on the Example:


1. Table specification new_table is resolved to the new table alias, because the
alias name has innermost scope. Since new_table is defined within this trigger,
all its column names are made available to name resolution. Thus, the
unqualified reference location is resolved to the column of that name within
new_table.
2. The UPDATE statement allows column references in the change specification
list; thus, the unqualified references price and location are resolved to the
sch2.houses table. A specific qualification is needed, for example,
new_house.location, to refer to items in other rows.
3. Assume that table changes has the columns HNO, price, new_price. The INSERT
statement does not allow column references in the value list; therefore,
unqualified references are resolved within the trigger definition. There are no
SQL variables named hno or price, so these unqualified references are resolved
to the columns of the same name within the row old_house.
4. Explicit qualification in a reference resolves to a specifically named item. Since
old_house is defined first in the REFERENCING clause, you always need explicit
qualification to refer to columns within row new_house.
5. The SET statement resolves the unqualified reference description to the SQL
variable defined within this compound statement, because it has innermost
scope.
6. The IF statement resolves the unqualified reference location to the column of
that name within the row old_house.

7830 8160–027 4–39


Statements and Keywords

7. Table customers has the columns CNO, CNAME, MAXPRICE, DESIREDLOC.


This statement resolves the unqualified reference location to the column of that
name within the row old_house.
If neither an old nor a new row correlation name is specified in the
REFERENCING clause, then this reference to location results in an undefined
reference error. Unqualified references are never resolved to old or new table
alias names or to the subject table.

4.12.4. Create Variable: DECLARE


The DECLARE statement creates SQL variables for use within a routine or trigger.
DECLARE statements immediately follow the BEGIN keyword.

Format

DECLARE variable-name data-type

[ DEFAULT { NULL  literal  datetime-function } ] ;

where:

variable-name
is the name for the variable, which can then be used in the body of the routine or
trigger. The name must be a valid name as defined in 2.2.1.

Variable names cannot be RDMS reserved words (see Appendix A).

data-type
is any valid data type as defined in 2.8, except that the BLOB data type is not
permitted.

literal
is a literal string you specify, set by RDMS when the routine or trigger is invoked.

datetime-function
is CURRENT_DATE, CURRENT_TIME, or CURRENT_TIMESTAMP. For details,
see 2.5.7.

The implied data type of the default value must be compatible with the data type of
the variable.

If you omit the DEFAULT clause, the default value is NULL.

Note: When you assign a value to an SQL variable using the SET statement (9.11),
the FETCH statement (8.6), or the SELECT Single Row statement (9.10), the data
types (including precision and length, if applicable) of the source and target must be
compatible. If they are not compatible, exceptions, truncations, conversions, and so
forth are raised in a manner consistent with normal RDMS handling of value
assignments to columns. For further information on data type compatibility of
numeric, datetime, and character data, see 2.8.

4–40 7830 8160–027


Statements and Keywords

Examples

DECLARE how_many NUMERIC;

DECLARE color CHAR(9);

DECLARE default_color CHAR(9) DEFAULT 'mauve';

4.12.5. Execute Conditionally: IF


Statements in an IF statement execute based on the truth or falsity of a condition or
conditions.

Format

IF Boolean-expression THEN statement-list ;

[ ELSEIF Boolean-expression THEN statement-list ]...;

[ ELSE statement-list ] ;

END IF ;

where:

Boolean-expression
can include parameters, SQL variables, literals, RDMSAUXINFO, SQLSTATE, OLD
and NEW ROW correlation-name.column-name references. For more information,
see the following:
• 2.4.2 (Boolean expressions)
• 4.6 (parameters)
• 4.12.4 (variables)
• 4.9.1 (RDMSAUXINFO)
statement-list
is a statement or statements (refer to 4.12.2 and Table 4–3).

The evaluation and execution of an IF statement proceeds as follows:

• RDMS executes the THEN statement list if the Boolean expression evaluates to
TRUE. Otherwise, if the Boolean expression evaluates to FALSE or UNKNOWN,
RDMS continues and evaluates subsequent ELSEIF clauses or executes the ELSE
statement list, if specified.
• If no Boolean expressions evaluate to TRUE and if no ELSE clause is specified,
RDMS continues execution with the statement following the END IF statement.

7830 8160–027 4–41


Statements and Keywords

Example 1
The following example selects houses based on a single criterion—houses located in
Minneapolis. If not enough houses are found, it broadens the search criteria.

PROCEDURE house_schema.minneapolis_houses
(OUT how_many NUMERIC, OUT metro_flag NUMERIC)
BEGIN
SET metro_flag = 0;
SELECT COUNT(*) INTO how_many FROM houses WHERE location =
"MINNEAPOLIS";
IF how_many < 10 THEN
SELECT COUNT(*) INTO how_many FROM houses WHERE location =
"TCMETRO";
SET metro_flag = 1;
END IF;
END;

Example 2
The next example selects houses whose price is lower than a specified threshold.
Note that Boolean expressions can include AND, OR, or NOT operators:

PROCEDURE house_schema.find_houses(OUT flag CHAR(20))


BEGIN
DECLARE how_many NUMERIC;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < 100000;
IF how_many = 0 THEN
SET flag = 'found none';
ELSEIF how_many <= 5 THEN
SET flag = 'found too few';
ELSEIF how_many >= 5 AND how_many <= 20 THEN
SET flag = 'found enough';
ELSE
SET flag = 'found a lot';
END IF;
END;

4–42 7830 8160–027


Statements and Keywords

Example 3
The final example sets a maximum price based on the input salary and then selects
houses based on the maximum price:

FUNCTION house_schema.find_houses_from_salary(IN salary NUMERIC)


RETURNS NUMERIC
BEGIN
DECLARE how_many INTEGER;
DECLARE max_price NUMERIC DEFAULT 50000;
IF salary > 20000 THEN
SET max_price = 2 * salary;
END IF;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

4.12.6. Return Value from Stored Function: RETURN


The RETURN statement sets the value to which a stored function has been evaluated
and terminates execution of the function. After RDMS processes the RETURN
statement, it returns control to the caller.

Note: The RETURN statement must be the last statement executed in a function.
If the function terminates without executing a RETURN statement, RDMS returns an
error.

Format

RETURN { literal │ parameter-name │ variable-name │ expression │ NULL │

RDMSAUXINFO │ SQLSTATE } ;

where:

literal
is a literal string you specify, set by RDMS when the function is invoked.

parameter-name
is the name of a parameter (see 4.6).

variable-name
is the name of an SQL variable (see 4.12.4).

expression
is an arithmetic expression, a datetime arithmetic expression (2.4.7), a datetime
function (2.5.7), an extract function (3.8.19), a cast function (3.8.2), or the result of a
scalar function (Section 3).

7830 8160–027 4–43


Statements and Keywords

The data type of the value on the RETURN statement must be compatible with the
data type on the RETURNS clause of the FUNCTION statement (see 8.8). If they are
not compatible, exceptions, truncations, conversions, and so forth are raised in a
manner consistent with normal RDMS handling of value assignments to columns. For
further information on data type compatibility of numeric, datetime, and character
data, see 2.8.

Example 1
The following example determines the number of houses in a given price range:

FUNCTION house_schema.select_houses(IN max_price NUMERIC) RETURNS


NUMERIC
BEGIN
DECLARE how_many NUMERIC;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

Example 2
The next example illustrates a case where the RETURN statement may not be
executed, depending on the value of MAX_PRICE:

FUNCTION house_schema.select_houses(IN max_price INTEGER) RETURNS


INTEGER
BEGIN
DECLARE how_many INTEGER;
IF max_price > 20000 THEN
SELECT COUNT(*) INTO how_many FROM houses WHERE price <
max_price;
RETURN how_many;
END IF;
END;

RDMS returns an error if MAX_PRICE is less than 20,000, because the RETURN
statement was not executed before the end of the routine.

4.12.7. Assign Data Value to Parameter or Variable: SET


The standard SET statement assigns a data value to a parameter or SQL variable.

Format

SET target = source ;

where:

target
is one of the following:

• An SQL variable
• The name of an OUT or INOUT parameter

4–44 7830 8160–027


Statements and Keywords

• The result of a scalar function (see Section 3)


• A NEW ROW correlation-name.column-name reference, if used in a BEFORE
ROW trigger (see 7.1)

The name must be a valid name as defined in 2.2.1.

source
is one of the following:

• An SQL variable name


• The name of an IN or INOUT parameter
• A literal
• An arithmetic expression
• A datetime arithmetic expression (see 2.4.8)
• A datetime function (see 2.5.7)
• An extract function (see 3.8.19)
• A cast function (see 3.8.2)
• RDMSAUXINFO (see 4.9.1)
• SQLSTATE (see 4.9.2)
• OLD or NEW ROW correlation-name.column-name reference (7.1)
• The NULL keyword

The data types (including precision and length, if applicable) of the source and target
must be compatible; otherwise, exceptions, truncations, conversions, and so forth are
raised in a manner consistent with normal RDMS handling of value assignments to
columns.

Notes:
• Use this standard SET statement in a routine or trigger to assign a value to a
parameter or variable.
• Use the nonstandard SET statement (see 9.11) in a host language program (for
example, COBOL) or in a routine or trigger to invoke a stored function.

Examples
Here are two stand-alone examples:

DECLARE count NUMERIC;


SET count = parameter_1;

DECLARE color CHAR(20);


SET color = 'green';

7830 8160–027 4–45


Statements and Keywords

The following example sets a maximum price based on the input salary, and then
selects houses based on the maximum price:

FUNCTION house_schema.find_houses_from_salary(IN salary NUMERIC)


RETURNS NUMERIC
BEGIN
DECLARE how_many NUMERIC;
DECLARE max_price NUMERIC;
IF salary <= 20000 THEN
SET max_price = 50000;
ELSE
SET max_price = 2 * salary;
END IF;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

4.12.8. Terminate Routine or Trigger Execution: SIGNAL


The nonstandard SIGNAL statement is used to raise exception conditions from within
a routine or trigger and to issue user-defined error messages. A form of this
statement may also be used as a test aid to issue a message from a routine or trigger
and to continue executing the routine or trigger.

Format

SIGNAL [SQLSTATE [ VALUE ] character string 1 ] character string 2 ;

where:

character string 1
can be an SQL variable, a routine parameter, or a literal of character data type. A
system variable is not permitted.

Its value must be ‘00000’. If a value other than ‘00000’ is encountered during
execution of the SIGNAL statement, an error is issued and processing of the
routine or trigger is terminated.

character string 2
can be an SQL variable, a routine parameter, a correlation-name-qualified item, or a
literal of character data type. A system variable is not permitted.

character string 2 has a maximum length of 708 characters (12 lines of 59


characters). If character string 2 exceeds 708 characters, it is truncated.
If character string2 has a null value, RDMS presents the string as

<NULL Signal Message Text Found>

4–46 7830 8160–027


Statements and Keywords

The form of the SIGNAL statement that does not include an SQLSTATE value provides
a method of terminating a routine or trigger execution. The CALL, SET, or SQL
statement that resulted in execution of this SIGNAL statement is terminated with an
exception condition, the issuance of the text message specified as character string 2,
and rollback if any database changes were made during the processing of that
statement.

The form of the SIGNAL statement including an SQLSTATE value provides a “Print”
function. This can be used in a test environment to provide a trail of an execution path
through a routine or trigger. If SQLSTATE value is specified and character string 1
value equals ‘00000’ (a nonstandard value), then RDMS handles the command as a
“Print”; any other value is an error. RDMS issues the text message(s) specified as
character string 2 then continues to execute the routine or trigger. This form of the
SIGNAL statement is not recommended for use in a production environment since
normal RDMS error processing is used to display the SIGNAL output.

When a SIGNAL statement without the SQLSTATE value specified is encountered, one
of the following general error messages is issued:

• For routines:

Stored routine schema.name was terminated by a SIGNAL statement -


see following messages for the reason.

• For triggers:

Trigger schema.name on table schema.name was terminated by a SIGNAL


statement - see following messages for the reason.

This message is followed by another message or messages containing the character


string 2 text specified on the SIGNAL statement. The following also occur:

1. SQLSTATE is set to ‘4xxxx’.


2. error_status is set to 6007.
3. SQLCODE is set to –6007.

Example
SIGNAL ' Table s1.t1 may not be modified at this time.'

7830 8160–027 4–47


Statements and Keywords

When a SIGNAL statement with the SQLSTATE value specified is encountered, one of
the following general error messages is issued.

• For routines:
Stored routine schema.name executed a SIGNAL statement and issued
the following messages.

• For triggers:
Trigger schema.name on table schema.name executed a SIGNAL statement
and issued the following messages.

This message is followed by another message (or messages) containing the character
string 2 text specified on the SIGNAL statement.

Examples
SIGNAL SQLSTATE VALUE '00000' 'No Find on Fetch First on cursor C1.'

SIGNAL SQLSTATE '00000' 'Count(*) returned over 10,000 records'

4.12.9. Execute Repeatedly Based on Condition: WHILE


Statements that follow the DO keyword execute repeatedly based on the truth or
falsity of a condition.

Format

WHILE Boolean-expression DO statement-list END WHILE ;

where:

Boolean-expression
can include parameters, SQL variables, literals, RDMSAUXINFO, SQLSTATE, and
OLD and NEW ROW correlation-name.column-name references. See the
following:
• 2.4.2 (Boolean expressions)
• 4.6 (parameters)
• 4.12.4 (variables)
• 4.9.1 (RDMSAUXINFO)
statement-list
is a statement or statements (see Table 4–2 and Table 4–3).

The statements in the list continue to execute until the search condition becomes
FALSE or UNKNOWN.

4–48 7830 8160–027


Statements and Keywords

Example

FUNCTION house_schema.find_10_houses(INOUT max_price NUMERIC) RETURNS


NUMERIC
BEGIN
DECLARE how_many NUMERIC;
SET how_many = 0;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
WHILE how_many < 10 AND max_price < 1000000 DO
SET max_price = max_price + 10000;
SELECT COUNT(*) INTO how_many FROM houses WHERE price <
max_price;
END WHILE;
RETURN how_many;
END;

7830 8160–027 4–49


Datetime and Interval Data Types

4.13. Datetime and Interval Data Types


To pass a datetime value to an SQL routine, use an IN parameter of type character and
pass a datetime value in character representation. Use the cast function within the
routine to convert it to a datetime data type value. For further details, see 2.5.7
(datetime functions) and 2.8.3 (datetime data types).

To receive a datetime value from a routine, use an OUT parameter of type datetime
and return the datetime value into a character type host variable. RDMS automatically
converts the datetime value to character representation and stores it in the host
variable. The character representation of a datetime value is described in 2.8.3.

Example 1
The following example adds the specified DAY interval value to the current system
date and returns the result:

FUNCTION my_schema.add_days_to_current_date
(IN p1 CHAR(30)) RETURNS DATE
BEGIN
RETURN (CURRENT_DATE + CAST(p1 AS INTERVAL DAY(4)));
END;

You can call the function from a COBOL program as follows, where HOST-VAR1 is
defined as PIC X(30) and HOST-VAR2 is defined as PIC X(5):

MOVE '+30' TO host-var2


ENTER MASM 'acob$rdmr' USING
'SET $p1 $p2 = my_schema.add_days_to_current_date($p3);',
error-status,aux-info,host-var1,ind-var1,host-var2

4–50 7830 8160–027


Datetime and Interval Data Types

Example 2
The following example converts the specified TIME value and performs a range search
using the HOUR-MINUTE interval value:

PROCEDURE my_schema.how_many_records
(IN p1 CHAR(30), IN p2 CHAR(30), OUT p3 INTEGER)
BEGIN
DECLARE time_var1 TIME(6);
DECLARE time_var2 TIME(6);
DECLARE time_var3 TIME(6);
SET p3 = 0;
SET time_var1 = CAST(p1 AS TIME(6));
SET time_var2 = time_var1 + CAST(p2 AS INTERVAL HOUR(4) TO MINUTE);
IF time_var1 > time_var2 THEN
SET time_var3 = time_var1;
SET time_var1 = time_var2;
SET time_var2 = time_var3;
END IF;

SELECT COUNT(*) INTO p3 FROM my_schema.my_tbl


WHERE time_col BETWEEN time_var1 AND time_var2;
END;

You can call the procedure from a COBOL program as follows, where HOST-VAR1 is
defined as PIC X(30), HOST-VAR2 is defined as PIC X(30), and HOST-VAR3 is PIC S1(36):

MOVE '12:34:56.789' TO host-var1.


MOVE '-6:00' TO host-var2.
ENTER MASM 'acob$rdmr' USING
'CALL my_schema.how_many_records($p1,$p2,$p3 $p4);',
error-status,aux-info,host-var1,host-var2,host-var3,ind-var3.

7830 8160–027 4–51


Datetime and Interval Data Types

4–52 7830 8160–027


Section 5
SQL Statements Introduction and
Summary

Sections 6 through 10 describe (in alphabetical order) each statement in the RDMS
implementation of SQL 92. RDMS offers extended syntax to some standard SQL
statements. RDMS also offers statements beyond those described in the standard.

5.1. Content and Format of Reference Information


After a brief introduction to each statement, there is an information box that includes
the following columns:

• Interpreter Interface
Whether the statement can be used from third-generation programming
languages, the IPF SQL Interface, and the MAPPER Relational Interface (MRI)
through the interpreter interface.
• Static ESQL
Whether the statement can be embedded in UCS COBOL and UCS C programs
using static ESQL.
• Dynamic ESQL
Whether the statement can be embedded in UCS COBOL and UCS C programs
using dynamic ESQL.
• Module
Whether the statement can be used in module programs.
• XREF
Whether the statement is cross-referenced (XREF). For further information about
cross-referencing, see the Relational Database Server for ClearPath OS 2200
Administration Guide and the COBOL Compiler Programming Reference Manual
Volume 2.

7830 8160–027 5–1


Content and Format of Reference Information

• Standard
Whether the statement complies with entry, intermediate or full level SQL 92, or
the current version of SQL 99. If so, this box also indicates whether RDMS offers
extensions to the standard SQL form. The meanings of the values in the Standard
column are as follows:

E The statement complies with entry level SQL92.


F The statement complies with full level SQL92.
I The statement (or an enhancement of the statement) complies with
intermediate level SQL92 (a superset of entry level).
P The statement is similar to but not necessarily identical with the current
version of the SQL99 standard.
X The statement is an RDMS extension, or RDMS offers an extension to
the standard statement.

In the following example for the ALLOCATE CURSOR statement, the Standard box
indicates “F/X.” The F indicates that the ALLOCATE CURSOR statement complies with
full level SQL 92. The X indicates that RDMS offers one or more extensions to this
statement.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No Yes No F/X

The information box is followed in order by

• Syntax
• Examples
• Rules and guidelines

5–2 7830 8160–027


Comments in SQL Statements

5.2. Comments in SQL Statements


5.2.1. Hyphens
Two consecutive hyphens ( -- ) in an SQL statement signal a comment. The text of a
comment is for information only; the text is not part of the statement. In static ESQL,
the comment ends at the end of the line. In dynamic ESQL and in the interpreter
interface, the comment extends to the end of the string or parameter that contains
the SQL statement.

In the following examples, comments are in italics.

For static ESQL—COBOL:

EXEC SQL INSERT INTO sample_table VALUES


('Charles', -- this is a comment
'This is NOT a comment',
15 ) -- this is another comment
END-EXEC.

For dynamic ESQL—UCS C:

EXEC SQL PREPARE rb FROM


'DELETE FROM sample_table -- remove all rows';

For the C interpreter interface:

rsa ("ROLLBACK WORK; -- discard updates",


error_status, &auxiliary_information);

For the COBOL interpreter interface:

ENTER MASM 'ACOB$RDMR' USING


'ROLLBACK WORK; -- discard updates' ,
error-code, extra-info.

For the FORTRAN interpreter interface:

CALL F$RDMR('ROLLBACK WORK -- discard updates',


+ errcod, auxinf)

7830 8160–027 5–3


Comments in SQL Statements

5.2.2. /* and */ Delimiters


You can also use the /* and */ delimiters to enclose comments.

In the following examples, comments are in italics.

For static ESQL—COBOL:

EXEC SQL INSERT INTO sample_table VALUES


('Charles', /* this is a comment */
'This is NOT a comment',
15 ) /* this is another comment */
END-EXEC.

For dynamic ESQL—UCS C:

EXEC SQL PREPARE rb FROM


'DELETE FROM sample_table /* remove all rows*/';

For the C interpreter interface:

rsa ("ROLLBACK WORK /* discard updates*/",


error_status, &auxiliary_information);

For the COBOL interpreter interface:

ENTER MASM 'ACOB$RDMR' USING


'ROLLBACK WORK /* discard updates*/' ,
error-code, extra-info.

5–4 7830 8160–027


Alphabetical Summary of SQL Statements

5.3. Alphabetical Summary of SQL Statements


Table 5–1 summarizes information about the SQL statements described (in
alphabetical order) in Sections 6 through 10. The table contains the same information
as the information box included in the detailed reference information for each
statement (see 5.1).

Note: In the table, an asterisk ( * ) indicates that you can prepare and execute the
COMMIT, END THREAD, and ROLLBACK statements only from an implicit thread
(see the BEGIN THREAD statement).

Table 5–1. SQL Statements Summary

Interpreter Static Dynamic


Statement Interface ESQL ESQL Module XREF Standard

ALLOCATE No Yes No Yes No I/F/X


CURSOR

ALTER TABLE Yes Yes No Yes No I/X

BEGIN DECLARE No Yes No n/a No E

BEGIN THREAD Yes Yes No Yes No X

CALL Yes Yes No Yes No P


(not IPF SQL)

CLOSE Yes Yes No Yes No E/X

COMMIT Yes Yes Yes* Yes No E/X

CREATE INDEX Yes Yes No Yes No X

CREATE ROLE Yes No No No No X

CREATE SCHEMA Yes Yes No Yes No E

CREATE TABLE Yes Yes No Yes No E/I/F/X

CREATE TRIGGER Yes No No No No P


(not IPF SQL)

CREATE VIEW Yes Yes No Yes No E/X

DEBUG Yes Yes Yes Yes No X

DECLARE CURSOR Yes Yes No Yes Yes E/F/X

DELETE Yes Yes Yes Yes Yes E/X

DROP CURSOR Yes No No No No X

DROP FUNCTION Yes No No No No P


(not IPF SQL)

DROP INDEX Yes Yes No Yes No X

DROP PROCEDURE Yes No No No No P


(not IPF SQL)

7830 8160–027 5–5


Alphabetical Summary of SQL Statements

Table 5–1. SQL Statements Summary

Interpreter Static Dynamic


Statement Interface ESQL ESQL Module XREF Standard

DROP ROLE Yes No No No No X

DROP TABLE Yes Yes No Yes No I/X

DROP TRIGGER Yes No No No No P


(not IPF SQL)

DROP VIEW Yes Yes No Yes No I/X

END DECLARE No Yes No n/a No E

END THREAD Yes Yes Yes* Yes No X

EXECUTE No Yes No Yes No I

EXECUTE No Yes No Yes No I


IMMEDIATE

EXPLAIN Yes No No No No X

FETCH Yes Yes No Yes No E/I/F/X

FETCH NEXT n No Yes No n/a No X

FUNCTION Yes No No No No P
(not IPF SQL)

GET DESCRIPTION Yes No No No No X


(not IPF SQL)

GETERROR Yes Yes No Yes No X


(not IPF SQL)

GET PARAMETERS Yes No No No No X

GET RESULT SET Yes No No No No X


CURSOR NAME

GRANT Yes Yes No Yes No E/X

INSERT Yes Yes Yes Yes Yes E/X

LEVEL Yes No No No No X
(not IPF SQL)

LOCATE Yes Yes Yes Yes No X


(not IPF SQL)

LOCK Yes Yes Yes Yes No X

OPEN Yes Yes No Yes No E/X


(not IPF SQL)

PREPARE No Yes No Yes No I

PROCEDURE Yes No No No No P
(not IPF SQL)

REVOKE Yes Yes No Yes No I/X

5–6 7830 8160–027


Alphabetical Summary of SQL Statements

Table 5–1. SQL Statements Summary

Interpreter Static Dynamic


Statement Interface ESQL ESQL Module XREF Standard

ROLLBACK Yes Yes Yes* Yes No E/X

SELECT Multirow IPF SQL only No No No No F/X

SELECT Single Row Yes Yes No Yes No E/X


(not IPF SQL)

SET Yes Yes No Yes No X

SET AUXINFO Yes Yes Yes Yes No X

SET RESULT SET Yes No No No No X

SET STATISTICS Yes Yes Yes Yes No X

UNLOAD Yes Yes No Yes Yes X

UNLOCK Yes Yes Yes Yes No X

UPDATE ALL Yes Yes Yes Yes Yes X

UPDATE Positioned Yes Yes Yes Yes Yes E/X

UPDATE Searched Yes Yes Yes Yes Yes E/X

UPDATE No Yes No Yes Yes X


SYNCHRONIZE

UPDATE VALUES Yes Yes Yes Yes Yes X

USE DEFAULT Yes Yes Yes n/a No X

WHENEVER No Yes No n/a No E

7830 8160–027 5–7


Alphabetical Summary of SQL Statements

5–8 7830 8160–027


Section 6
SQL Statements ALLOCATE CURSOR
Through CREATE TABLE

This section contains reference information about the following SQL statements:

• ALLOCATE CURSOR (6.1)


• ALTER TABLE (6.2)
• BEGIN DECLARE (6.3)
• BEGIN THREAD (6.4)
• CALL (6.5)
• CLOSE (6.6)
• COMMIT (6.7)
• CREATE INDEX (6.8)
• CREATE ROLE ( 6.9)
• CREATE SCHEMA (6.10)
• CREATE TABLE (6.11)

7830 8160–027 6–1


ALLOCATE CURSOR

6.1. ALLOCATE CURSOR


Use the ALLOCATE CURSOR statement to associate a cursor name with a prepared
query specification.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes Yes Yes No F/X

6.1.1. Syntax
SQL 92 Syntax (Intermediate Level)
ALLOCATE cursor-name CURSOR

FOR statement-name

RDMS Extended Syntax


ALLOCATE cursor-name CURSOR

[ FOR RETENTION ]

FOR statement-name

where:

cursor-name
is a unique name within the compilation unit.

statement-name
is any valid SQL name (see 2.2.1). It cannot be a host program variable name.

FOR RETENTION
means to keep the cursor opened after a COMMIT statement in update or
read-only threads and after a rollback (ROLLBACK statement or rollback error)
in read-only threads. If you omit this clause and execute a COMMIT statement,
or are rolled back, RDMS closes the cursor automatically. Within update
threads, a ROLLBACK statement or rollback error causes RDMS to close the
cursor automatically.

6–2 7830 8160–027


ALLOCATE CURSOR

6.1.2. Example
The following ESQL statements prepare a named statement that contains the query
specification for a cursor, declare the cursor using the ALLOCATE CURSOR statement,
open the cursor, and fetch a row from the cursor:

EXEC SQL PREPARE price_statement


FROM 'SELECT SUM(price) FROM houses'
END-EXEC.
EXEC SQL ALLOCATE price_cursor CURSOR
FOR price_statement END-EXEC.
EXEC SQL OPEN price_cursor END-EXEC.
EXEC SQL FETCH price_cursor
INTO :sumprice END-EXEC.

6.1.3. Rules and Guidelines


Read the following rules and guidelines before using the ALLOCATE CURSOR
statement, where these rules apply to the use of cursors in dynamic ESQL.

Placement
You can place the ALLOCATE CURSOR statement anywhere in a program as long as it
textually precedes any reference to the cursor it declares.

Use of OPEN Statement


Before you access the cursor (for example, with a FETCH statement), you must open
it with the OPEN statement.

Use of CLOSE, but Not DROP CURSOR Statement


On cursors declared with the ALLOCATE CURSOR statement, you can use the CLOSE
statement but you cannot use the DROP CURSOR statement.

Use with Dynamic Query Specification


You must use the ALLOCATE CURSOR statement to declare a cursor for a dynamically
prepared query specification.

Execution
The ALLOCATE CURSOR statement is not executed when the program is executed. It
therefore has no effect on run-time entities such as SQLSTATE (see B.5).

7830 8160–027 6–3


ALTER TABLE

6.2. ALTER TABLE


Use the ALTER TABLE statement to change some of the characteristics of a base
table. If a table has an owner, only the owner can alter the table. For more information
about owned and unowned tables, see rules and guidelines for the CREATE SCHEMA
statement in 6.10.3.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No I/F/X*

* The illustrated syntax is referred to as “RDMS extended syntax” because RDMS extensions
are included in the intermediate and full level SQL 92 syntax.

6.2.1. RDMS Extended Syntax


ALTER TABLE table-specification edit-specification-list

where:

table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.
The ALTER TABLE statement changes the definition that is common to all
versions of the table.

edit-specification-list
is a list of supported combinations of edit specifications (see 6.2.2). These edit
specifications allow you to

• Increase the size of columns


• Allow nulls in a column
• Set and drop default clauses
• Add and drop columns, table constraints, foreign keys, and partitions
• Change access to tables
• Change the table's owner
• Rename existing columns
• Indicate whether the table can share a storage area with other tables

6–4 7830 8160–027


ALTER TABLE

6.2.2. Edit Specifications


You can have up to 32 edit specifications in the edit-specification-list of an ALTER
TABLE statement; however, if you specify certain of the following edit specifications,
no other edit specifications are allowed in the same statement. See the
documentation for each of the edit specifications for information about restrictions;
also see 6.2.3 for examples.

Each of the following edit specifications is optional.

Use commas to separate items in an edit specification list.

CHANGE [COLUMN] column-name

{ TO unsigned-integer

{ CHARACTER| NUMERIC }[ NULLS ALLOWED] | TO NULLS ALLOWED |

SET { default-clause | generated-default-clause |RESTART WITH


restart_value } |

DROP { DEFAULT | IDENTITY | EXPRESSION }

[column-constraints] [collate-clause] }

ADD column-definition

DROP column-name

ADD [ CONSTRAINT constraint-name ]

{ UNIQUE (unique-column-list) [ storage-area-specification ] │

CHECK (Boolean-expression )│

FOREIGN KEY ( column-name-list ) REFERENCES table-specification

[ ( parent-column-name-list ) ] }

DROP CONSTRAINT constraint-name

ADD FOREIGN KEY key-name IS column-name-list

REFERS TO [ parent-column-name-list OF ] table-specification

DROP FOREIGN KEY key-name

OWNER IS user-id

RENAME [ COLUMN ] old-column-name TO new-column-name

DATA ACCESS CONTROL IS { ACTIVE │ INACTIVE }

ADD partition-specification

7830 8160–027 6–5


ALTER TABLE

DROP PARTITION partition-name

ADD BLOB STORAGE TO { TABLE │ partition-name }

ALLOW MULTIPLE TABLE FILE

REQUIRE SINGLE TABLE FILE

where:

column-name
is the name of a column in the table named in the ALTER TABLE statement.

unsigned-integer
is the number of characters or the numeric precision the column is to have:

• For CHARACTER, this number must be greater than the column's current size.
• For NUMERIC, this number
− Must be greater than the current specified precision.
− Must not change the memory usage (1 word if precision is 1 to 11, 2 words
if precision is 12 to 21).

If there is a SET default clause edit specification on this column, the original
column size is used in the default value; therefore, you should issue the SET
default clause in a separate ALTER TABLE statement. You cannot change the size
of a column with data type BLOB.

NULLS ALLOWED
changes the column to allow it to contain nulls. This change is permanent. You can
alter any NOT NULL column of a primary key to NULLS ALLOWED if it is not
related to any child table through a foreign key. You cannot alter a column that is
part of a unique constraint.

SET default-clause
sets a default clause for a column. If the column is NOT NULL, the default clause
for this column cannot be NULL. For a description of default clauses, see 6.11.4.

SET generated_default_clause
makes an existing primary key column into an identity column or a column for
which a value is generated. See CREATE TABLE for a complete explanation and
description of the generated_default_clause.

If adding a new column with a generated expression you must first do an ALTER
TABLE table-name ADD COLUMN followed by a separate ALTER TABLE ..SET
generated_default_clause.

DROP DEFAULT
drops the default clause explicitly defined for the column. If the column is NULL
and the default clause is not used, the column is by default NULL. DROP DEFAULT
implicitly results in either a DROP IDENTITY—if IDENTITY is specified on the
column, or DROP EXPRESSION—if an expression is specified on the column.

6–6 7830 8160–027


ALTER TABLE

DROP IDENTITY
removes the information added to the column by GENERATED AS IDENTITY
clause.

DROP EXPRESSION
removes the information added to the column by GENERATED AS (expression)
clause.

RESTART WITH restart_value


where restart_value is a signed or unsigned integer that is larger than MINVALUE
and smaller than MAXVALUE. It is used to reset the start value, included either
explicitly or implicitly, during SET generated_default_clause when IDENTITY was
specified. The next record inserted will use this value.

ADD column-definition
adds a new column to an existing table (see 6.11 for a detailed description of a
column definition.) Columns added by this statement automatically allow nulls.
The value of all new columns for all existing rows is NULL and can be changed
only by future UPDATE statements.

To perform additional ALTERs such as adding a default clause or a column


constraint on this column, you must issue an additional ALTER TABLE statement.

Note: For DECIMAL columns defined in an owned schema, the number of


decimal digits is one greater than the number of decimal digits in the original
definition. This is because of the difference in the semantics of this value
between the SQL standard and RDMS. For more information, see 2.8.2.

You do not have to reorganize or dump and reload a database after an ALTER
TABLE ADD statement. However, because it changes the table definition, existing
programs that access the table may be affected.

A table can contain up to 510 columns (509 columns if no primary key exists for
the table), including any dropped columns.

If you add a column with data type BLOB to a partitioned table, you must use two
ALTER TABLE statements: in the first ALTER TABLE statement, add the column; in
the second ALTER TABLE statement, add BLOB storage areas to each partition. If
the table is not partitioned, include the storage area(s) with the column definition.
You cannot add an in-record BLOB to a partitioned table. You must drop and
recreate the table to include an in-record BLOB.

DROP column-name
removes a column from the definition of the table. After using this clause, you
cannot access data in that column. If any statement attempts to refer to a
dropped column, RDMS returns an error.

The limit of 510 columns per table includes dropped columns and any implicit
primary key column. You cannot drop a column that is part of a primary key,
secondary index, unique constraint, or check constraint. You also cannot drop the
last remaining column of a table.

7830 8160–027 6–7


ALTER TABLE

ADD CONSTRAINT constraint-name


adds a new unique, check, or foreign key table constraint to an existing table. You
can specify a name for the constraint, or you can let RDMS attach a name to it
(UNIQUE$1,...UNIQUE$n or CHECK$1,...CHECK$n or FKEY$1,...FKEY$n).

unique-column-list
is a list of up to 25 column names. You must also specify NOT NULL on each
column definition.

storage-area-specification
has the form

IN storage-area-name

where storage-area-name is the name for the storage area for the unique
index as defined in 2.2.5. You must create the storage area before executing
the ALTER TABLE statement. You cannot specify a storage area name if the
table was created with the CREATE TABLE statement and the storage area
was implicitly defined by RDMS (see 6.11).

Boolean-expression
is a condition that must be satisfied by every row in the table.

column-name-list
is a list of up to 25 column names that make up the foreign key. The data
types of the columns in the column name list must match the data types of
the columns in the parent column name list.

table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.

parent-column-name-list
is the list of column names in the parent table's primary key or unique
constraint. Each item in this list must correspond to the item in the same
relative position in column-name-list.

DROP CONSTRAINT constraint-name


removes the specified constraint from the table. You cannot drop a unique
constraint that is referenced by a foreign key or a primary key constraint.

ADD FOREIGN KEY


adds foreign keys to the table definition of existing tables. You can have up to 25
foreign keys in a table. Separate foreign key clauses from one another with at
least one blank space. If the referenced parent table of the foreign key is owned
and data access control is active, you cannot add a foreign key unless the child
table of the foreign key is owned and the owner of the child table holds the
REFERENCES privilege on the referenced columns or on the parent table.

key-name
is the name of the foreign key.

6–8 7830 8160–027


ALTER TABLE

parent-column-name-list
is the list of column names in the parent table's primary key or unique
constraint. Each item in this list must correspond to the item in the same
relative position in column-name-list. You can omit this list if the column name
list is identical to the parent table's primary key.

DROP FOREIGN KEY key-name


removes the specified foreign key from the table.

OWNER IS user-id
changes the owner of the table to user-id, where user-id is any valid user ID. Do
not use this clause if the table is in an owned schema (see 6.10 and 6.11), or if the
table references a foreign key. The user ID must be defined on the local database
system. See also 6.2.4.

RENAME [ COLUMN ] ... TO ...


renames a column from old-column-name to new-column-name. The new column
name cannot already exist as a column name in the table. The following
restrictions also apply:

• Other edit specifications are not allowed in the same ALTER TABLE statement
in which a column is renamed.
• Any privileges already granted on the column must be revoked before
renaming (the privileges can be granted again after the column is renamed).
• The table specified in the ALTER TABLE statement cannot be the base table of
a view.

The table cannot have any foreign keys, nor can it be referenced by another table's
foreign key.

DATA ACCESS CONTROL IS


turns on or off (ACTIVE or INACTIVE) access to the table. Do not use this clause if
the table is in an owned schema (see 6.10 and 6.11). RDMS enforces data access
control only on tables that have an owner and on which data access control is
active.

ADD partition-specification (see CREATE TABLE, 6.11.11 and 6.11.12)


adds a partition to a table and allows the primary key or secondary index B-trees
or UNIQUE constraint B-trees to be partitioned into ranges in multiple storage
areas according to the values of the leading columns in the key or index.

All versions of the table have the same partitions and therefore have the same
ranges.

Once a partition is added, it is in an attached state. New partitions may be added


to a previously partitioned table. A nonpartitioned table can be converted to a
partitioned table using the ADD PARTITION command. When a nonpartitioned
table is partitioned, the primary key storage area cannot contain any other indexes
or tables.

7830 8160–027 6–9


ALTER TABLE

Adding a partition never affects the RDT timestamp and therefore does not
invalidate static embedded SQL programs. It is necessary to have exclusive use of
the table definition in order to add a partition.

The ADD PARTITION command fails if any row contains a key value that logically
does not meet the boundaries specified, or if any record in adjacent partitions falls
in the range of this partition.

Caution
DROP INDEX, DROP PARTITION, and DROP TABLE do not clear the storage
areas containing the partition. If you are reusing a storage area and expect
it to be empty, you must initialize it using the UREP PROCESS STORAGE
AREA … DELETE and PROCESS STORAGE AREA … INSTALL commands.

When specified, the ADD PARTITION command is generally the only edit
specification allowed in the ALTER TABLE statement. The exception is the addition
of a unique constraint to a partitioned table. A single ADD PARTITION edit
specification can generally contain only a PARTITION PRIMARY KEY clause or a
single PARTITION INDEX clause. The exception is when a nonpartitioned table is
migrated to a partitioned table. Thus, a single ALTER TABLE statement can add
partitions to the primary key or to a specified index. To add partitions to the
primary key or multiple indexes (except when migrating), use multiple ALTER
TABLE statements.

DROP PARTITION partition-name


drops a partition from a partitioned table. partition-name is the name of the
partition. All partitions in a table must have unique names, regardless of whether
they are partitions of the same primary key or index.

The partition being dropped can be in any of the states attached, detached, or
hidden. A partition can be dropped even if it is not empty. The partition is
removed from the table, but the storage area is not erased (meaning that the file
containing the storage area still contains the records belonging to the partition).
Foreign key references are not checked.

If the table has any secondary or unique indexes, and you drop any primary key or
index partitions that are not empty, the table is in an inconsistent state. Therefore,
it is recommended that you do not drop a partition in a table that has secondary or
unique indexes unless the partition is empty. Otherwise there will be more
records in some indexes than others, a condition that RDMS considers corrupted.
RDMS issues an RDM 63050 corruption error message when it detects such
corruption. For example, this would happen if an attempt is made to delete a
record WHERE primary_key = some value, that is in the primary key but not in the
secondary index, or RDMS attempts to retrieve a record through the secondary
index but the record does not exist in the primary key.

Dropping a partition does not affect the RDT. It therefore does not invalidate
static embedded SQL programs.

6–10 7830 8160–027


ALTER TABLE

It is necessary to have exclusive use of the table definition in order to drop a


partition; therefore, other users cannot access the table until the DROP PARTITION
command has completed.

The table remains a partitioned table even after the last partition has been
dropped. It is not possible to use the table because the table is effectively in a
DOES NOT EXIST state.

Notes:
• When specified, the DROP PARTITION command is the only edit
specification allowed in the ALTER TABLE statement.
• Dropping the first partition of a primary key or index destroys the load
restart information for the table, or for the index if the LOAD INDEX
command was used. Therefore, complete all loads before dropping the first
partition.

ADD BLOB STORAGE


adds storage areas to a column with data type BLOB. The format of the edit
specification is

ADD BLOB STORAGE TO { TABLE | partition-name }


column-name IN storage-area-list
[ , column-name IN storage-area-list ]. . .

where:

TABLE
is the keyword used if the table is not partitioned.

partition-name
is the partition to which the new BLOB storage areas are added if the table is
partitioned.

column-name
is the name of the BLOB column.

storage-area-list
identifies the storage area(s) to add to the BLOB column. Storage areas may
not be shared across partitions. If you are adding one storage area to a
column, use the following format:

storage-area-name

If you are adding several storage areas, include the list in parentheses and
separate the names with commas, as follows:

( storage-area-name, storage-area-name, ... )

Each BLOB column in each partition can have up to 511 storage areas. (See
2.2.5 for information about storage area names.)

7830 8160–027 6–11


ALTER TABLE

ALLOW MULTIPLE TABLE FILE


REQUIRE SINGLE TABLE FILE
specifies whether the table can share a storage area with other tables.

ALLOW MULTIPLE TABLE FILE specifies that this table can share a storage area
with other tables. You cannot specify ALLOW MULTIPLE TABLE FILE for
partitioned tables, global temporary tables, and multifile tables.

If you specify REQUIRE SINGLE TABLE FILE, UREP verifies that no other tables
share the same storage area as table-name. UREP thereafter prevents other tables
from being declared within this storage area.

The default depends on the type of table. For partitioned, global temporary, and
multifile tables, the default is REQUIRE SINGLE TABLE FILE. Otherwise, the default
is ALLOW MULTIPLE TABLE FILE.

Note: When you specify either ALLOW MULTIPLE TABLE FILE or REQUIRE
SINGLE TABLE FILE, no other edit specifications can appear in the same ALTER
TABLE statement.

6.2.3. Examples
Example 1
This example sets the default value of column DESCRIPTION in table HOUSES to
4+ BEDROOM HOUSE and adds a constraint on column PRICE:

ALTER TABLE houses


CHANGE COLUMN description
SET DEFAULT '4+ bedroom house',
ADD CONSTRAINT cc
CHECK (price > 25000)

You can use the following statement to drop these specifications:

ALTER TABLE houses


CHANGE COLUMN description
DROP DEFAULT,
DROP CONSTRAINT cc

Example 2
The next example specifies owner 123X for table HOUSES and activates data access
control:

ALTER TABLE houses


OWNER IS "123X",
DATA ACCESS CONTROL IS ACTIVE

6–12 7830 8160–027


ALTER TABLE

Example 3
The next example changes the name of the column DESIREDLOC in table CUSTOMERS
to LOC_DESIRED:

ALTER TABLE customers


RENAME COLUMN desiredloc TO loc_desired

Example 4
This example adds two primary key partitions to table MONTHS.
ALTER TABLE months
ADD
PARTITION PRIMARY KEY
nov1999 <= '1999-12-01-00:00:00' IN (DATA sa-data-nov-1999, INDEX sa-
primkey-nov-999)
dec1999 <= '2000-01-01-00:00:00' IN (DATA sa-data-dec-1999, INDEX sa-
primkey-dec-999)

Example 5
The following example adds two secondary index partitions to table PARTS:

ALTER TABLE parts ADD


PARTITION INDEX seckey
new-id-codes1 <= 50000 IN sa-secindex-new-id-codes-1,
new-id-codes2 <= 75000 IN sa-secindex-new-id-codes-2

Example 6
The next example shows how to convert a nonpartitioned table into a partitioned
table.

The original nonpartitioned table definition is as follows:

CREATE TABLE s.table1


( IN s.sa1
c1 : INTEGER NOT NULL
c2 : INTEGER
c3 : INTEGER
PRIMARY KEY (c1 ASCENDING) IN s.sa2
INDEX si1 ON c2 ASCENDING IN s.sa3
INDEX si2 ON c3 ASCENDING IN s.sa4
)

7830 8160–027 6–13


ALTER TABLE

The ALTER TABLE syntax below converts the table into a partitioned table. A single
primary key partition named p1_data is created. Similarly, single secondary index
partitions are created for each of the secondary indexes. When you convert a
nonpartitioned table to a partitioned table, the primary key and all indexes must each
have a single partition specified. It is not possible to convert a table to a partitioned
table if any version of the table is locked.

ALTER TABLE s.table1


ADD
PARTITION PRIMARY KEY
p1_data <= (MAXVALUE) IN (DATA s.sa1, INDEX s.sa2)
PARTITION INDEX si1
p1_si1 <= (MAXVALUE) IN s.sa3
PARTITION INDEX si2
p1_si2 <= (MAXVALUE) IN s.sa4

The original table storage areas must be used when converting a nonpartitioned table
into a partitioned table. A nonpartitioned table cannot be converted to a partitioned
table and at the same time moved into new storage areas.

Example 7
This example drops that partition named new-id-codes2.

ALTER TABLE parts


DROP PARTITION new-id-codes2

Example 8
This example adds a unique constraint on columns c2 and c3 to partitioned table
s.table1. Note that the unique constraint is named and that the storage area is
specified in the ADD PARTITION INDEX edit_specification.

ALTER TABLE s.table1


ADD CONSTRAINT unique1 UNIQUE (c2,c3),
ADD PARTITION INDEX unique1
p_unique1_all <= (MAXVALUE) IN sa_unique_1

Example 9
This example adds BLOB storage areas to a nonpartitioned table T1:

ALTER TABLE t1
ADD BLOB STORAGE TO TABLE
house_photo IN (s1.house_photo_3, s1.house_photo_4),
detail_description IN s1.house_long_desc_2

6–14 7830 8160–027


ALTER TABLE

Example 10
This example adds BLOB storage areas to a partitioned table year_2000.

ALTER TABLE year_2000


ADD BLOB STORAGE TO january
house_photo IN (s1.house_photo_3, s1.house_photo_4),
detail_description IN s1.house_long_desc_2

ALTER TABLE year_2000


ADD BLOB STORAGE TO february
house_photo IN (s1.house_photo_5, s1.house_photo_6),
detail_description IN (s1.house_long_desc_3,
s1.house_long_desc_4)

.
.
.

ALTER TABLE year_2000


ADD BLOB STORAGE TO december
house_photo IN s1.house_photo_25,
detail_description IN s1.house_long_desc_14

Example 11
This example adds two primary key partitions to the table softball_table.

Note: The secondary index softball_table_lk is a LOCAL index.

ALTER TABLE softball_table


ADD PARTITION PRIMARY KEY
P2 <= 'S' IN (DATA softball_data_sa2, INDEX softball_index_sa2,
softball_table_1k softball_local_sa2),
P3 <= 'Z' IN (DATA softball_data_sa3, INDEX softball_index_sa3,
softball_table_1k softball_local_sa3);

Example 12

The following example drops the identity information for the column:

ALTER TABLE seed CHANGE COLUMN order_no DROP IDENTITY

Example 13

The following example alters the table to add identity to the column. The default
values are used for generator options START, INCREMENT, MINVALUE, MAXVALUE,
CYCLE, and cache options.

ALTER TABLE seed CHANGE COLUMN order_no


SET GENERATED BY DEFAULT AS IDENTITY

7830 8160–027 6–15


ALTER TABLE

Example 14

The following example alters the table to add identity to the column. Specific values
are used for the generator options and cache option.

ALTER TABLE seed CHANGE COLUMN order_no


SET GENERATED BY DEFAULT AS IDENTITY
(START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 100000 NOCYCLE CACHE
DYNAMIC);

Example 15

The following example alters the table to specify a restart value for the column using
identity. The next insert will use the restart value if default is specified for the column
value.

ALTER TABLE seed CHANGE COLUMN order_no SET RESTART WITH 107

Example 16

The following example drops the expression (for example, partition_id()) for the
column:

ALTER TABLE seed CHANGE COLUMN order_no DROP EXPRESSION

Example 17

The following example alters the table to add partition_id expression to the column.

ALTER TABLE seed CHANGE COLUMN order_no


SET GENERATED ALWAYS AS (partition_id())

Example 18

Add a partition to a table that has a multiple-column primary key, but partitions by only
the leading primary key column. See Example 8 in the CREATE TABLE section for the
definition of table mybank.today.

ALTER TABLE mybank.today ADD PARTITION PRIMARY KEY


p4 <= ('2003-09-04')
IN (DATA DT20030904, INDEX IT20030904);

6–16 7830 8160–027


ALTER TABLE

6.2.4. Rules and Guidelines


Read the following rules and guidelines before using the ALTER TABLE statement.

User ID Considerations
If a user ID starts with a number, express it as a delimited uppercase identifier as
illustrated in the following examples:

"1BIG" "2NOT" "3ORG"

RDMS converts lower case user IDs to uppercase, regardless of whether it is


undelimited or delimited. RDMS rejects delimited lowercase user IDs (for example,
“Bob”) for the authorization-id (use BOB instead).

RDMS does not verify the existence of the user ID on the system. If you specify a
nonexisting user ID and data access control is active, the data is inaccessible to other
users until the user ID is defined on the local database system.

Access Conflicts
If another thread has a cursor declared that includes the table you are altering, your
thread queues until the other thread ends. If your own thread has such a cursor
declared, RDMS returns an error and does not alter the table definition.

Adding a Unique Constraint to a Partitioned Table


RDMS adds a unique constraint to a partitioned table using two edit specifications.
The first edit specification adds the unique constraint. It must include a
constraint_name and must not include a storage_area_specification. The second edit
specification is an ADD PARTITION INDEX that names the constraint just added and
adds at least one partition.

Effect on Updatable Cursors


Exercise caution when updating columns of a secondary index using UPDATE WHERE
CURRENT OF cursor unless you are updating a single record only, or unless you
specify FOR UPDATE OF as part of the cursor declaration. Before creating a secondary
index, verify that all cursors updated using WHERE CURRENT OF cursor contain the
FOR UPDATE OF clause. If not, add the FOR UPDATE OF clause to the cursor.

Note: The same problem can occur if you fetch and update records from a cursor
one at a time, even if the update operation is performed using the UPDATE
SEARCHED or UPDATE Positioned statement.

Automatic Dropping of Views


The ALTER TABLE statement can cause views that are dependent on the table being
altered to be dropped. For more information, see the Relational Database Server for
ClearPath OS 2200 Administration Guide.

7830 8160–027 6–17


ALTER TABLE

Automatic Dropping of Foreign Key


RDMS drops the foreign key automatically in either of these cases:

• When you revoke the REFERENCES privilege from the owner of the child table
• When you enforce the security on a parent table that used to be a public access
table (that is, you give the table an owner and make data access control active)

Constraints and Data Integrity


If you add a foreign key or check constraint, RDMS does not check the integrity of
existing data. However, RDMS does prevent you from adding a unique constraint if
the existing data is not unique.

Dropping a Partitioned Unique Constraint


The drop of a partitioned unique constraint is handled in the same manner as the drop
of a partitioned index. When the table contains partitions, this is the only edit
specification allowed on the ALTER TABLE statement.

Revoking Privileges Granted by Former Table Owner


Sometimes you have to completely overhaul user privileges when table ownership
changes. You can use the REVOKE statement to revoke all privileges from all users of
a table.

Effect on Compiled Programs


Some changes made by the ALTER TABLE statement may invalidate previously
compiled ESQL programs. For more information, see 2.11.2.

Changes made by the ALTER TABLE statement do not invalidate previously compiled
interpreter interface programs. They do, however, invalidate previously compiled
ESQL programs.

If a previously compiled interpreter interface program references a column dropped


by the ALTER TABLE statement, the program does not run correctly.

Whenever you change the definition of a table, you should determine which programs
have to be changed and recompiled.

Cast Function Restriction


You cannot use the cast function in the DEFAULT clause or in Boolean expressions in
the check constraint of CREATE TABLE and ALTER TABLE statements.

Interval Data Type Restriction


You cannot define a column of data type interval.

6–18 7830 8160–027


ALTER TABLE

Effect on Triggers
The ALTER TABLE statement causes triggers to be implicitly dropped if the trigger
references the table. The implicit dropping of triggers can be prevented through the
use of the UREP configuration attribute RDMS-TRIGGER-DROPPING. RDMS-
TRIGGER-DROPPING is set to CASCADE by default. CASCADE allows RDMS to drop
any triggers associated with the altered table. Setting RDMS-TRIGGER-DROPPING to
RESTRICT, causes any ALTER statement to fail if it would cause the implicit dropping
of a trigger.

Global Temporary Tables Restriction


You cannot use the ALTER TABLE statement with a global temporary table. To alter a
global temporary table, drop the table and then re-create it.

Effect on Table Definitions


The page structure resulting from an ALTER table command is different from the page
structure which results if the table is dropped and then recreated using the CREATE
table command. Consequently, if an IRU backup of a table that reflects the altered
table is reloaded into a table that was dropped and recreated, then RDM 57070 errors
might occur. To avoid this, the table needs to be recreated as it was prior to the
ALTER table command. Following this, any ALTER commands must be applied in the
correct sequence prior to reloading the table.

7830 8160–027 6–19


BEGIN DECLARE

6.3. BEGIN DECLARE


Use the BEGIN DECLARE statement to mark the beginning of the SQL data definition
portion of the WORKING STORAGE SECTION of an ESQL COBOL program or the
equivalent declaration in a C program.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No N/A No E

6.3.1. SQL 92 Syntax (Entry Level)


BEGIN DECLARE SECTION

6.3.2. Example
In the following example, the variables HNO, LOC, and XTALLY can be used in ESQL
statements:

EXEC SQL BEGIN DECLARE SECTION END-EXEC.


01 HNO PIC X(4).
01 LOC PIC X(32).
EXEC SQL END DECLARE SECTION END-EXEC.
01 XTALLY PIC 9(10).

6.3.3. Rules and Guidelines


Read the following rules and guidelines before using the BEGIN DECLARE statement.

Optional BEGIN DECLARE Statement


Standard SQL requires you to use the BEGIN DECLARE statement to identify variables
you intend to use in ESQL statements. RDMS does not require it, however.

Extensions to Standard SQL


Standard SQL requires variables declared in the DECLARE SECTION to be either 01 or
77 level items. RDMS allows variables to be of any level and to be subscripted.

As an extension to standard SQL, variables declared outside the BEGIN DECLARE to


END DECLARE section are allowed in ESQL statements.

If the UCS COBOL LEVEL/SQL FLAGGER is turned on, the compiler issues warnings for
variables declared outside the BEGIN DECLARE to END DECLARE section that are used
in ESQL statements.

6–20 7830 8160–027


BEGIN THREAD

6.4. BEGIN THREAD


Use the BEGIN THREAD statement to register a thread with UDS and specify

• The application group to use


• The occurrence or not of updates to the database
• The type of recovery to use in the event of system failure during or after a
database update

From most interfaces, if a BEGIN THREAD statement is not executed at the beginning
of the session, RDMS executes one implicitly. See 6.4.3.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No X

6.4.1. RDMS Extended Syntax


BEGIN THREAD [thread-name] FOR [ APPLICATION ] application-name

[ READ │ RETRIEVE │

UPDATE [ ( { DEFERRED │ QUICKLOOKS │ COMMANDLOOKS │ NONE } ) ] ]

[ UDSMSG │ UDSMESSAGE │ UDSMESSAGES ]

where:

thread-name
is the name for the new thread. Thread names are 12 characters (alphanumeric) or
less, begin with a letter, and can contain underscores. You cannot use an
underscore as the final character. If omitted, the default thread name is the run-id
under which the program is running.

application-name
is the name or alias of the application group you want to use. Application group
names are limited to 6 characters and alias names are limited to 12 characters.

Note: For ESQL only, the FOR [ APPLICATION ] application-name clause is optional.
If the application name is specified in an embedded BEGIN THREAD statement, a
warning is returned to the program during compilation informing the user that the
specified name is being ignored.

7830 8160–027 6–21


BEGIN THREAD

The recovery options are as follows. For more information about these recovery
options, see 6.4.3.

READ/RETRIEVE Specifies a read-only thread that can make no attempt to update


the database. An attempt to update the database on a read-only
thread results in an error. Use this option when you do not plan to
update tables with this thread; READ is more efficient than
UPDATE.
UPDATE (Default) The thread can perform updates to tables in the database.
If you specify UPDATE, you can also specify the type of recovery
looks this thread is to use for updating recoverable files. A
recovery look is a copy of a data page (unit of I/O) before or after
the update takes place.
DEFERRED (Default) No updates are actually made to the database until the
next COMMIT or END THREAD statement. Only the most recent
updated copy of each page is saved until the end of the step.
QUICKLOOKS A quick-look is the image of a page before you update it. If you
specify QUICKLOOKS, a copy of the unchanged page is saved the
first time the page is updated (unless it was already saved during
the current step). Use QUICKLOOKS when you plan to make a
large number of updates to the database in the thread.
COMMANDLOOKS The image of the page being updated is saved before the page is
changed (just like QUICKLOOKS). However, the look is taken not
only once for every step, but also once for every SQL statement
that updates the page. In a COMMANDLOOKS thread, most errors
do not cause a thread rollback because RDMS is able to roll back to
the beginning of the current statement.
COMMANDLOOKS is the slowest (and most expensive in terms of
computer resources) of all recovery options.
Use COMMANDLOOKS for interactive programs where
statements submitted to RDMS depend on user input that may be
in error.
NONE This option declares your thread to be nonrecoverable. If you
specify NONE, RDMS expects that none of the files updated are
recoverable (as specified in the storage area definition that defines
the characteristic of the file). If you specify NONE and attempt to
update a recoverable file, RDMS returns an error.
It is strongly recommended that you do not use this recovery
option because of possible data corruption and subsequent
software failure. Since all RDMS internal files (RDT$FILE, FDT$FILE,
AUTH$FILE,VIEWDEP$FILE) are recoverable, you cannot create,
alter, or drop tables or views. You also cannot grant or revoke
privileges from a thread using the NONE recovery option.

6–22 7830 8160–027


BEGIN THREAD

UDSMSG/ When RDMS detects an error, it immediately prints an error


UDSMESSAGE/ message, without the program taking any action. To give the
UDSMESSAGES program control over when, where, and how such messages are
issued, use the GETERROR statement instead. The UDSMSG
option causes error messages to be printed whether or not you
use the GETERROR statement.

6.4.2. Examples
The following example registers an unnamed thread with application group UDSSRC.
Since it specifies no access option, it uses the default option, UPDATE(DEFERRED).
This statement does not instruct RDMS to print error messages.

BEGIN THREAD FOR udssrc

The next example is like the preceding example except that it specifies the UPDATE
access option. It does not specify a recovery option, however; therefore, it uses the
default option DEFERRED.

BEGIN THREAD FOR udssrc UPDATE

The next example registers thread T1 with RDMS in application group UDSSRC. This
thread cannot update the database. The UDSMSG option means that if RDMS or
UDS Control detects any errors while processing this thread, it immediately prints an
appropriate error message.

BEGIN THREAD t1 FOR udssrc READ UDSMSG

The next example registers thread PUBS in application group alias ACCT_APP. This
thread can update the database. Any updates use the DEFERRED recovery option.

BEGIN THREAD pubs FOR acct_app UPDATE(DEFERRED)

6.4.3. Rules and Guidelines


Read the following rules and guidelines before using the BEGIN THREAD statement.

Determining the Application Group Name


RDMS determines the name of the application group in one of four ways at execution
time, depending on the environment of execution and following an order of
precedence and determination:

1. TIP connect
2. Interpreter BEGIN THREAD statement
3. Link of ESQL program
4. Link or collection of non-ESQL program

7830 8160–027 6–23


BEGIN THREAD

Precedence 1
Precedence 1 is the rule if the application program connects to TIP or HVTIP. The
application program must perform that connection before executing any RDMS
statement, including BEGIN THREAD. The name of the application group is therefore
determined by the TIP connection.

Precedence 2
Precedence 2 is the rule if the application program executes an interpreter BEGIN
THREAD statement. The application group name given on the BEGIN THREAD
statement is used.

Precedence 3
Precedence 3 is the rule whenever ESQL programs are compiled as follows:

@UCOB,...,APPLICATION/application-group-name

where application-group-name is the name of the application group in which the


program is compiled. If the program contains the following statement, the name of
the application group on the BEGIN THREAD statement is ignored:

EXEC SQL BEGIN THREAD FOR


APPLICATION application-group-name2 END-EXEC.

The application group in which to execute the ESQL program is bound when the
program is linked. For information on linking to application groups, see the Application
Development Programming Guide.

Link time binding means that application programs must be linked to the proper
application group. If an existing application program has an incorrect link (for example,
it erroneously links to APP$n but the application was in fact APP$m), the program is
executed in the wrong application group (in this example, APP$n instead of APP$m).

Precedence 4
Precedence 4 is an implicit RDMS thread. The application group name is determined
by which copy of element CBEP$$RSA was collected or by which copy of element
RSAC-UCSEMOM was linked. From these elements, RDMS determines which
relational intercept and connect routine (RICR) bank (UDS$RDMICR) to call.

The configuration contains this bank descriptor index (BDI) as an alias for an
application group, which in turn becomes the application group used. This implies that
it is not possible to use this method with shared I-banks, because an application group
that shares an I-bank with another application group does not have its own
UDS$RDMICR BDI.

6–24 7830 8160–027


BEGIN THREAD

Implicit BEGIN THREAD Statement


If the first SQL statement the program tries to execute is anything other than a thread
control statement (BEGIN THREAD, COMMIT, ROLLBACK, or END THREAD), RDMS
executes the following BEGIN THREAD statement by default:

BEGIN THREAD FOR application-group-name


UPDATE(DEFERRED)

where the rules for determining application-group-name are described in the


preceding subsection “Determining the Application Group Name.”

Since the implicit BEGIN THREAD statement does not use the UDSMSG option, you
must use the GETERROR statement in the program to retrieve any error messages
generated during the thread.

You cannot use an implicit BEGIN THREAD statement with IPF SQL. The first SQL
statement must be an explicit BEGIN THREAD statement.

Initial Thread Control Statements


If the first SQL statement a program tries to execute is a COMMIT, ROLLBACK or END
THREAD statement, RDMS returns an error and does not execute an implicit BEGIN
THREAD statement.

Changing Application Groups


The first BEGIN THREAD statement a program executes determines the application
group for the rest of the program execution. You cannot change the application group
within one program execution.

Accessing RDMS, DMS, and SFS Concurrently


An application program can access RDMS, Data Management System (DMS), and
Shared File System (SFS) from the same thread of an application program. You can, in
other words, access relational data, DMS network data, and SFS direct system data
format (DSDF) and multiindexed sequential access method (MSAM) data files from the
same thread.

To accomplish this, execute a BEGIN THREAD statement before executing a


DMS IMPART command or before opening an SFS file.

The BEGIN THREAD statement recovery option specified applies to all data models
used in the thread. This means that the recovery unit specified by the DMS run unit is
ignored.

7830 8160–027 6–25


BEGIN THREAD

Passing Parameters
When executing a BEGIN THREAD statement from a program through the interpreter
interface, do not pass any parameters beyond the standard command string, error
status, and auxiliary information. Additional parameters are reserved for Unisys
internal interfaces and may cause errors if you attempt to use them.

Updating Using Different Recovery Options


Assume that you update page P1 three times during a step. The three updates are
P11 (the first update), P12 (the second update), and P13 (the third update). The following
describes the results of commits and rollbacks when you use the different recovery
options.

UPDATE(DEFERRED)
The database retains the original page P1. By the time the third update takes place, P13
is already saved (that is, set aside elsewhere, not actually saved in the database). The
first two updates (P11 and P12) are discarded.

A COMMIT or END THREAD statement executed at this time causes RDMS to discard
P1 from the database and replace it with the updated copy P13.

If a rollback occurs instead, however, either because you execute a ROLLBACK


statement or because of an error, RDMS does not take action on the database and
discards the copy P13. Thus, the database retains its original form (P1).

UPDATE(QUICKLOOKS)
The database contains P13 and the quick-look copy saves the original page P1. Here
“database” means the permanent copy of the database, including working copies of
updated pages that are not yet permanent.

A COMMIT or END THREAD statement executed at this time causes RDMS to discard
P1 (which was taken as a quick-look) and make database page P13 permanent.

If a rollback occurs instead, however, either because you execute a ROLLBACK


statement or because of an error that causes a rollback, the quick-look copy P1
replaces P13 in the database.

UPDATE(COMMANDLOOKS)
The image of the current page is saved not only before the first update in the step
takes place, but also before each statement that updates the page.

If you update page P1 twice during the current step to P11 and then to P12, both the
original page (P1) and the copy taken just before the second update P12 are saved. The
database contains P12.

Suppose RDMS then encounters a problem with the second update statement that
results in a statement rollback. If the second update statement is undone because of
an error, the P12 copy is removed from the database and replaced with P11, the copy
saved just before the second update statement.

6–26 7830 8160–027


BEGIN THREAD

If the second update statement is executed successfully and the updates are
committed with a COMMIT or END THREAD statement, both backup copies (P1 and
P11) are discarded. The database contains a permanent copy of P12.

On the other hand, if a ROLLBACK statement is executed or if the current step is


rolled back by RDMS because of a more serious error, the original page P1 replaces
the P12 copy in the database.

UPDATE(NONE)
No recovery occurs during the thread. This means that all changes are made directly to
the database and that UDS Control does not save original copies of updated pages in a
recovery file. You can use this option only when updating a table located in a
nonrecoverable storage area.

The use of NONE always introduces the danger of database corruption. When
UDS Control internal main storage data page buffers in the page D-banks fill up,
UDS Control writes some of the nonrecovered, updated pages to their storage areas
in mass storage to make room for new pages.

If a thread is rolled back, updated pages in the page D-banks are discarded, but pages
written to their storage areas are unaffected. This causes serious inconsistencies and
corruption in the database.

7830 8160–027 6–27


CALL

6.5. CALL
Use the CALL statement to invoke a previously defined stored procedure.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes No Yes No P

* Not IPF SQL

6.5.1. Syntax
SQL Syntax
CALL [schema-name.]routine-name ([ parameter [ ,parameter ] ...])
[UPDATE COUNT OFF]

Syntax When Used in Routines or Triggers


CALL [schema-name.]routine-name ([ parameter [ ,parameter ] ...])

where:

schema-name
is the name of the schema that contains the procedure.

routine-name
is the name of the procedure.

Schema and routine names must be valid names as defined in 2.2.1.

parameter
is the parameter or parameters to pass to the procedure. The number and type of
parameters specified here must match the number and type of parameters on the
procedure or function declaration. See your compiler documentation for
information on type compatibility.

UPDATE COUNT OFF


For this CALL or SET, the specification of UPDATE COUNT OFF on the CALL or SET
statement overrides a global SET RESULT SET UPDATE COUNT ON statement.
UPDATE COUNT OFF is not allowed in stored procedures or triggers or in ESQL.

When a CALL statement is used outside of a routine or trigger, you can use indicator
variables as parameters for specifying or retrieving null values. The use of indicator
variables in a procedure invocation is identical to their use in any other context. When
a CALL statement is used within a routine or trigger, indicator variables may not be
used.

6–28 7830 8160–027


CALL

Valid values for parameters depend on the type of formal parameter. The data type of
the actual parameter passed from the calling program, routine, or trigger must be as
indicated for the parameter in the procedure declaration. For more information on the
PROCEDURE statement, see 9.6.

You can refer to the procedure declaration or use the GET PARAMETERS statement to
determine the formal type of each parameter.

You must initialize the variables used as IN and INOUT parameters to valid values
before executing the CALL statement. RDMS returns an error on an uninitialized input
parameter if its contents are not legal for its data type.

You must use the parentheses in all cases, even if the stored procedure has no
parameters.

6.5.2. Examples
The following example, which has no parameters, calls the procedure
UPDATE_HOUSE_PRICE:

This is the procedure declaration:

PROCEDURE house_schema.update_house_price( )
UPDATE houses SET price = 21000 WHERE price = 20000;

This is the procedure invocation:

CALL house_schema.update_house_price( );

The next example calls procedure SELECT_HOUSES, passes MAX_PRICE as an input


parameter into the placeholder variable $P1, and returns the value HOW_MANY
into $P2:

This is the procedure declaration:

PROCEDURE house_schema.select_houses
(IN max_price NUMERIC, OUT how_many NUMERIC)
SELECT COUNT(*) INTO how_many FROM houses;

This is the procedure invocation:

CALL house_schema.select_houses($p1, $p2);

The final example, also based on the preceding example, passes a constant for
MAX_PRICE as a numeric literal:

CALL house_schema.select_houses(80000, $p1);

7830 8160–027 6–29


CALL

6.5.3. Rules and Guidelines


Read the following rules and guidelines before using the CALL statement.

Nested Invokes
You can use a CALL statement to invoke a stored procedure within a routine or
trigger. The invoked stored procedure must have either been successfully created
prior to its reference or it must be the same as the procedure being defined (recursive
reference).

Note: A nested stored procedure has no knowledge of the SQL variables,


parameters, cursors, RDMSAUXINFO value, or SQLSTATE value of the invoking
routine. Any information from the invoking routine that is needed by the invoked
stored procedure must be passed as parameters of the invoked stored procedure.

Invoking Procedures and Functions


Use the CALL statement to invoke a stored procedure. Use the nonstandard SET
statement to invoke a stored function.

Errors
If an error occurs during the execution of a stored procedure, control returns
immediately to the caller. The caller must examine the error variable for more
information (refer to Appendix B and Appendix C).

6–30 7830 8160–027


CLOSE

6.6. CLOSE
Use the CLOSE statement to release an opened cursor.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No E/X

6.6.1. Syntax
SQL 92 Syntax (Entry Level)
CLOSE cursor-name

RDMS Extended Syntax


{ CLOSE │ RELEASE [ CURSOR ] } cursor-name

Syntax When Used in Routines or Triggers


CLOSE cursor-name

where cursor-name is the name of the opened cursor being released.

Note: The RELEASE [CURSOR] form is not allowed in ESQL, routines, or triggers.

6.6.2. Example
The following example releases the cursor MATCHPRICE:

CLOSE matchprice

6.6.3. Rules and Guidelines


Read the following rules and guidelines before using the CLOSE statement.

Effect
Memory allocated to the cursor by the OPEN statement is still occupied, and the
processing performed during cursor declaration is not lost. The cursor is inaccessible
until it is reopened, however.

Usage
The CLOSE statement is optional in the interpreter interface. When you use the
interpreter interface, two consecutive OPEN statements on the same cursor imply a
CLOSE statement of the cursor before RDMS reopens it.

In ESQL, the cursor must be open; otherwise, an error status is returned.

7830 8160–027 6–31


CLOSE

Automatic Cursor Closure


Unless RETENTION is specified in a DECLARE CURSOR statement, RDMS
automatically closes cursors if a COMMIT statement is executed.

Performance
Opened cursors occupy space in memory. In some cases, closing an idle cursor frees
up the space it was using and can improve performance.

Routines and Triggers and the CLOSE CURSOR Statement


The cursor being closed must have been defined by a DECLARE CURSOR statement
specified within the same compound statement as the CLOSE statement or at an
outer level of nesting. The cursor name reference is resolved during routine or trigger
creation.

If you attempt to close a cursor that has not been opened, RDMS returns an error
status. This check is made during routine or trigger execution. This error terminates
the execution of a routine or trigger.

All cursors declared within a compound statement are automatically closed, if open,
and dropped when the END statement of that compound statement is executed.

6–32 7830 8160–027


COMMIT

6.7. COMMIT
Use the COMMIT statement to write all updates made to the database since the
beginning of the step (that is, since the last thread control statement).

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes* Yes No E/X

* See 6.7.3 on implicit threads.

6.7.1. Syntax
SQL 92 Syntax (Entry Level)
COMMIT WORK

RDMS Extended Syntax


COMMIT [ WORK │ THREAD ] [ ADVANCE │ TERMINATE ]

where ADVANCE and TERMINATE are Step Control options and cause the operating
system to advance or terminate its current Integrated Recovery step. In any case,
RDMS assumes that a COMMIT statement terminates the thread’s step.

• ADVANCE advances the operating system Integrated Recovery step counter but
does not end the Integrated Recovery step, even though RDMS considers the
thread’s step ended.
• TERMINATE ends the current Integrated Recovery step.

If you do not specify ADVANCE or TERMINATE, the run’s VALTAB parameter for
transaction programs contains the default option. For all other programs, the default
option is TERMINATE, unless the program was connected to TIP before the start of
the current step; in that case, you should specify the default option when connecting
to TIP.

6.7.2. Example
The following example writes all updates for the current step (that is, since the last
thread control statement) to the database:

COMMIT WORK

7830 8160–027 6–33


COMMIT

6.7.3. Rules and Guidelines


Read the following rules and guidelines before using the COMMIT statement.

Effect on Recovery Steps


The COMMIT statement also ends the thread’s current step, but may or may not end
the current Integrated Recovery step on the operating system, depending on the Step
Control option you specify.

For more information on recovery steps and the Integrated Recovery step counter,
consult with your database administrator and see

• Integrated Recovery Utility Operations Guide


• Exec Administration Reference Manual
• Exec Installation and Configuration Guide

Effect on Locks
Committing a thread releases all locks except those set by LOCK statements.

Effect on Cursors
Committing a thread closes all opened cursors except those declared with
RETENTION specified. For more information about cursors, see the following:

• 7.4 (DECLARE CURSOR)


• 7.6 (DROP CURSOR)
• 9.2 (LOCATE)

Effect on Prepared Statements


Prepared statements (see 9.5) executed before a COMMIT statement are not available
after the COMMIT statement, except for prepared query specifications of cursors
allocated with RETENTION specified.

Effect on Temporary Tables


When the COMMIT statement is executed, all records are removed from a global
temporary table unless its declarations include ON COMMIT PRESERVE.

Implicit Threads and Prepared COMMIT Statements


You can prepare and execute a COMMIT statement only from an implicit thread
(see 6.7).

Errors
If an error occurs on a COMMIT statement, you must terminate the thread with an
END THREAD statement before attempting to execute further SQL statements,
whether the thread is explicit or implicit.

6–34 7830 8160–027


CREATE INDEX

6.8. CREATE INDEX


Use the CREATE INDEX statement to add a secondary index. If the table has an owner,
only the owner can add the secondary index.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No X

6.8.1. RDMS Extended Syntax


CREATE [ UNIQUE ] INDEX index-name [ FLASH ] [ LOCAL ]

ON table-specification (sort-column-list)

[ storage-area-specification ]

[ index-partition-specification ]

where:

UNIQUE
indicates that no duplicate records are allowed in the index. This is an
alternative to using the ALTER TABLE ADD CONSTRAINT UNIQUE syntax.

index-name
is the name for the index you are creating.

FLASH
indicates that this index is a flash index. A flash index links a secondary index
to the primary index to allow significant performance improvements for key
searches. When FLASH is specified and the table is partitioned, LOCAL must
also be specified.

LOCAL
indicates that this index is local rather than global (default). To have a local
index, the table must be partitioned. A local index allows you to use partition
manipulation commands such as DETACH and HIDE. See 6.8.3 for more
information about using local indexes.

table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.

sort-column-list
is a list of the columns to make up the index and their sorting order. A
secondary index can contain up to 25 columns. Use commas between items in
the list.

7830 8160–027 6–35


CREATE INDEX

The format for each item in the list is

column-name [ ASCENDING │ DESCENDING ]

where ASCENDING (default) or DESCENDING (or abbreviation ASC or DESC)


sorts in ascending or descending order. For CHARACTER columns, the column
definition's implicit or explicit collation order is used.

A null in a secondary index column is considered greater than any nonnull in


the column in determining the ascending ordering of the index, and vice versa
for descending. A secondary index should not include an approximate numeric
column.

storage-area-specification
has the form

IN storage-area-name

where storage-area-name is the name for the storage area for the index as
defined in 2.2.5. You must create the storage area before executing the CREATE
INDEX statement. You cannot specify a storage area name if the table was
created with the CREATE TABLE statement and the storage area was implicitly
defined by RDMS (see 6.11). The storage-area-specification is allowed only for
global indexes, when the table is partitioned.

index-partition-specification
partitions a secondary index according to the leading columns specified in the
index specification followed by the leading columns of the primary key. The
index-partition-specification partitions an index constraint according to the
leading columns specified in the index specification.

This clause defines the storage areas where ranges of the index records are
placed. If specified, this is the only place you may specify a storage area for the
index or constraint. The maximum number of partitions per secondary index is
511.

Format
PARTITION INDEX index-name
index-storage-area-specification [,index-storage-area-
specification] ...

where:

index-name
is the name of the secondary index or unique constraint being partitioned.

index-storage-area-specification
is as follows:

partition-name [ partition-range ] IN storage-area-name

6–36 7830 8160–027


CREATE INDEX

where:

partition-name
is the name of the partition. All partitions in a table must have unique
names.

partition-range
is as follows:

<= (column-upper-bound [ ,column-upper-bound ]... )

The partition-range is not allowed for local indexes but is required for
global indexes.

IN storage-area-name
is the name of the storage area where the index records belonging in the
range of this partition are stored, as defined in 2.2.5. The data format must be
RSM-INDEX-ONLY.

Each index partition may have different storage area attributes, except for
the data format, directory-id, logging, and lock-strategy, which must be
identical. This allows the page-size to be different for different partitions, for
example.

The same storage area cannot be used in multiple partitions, and it cannot
contain multiple B-trees.

6.8.2. Examples
The following examples create identical indexes with ascending house numbers and
descending locations:

CREATE INDEX ix5 ON houses (hno ASC, location DESC)

CREATE INDEX ix6 ON houses (hno, location DESC)

The next examples create identical indexes in different storage areas:

CREATE INDEX ix7 ON houses (hno ASC, location DESC) IN mf.a3

CREATE INDEX ix8 ON houses (hno ASC, location DESC) IN mf.a2

The partitions of index ix9 cover all possible values that can be inserted. Because of
this, an error does not occur for the CREATE INDEX statement when a value is out of
range of all partitions.

CREATE INDEX ix9 ON mybank.today(c_check_number ASC,c_check_amount ASC)


PARTITION INDEX ix9
ix9_part_1<=(99999, 12000) in SI1,
ix9_part_2<=(99999, MAXVALUE) in SI2,
ix9_part_2<=(MAXVALUE, MAXVALUE) in SI3

7830 8160–027 6–37


CREATE INDEX

The partitions of index ix10 do not cover all possible values that can be inserted.
RDMS issues an error if the table mybank.today contains any record in which
c_check_number is greater than 199999.

CREATE INDEX ix10 ON mybank.today(c_check_number ASC)


PARTITION INDEX ix10
ix10_part_1<=99999 in SI1,
ix10_part_2<=199999 in SI2

6.8.3. Rules and Guidelines


Read the following rules and guidelines before using the CREATE INDEX statement.

Partitioned Tables
If the primary key or any index is partitioned, the table is called a partitioned table. For
a partitioned table, each primary key and index must be in its own storage area. It is
not possible for the primary key or any index of a partitioned table to share storage
areas. In a partitioned table, the primary key and all indexes must be partitioned (even
if they only have one partition whose upper bound is MAXVALUE).

If index-partition-specification is specified, storage-area-specification may not be


specified.

When the CREATE INDEX command is issued, the partitions of the primary key can be
in the attached, detached, or hidden state. However, they are treated as though they
are in the attached state in that the index is populated with a record for every record
in the primary key, regardless of the state of the primary key partition.

Partitions created via the CREATE INDEX command begin in an attached state.

Caution
DROP INDEX, DROP PARTITION, and DROP TABLE do not clear the storage
area(s) containing the partition. If you are reusing a storage area and expect
it to be empty, you must initialize it using the UREP PROCESS STORAGE
AREA … DELETE and PROCESS STORAGE AREA … INSTALL commands.

LOCAL Indexes
For a LOCAL index, there must be an index-partition-specification clause for every
primary key partition. The partition name must be the same as the primary key
partition name. Every partition must have an index-storage-area-specification. For
LOCAL indexes, however, the partition-range is not allowed.

6–38 7830 8160–027


CREATE INDEX

Example
The following is an example table definition.

CREATE TABLE softball_table


(
name: CHARACTER(24) NOT NULL,
position: CHARACTER(12),
emp_number: CHARACTER(16),
CONSTRAINT softball_table_pk PRIMARY KEY(name ASC),
CONSTRAINT softball_table_fk FOREIGN KEY (emp_number) REFERENCES
personnel_table (emp_number)
PARTITION PRIMARY KEY
p1 <= 'M' IN (DATA softball_data_sa1, INDEX softball_index_sa1),
p2 <= MAXVALUE IN (DATA softball_data_sa2, INDEX softball_index_sa2))

To create a LOCAL index on emp_number, the index definition must include the
primary key partition keys, specified in the same order and sort direction as the
primary key partition definition.

CREATE INDEX ix10 LOCAL


ON softball_table (name ASC, emp_number ASC)
PARTITION INDEX ix10
P1 in softball_local_sa1,
P2 in softball_local_sa2;

Note: CREATE INDEX always populates pages with a 100 percent load factor.

Performance
If a table is very large, RDMS can take a long time to execute a CREATE INDEX
statement, because it must create a data structure that contains as many rows as the
table contains.

You should use the QUICKLOOKS recovery option in the BEGIN THREAD statement
when creating or dropping a secondary index, to ensure adequate performance.

Limits
You can have up to 50 secondary indexes and unique constraints in a table. A
secondary index can include up to 25 columns. The maximum number of partitions per
secondary index or unique constraint is 511.

Storage Area Designation


The optional IN clause lets you designate a storage area for the new secondary index
pages. If you omit the IN clause, RDMS uses the storage area that contains the
primary key index pages.

7830 8160–027 6–39


CREATE INDEX

The storage area for the secondary index should have a data format
RSM-INDEX-ONLY, or RSM if the storage area contains the primary key data pages.
For more information, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

Effect on Compiled Programs


Changes made by the CREATE INDEX statement may invalidate previously compiled
programs, requiring these programs to be recompiled (without any logic changes).

Changes have no effect on previously compiled interactive interface programs (aside


from performance during execution). For more information, see 2.11.2.

Effect on Search Paths


Creating a new secondary index for a table can change the access path used by
existing cursors and other SQL statements. This is normally desirable, for example, if
the new access paths have better performance than the old access paths.

However, it is possible for a program to use RDMS SQL in such a way that the
program depends on the access path used by RDMS. In this case, when you create a
new secondary index, existing programs may no longer work as required.

Here are examples of the types of programs that may be affected:

• A program is dependent on the order of the rows of a cursor result set, but the
ORDER BY clause is not used on the cursor declaration.
• A program opens a sensitive or asensitive cursor, and then the program updates
the table used by the cursor. The updated rows can become part of the cursor
result set. The position of the updated rows in the result set, relative to the
current cursor position, depends on the access path, but the program assumes
that the updated rows are always before (or after) the current cursor position.

Effect on Triggers
The CREATE INDEX statement causes triggers to be implicitly dropped if the trigger
references the table. The implicit dropping of triggers can be prevented through the
use of the UREP configuration attribute RDMS-TRIGGER-DROPPING.
RDMS-TRIGGER-DROPPING is set to CASCADE by default. CASCADE allows RDMS to
drop any triggers associated with the create index table. Setting
RDMS-TRIGGER-DROPPING to RESTRICT, causes any CREATE INDEX statement to fail
if it would cause the implicit dropping of a trigger.

6–40 7830 8160–027


CREATE ROLE

6.9. CREATE ROLE


Use the CREATE ROLE statement to create a new role. Roles are used as a ‘shortcut’
for performing a large number of grants to a user. Privileges are granted to the role,
and then the user is granted membership in the role.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No X

6.9.1. Syntax
CREATE ROLE role-name

where role-name can consist of numbers between 1 and 29 ASCII (not UNICODE or
KANJI), characters between A-Z, 0-9, period, and hyphen. The best practice is to use
an invalid user ID as a role name. To do this, use a name between 13 and 29
characters. You can also use a valid user ID, and role name of any length. Do not use
the prefix “RDMS-“, because it is used by RDMS predefined roles.

6.9.2. Examples
CREATE ROLE "ROLE-PROGRAMMER"

6.9.3. Rules and Guidelines


The user ID that creates the role becomes the owner of the role. Only the owner of
the role can drop the role and associate a user with that role. Normally (unless a
separate security officer exists on site), the owner of the role must be the same as
the owner of the tables, for example, the DBA.

The grant of privileges to the role must not include WITH GRANT OPTION.

A site can create any number of roles, but it is anticipated that a given site probably
creates 10 or less.

The CREATE ROLE statement must not be included as part of a CREATE SCHEMA
statement and it cannot be executed as part of a routine or trigger.

The value of aux-info is zero following successful execution of CREATE ROLE.

To execute the CREATE ROLE statement the user must be a member of RDMS
predefined role "RDMS-ROLE-CREATOR." The user ID that installs UREP is the owner
of role "RDMS-ROLE-CREATOR", and therefore can always issue the CREATE ROLE
statement.

7830 8160–027 6–41


CREATE SCHEMA

6.10. CREATE SCHEMA


Use the CREATE SCHEMA statement to create a new schema.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No E

6.10.1. SQL 92 Syntax (Entry Level)


CREATE SCHEMA [schema-name] AUTHORIZATION authorization-id

[ { table-definition │ view-definition │

privilege-definition } ]

where:

schema-name
is a valid identifier, as defined in 2.2.1. If you omit the schema name, RDMS
uses the authorization-id.

authorization-id
is your session user ID. Use uppercase letters only.

table-definition
is the standard SQL CREATE TABLE statement.

view-definition
is the standard SQL CREATE VIEW statement.

privilege-definition
is the standard SQL GRANT statement.

6–42 7830 8160–027


CREATE SCHEMA

6.10.2. Example
The following example creates two tables, one view, and grants privileges to another
user. Assume that DRUID is a valid user ID.

CREATE SCHEMA AUTHORIZATION DRUID


CREATE TABLE t01
(col1 : CHAR(10) NOT NULL PRIMARY KEY,
col2 : CHAR(10)
)
CREATE VIEW v01 (vcol1,vcol2)
AS SELECT col1, col2 FROM t01
CREATE TABLE t02
(col1 : CHAR(10) NOT NULL PRIMARY KEY,
col2 : CHAR(10)
)
GRANT SELECT ON t01 TO jacques

This establishes authorization-id DRUID as the owner of tables and view T01, V01,
and T02. View access control is active for V01 and table access control is active for
T01 and T02. DRUID is the grantor of select privileges to JACQUES for the first table,
T01.

6.10.3. Rules and Guidelines


Read the following rules and guidelines before using the CREATE SCHEMA statement.

Use of Standard Statements


Use standard SQL CREATE TABLE, CREATE VIEW, and GRANT statements only.

User IDs
If a user ID starts with a number, express it as a delimited uppercase identifier as
illustrated in the following examples:

"1BIG" "2NOT" "3ORG"

RDMS converts undelimited lowercase user IDs to uppercase. RDMS rejects delimited
lowercase user IDs (for example, “Mary”) for the authorization-id (use “MARY”
instead).

RDMS does not verify the existence of the user ID on the system. If you specify a
nonexisting user ID and data access control is active, the data is inaccessible to other
users until the user ID is defined on the local database system.

7830 8160–027 6–43


CREATE SCHEMA

Owned and Unowned Schemas and Security


A schema that is created by the CREATE SCHEMA statement is referred to as an
owned schema. A schema created through UREP is referred to as an unowned
schema.

All tables and views in an owned schema are owned by the user specified in the
authorization-id of the CREATE SCHEMA statement.

Data access control is implicitly active for all tables and views in owned schemas.

In owned schemas, ownership and security are turned on for all tables and views, and
these attributes cannot be altered. If the user ID for the current session does not
match the authorization-id specified in the CREATE SCHEMA statement, RDMS
returns an error. RDMS rejects delimited lowercase authorization-ids (for example,
“Mary”) for the authorization-id (use “MARY” instead.)

You cannot relate an entity in an owned schema to an unowned schema:

• You cannot define a foreign key on a table in an owned schema that refers to a
table in an unowned schema, and vice versa.
• You cannot create a table in an owned schema that is associated with a storage
area in an unowned schema, and vice versa.
• You cannot create a view in an owned schema that refers to a table in an
unowned schema, and vice versa.

You can create a routine or trigger in an owned schema only. A routine can access
tables and views in both owned and unowned schemas. A trigger can only access
objects that are unowned or owned by the trigger creator.

Note: For DECIMAL items defined in an owned schema, the number of decimal
digits stored in the UREP metadatabase is one greater than the number of decimal
digits in the original definition. This is because of the difference in the semantics of
this value between the SQL standard and RDMS. For more information, see 2.8.2.

Table and View Name Qualifiers


If the table specification used in the table, view, or privilege definition is explicitly
qualified, the qualifier must be the schema name of the CREATE SCHEMA statement.

If the table specification does not include a qualifier, RDMS implicitly qualifies it with
the schema name.

6–44 7830 8160–027


CREATE TABLE

6.11. CREATE TABLE


Use the CREATE TABLE statement to add a new relational table to the database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard*
Yes Yes No Yes No E/I/F/X

* RDMS supports the SQL 92 intermediate level data types DATE, TIME, and TIMESTAMP, as
well as the SQL 92 entry level data types. RDMS supports character handling from the SQL
92 intermediate and full level.

6.11.1. Syntax
SQL 92 Syntax (Entry Level)
CREATE [ GLOBAL TEMPORARY ] TABLE table-specification

( { column-definition │ table-constraint-specification }

[, { column-definition │ table-constraint-specification } ]...)

[ ON COMMIT { PRESERVE | DELETE } ROWS ]

[ ON ROLLBACK { PRESERVE | DELETE } ROWS ]

Note: ON COMMIT and ON ROLLBACK apply only to GLOBAL TEMPORARY tables.

RDMS Extended Syntax 1


CREATE [ GLOBAL TEMPORARY ] TABLE table-specification

( [ table-storage-area, ] column-definition

[ , { column-definition │ table-constraint-specification } ] ...

[ [ , ] index-specification ...]

[ partition-primary-key-specification [ partition-index-specification
]...])

[ ON COMMIT { PRESERVE | DELETE } ROWS ]

[ ON ROLLBACK { PRESERVE | DELETE } ROWS ]

Notes:
• Only one storage area specification is allowed if the table is not partitioned.
• The index specification must be the second to the last clause.
• The partition specification must be the last clause.
• ON COMMIT and ON ROLLBACK apply only to GLOBAL TEMPORARY tables.

7830 8160–027 6–45


CREATE TABLE

RDMS Extended Syntax 2


This form of the CREATE TABLE command must either contain a storage-area-
specification for a nonpartitioned table, or a partition-specification for the primary
key.

{ CREATE │ DEFINE } [ GLOBAL TEMPORARY | PERMANENT ] TABLE

table-specification [ table-storage-area ]

COLUMNS [ ARE ] column-definition

[, { column-definition │ table-constraint-specification } ]...

primary-key-specification

[ foreign-key-specification ...]

[ index-specification ...]

[ owner-specification ]

[ access-specification ]

[ partition-primary-key-specification [ partition-index-specification
] ...]

[ ON COMMIT { PRESERVE | DELETE } ROWS ]

[ ON ROLLBACK { PRESERVE | DELETE } ROWS ]

Notes:
• A column definition must always precede any table constraint that references
that column.
• No storage area specification is allowed for a GLOBAL TEMPORARY table.
• ON COMMIT and ON ROLLBACK apply only to GLOBAL TEMPORARY tables.

Global Temporary and Permanent Tables


If GLOBAL TEMPORARY is specified in the CREATE TABLE syntax, the table is created
as a global temporary table. If GLOBAL TEMPORARY is not specified, the table is
created as a persistent base table (PERMANENT table).

A global temporary table has a persistent definition, but the data is not persistent. By
default, a temporary table is emptied upon a commit, rollback, or END THREAD.

The ON COMMIT and ON ROLLBACK clauses apply only to global temporary tables. If
you specify ON COMMIT PRESERVE ROWS or ON ROLLBACK PRESERVE ROWS, the
table remains populated with data after a commit or rollback. The default actions are
specified by ON COMMIT DELETE ROWS and ON ROLLBACK DELETE ROWS.

For more information about using global temporary tables, see in 6.11.14.

6–46 7830 8160–027


CREATE TABLE

Storage Area Names


Storage areas are UREP definitions of underlying TIP or Exec files. Storage areas are
where RDMS stores the data pages and index pages for a table. In the CREATE TABLE
syntax, you can specify zero, one, or several storage area names, as follows:

• Zero storage area names


Standard SQL has no clause to tell RDMS where to store the data and index pages
associated with the table. RDMS implicitly creates a storage area whose name
matches the table name. RDMS implicitly creates an underlying Exec file whose
name is created uniquely from a system counter. RDMS writes the table’s data
pages and index pages to this file.
• One storage area name
RDMS Extended Syntax 1 and 2 allow you to specify one storage area name
immediately following the table-specification. If you specify only one storage
name in CREATE TABLE syntax, RDMS writes the table’s data pages and index
pages to this file.
• Several storage names
RDMS Extended Syntax 1 and 2 allow you to specify several storage area names.
This is called a multifile table. Where the names are allowed in the syntax
depends on whether the table is partitioned, as follows:.
− Table not partitioned
RDMS allows you to specify different storage areas for the data pages and
index pages. It allows one storage area for the table’s data pages, one
storage area for the primary key index, one storage area for each secondary
key index, and one storage area for each unique constraint index.
− Table partitioned
RDMS allows you to specify different storage areas for the data pages and
index pages for each partition. It allows one storage area for each partition of
the table’s data pages, one storage area for each partition of the primary key
index, one storage area for each partition of each secondary key index, and
one storage area for each partition of each unique constraint index.

See the following descriptions of each clause (6.11.2 through 6.11.12) for more
information.

7830 8160–027 6–47


CREATE TABLE

6.11.2. Table-Specification Clause


The table-specification clause is the name for the table.
Format
[schema.] table-name

where:

schema
is the name of the schema containing the table. If the schema is an owned
schema, only the owner can execute the CREATE TABLE command. (See 6.10
for more information about owned schemas.) If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses
the default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information see the Repository for
ClearPath OS 2200 Administration Guide.

table–name
is the name of the table following the naming conventions in 2.2.1. Version
names are not allowed since only one definition exists for all versions of the
same table.

6.11.3. Table-Storage-Area Clause


The table-storage-area clause identifies the storage area in which RDMS stores the
data pages for this table. If the table is partitioned, this clause is not allowed; you must
put the storage area name on the partition-primary-key-specification clause instead.

If you omit this clause, RDMS implicitly creates a storage area whose name matches
the table name. RDMS implicitly creates an underlying Exec file, the name of which is
created uniquely from a system counter.

If you include this clause, the storage area must have one of the following attributes:

• DATA-FORMAT RSM, if you want the storage area to hold both data pages and
index pages for the table
• DATA-FORMAT RSM-DATA-ONLY, if you want the storage area to hold only the
table’s data pages and another storage areas to hold the table’s index pages

If you include a storage area name on a primary-key-specification, a


table-constraint-specification, or an index-specification clause and the storage area
name is different from the one you included on the table-storage-area clause, then the
storage area you use on the table-storage-area clause must have DATA-FORMAT
RSM-DATA-ONLY.

6–48 7830 8160–027


CREATE TABLE

Format
IN storage-area-name

where storage-area-name is the name of the storage area as defined in 2.2.5.

6.11.4. Column-Definition Clause


The column-definition clause is the name, data type, size, and scale of each column in
the table. At most, 510 columns can be specified in a CREATE TABLE statement (509 if
there is no explicitly defined primary key).
Format
column-name [:] data-type
[default-clause | generated-default-clause ]
[column-constraints] [collate-clause]

where:

column-name
is the name for the column as defined in 2.2.3.

data-type
is a data type as defined in 2.8. Refer also to 2.9.1 and 2.9.2 for information on
character value assignment and internationalization considerations for character
data.

default-clause
is the default value for the column in the form

DEFAULT { literal │ USER │ NULL │ datetime-function }

where datetime-function can be CURRENT_DATE, CURRENT_TIME, or


CURRENT_TIMESTAMP (see 2.5.7).

generated-default-clause
All columns of the primary key must be ascending when the table contains a
generated default clause. If the generated expression is on a column that is part
of an index, all columns within that index must also be ascending.

All columns that have generated defaults must be part of either the primary key or
an index.

GENERATED {ALWAYS | BY DEFAULT } AS


{ ( { function } ) | IDENTITY [( generator-options )] }

7830 8160–027 6–49


CREATE TABLE

GENERATED
GENERATED ALWAYS means that it is not possible for an application program to
specify a value for the column on the INSERT statement1 . The column must either
be omitted from the INSERT (the column-name-list or column-and-value) or must
be specified using the DEFAULT keyword. RDMS always generates the value for
the column.

GENERATED BY DEFAULT means that if the application program supplied the


column’s value, that value is used. Otherwise, RDMS generates the value for the
column.

AS
This clause tells RDMS how to generate the value:

function can be any of the following:

CURRENT_DATE
CURRENT_TIME [ (time-precision) ]
CURRENT_TIMESTAMP [ (timestamp-precision) ]
partition_id()
IDENTITY [ ( generator-options ) ]

IDENTITY can be specified at most once per table. There is at most one
generated-default-clause for each primary key or index or unique constraint, but
only two are allowed for each table—either identity or partition_id() on the primary
key and an index whose leading column is generated as current_date,
current_time, or current_timestamp. IDENTITY and partition_id() need not be the
entire primary key; however, they must be the leading primary key column. The
nonleading primary key columns may not be data type CHARACTER WITH
CHARACTER SET and COLLATION. When IDENTITY is used, the table cannot be
partitioned. When partition_id() is used, the table must be partitioned. The primary
key column must be an ascending key. When the column is generated AS {
function }, that column must be the leading primary key or index column. All
columns of the primary key or index must be ascending.

The expression following the AS is the same format as can be specified as a


DEFAULT clause. This means that the following are equivalent logically, but not in
the way locking is performed:

DEFAULT CURRENT_TIMESTAMP
and
GENERATED BY DEFAULT AS (CURRENT_TIMESTAMP) CACHE 0

___________________
1
LOAD ignores GENERATED ALWAYS, so values can be specified on LOAD.

6–50 7830 8160–027


CREATE TABLE

‘GENERATED BY DEFAULT AS (CURRENT_TIMESTAMP)’ is logically the same as


‘DEFAULT CURRENT_TIMESTAMP’. However, the inserts are ordered such that
once RDMS generates the timestamp, it does not generate a timestamp for
another run until the record containing the timestamp that was just generated has
been inserted into the table.

When the leading key column is IDENTITY or partition_id(), RDMS knows there is a
range. RDMS performs preconditioning such that each value of the identity column
is placed on a different page.

cache-option

{ CACHE [num-values-to-precondition | DYNAMIC] |


NO CACHE | NOCACHE }

where num-values-to-precondition is an unsigned integer from 0 to 262143 that


signifies how many key values to precondition at once. It gives RDMS an
approximation of how much preconditioning the user wants done at any one time.

For example, a very large value, such as 262143, directs RDMS to precondition as
much as is reasonable. CACHE 0 and CACHE 1 are exact, meaning RDMS
preconditions exactly 0 or 1 page respectively. When num-values-to-precondition
>= 2, RDMS rounds up, or down, to internally defined limits to get the most
preconditioning done for the same cost. For example, if a level 1 index page has
room for 10 index records, but the user specified CACHE 9 (or CACHE 11) RDMS
might operate as though CACHE 10 were specified. This enables RDMS to
completely fill the index page, so that the next user to precondition can start with
a new (empty) index page. In short, when num-values-to-precondition >= 2, RDMS
uses the specified value as a hint, but still does whatever is needed to be efficient.
When CACHE is not specified, DYNAMIC is assumed. DYNAMIC instructs RDMS to
perform dynamic preconditioning efficiently. CACHE 0 turns off dynamic
preconditioning.

The most advantageous value to use depends on many factors such as number of
records for each data or index page, data or index page size, type of disks, and so
on. NO CACHE has the same semantics as CACHE(0). CACHE must be 0,
DYNAMIC, or 1 when current_time or current_timestamp is used.

When CACHE is not specified, DYNAMIC is assumed. CACHE DYNAMIC along with
current_date, current_time or current_timestamp operates as though CACHE 1
were specified.

The CACHE clause is also one of the attributes that determines the maximum
number of values that might be lost during a system restart. Refer to Relational
Database Server for ClearPath OS 2200 Administration Guide for more
information.

7830 8160–027 6–51


CREATE TABLE

generator-options

{ [START WITH start-value]


[INCREMENT BY increment-value]
[MINVALUE minimum-value | NO MINVALUE | NOMINVALUE]
[MAXVALUE maximum-value | NO MAXVALUE | NOMAXVALUE]
[CYCLE | NO CYCLE | NOCYCLE]
[cache-option] }

where start-value is a signed or unsigned integer. The possible absolute value of


the integer depends on the data type of the column. When no START WITH option
is included, RDMS uses the value 1.

Note: The ALTER TABLE includes a RESTART keyword to enable the user to
specify the next value to use when RDMS must restart the sequence.

increment-value is a signed or unsigned integer. It cannot be zero. The possible


absolute value of the integer depends on the data type of the column. When no
INCREMENT BY option is included, RDMS uses 1. A negative value for
increment-value results in a descending sequence. Descending sequences are not
supported by the initial release of this feature. If increment-value is negative or
zero, RDMS returns an error.

minimum-value and maximum-value are signed or unsigned integers. The possible


absolute value of the integer depends on the data type of the column. When the
MINVALUE option is omitted, RDMS uses the specified start-value (when no
start-value is specified, 1 is used). When the MAXVALUE option is omitted, RDMS
uses the column's largest possible value as MAXVALUE, which is determined by
the data type of the column. When CYCLE is specified, and RDMS advances the
counter to beyond the maximum-value, the counter is reset to the minimum-value.
NOCYCLE is the default.

column-constraints
restrict the values allowed for the column. Columns with data type BLOB cannot
participate in UNIQUE, CHECK, PRIMARY KEY, or REFERENCES constraints.

Format
{ NOT NULL [ [ CONSTRAINT constraint-name ] { UNIQUE │ PRIMARY KEY } ]

│ [ CONSTRAINT constraint-name ] CHECK (Boolean-expression)

│ [ CONSTRAINT constraint-name ]

REFERENCES table-specification [ (parent-column-name) ] }

6–52 7830 8160–027


CREATE TABLE

where:

NOT NULL
is data to be stored in the column that cannot be null. If you attempt to store a
null in the column, RDMS returns an error message. If you do not use NOT
NULL, nulls are allowed in the column.

constraint-name
is the name for the constraint. You can specify a name for the constraint, or
you can let RDMS attach a name to it (UNIQUE$1, . . .UNIQUE$n or
CHECK$1, . . .CHECK$n or FKEY$1, . . .FKEY$n).

UNIQUE KEY or PRIMARY KEY


establishes a unique column constraint, which ensures that no two rows in a
table have the same value in a specified column. If you specify UNIQUE KEY or
PRIMARY KEY, you must also specify NOT NULL.

If you attempt to store a duplicate row in a table, RDMS returns an error. The
number of unique constraints in a table cannot exceed 10. Only one primary
key constraint is allowed.

CHECK (Boolean-expression)
establishes a condition that every data item in this column must satisfy.
Datetime functions are not allowed. Include only this specific column name in
the Boolean expression (see 2.4.2).

REFERENCES table-specification [ (parent-column-name) ]


establishes a referential (or foreign key) column constraint. Include the table
specification and, optionally, the parent column name, which is the name of a
column in the parent table. This column must solely constitute a unique or
primary key constraint.

If you omit the name of the parent column, the parent table must contain a
primary key that consists of one column. For more information about the
correspondence between columns in parent and child tables, see the
Relational Database Server for ClearPath OS 2200 Administration Guide.

collate-clause

is the collation (sorting) order RDMS is to use for comparing and ordering data values
in a character column and the order in which to create indexes related to the column
(see 2.8.2). If you use a COLLATE clause on a column definition, you must also use a
CHARACTER SET clause. The character set on the CHARACTER SET clause must
match the character set associated with the collation name on the COLLATE clause. If
you omit this clause, the default (implicit) collation order is binary, based on the octal
character codes. With a COLLATE clause, the maximum column size is 4,085
characters.

7830 8160–027 6–53


CREATE TABLE

Rules and Guidelines for Using the GENERATED Clause


The following table describes the conditions that must be met when IDENTITY,
partition_id() or current_date, current_time, or current_timestamp are used in the
GENERATED clause.

Current_date/time/
Condition Identity Partition_id() timestamp

Restriction on Must be on the Must be on the Must be on the leading


position of column which is the column which is the column of the primary key
column within single column single column or index.
index primary key. primary key.
Restriction on Ascending only Ascending only Ascending only
sort direction
Partitioned table Table may not be Table must be Either partitioned or
partitioned. partitioned. non-partitioned is fine.
NULL values Requires NOT NULL. Requires NOT Requires NOT NULL. NOT
NOT NULL is implicit NULL. NOT NULL is NULL is implicit when the
when the column is implicit when the column is specified in a
specified in a column is specified GENERATED clause on
GENERATED clause in a GENERATED CREATE TABLE.
on CREATE TABLE. clause on CREATE
TABLE.
CACHE CACHE may be CACHE may be CACHE must be
anywhere from 0 to anywhere from 0 to DYNAMIC, 0 or 1.
262143. In the XTC 262143.
environment, unless
CACHE 0 was
specified, RDMS
operates as though
CACHE 1 were
specified.
CACHE DYNAMIC The number of index The number of 1
value records which fill a index records
page, unless this is which fill a page.
the XTC
environment in
which case RDMS
uses CACHE 1.

6–54 7830 8160–027


CREATE TABLE

Identity columns are a type of default—the default that is used by the INSERT
statement, and by UPDATE when the DEFAULT keyword is specified as the new value
of the column. You cannot specify a default-clause along with a
generated-default-clause. Columns with a generated-default-clause must be NOT
NULL. NOT NULL is implicit for columns including a generated-default-clause as part of
CREATE TABLE.

Examples Using GENERATED Clause


Example 1

The following example shows how to declare an identity column. Because none of the
generation options are explicitly specified, the following are assumed by RDMS:

• START WITH 1
• INCREMENT BY 1
• MINVALUE +1
• MAXVALUE +34359738366
• NOCYCLE
• CACHE DYNAMIC

If you define explicit storage areas for this table, you must have the following:

• merge-factor 1
• data-page-factor 1
• data-page-size 112 words
• index-page-size 1792
• lock-strategy record

CREATE TABLE my_identity


(id_col : INTEGER GENERATED BY DEFAULT AS IDENTITY
NOT NULL PRIMARY KEY,
id_name: CHARACTER(20))

7830 8160–027 6–55


CREATE TABLE

Example 2

The following example shows the use of an identity column. The identity column is
used to create a unique prescription number. Assume that the prescriptions live
forever and are never deleted. We assume that there is enough concurrency so that
dynamic preconditioning is needed, but not enough concurrency to partition the table.
The first prescription is a 4 digit number, so start with 1000. Since NOMAXVALUE is
implied, the largest prescription_no is the largest value that fits within the column’s
data type NUMERIC(21,0), which is equivalent to MAXVALUE
+999999999999999999999.

The implicit storage areas have:

• merge-factor 1
• data-page-factor 100
• page-size 896
• lock-strategy record
If explicitly defined, the storage areas must have:

• merge-factor 1
• data-page-factor 1
• data-page-size 112 words
• index-page-size 1792
• lock-strategy record

CREATE TABLE druggist.prescriptions


(prescription_no : NUMERIC2 (21,0)
GENERATED BY DEFAULT AS IDENTITY
(START WITH 1000 CACHE DYNAMIC)
NOT NULL,
drug : CHAR(32) NOT NULL,
name : CHAR(32) NOT NULL,
CONSTRAINT prescriptions_pk PRIMARY KEY (prescription_no ASC) )

Example 3

The following example shows how to use CYCLE to implement a queue as an RDMS
table. The usage of this table is to insert records at the end and delete records from
the beginning. The storage areas must have:

• merge-factor 0
• data-page-factor 1
• page-size 896 words
• lock-strategy record

6–56 7830 8160–027


CREATE TABLE

The start-value is 10000. Use merge-factor 0 for cycles because empty pages get
reused on the next cycle. Merge-factor 0 ensures that DELETE does not affect index
pages, and reduces the possibility of DELETE being involved in queuing or deadlock.

CREATE TABLE my_messages


(IN my_message_sa,
Msg_id : NUMERIC(21,0)
GENERATED BY DEFAULT AS IDENTITY
(START WITH 10000 MINVALUE 10000 MAXVALUE 40000 CYCLE)
NOT NULL PRIMARY KEY,
Msg_text : CHARACTER(2000) NOT NULL)

Example 4

This example demonstrates how to cause all records for a given value of the IDENTITY
column, which is the leading column of a multi-column key, to be written to the same
data page. For example, it is desired that records (1,1), (1,2), … (1,n) be written to a
single data page, provided there is room for all those records and that records (2,1),
(2,2), … (2,n) be written to a different data page. To do this, the storage-area
my_message_subscriptions_sa is defined with data-page-factor 100, and the table is
declared as follows (with the IDENTITY column being the first column of the two-
column primary key):

CREATE TABLE my_message_subscriptions


(IN my_message_subscriptions_sa,
Msg_id : NUMERIC(21,0)
GENERATED BY DEFAULT AS IDENTITY NOT NULL,
Channel_id : NUMERIC(21.0) NOT NULL,
CONSTRAINT multi_key_example_pk PRIMARY KEY(Msg_id ASC, Channel_id ASC))

Example 5

This example shows the use of partitioned tables. The storage areas can have:

• merge-factor 1
• data-page-factor 100
• data-page-size 1792 words
• index-page-size 1792

This provides multiple records per data page. This means that at most the number of
concurrent inserts allowed would be equal to the number of partitions. The largest
allowable value of C1 is 2000. This becomes the implicit maximum-value for the
partition_id() column. This example also demonstrates the use of the GENERATED
clause on column C1.

7830 8160–027 6–57


CREATE TABLE

CREATE TABLE t1
Columns are
C1: integer GENERATED ALWAYS AS (partition_id()),
C2: integer,
C3: integer
primary key primkey is C1 ASC
index seckey on C3
PARTITION PRIMARY KEY
P1 <= 1000 IN (DATA sa_data_p1, INDEX sa_index_p1),
P2 <= 2000 IN (DATA sa_data_p2, INDEX sa_index_p2)
PARTITION INDEX seckey
S1 <= 5000 IN sa_s1,
S2 <= 10000 IN sa_s2

Example 6

The following example shows how to inform RDMS that your leading secondary index
column is monotonically increasing, and to instruct RDMS to perform dynamic
preconditioning for that index—this reduces contention for index pages. It is useful for
RDMS to always generate the timestamp on INSERT, rather than for the user to supply
this value because it allows RDMS to synchronize the INSERT statements so that
records with lower timestamps always get inserted into the table before records with
larger timestamps. CACHE 1 indicates that RDMS is to get a single data page at a time.
This is necessary because RDMS does not know the value of the next timestamp
ahead of time. RDMS uses CACHE 1 or CACHE DYNAMIC for this case.

CREATE TABLE t1
Columns are
C1: integer GENERATED ALWAYS AS (partition_id()) NOT NULL,
C2: integer,
C3: timestamp GENERATED ALWAYS AS (CURRENT_TIMESTAMP) CACHE 1 NOT NULL
primary key primkey is C1 ASC
index seckey on C3
PARTITION PRIMARY KEY
P1 <= 1000 IN (DATA sa_data_p1, INDEX sa_index_p1),
P2 <= 2000 IN (DATA sa_data_p2, INDEX sa_index_p2)
PARTITION INDEX seckey
S1 <= 5000 IN sa_s1,
S2 <= 10000 IN sa_s2

Note: This table has two GENERATED clauses. After inserting a new row into the
table, the identity_val_local function returns the value for the column C1 since only
C1 is part of the primary key column.

6–58 7830 8160–027


CREATE TABLE

6.11.5. Table-Constraint-Specification Clause


The table-constraint-specification contains the unique, check, and foreign key table
constraints.

Columns with data type BLOB cannot participate in UNIQUE, CHECK, PRIMARY KEY, or
FOREIGN KEY constraints.

Format
[ CONSTRAINT constraint-name ]

{ UNIQUE (unique-column-list) [ storage-area-specification ]

│ PRIMARY KEY (sort-column-list) [ storage-area-specification ]

│ CHECK (Boolean-expression)

| standard-foreign-key-specification }

where:

constraint-name
is the name for the constraint. You can specify a name for the constraint, or
you can let RDMS attach a name to it (UNIQUE$1, . . .UNIQUE$n or
CHECK$1, . . .CHECK$n or FKEY$1, . . .FKEY$n).

unique-column-list
is a list of up to 25 column names. You must specify NOT NULL on each
column included in the list.

storage-area-specification
is the name of the storage area in which RDMS writes the index pages for the
unique constraint or primary key. If the table is partitioned, this clause is not
allowed; you must put the storage area name on the partition-primary-key-
specification clause or partition-index-specification clause instead.

If you omit this clause or if you include this clause and its name matches the
name on the table-storage-area clause, RDMS writes the index pages to the
storage area you included on the table-storage-area clause and its
DATA-FORMAT must be RSM-INDEX-ONLY. The DATA-FORMAT of the
storage area on the table-storage-area clause must be RSM-DATA-ONLY.

The same storage area can be used for multiple constraints and indexes.

Format
IN storage-area-name

where storage-area-name is the name of the storage area as defined in 2.2.5.

7830 8160–027 6–59


CREATE TABLE

sort-column-list
is the column or columns that make up the primary key and the order in which
they are to be sorted. A primary key can have up to 25 columns. Use commas
between items in the list.

Format
column-name [ ASCENDING │ DESCENDING ]

where ASCENDING (default) or DESCENDING (or abbreviation ASC or DESC) means


to sort in ascending or descending order. For CHARACTER columns, the column
definition's implicit or explicit collation order is used.

Boolean-expression
is a condition that every row in this table must satisfy. The Boolean expression
can include only columns that are in the table being created.

standard-foreign-key-specification
is the standard SQL syntax for specifying a foreign key table constraint, which has
the same effect as the RDMS extended format, in the form

FOREIGN KEY (column-name-list) REFERENCES table-specification

[ (parent-column-name-list) ]

where:

column-name-list
is a list of up to 25 column names to make up the foreign key. The data types
of the columns in the column name list must match the data types of the
columns in the parent column name list.

table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.

parent-column-name-list
is the list of column names in a unique or primary key constraint of the parent
table. The columns in this list must correspond one-to-one with the columns in
column-name-list.

If you omit this list, the parent table must include a primary key whose
columns correspond one-to-one with the columns in column-name-list.

For more information about corresponding columns and defining foreign keys,
see the Relational Database Server for ClearPath OS 2200 Administration
Guide.

6–60 7830 8160–027


CREATE TABLE

6.11.6. Index-Specification Clause


The index-specification clause contains any secondary indexes in addition to the
primary key (which is automatically a primary index). You can have up to 50 secondary
indexes and unique constraints in a table. Separate indexes from one another with at
least one blank space.

Columns with data type BLOB cannot be indexed.

Format
INDEX index-name [LOCAL] ON sort-column-list [storage-area-specification]

where:

index-name
is the name for the index. It must be a valid name as defined in 2.2.1. You must
specify a unique name for each secondary index in the table; otherwise, RDMS
returns an error.

LOCAL can be specified only when the table is partitioned. If LOCAL is not
specified, the index is GLOBAL.

sort-column-list
is a list of the columns to make up the index and their sorting order. A secondary
index can contain up to 25 columns. Use commas between items in the list.

Format
{ column-name │ (column-name-list) } [ ASCENDING │ DESCENDING ]

where ASCENDING (default) or DESCENDING (or abbreviation ASC or DESC) means


to sort in ascending or descending order. For CHARACTER columns, the column
definition's implicit or explicit collation order is used.

A null in a secondary index column is considered greater than any non-null in the
column in determining the ascending ordering of the index, and vice versa for
descending. A secondary index should not include an approximate numeric
column.

The sort-column-list for a LOCAL index is slightly different from that for a GLOBAL
index. The leading columns of the sort-column-list for LOCAL indexes must be the
leading columns of the primary key used as the partitioning key. The partitioning
key columns in the local index cannot be sorted in a direction different from the
primary key index.

storage-area-specification
is the name of the storage area in which RDMS writes the index pages for this
secondary index. If the table is partitioned, this clause is not allowed; you must
put the storage area name on the partition-index-specification clause instead.

7830 8160–027 6–61


CREATE TABLE

If you omit this clause or if you include this clause and its name matches the name
on the table-storage-area clause, RDMS writes the index pages to the storage
area you included on the table-storage-area clause, and its DATA-FORMAT must
be RSM.
If you include this clause and the storage-area-name does not match the name on
the table-storage-area clause, RDMS writes the index pages to the specified
storage area, and its DATA-FORMAT must be RSM-INDEX-ONLY. The
DATA-FORMAT of the storage area on the table-storage-area clause must be
RSM-DATA-ONLY.
The same storage area can be used for multiple constraints and indexes.

Format
IN storage-area-name

where storage-area-name is the name of the storage area as defined in 2.2.5.

6.11.7. Primary-Key-Specification Clause


The primary-key-specification clause (required for RDMS extended syntax 2)
establishes the primary key for the table. A primary key is a column (or combination of
columns) that uniquely identifies each row in a table. A primary key that consists of
more than one column is called a composite key. RDMS returns a syntax error if a
primary key also appears in a column or table constraint.
Columns with data type BLOB cannot be part of a primary key.

Format
PRIMARY [ KEY ] key-name IS sort-column-list [storage-area-specification]

where:

key-name
is the name for the primary key.

sort-column-list
is the column or columns to make up the primary key and the order in which they
are to be sorted. A primary key can have up to 25 columns. Use commas
between items in the list.

Format
{ column-name │ (column-name-list) } [ ASCENDING │ DESCENDING ]

A primary key should not include an approximate numeric column.

storage-area-specification
is the name of the storage area in which RDMS writes the index pages for the
primary key. If the table is partitioned, this clause is not allowed; you must put the
storage area name on the partition-primary-key-specification clause instead.

6–62 7830 8160–027


CREATE TABLE

If you omit this clause or if you include this clause and its name matches the name
on the table-storage-area clause, RDMS writes the index pages to the storage
area you included on the table-storage-area clause and its DATA-FORMAT must
be RSM.
If you include this clause and the storage-area-name does not match the name on
the table-storage-area clause, RDMS writes the index pages to the specified
storage area, and its DATA-FORMAT must be RSM-INDEX-ONLY. The
DATA-FORMAT of the storage area on the table-storage-area clause must be
RSM-DATA-ONLY.
The same storage area can be used for multiple constraints and indexes.
If one or more columns in your table have a data type of BLOB, you cannot use the
standard SQL syntax to create the table. You must explicitly provide a storage
area for the BLOB data, as well as explicit storage areas for the table data and any
indices.
Format
IN storage-area-name

where storage-area-name is the name of the storage area as defined in 2.2.5.

6.11.8. Foreign-Key-Specification Clause


The foreign-key-specification clause creates a relationship between each row in the
table you are creating and a row in a parent table.

Note: This is legacy RDMS syntax used for specifying foreign keys in RDMS
extended syntax 2 format. You cannot use this format if the CREATE TABLE
statement includes table constraint specifications or column constraints that
specify a foreign key.

You can have up to 25 foreign keys in a table. Separate foreign key clauses from one
another with at least one blank space.

Format
FOREIGN KEY key-name IS column-name-list

REFERS TO [ parent-column-name-list OF ] table-specification

where:

key-name
is the name for the foreign key.

column-name-list
is a list of column names to make up the foreign key. This list can contain up to 25
column names. The data types of the columns in the column name list must
match the data types of the columns in the parent column name list.

7830 8160–027 6–63


CREATE TABLE

parent-column-name-list
is the list of column names in the parent table’s unique constraint or primary key.
Each item in this list must correspond to the item in the same relative position in
the column name list. The items must appear in the same order as the list of
columns in the unique constraint or primary key clause of the parent table
definition.

You can omit this list if the column name list is identical in number, order, and type
to the parent table's primary key. If you omit this list, the parent table must define
a primary key; and the order of column names in the column name list must
correspond to the order of column names in the parent table's primary key.

table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.

6.11.9. Owner-Specification Clause


Note: The next two clauses are not allowed if the table is owned (that is, if it exists
in a schema that was created by the CREATE SCHEMA statement).

The owner-specification clause establishes the owner of the table, in the form

OWNER IS { user-id │ USER }

where user-id is any valid user ID. RDMS does not verify the existence of the user ID
on the system. If you specify a nonexisting user ID and data access control is active,
the data is inaccessible to other users until the user ID is defined on the local database
system. See also 6.11.14.

6.11.10. Access-Specification Clause


The access-specification clause establishes control over who can access the table, in
the form

DATA ACCESS CONTROL IS { ACTIVE │ INACTIVE }

If omitted, data access control is active.

6.11.11. Partition-Primary-Key-Specification Clause


The partition-primary-key-specification clause partitions the primary key B-tree into
ranges in multiple storage areas, according to the values of the leading columns in the
key. All versions of the table have the same partitions and therefore have the same
ranges. Partitions created with the CREATE TABLE command start in an attached
state. See information about the RDMUTL processor in the Relational Database
Server for ClearPath OS 2200 Administration Guide.
This clause defines the storage areas where ranges of the primary key records are
placed. If specified, this is the only place you can specify a storage area specification.
The maximum number of primary key partitions is 511.

6–64 7830 8160–027


CREATE TABLE

Format
PARTITION PRIMARY KEY

primary-key-range-specification [ ,primary-key-range-specification ] ...

where primary-key-range-specification is the expression describing one slice of the


primary key range and its corresponding storage area.

For a LOCAL index, the index storage area is specified as part of the primary key
partition; there is no PARTITION INDEX clause.

Format
partition-name <= { column-upper-bound | ( column-upper-bound

[ ,column-upper-bound ]... ) }

IN { ( storage-area-name [ ,local-index-partition-spec]...) |

( DATA storage-area-name,INDEX storage-area-name

[ ,local-index-partition-spec] ... ) }

[ blob-storage-area-clause ]

where:

partition-name
is the name of the partition. All partitions in a table must have unique names,
whether or not they are partitions of the same primary key or index.

column-upper-bound
describes the range of the partition.

Format
{ string-literal | numeric-literal | alternate-based-literal |
datetime-literal | MAXVALUE }

storage-area-name
is the name of the storage area where the index records belonging in the
range of this partition are stored, as defined in 2.2.5.

7830 8160–027 6–65


CREATE TABLE

Specify two storage areas if you want the primary key data pages in a different
storage area from the primary key index pages. The storage area specified for the
primary key data must be RSM-DATA-ONLY. The storage area for the primary key
index pages must be RSM-INDEX-ONLY and may not be identical to the name
specified for the RSM-DATA-ONLY storage area. This form of the syntax is used
as follows:

IN (DATA storage-area-name,INDEX storage-area-name


[ , local-index-partition-spec] ... )

When only a single storage area is specified, it contains both the primary key data
and primary key index pages and therefore must have data-format RSM. This form
of the syntax is as follows:

IN (storage-area-name[ , local-index-partition-spec] ... )

If you specify two storage areas for one partition of the primary key, you must
specify two storage areas for each partition of the primary key.

local-index-partition-spec
identifies a LOCAL index and the index's storage area for the partition.

Format
index-name storage-area-name

index-name
is the name of a LOCAL index that was specified in an index-specification
clause. The storage-area-name that follows is used to store the LOCAL index.
There must be one local-index-partition-spec for each LOCAL index in the
table. The local-index-partition-specs must be in the same order as the
index-specifications of the indexes.

For example

CREATE TABLE softball_table


(
name: CHARACTER(24) NOT NULL,
position: CHARACTER(12),
emp_number: CHARACTER(16)
PRIMARY KEY softball_table_pk is name ASC
INDEX softball_table_lk LOCAL on name ASC, emp_number ASC
PARTITION PRIMARY KEY
p1 <= 'M' IN (DATA softball_data_sa1, INDEX softball_index_sa1
softball_table_lk softball_lindex_sa1),
p2 <= MAXVALUE IN (DATA softball_data_sa2, INDEX softball_index_sa2
softball_table_lk softball_lindex_sa2))

If you do not want to store the primary key data pages in a separate storage
area from the primary key index pages, you use the other form of the
partition-index-specification IN clause.

6–66 7830 8160–027


CREATE TABLE

For example

CREATE TABLE badminton_table


(
name : CHARACTER(24) NOT NULL,
emp_number : CHARACTER(16),
aces : INTEGER
PRIMARY KEY badminton_table_pk IS name
INDEX badminton_table_idx LOCAL ON name ASC, emp_number ASC
PARTITION PRIMARY KEY
p1 <= 'N' IN (badminton_sa1,
badminton_table_idx badminton_idx_sa1),
p2 <= MAXVALUE IN (badminton_sa2,
badminton_table_idx badminton_idx_sa2))

Each partition of the index can have different storage area attributes, except for
the data-format, directory-id, logging, and lock-strategy, which must be identical.
For example, this allows the page size to be different for different partitions.

The same storage area may not be used in multiple partitions, and it may not
contain multiple B-trees.

blob-storage-area-clause
identifies the storage areas where RDMS will store the BLOB data for each BLOB
column in the table. When there is no storage-area-list for a BLOB column, the
BLOB values of the column are stored as part of the record. For a given BLOB
column there must be a storage-area-list either for every partition or for no
partitions.

Format

blob-column-name IN storage-area-list

[ , blob-column-name IN storage-area-list ] ...

where:

blob-column-name
is the name of the BLOB column.

storage-area-list
identifies the storage area(s) where RDMS will store the BLOB data for this
column in this partition. The format of each storage area must be RSM-LOB.
Storage areas may not be shared across partitions. If you are adding one
storage area to a column use the format

storage-area-name

7830 8160–027 6–67


CREATE TABLE

If you are adding several storage areas, include the list in parentheses and
separate the names with commas, as follows:

( storage-area-name, storage-area-name, ... )

The storage-area-name is the name of the storage area where the BLOB data
belonging to this partition is stored, as defined in 2.2.5.

Each BLOB column in each partition can have up to 511 storage areas.

For an example of BLOB columns in a partitioned table, see Example 11 in


6.11.12.

Rules and Guidelines


The term “index” is used in the definition of column-upper-bound to mean secondary
index, unique constraint, or primary key.

The number of column-upper-bounds must be less than or equal to the number of


columns in the index. The leftmost column-upper-bound corresponds to the first
column in the index. The second column-upper-bound corresponds to the second
column in the index, and so forth. The same number of columns must be specified for
all partitions of a given key or index. The value of the leading column-upper-bound is
always greater than or equal to the value of the index’s leading column for every
record in the partition. Subsequent column-upper-bounds are used only when all
previous column-upper-bound values are equal to the index’s corresponding leading
values. As a general guideline, use only one column-upper-bound.

The data type of each column-upper-bound must be comparable to the data type of
the corresponding index column. A column-upper-bound need not be specified for all
the columns of the index. Normally, only a single column-upper-bound is specified,
meaning that the table is partitioned only on the first column of the index. Each
column-upper-bound must fit within 68 bytes of storage space.

If a column of the index is of data type CHAR, a string literal 68 characters or less
must be specified. If the data type is CHAR with CHARACTER SET and COLLATE, the
internal format of the string literal created for comparison purposes must be 68 bytes
or less.

If a column of the index is of data type NCHAR, a string literal 64 bytes or less can be
specified.

6–68 7830 8160–027


CREATE TABLE

MAXVALUE represents a value larger than any value (including NULL) that can be
stored in a column of a given data type. Once MAXVALUE is specified as a leading
column-upper-bound, all subsequent column-upper-bounds for that partition must
have a value of MAXVALUE (for example, partition_name <= (MAXVALUE, 16) is not
allowed). It is not necessary to have partitions that cover the entire range of values of
the first column of the index; that is, MAXVALUE does not have to be specified for the
leading key partition. However, an attempt to insert a row that does not fall into any
partition results in the error 6021. The upper bound of a partition cannot be the
character string ‘MAXVALUE’. If more than one column-upper-bound is specified and
the sort directions of those columns differ, it is necessary to cover the entire range of
values for all but the leading column.

Examples
Example 1
The partition key is c1 ascending, c2 descending, c3 ascending.

Legal Partition Specification


p1 <= 1000, MAXVALUE, MAXVALUE

p2 <= 1000, 1000, MAXVALUE

p3 <= 2000, MAXVALUE, MAXVALUE

p3 <= 3000, MAXVALUE, MAXVALUE

Illegal Partition Specification


p1 <= 1000, MAXVALUE, MAXVALUE

p2 <= 1000, 1000, MAXVALUE

p3 <= 2000, 2000, MAXVALUE

p4 <= 3000, MAXVALUE, MAXVALUE

Records in the range 2000,2001,xxx to 2000,MAXVALUE,xxx would be inserted into


partition p4. This results in the records not being stored in sorted order. The correct
placement of these records is between partition p2 and partition p3. The partition
specifications cannot change the sorted order of the index being partitioned.

7830 8160–027 6–69


CREATE TABLE

Example 2
The partition key is c1 descending, c2 ascending.

Legal Partition Specification


p1 <= (3000,MAXVALUE) IN sa1,

p2 <= (2000,MAXVALUE) IN sa2,

p3 <= (1000,1000) IN sa3,


p4 <= (1000,MAXVALUE) IN sa4

Illegal Partition Specification


p1 <= (3000,1000) IN sa1,

p2 <= (2000,1000) IN sa2,


p3 <= (1000,1000) IN sa3,

p4 <= (1000,MAXVALUE) IN sa4

Records in the range 2000,1001 to 2000,MAXVALUE would be inserted into partition


p1 because 3000,1000 > 2000,1001 > 2000,1000. The index sort order requires these
records to be located between partition p2 and partition p3.

It is not necessary to order (numerical or collating sequence order) the column upper
bounds. Regardless of which order they are specified to RDMS, RDMS operates as
though they were entered in the order of the corresponding index column.

Caution
DROP INDEX, DROP PARTITION, and DROP TABLE do not clear the storage
areas containing the partition. If you are reusing a storage area and expect
it to be empty, you must initialize it using the UREP PROCESS STORAGE
AREA … DELETE and PROCESS STORAGE AREA … INSTALL commands.

6–70 7830 8160–027


CREATE TABLE

6.11.12. Partition-Index-Specification Clause


The partition-index-specification clause partitions a non-LOCAL secondary index
B-tree into ranges in multiple storage areas according to the leading columns included
in the index specification followed by the leading columns of the primary key. It
partitions a UNIQUE constraint B-tree according to the leading columns specified in
the index specification.

Note: UNIQUE constraint index records do not contain the primary key values.

This clause defines the storage areas where ranges of the index records will be
placed. If used, this is the only place you may specify a storage area for the index or
constraint. The maximum number of partitions per secondary index or UNIQUE
constraint is 511.

Format
PARTITION INDEX index-name

index-range-specification [ ,index-range-specification ] ...

where:

index-name
is the name of the non-LOCAL secondary index or unique constraint being
partitioned.

index-range-specification
is the expression describing one slice of the index value range and its
corresponding storage area.

Format
partition-name <= (column-upper-bound [ , column-upper-bound ]... )

IN storage-area-name

where:

partition-name
is the name of the partition. All partitions in a table must have unique names,
whether or not they are partitions of the same primary key or index.

column-upper-bound
describes the range of the partition.

storage-area-name
is the name of the storage area where the index records belonging in the
range of this partition are stored, as defined in 2.2.5.

7830 8160–027 6–71


CREATE TABLE

Each partition of the index may have different storage area attributes, except
for the data-format, directory-id, logging, and lock-strategy, which must be
identical. For example, this allows the page-size to be different for different
partitions.

The same storage area cannot be used in multiple partitions, and it cannot
contain multiple B-trees.

Example
CREATE TABLE T1
COLUMNS ARE
C1 : INTEGER,
C2 : INTEGER,
C3 : INTEGER
PRIMARY KEY primkey IS C1 ASC
index seckey ON c3
PARTITION PRIMARY KEY
P1 <= 1000 IN (DATA sa_data_p1, INDEX sa_index_p1),
P2 <= 2000 IN (DATA sa_data_p2, INDEX sa_index_p2)
PARTITION INDEX seckey
s1 <= 5000 in sa_s1,
s2 <= 10000 in sa_s2

6.11.13. CREATE TABLE Examples


Example 1
These two examples illustrate how to define tables HOUSES and CUSTOMERS of the
sample database:

CREATE PERMANENT TABLE s1.houses IN s1.a1


COLUMNS ARE
hno: CHARACTER(4) NOT NULL,
location: CHARACTER(28),
price: DECIMAL(14),
description: CHARACTER(40)
PRIMARY KEY k1 IS hno ASCENDING
INDEX ix ON price ASCENDING

CREATE TABLE s1.customers IN s1.s2


COLUMNS cno : CHARACTER(4) NOT NULL,
cname : CHARACTER(28),
maxprice : DECIMAL(14),
desiredloc : CHARACTER(28)
PRIMARY KEY pk IS cno ASCENDING

6–72 7830 8160–027


CREATE TABLE

Example 2
Suppose you are setting up a table to keep track of a company’s softball team. The
only eligible players are employees of the company. Therefore, you must ensure that
no names appear in the softball team table that are not in the personnel table. You can
write a program to enforce this, or you can let RDMS do it with foreign keys.

With this option, create the softball team table with a foreign key that refers to the
personnel table, as follows:

CREATE TABLE softball_table


IN diamond
COLUMNS ARE
name: CHARACTER(24),
position: CHARACTER(12),
emp_number: CHARACTER(16)
PRIMARY KEY pk IS name ASCENDING
FOREIGN KEY fk IS emp_number
REFERS TO emp_number OF personnel_table

This establishes PERSONNEL_TABLE as the parent table and SOFTBALL_TABLE as the


child table.

Example 3
This example illustrates table HOUSES created as a multifile table. Its primary key data
pages are in storage area MF.A1, which has data format RSM-DATA-ONLY. The
primary key index pages are in storage area MF.A2, which has data format
RSM-INDEX-ONLY. The secondary index IX is in storage area MF.A3, which has data
format RSM-INDEX-ONLY.

CREATE PERMANENT TABLE mf.houses IN mf.a1


COLUMNS ARE
hno: CHARACTER(4) NOT NULL,
location: CHARACTER(28),
price: DECIMAL(14),
description: CHARACTER(40)
PRIMARY KEY k1 IS hno ASCENDING IN mf.a2
INDEX ix ON price ASCENDING IN mf.a3

7830 8160–027 6–73


CREATE TABLE

Example 4
This example illustrates the use of column constraints, a table constraint, and a
self-referencing foreign key:

• Columns AREA-CD and PHONE, through the use of column constraints, must be
numeric.
• Columns AREA-CD and PHONE together, through the use of a table constraint,
must also be unique.
• Since a manager is also an employee in the table, the relationship between an
employee and the employee's manager is defined through the use of a
self-referencing foreign key.

CREATE TABLE s1.employee IN s1.a1


COLUMNS ARE
emp_no : CHAR(4) NOT NULL,
emp_name : CHAR(28) NOT NULL,
area_cd : CHAR(3) NOT NULL CHECK (area_cd >= '000'
AND area_cd <= '999'),
phone : CHAR(7) NOT NULL CONSTRAINT phcc
CHECK (phone >= '0000000'
AND phone <= '9999999'),
CONSTRAINT phcon UNIQUE (area_cd, phone),
mngr_no : CHAR(4)
PRIMARY KEY pk IS emp_no ASCENDING
FOREIGN KEY fk IS mngr_no REFERS TO
emp_no OF s1.employee

Example 5
In this example, a table constraint is imposed on table HOUSES, so that the value of
column MINPRICE must be less than or equal to the value of column ASKPRICE. The
default clauses require the insertion of the value MINNEAPOLIS in column LOCATION
and 2-BEDROOM RAMBLER in column DESCRIPTION if a value is not specified for
both columns on another insertion.

CREATE TABLE s1.houses IN s1.a1


COLUMNS ARE
hno : CHARACTER(4) NOT NULL,
location : CHARACTER(28) DEFAULT
'Minneapolis',
minprice : DECIMAL(14,2),
askprice : DECIMAL(14,2),
CHECK (minprice <= askprice),
description : CHARACTER(40) DEFAULT
'2-bedroom rambler'
PRIMARY KEY pk IS hno ASCENDING

6–74 7830 8160–027


CREATE TABLE

Example 6
Using RDMS extended syntax 1 (essentially standard SQL syntax with RDMS
extensions), this example illustrates how to create a table in an unowned schema and
specify storage areas:

CREATE TABLE excs001.table1 --this table is in unowned schema excs001


(IN excs001.pkd,--storage area pkd contains the primary key data
--it has file type rsm-data-only
c1 INTEGER NOT NULL,
c2 INTEGER,
c3 INTEGER,
PRIMARY KEY (c1 ASCENDING) IN excs001.pki
--storage area pki contains the primary key index pages
--it has file type rsm-index-only
INDEX si1 ON c2 ASCENDING IN excs001.si1
--storage area si1 contains the secondary index si1
--it has file type rsm-index-only
INDEX si2 ON c3 ASCENDING IN excs001.si2
--storage area si2 contains the secondary index si2
--it has file type rsm-index-only

7830 8160–027 6–75


CREATE TABLE

Example 7
This example demonstrates the collating sequence for multicolumn partitioning. In this
example, the primary key consists of two integer columns, both in ascending order.
ANSI SQL 92 vector comparison rules are applied. Note that in partition P1 and
partition P2 the first-order key is 1000. Placement of the records into the correct
partition is determined by the second-order keys 100 and MAXVALUE. Thus, key 1000,
99 goes into P1, and key 1000,101 goes into partition P2.

CREATE TABLE multi_key_example


(number1 :INTEGER NOT NULL,
number2 :INTEGER NOT NULL,
color :CHAR(20),
sku_code :INTEGER,
supplier :CHAR(50),
CONSTRAINT multi_key_example_pk PRIMARY KEY(number1 ASC,number2 ASC)
PARTITION PRIMARY KEY
p1 <= (1000,100) IN (DATA multi_data_sa1, INDEX multi_prim_key_sa1 ),
p2 <= (1000,MAXVALUE) IN (DATA multi_data_sa2, INDEX multi_prim_key_sa2 ),
p3 <= (2000,100) IN (DATA multi_data_sa3, INDEX multi_prim_key_sa3 ),
p4 <= (2000,MAXVALUE) IN (DATA multi_data_sa4, INDEX multi_prim_key_sa4 ),
p5 <= (3000, MAXVALUE) IN (DATA multi_data_sa5, INDEX multi_prim_key_sa5 ),
p6 <= (MAXVALUE,MAXVALUE) IN (DATA multi_data_sa6, INDEX multi_prim_key_sa6 ))

PARTITION: P1 <= (1000,100)


Keys: (10, 700)
(400, 99999)
(1000, 99)
(1000, 100)
PARTITION: P2 <= (1000, MAXVALUE)
Keys: (1000, 101)
(1000, 350)
(1000, 500)
(1000,501)

PARTITION: P3 <= (2000, 100)


Keys: (1750, 999)
(2000, 100)

PARTITION: P4 <= (2000, MAXVALUE)


Keys: (2000, 101)
(2000, 9999)

PARTITION: P5 <= (3000, MAXVALUE)


Keys: (2001, 9999)
(2999, 9999)

PARTITION: P6 <= (MAXVALUE,MAXVALUE)


Keys: (3001, 0)
(9999, 0)
(999999, 999999)

6–76 7830 8160–027


CREATE TABLE

Example 8
You do not have to use all the columns of the primary key for partitioning. For
example, suppose you have a database that you want to partition by day with a day
per partition, over a range of four days:

CREATE TABLE mybank.today


columns are
c_transaction_date : date NOT NULL,
c_account_number : numeric(14,0) NOT NULL,
c_transaction_code : character(3) NOT NULL,
c_transaction_time : time(0) NOT NULL,
c_check_number : integer,
c_check_amount : numeric(14,2)

PRIMARY KEY primkey IS c_transaction_date, c_account_number,


c_transaction_code, c_transaction_time

PARTITION PRIMARY KEY


p1 <= ('2003-09-01')
IN (DATA DT20030901, INDEX IT20030901)
p2 <= ('2003-09-02')
IN (DATA DT20030902, INDEX IT20030902),
p3 <= ('2003-09-03')
IN (DATA DT20030903, INDEX IT20030903),
p4 <= ('2003-09-04')
IN (DATA DT20030904, INDEX IT20030904);

All days earlier than the 2nd of September are placed by RDMS in partition p1. An error
is issued by RDMS if an attempt is made to insert a record with c_transaction_date
greater than 2003-09-04 into this table.

You can add partitions later using the ALTER TABLE ADD PARTITION statement.

7830 8160–027 6–77


CREATE TABLE

Example 9
The following example shows how to create the softball_table as a partitioned table
with two partitions, with names from A to M in the first partition, and the rest of the
names in the second partition.

CREATE TABLE softball_table


(
name: CHARACTER(24) NOT NULL,
position: CHARACTER(12),
emp_number: CHARACTER(16),

CONSTRAINT softball_table_pk PRIMARY KEY(name ASC),


CONSTRAINT softball_table_fk FOREIGN KEY (emp_number) REFERENCES
personnel_table

(emp_number)

PARTITION PRIMARY KEY


p1 <= ’M’ IN (DATA softball_data_sa1, INDEX softball_index_sa1),
p2 <= MAXVALUE IN (DATA softball_data_sa2, INDEX
softball_index_sa2))

Example 10
The following example shows how to include BLOB columns in a nonpartitioned table.

CREATE TABLE softball_table


( IN softball_data_sa1
name: CHARACTER(24) NOT NULL,
position: CHARACTER(12),
emp_number: CHARACTER(16),
batting_photo: BLOB(50K) IN softball_bat1 NOT NULL,
action_photo: BLOB(50K) IN (softball_act1, softball_act2) DEFAULT
NULL,

CONSTRAINT softball_table_pk PRIMARY KEY(name ASCENDING) IN


softball_index_sa1 )

6–78 7830 8160–027


CREATE TABLE

Example 11
The following example shows how to include BLOB columns in a partitioned table.

CREATE TABLE softball_table


(
name: CHARACTER(24) NOT NULL,
position: CHARACTER(12),
emp_number: CHARACTER(16),
batting_photo: BLOB(50K) NOT NULL,
action_photo: BLOB(50K) DEFAULT NULL,

CONSTRAINT softball_table_pk PRIMARY KEY(name ASCENDING)

PARTITION PRIMARY KEY


part_low_alpha <= 'M'
IN (DATA softball_data_sa1, INDEX softball_index_sa1)
batting_photo IN softball_bat1,
action_photo IN (softball_act1p1, softball_act2p1),

part_hi_alpha <= MAXVALUE


IN (DATA softball_data_sa2, INDEX softball_index_sa2)
batting_photo IN softball_bat2,
action_photo IN (softball_act3p2, softball_act4p2) )

6.11.14. Rules and Guidelines


Read the following rules and guidelines before using the CREATE TABLE statement.

User IDs
If a user ID starts with a number, express it as a delimited uppercase identifier as
illustrated in the following examples:

"1BIG" "2NOT" "3ORG"

RDMS converts undelimited lowercase user IDs to uppercase. RDMS rejects


delimited lowercase user IDs (for example, “Mary”) for the authorization-id (use
“MARY” instead).

RDMS does not verify the existence of the user ID on the system. If you specify a
nonexisting user ID and data access control is active, the data is inaccessible to other
users until the user ID is defined on the local database system.

Storage Area Designations


If you use standard SQL syntax and do not include a storage area specification, RDMS
implicitly creates and installs one for you. Using this method, the thread in which the
table was created must be committed before the table is available for inserting data.
If you attempt to insert data into an uncommitted table that has an implicitly created
storage area, RDMS returns an error.

7830 8160–027 6–79


CREATE TABLE

To create a single file table, use only the stand-alone format of the storage area
specification; or, if you use standard SQL syntax, do not include a storage area
specification.

To create a multifile table, you must include either a primary key storage area
specification or at least one secondary index storage area specification, or both.

Stand-alone storage areas can have data format RSM (which means that the storage
area can contain both data and index pages) or data format RSM-DATA-ONLY (which
means that the storage area can contain only primary key data pages).

If you plan to store only data pages in the file, you should specify RSM-DATA-ONLY.
If a table has only one storage area associated with it, it must have data format RSM.

Primary key and secondary index storage areas should have data format
RSM-INDEX-ONLY.

If the table is created with standard SQL syntax without a storage area specification,
the resulting storage area has data format RSM.

Storage area names need not be unique. For more information about storage area
data formats, see the Repository for ClearPath OS 2200 Programming Reference
Manual.

Partitioning is specified using CREATE TABLE syntax. RDMS requires that the user
explicitly specify storage areas on the CREATE TABLE command in order to use
partitioning (implicit storage areas are not supported). RDMS requires that the user
explicitly specify the primary key. Implicit primary keys are not supported.

Note: If the primary key or any index key is partitioned, the table is called a
partitioned table. If a table is a partitioned table, the primary and all indexes must be
partitioned. The primary key and any index of a partitioned table are not allowed to
share storage areas.

Constraints
The column definition must appear before any constraint that uses that column.

Check Constraints
The number of predicates in the check constraints, both column and table, cannot
exceed 255. That is, the sum total number of predicates in all column and table
constraints cannot exceed 255.

Check constraints used on approximate numeric data types (REAL, DOUBLE


PRECISION, and FLOAT) may not perform well near their boundaries.

6–80 7830 8160–027


CREATE TABLE

Nulls in Primary Keys


Each row of a table must contain a unique primary key. Primary keys can contain
columns that allow nulls, but only one row can have a primary key that is null in every
column. (Standard SQL does not permit nulls in primary key columns.)

If you plan to use a table as the parent table in a foreign key relationship related by the
primary key, you must declare all primary key columns with the NOT NULL clause.

A null in a primary key column is treated as being greater than any non-null in the
column in determining the ascending ordering of the key.

Default Clauses
If the column is defined as NOT NULL, the default clause for this column cannot be
NULL.

If the column is defined to allow nulls and the default clause is not used, the value is
by default NULL.

If the data type for the column is exact numeric, the default clause for this column
must be an exact numeric value.

If the data type for the column is approximate numeric, the default clause for this
column can be either an approximate or exact numeric value.

Foreign Keys
A foreign key provides consistency between tables. It establishes a relationship
between the primary key or unique constraint of one table (parent table) and one or
more columns in a second table (child table). If you specify a foreign key in the
CREATE TABLE or ALTER TABLE statement, one or more columns in one table (child
table) is dependent on the primary key or unique column of another table (parent
table). You cannot create a table with a foreign key that refers to a nonexistent table
or column.

When establishing foreign keys for tables, note the following:

• One table can be the parent of up to 63 children (foreign keys).


• One table can be the child of up to 25 parents (foreign keys).
• The primary key of the parent table cannot contain columns that allow nulls.
• Primary keys of a child table can contain columns that allow nulls. A primary key
column that does not allow nulls can be redefined to allow nulls, provided that it is
not related to any child table through a foreign key.
• The owner of the child table must hold the REFERENCES privilege either on the
parent table or on the referenced columns of the parent table before creating the
foreign key.

7830 8160–027 6–81


CREATE TABLE

• An unowned table can have a foreign key only if it refers to another unowned
table, or if data access control is inactive, or if the REFERENCES privilege is
granted to PUBLIC.
• A table in an owned schema cannot have a foreign key that refers to a table in an
unowned schema, and vice versa.

A child table’s row satisfies the foreign key constraint if it meets one of the following
conditions:

• It has at least one null value.


• All values equal the values in the corresponding columns of at least one row in the
parent table.

Foreign Key Enforcement


Foreign key enforcement works with certain statements to ensure data consistency
as follows:

• DELETE and UPDATE statements


If you delete a row or update the primary key or unique column value of a row in a
parent table, RDMS searches the child table for a foreign key value that matches
the primary key or unique column value you are deleting or updating. If RDMS
finds a matching value, it returns an error because you must first delete or update
the corresponding rows in the child table.
• INSERT statement
To insert a row into a child table, a row with the primary key or unique column
value of the foreign key child being inserted must already exist in the parent table
so the row has a match. If you insert a row into the child table first, RDMS returns
an error.
• ALTER TABLE statement
If you add a foreign key specification to an existing table, RDMS does not check
any existing rows to ensure that the foreign key values of the child table match
the parent table's primary key or unique column values. You must do your own
checking. RDMS checks for data consistency only on subsequent updates and
insertions.

Cast Function Restriction


You cannot use the cast function in the DEFAULT clause or in Boolean expressions in
the check constraint.

Interval Data Type Restriction


You cannot define a column of data type interval.

6–82 7830 8160–027


CREATE TABLE

Security with MAPPER Software and TIP


For RDMS security to work in a MAPPER software environment, the
MASTER-RUN-USERID attribute of the CONFIGURATION entity in the repository must
be set to contain the MAPPER system user ID. For more information, see the
Repository for ClearPath OS 2200 Administration Guide.

When you access RDMS through MRI, use the user's MAPPER user ID as the basis for
table access. When accessing RDMS through TIP, use the TIP user ID (available in Exec
level 41R1 and higher) as the basis for table access.

Access Control
Your site may want to establish control over who has access to data. For example,
one user may be granted permission to retrieve data from a table, but may not be
granted permission to update any of the data.

To control access to data in tables in unowned schemas, follow these two steps:

1. Establish an owner for the table.


• For a new table, use the CREATE TABLE statement and specify an owner
using the OWNER IS clause.
• For an existing table, use the ALTER TABLE statement and specify an owner
with the OWNER IS clause.
2. Use the DATA ACCESS CONTROL clause with the CREATE TABLE statement or
ALTER TABLE statement to specify that data access control is ACTIVE.

A table without a specified owner is essentially a “public” table. This means that every
user with access to the database can access and modify the structure and contents
for such a table. Privileges can be neither granted nor revoked for tables without an
owner. A table without an owner is designated in the repository by a user ID entity
name of PUBLIC.

The table owner is identified by a user ID. This is the same user ID used to access the
system. RDMS does not verify the existence of the user ID specified in the OWNER IS
clause on the system or whether data access control is active. If the user ID does not
exist, the table is inaccessible to other users until the user ID is created on the local
database system. To establish the user ID of the run executing the CREATE TABLE
statement as the owner of the table, specify OWNER IS USER.

When you have specified an owner for a table and ensured that data access control is
active, use the GRANT and REVOKE statements to specify which users can access a
table and for what purpose (for example, retrieval and update).

You can suspend data access control by specifying DATA ACCESS CONTROL IS
INACTIVE.

7830 8160–027 6–83


CREATE TABLE

Consider the following when working with access control:

• If the table owner deactivates access control, RDMS ignores the authorization
history. This allows all users all types of access. If the owner later reactivates
access control, RDMS resumes enforcing all access privileges as they were when
access control was deactivated. (You cannot execute the GRANT and REVOKE
statements while access control is deactivated.)
• UPDATE and DELETE are privileges that are effective only when the user also has
SELECT privileges for the tables involved. DELETE ALL is an exception; it does not
require the SELECT privilege because it deletes rows without looking at them.
• The authorization table is also a relational table. This means that to use GRANT and
REVOKE, you must specify the UPDATE clause in the BEGIN THREAD statement
that begins the session. Because the authorization table is recoverable, you must
use some recovery option other than NONE on the BEGIN THREAD statement.
You can use implicit BEGIN THREAD statements to begin sessions in which you
use the GRANT and REVOKE statements.
• If you use the ALTER TABLE statement to transfer ownership to another user ID,
RDMS does not delete the existing authorization history unless the new owner
revokes all privileges from the old owner.

You do not have to take special steps to control access to tables that reside in owned
schemas. These tables are implicitly access control active and implicitly owned by the
owner of the schema. If you want to establish public access to a table in an owned
schema, you can grant all privileges to PUBLIC. Access control on tables in owned
schemas cannot be deactivated, nor can the ownership of these tables be transferred.
For more information about owned and unowned schemas, see 6.10.

Global Temporary Tables


A global temporary table has a persistent table definition, but its data is not persistent.
This means that the table definition is created once, using the CREATE TABLE
statement, and that definition is committed and exists after the creating thread issues
an END THREAD.

Records in a global temporary table are local to the thread. No other thread can see
these records. A single thread can have multiple versions of a temporary table active
concurrently.

There are never any locking conflicts with other threads over records in temporary
tables. RDMS internally treats the global temporary table as if it is explicitly locked in
EXCLUSIVE UPDATE MODE. All explicit locks on temporary tables are ignored.

A global temporary table is empty when first referenced. When a thread first
references the table, RDMS allocates a storage area for the table. This storage area is
visible only to the thread. The storage area is neither recovered nor audited.

Records can be inserted, updated, deleted, or retrieved from this table, using the
same SQL statements as with a “permanent” persistent base table; however, such
updates can be done whether the thread is read-only or updatable.

6–84 7830 8160–027


CREATE TABLE

There are never any conflicts with other users of the same temporary table, because
all users have their own copies of the table.

Application programs reference global temporary tables in the same manner as


persistent base tables. The difference has to do with record persistence, summarized
as follows:

• The table is empty (has zero records) when first referenced by the thread.
• If you specified ON COMMIT PRESERVE ROWS, the records in the table remain
after commit processing; otherwise, all records in the table are deleted on a
commit.
• If you specified ON ROLLBACK PRESERVE ROWS, the records in the table remain
after rollback processing; otherwise, all records in the table are deleted on a
rollback.
• A temporary table is emptied at END THREAD and the storage area is destroyed.
• If a rollback occurs during the update to a temporary table, all records within that
temporary table are deleted, regardless of whether ON ROLLBACK PRESERVE
ROWS was specified.
• When the user ID changes (for example, TIP multiple-inital), all records are
removed from all temporary tables even if PRESERVE ROWS was specified.

There is only one temporary table per storage area. The DELETE ALL statement for a
temporary table is therefore very efficient, because it simply reinitializes the file
control information.

A sensitive RETENTION cursor remains open following a commit, if it specifies a


temporary table created without ON COMMIT PRESERVE ROWS; however, because
the temporary table has been emptied of records, a FETCH CURRENT statement
returns a no-find. Likewise, a sensitive RETENTION cursor that specifies a temporary
table created without ON ROLLBACK PRESERVE ROWS remains open following a
rollback; however, because the temporary table has been emptied of records, a FETCH
CURRENT statement returns a no-find.

The following restrictions apply to the use of global temporary tables:

• A temporary table cannot be used within the step that created the table definition.
• A temporary table cannot be altered (CREATE INDEX, DROP INDEX, ALTER TABLE).
To perform such an alteration, you must drop the table and create the table again
with the new definition.
• A temporary table definition cannot be dropped by a thread that has materialized
that table. If you want to drop a temporary table, the DROP TABLE statement
must be the first reference to the table within the thread.
• A temporary table cannot contain BLOB columns.
• It is not possible to specify separate storage areas for index and data pages or for
secondary indexes.
• Temporary tables cannot be partitioned.

7830 8160–027 6–85


CREATE TABLE

• A temporary table cannot participate in foreign key relationships.


• A trigger cannot be created on top of a temporary table; however, a trigger can
update a temporary table.
• The RDMUTL LOAD command cannot be performed for temporary tables. This is
because LOAD is its own thread.
• Statistics cannot be gathered for temporary tables with the RDMUTL RUN
STATISTICS command.
• A temporary table cannot be searched with fast searches, because these searches
are always performed on mass storage.

6–86 7830 8160–027


Section 7
SQL Statements CREATE TRIGGER
Through DROP VIEW

This section contains reference information about the following SQL statements:

• CREATE TRIGGER (7.1)


• CREATE VIEW(7.2)
• DEBUG (7.3)
• DECLARE CURSOR (7.4)
• DELETE (7.5)
• DROP CURSOR (7.6)
• DROP INDEX (7.7)
• DROP PROCEDURE/FUNCTION (7.8)
• DROP ROLE (7.9)
• DROP TABLE (7.10)
• DROP TRIGGER (7.11)
• DROP VIEW (7.12)

7830 8160–027 7–1


CREATE TRIGGER

7.1. CREATE TRIGGER


Use the CREATE TRIGGER statement to define a trigger.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No P

7.1.1. Syntax
CREATE TRIGGER [schema-name.]trigger-name

{ BEFORE | AFTER } {DELETE | INSERT | UPDATE } ON [schema.]table-name

[REFERENCING

{ OLD [ ROW ] [ AS ] correlation-name-1 |

NEW [ ROW ] [ AS ] correlation-name-2 |

OLD TABLE [ AS ] table-alias-1 |

NEW TABLE [ AS ] table-alias-2 }. . .

[ FOR EACH { ROW | STATEMENT} ]

{ SQL-procedure-statement |

BEGIN [ ATOMIC ] { SQL-procedure-statement ; }. . . END };

Note: The RDMS statements ALTER TABLE, CREATE INDEX, DROP INDEX, DROP
PROCEDURE, DROP FUNCTION, DROP TABLE, and DROP VIEW can cause triggers
to be implicitly dropped. The implicit dropping of triggers can be prevented through
the use of the UREP configuration attribute RDMS-TRIGGER-DROPPING. RDMS-
TRIGGER-DROPPING is set to CASCADE by default. CASCADE allows RDMS to drop
any triggers that reference an object which is dropped or modified. Setting
RDMS-TRIGGER-DROPPING to RESTRICT causes any RDMS statement to fail if it
would cause the implicit dropping of a trigger.

where:

schema-name
is the name of the schema to contain the trigger. If you do not specify a schema-
name, the current default qualifier is used as the schema name for the trigger.

trigger-name
is the name of the trigger. The name must be unique among all triggers defined for
this schema. Schema and trigger names must be valid names as defined in 2.2.1.

7–2 7830 8160–027


CREATE TRIGGER

BEFORE
indicates that the trigger is executed prior to processing the delete, insert, or
update statement which activated the trigger. A BEFORE trigger can never modify
the database. It can modify the value of data items on their way to the database,
however. The SQL-procedure-statement(s) within a BEFORE trigger may not
include a delete, insert, or update statement.

Further, the SQL-procedure-statement(s) may not invoke a routine if that routine


directly or indirectly modifies the database. (This rule implies that BEFORE triggers
are incapable of cascading.)

AFTER
indicates that the trigger is executed after processing the delete, insert, or update
statement which activated the trigger. An AFTER trigger can modify the database.
There are no restrictions on the SQL-procedure-statement(s) beyond those
discussed later in this section. Because an AFTER trigger can do database updates
other triggers may be executed. Care should be taken in the use of AFTER triggers
to avoid introducing multiple recursive triggers or the excessive nesting of
cascading triggers.

DELETE | INSERT | UPDATE


indicates which type of database modification causes the trigger to be executed.
A trigger can be associated with only one type of database modification
statement.

table-name
is the name of the table, optionally qualified by the schema-name, to which the
trigger applies, it must adhere to standard RDMS naming conventions (see 2.2.1).
Version name is not allowed. In addition, table-name cannot be the name of a
view.

FOR EACH STATEMENT


indicates that the trigger is executed only once for a table modification statement,
regardless of how many rows in the table may be affected by the modification. If
FOR EACH {ROW | STATEMENT } is omitted, then FOR EACH STATEMENT is
assumed.

FOR EACH ROW


indicates that the trigger is executed once for each row affected by the table
modification statement. When a statement modifies multiple rows, all
modifications to the rows are made before the first execution of the trigger.
Triggers that examine all the rows should be ROW triggers and not STATEMENT
triggers, because ROW triggers iterate through the modified table and perform
better.

REFERENCING OLD/NEW ROW


allows the trigger to examine the column values for the row that is being
modified. OLD ROW refers to the column values that currently exist in the
database and NEW ROW refers to the column values that are to be applied to the
database.

7830 8160–027 7–3


CREATE TRIGGER

REFERENCING OLD ROW and REFERENCING NEW ROW may be specified at most
once in a trigger definition. See the tables in this section for rules pertaining to
OLD and NEW ROW referencing.

OLD ROW correlation-name


RDMS obtains the OLD ROW correlation-name information in the following
manner: As each row affected by the user’s data modification statement is
processed, an image of that row, prior to applying the modification, is made
available to the trigger. The column values in this image can be referenced by
specifying correlation-name.column-name in the trigger body.

Generally, correlation-name.column-name references can be made wherever an


sql-variable is allowed in a statement. For information about exceptions, see the
syntax information about correlation-name-n later in this subsection.

NEW ROW correlation-name


There is a difference in the content of the NEW ROW correlation-name depending
on whether the trigger is a before trigger or an after trigger.

• For a before trigger, the column values of the NEW ROW reflect the values
that are about to be applied to the database but before foreign key and
constraint checking. These values can be modified by the before trigger.
• For an after trigger, the column values of the NEW ROW reflect the values that
were applied to the database.

In either case, the column values in the NEW ROW image can be referenced by
specifying correlation-name.column-name in the trigger body. The
correlation-name.column-name references can be made wherever an sql-variable
is allowed in a statement in the trigger body as long as the correlation-
name.column-name is not modified by the statement in an AFTER trigger.

REFERENCING OLD/NEW TABLE…


allows the trigger to examine the set of rows that were affected by the database
modification statement. OLD TABLE refers to the set of rows that existed in the
database prior to the database modification and NEW TABLE refers to that same
set of rows after the database modification. OLD and NEW TABLE will be empty if
the database modification statement did not affect any rows in the target table.
OLD TABLE and NEW TABLE may be specified at most once in a trigger definition.
See the tables in this section for rules pertaining to OLD and NEW TABLE
referencing.

RDMS obtains the OLD TABLE table-alias information in the following manner: A
snapshot of the candidate rows of the target table, which are affected by the
user’s data modification statement, is taken. This snapshot is taken prior to the
actual modification of any information in the database. The snapshot is then
viewable as if it were a read-only, temporary table.

7–4 7830 8160–027


CREATE TRIGGER

RDMS obtains the NEW TABLE table-alias information by applying the user’s data
modification statement to the candidate rows for the statement, creating a NEW
TABLE alias-name snapshot. The rows of the NEW TABLE snapshot reflect the
effect of the user’s data modification statement on the database, plus any update
to NEW ROW made by BEFORE ROW triggers.

The rows of the NEW TABLE snapshot do not reflect the effect of any changes
made directly to the table by this trigger, or any other triggers that may have been
invoked during the processing of the user’s data modification statement. The NEW
TABLE snapshot is viewable as if it were a read-only, temporary table.

correlation-name-n
is an identifier that provides a means to uniquely identify the before or after target
row. It must adhere to standard RDMS naming conventions (see 2.2.1). The name
cannot be the same as any other correlation-name or alias-name defined within
the trigger.

References to the values in the OLD ROW or NEW ROW are made by referencing
the associated correlation-name and the desired column within the row (for
example, old_row.column-name.) Note that an unqualified reference can also be
resolved to a column in the BEFORE or AFTER target row. These references can
be made wherever an SQL variable is allowed in the trigger body, with the
following exceptions:

• A correlation-name cannot be included in a value-list of an INSERT command.


• The OLD ROW correlation-name can never appear as the target of a SELECT
INTO statement or a FETCH INTO statement, or as an output parameter or
function result.
• The NEW ROW correlation-name can never appear as the target of a SELECT
INTO statement or a FETCH INTO statement, or as an output parameter or
function result in an AFTER trigger.
• The OLD ROW correlation-name cannot appear on the left side of an
assignment statement (SET).
• The NEW ROW correlation-name cannot appear on the left side of an
assignment statement (SET) in an AFTER trigger.

The correlation-name cannot be used as a table specification in an SQL statement.


Such a specification would not be resolved to the correlation-name, but instead to
an existing table name, if any.

See Section 4 for more information about SQL variable usage.

table-alias-n
is an identifier that provides the only means to reference the set of affected rows
of the target table. Table aliases are used for obtaining information over a range of
values; they are not designed to handle values from a single row. They must
adhere to standard RDMS naming conventions (see 2.2.1). The name cannot be the
same as any other alias-name or correlation-name defined within the trigger.

7830 8160–027 7–5


CREATE TRIGGER

References to the values in the OLD TABLE or NEW TABLE are made by
referencing the associated table-alias through the use of a SELECT statement. For
example

SELECT COUNT (*) INTO totalr FROM old_table

SELECT SUM (quantity) INTO totalq FROM new_table


WHERE quantity > (SELECT MAX (quantity) FROM old_table))

Neither the OLD TABLE nor the NEW TABLE table-alias can be the subject of a
random or updatable cursor or of a data modification statement.

SQL-procedure-statement
is either a single statement or the set of statements that perform the activity for
this trigger. In either case, each statement must only be from the set of
statements allowed within a routine definition. See 4.11 for more information.

7.1.2. Rules for BEFORE and AFTER Triggers


The following tables show the actions triggers can take, depending on whether they
are executed before or after statements or rows. In the tables

• “Reference” means that the trigger can use the value of an old or new row
column or retrieve rows from a table.
• “Modify” means that the trigger can change the value of a new row column, or it
can delete, insert, or update rows in a table.
• “NA” means “not applicable.”

Rules for BEFORE Statement Triggers

Trigger General
Event Old Row New Row Old Table New Table Tables

Insert NA NA NA Reference Reference


Update NA NA Reference Reference Reference
Delete NA NA Reference NA Reference

Rules for BEFORE ROW Triggers

Trigger General
Event Old Row New Row Old Table New Table Tables

Insert NA Reference NA NA Reference


Modify
Update Reference Reference NA NA Reference
Modify
Delete Reference NA NA NA Reference

7–6 7830 8160–027


CREATE TRIGGER

Rules for AFTER ROW Triggers

Trigger General
Event Old Row New Row Old Table New Table Tables

Insert NA Reference NA Reference Reference


Modify
Update Reference Reference Reference Reference Reference
Modify
Delete Reference NA Reference NA Reference
Modify

Rules for AFTER Statement Triggers

Trigger General
Event Old Row New Row Old Table New Table Tables

Insert NA NA NA Reference Reference


Update NA NA Reference Reference Reference
Modify
Delete NA NA Reference NA Reference
Modify

7.1.3. Examples
Example 1
The following example shows the use of a BEFORE statement trigger. If you attempt
to perform an insert on table t1 and it is not during normal business hours, the trigger
(and the INSERT statement) are terminated with an error message.

CREATE TRIGGER not_production BEFORE INSERT ON t1


FOR EACH STATEMENT
BEGIN
DECLARE time_of_day TIME;

SET time_of_day = CURRENT_TIME;

IF time_of_day< TIME '08:00:00' OR time_of_day> TIME '17:00:00'


THEN
SIGNAL 'Table t1 may not be modified at this time.';
END IF;
END;

7830 8160–027 7–7


CREATE TRIGGER

The invocation and processing of this trigger are as follows:

1. A user issues an INSERT statement for table t1.


2. The not_production trigger is invoked.
3. If the time of day is between 8:00 AM and 5:00 PM, the INSERT command is
executed.
If the time of day is not between 8:00 AM and 5:00 PM, the user’s INSERT
statement is not executed.
4. Control is returned to the user.

Example 2
The following example shows the use of an AFTER statement trigger which also
contains a single SQL-procedure-statement.

CREATE TRIGGER state_codes AFTER INSERT ON t1


FOR EACH STATEMENT
UPDATE t1 SET (t1.state = 'MN') WHERE t1.state = 'Minn';

The invocation and processing of this trigger are as follows:

1. A user issues an INSERT statement for table t1.


2. The INSERT statement is completed and trigger state_codes is invoked.
3. All state values in table t1 which equal “Minn” are changed to “MN”, including any
entered by the user’s INSERT command.
4. Control is returned to the user.

Example 3
This example shows the use of a BEFORE row trigger. The trigger ensures that vendor
information in newly inserted rows is accurate and consistent by obtaining that
information from an approved source (the vendors table):

CREATE TRIGGER vendor_info BEFORE INSERT ON t2


REFERENCING NEW ROW AS new_row
FOR EACH ROW
BEGIN
DECLARE vn CHAR(20);
DECLARE va CHAR(40);
SELECT vendor_name, vendor_address INTO vn, va
FROM vendors WHERE product_code = new_row.product_code;
SET new_row.vendor_name = vn;
SET new_row.vendor_address = va;
END;

7–8 7830 8160–027


CREATE TRIGGER

The invocation and processing of this trigger are as follows:

1. A user issues an INSERT statement for table t2.


2. Prior to doing the INSERT the vendor_info trigger is invoked.
3. The values for vendor_name and vendor_address are obtained from the vendors
table and placed in the new row image.
4. The new values for vendor_name and vendor_address are used as part of the new
row inserted into table t2.
Note: This process continues until all rows affected by the user’s INSERT
statement have been processed.
5. The user’s INSERT command is completed and control is returned to the user.

Example 4
The next example shows the use of an AFTER ROW trigger. The trigger ensures that if
a change is made to the vendor information in the vendors table; then the change is
also reflected in the appropriate rows of table t2:

CREATE TRIGGER update_t2 AFTER UPDATE ON vendors


REFERENCING OLD ROW AS old_row
NEW ROW AS new_row
FOR EACH ROW
BEGIN
IF new_row.vendor_name < > old_row.vendor_name OR
new_row.vendor_address < > old_row.vendor_address
THEN UPDATE t2
SET (vendor_name = new_row.vendor_name,
vendor_address = new_row.vendor_address)
WHERE product_code = new_row.product_code;
END IF;
END;

The invocation and processing of this trigger are as follows:

1. The user issues an UPDATE statement for table vendors.


2. After completing the UPDATE for a row, the trigger, update_t2, is invoked.
3. If either the vendor_name or the vendor_address was changed by the user’s
UPDATE statement, the vendor_name and vendor_address columns of all rows in
table t2 that have the matching product_code are updated to reflect that change.
Note: This process continues until all rows affected by the user’s UPDATE
statement have been processed.
4. The user’s UPDATE command is completed, and control is returned to the user.

7830 8160–027 7–9


CREATE TRIGGER

Example 5
This example shows the use of an AFTER STATEMENT trigger that references the old
table definition and modifies a general table. The trigger implements a cascading
delete from a parent table to a child table. If a record is deleted from the
personnel_table, the parent table, the record in the softball_table, the child table, with
an equivalent emp_number is deleted, if it exists. The trigger is an alternative way to
implement foreign key cascading delete functionality. When the table to which the
trigger applies is different from all the tables updated by the trigger; the trigger is not
copying a self-referencing foreign key.

CREATE TRIGGER cas_delete AFTER DELETE ON personnel_table


REFERENCING OLD TABLE old_table
FOR EACH STATEMENT
BEGIN
DECLARE id NUMERIC;
DECLARE c1 CURSOR SELECT emp_number FROM old_table;
FETCH NEXT FROM c1 INTO id;
WHILE SQLSTATE = '00000' DO
BEGIN
DELETE FROM softball_table WHERE emp_number = id;
FETCH NEXT FROM c1 INTO id;
END;
END WHILE;
END;

The invocation and processing of this trigger are as follows:

1. The user issues a DELETE statement for table personnel_table.


2. After completing the delete statement, the trigger, cas_delete is invoked.
3. The deleted records from the personnel_table, stored in old_table, are iterated
through and the record with the equivalent emp_number is deleted from the
softball_table. Since a delete statement first performs a select on the table, a
delete is issued on the softball_table only if the equivalent record exists.
4. The user’s DELETE command is completed, and control is returned to the user.

7.1.4. Rules and Guidelines


Read the following rules and guidelines before using the CREATE TRIGGER statement.

Commit
If you commit the run unit, RDMS stores the trigger in the database and the trigger
becomes active.

Cursors
You cannot create a trigger if there is an open cursor on the target table of the trigger.

Dropping a Trigger
Use the DROP TRIGGER statement to remove a trigger from the database.

7–10 7830 8160–027


CREATE TRIGGER

IPF SQL
When you submit a CREATE TRIGGER statement from an IPF SQL session, do not
place a semicolon after the final END statement. Do not include any SQL comments in
the trigger definition.

JDBC
When you submit a CREATE TRIGGER statement through JDBC, do not place a
semicolon after the final END statement. Do not include any SQL comments in the
trigger definition.

Ownership
A trigger can only be created in an owned schema. It can reference objects in other
schemas, but if the referenced object is owned, it must be owned by the creator of
the trigger.

Rollback
If you issue a rollback command before committing a trigger definition, the trigger is
never available to other users.

System Tables
You cannot create a trigger whose target table is an RDMS system table.

Table Versions
A trigger is always associated with a specific table definition, referred to as the target
table of the trigger, and never with a specific table version.

Saving Trigger Syntax


The CREATE TRIGGER statement saves the trigger syntax in the repository. To report
the syntax, use the following UREP command:

REPORT INCLUDE ATTRIBUTE SYNTAX SQL-TRIGGER trigger-name FOR SCHEMA


schema-name.

7830 8160–027 7–11


CREATE VIEW

7.2. CREATE VIEW


Use the CREATE VIEW statement to define a different logical access to the data in
tables.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No E/X

7.2.1. Syntax
SQL 92 Syntax (Entry Level)
CREATE VIEW [schema-name.]view-name [(column-name [,column-name]...)]

AS query-specification

[ WITH CHECK OPTION ]

RDMS Extended Syntax


CREATE VIEW [schema-name.]view-name [(column-name [,column-name]...)]

AS query-specification

[ WITH CHECK OPTION ]

[ WITH ACCESS CONTROL ]

where:

schema-name
is the name of the schema containing the view. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user-id of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAUL-QUALIFIER. For additional information see the Repository for
ClearPath OS 2200 Administration Guide.

view–name
is the name of the view following the naming conventions in 2.2.1. Version names
are not allowed since only one definition exists for all versions of the same view.

column-name
is the name or names for the columns. If omitted, the default column names for
the view are the same as the column names from the select list of the query
specification. Column names are mandatory when the select list contains an
arithmetic operation, a function, a constant, or duplicate column names.

7–12 7830 8160–027


CREATE VIEW

Also, if you use column names, they must be valid names and unique within the
column name list:

• The number of columns specified must be equal to the number of items


appearing in the select list of the query specification.
• The order of the columns in the view column list must parallel columns
derived from the select list of the query specification.

query-specification
is a query specification as defined in 2.7, except that it cannot contain an
embedded variable, parameter marker, or placeholder variable.

An OUTER joined-table is not allowed in query-specification of CREATE VIEW.

Also, since view definitions are not bound to specific versions of underlying
tables, the query specification cannot refer to a specific version of a table (that is,
the optional :version-name portion of the table specification as described in 2.2.2
is not allowed).

WITH CHECK OPTION


means that you want UPDATE and INSERT operations against the view checked to
ensure that the updated or inserted row satisfies the WHERE clause of the
definition of the view. The WITH CHECK OPTION clause prevents the entry of data
that cannot be retrieved by the same view.

WITH ACCESS CONTROL


establishes control over who can use a particular view. This clause is not allowed
if the table is owned (that is, if it exists in a schema that was created by the
CREATE SCHEMA statement). For more information about owned and unowned
schemas and tables, see 6.10.3 and also the Relational Database Server for
ClearPath OS 2200 Administration Guide.

7.2.2. Example
The following example defines a view based on table HOUSES:

CREATE VIEW s1.v1_houses


(v1_hno, v1_Loc, v1_price)
AS SELECT hno, location, price FROM s1.houses
WHERE price > 150000
WITH CHECK OPTION

7830 8160–027 7–13


CREATE VIEW

7.2.3. Rules and Guidelines


Read the following rules and guidelines before using the CREATE VIEW statement.

Nesting Views
Views can be made up of views or any combination of views and tables.

Read-Only Views
Views can be either updatable or read-only. A view is read-only if the CREATE VIEW
statement includes at least one of the following characteristics:

• The keyword DISTINCT


• A select list that has an entry that is not just a column specification (for example,
an arithmetic operation or a function)
• A column specification that appears more than once in the select list
• A GROUP BY clause
• A HAVING clause
• A FROM clause that references more than one table or view
• A FROM clause that identifies a read-only view (one that cannot be updated)
• A subquery

Using the UPDATE, INSERT, and DELETE Statements with Views


You can use the UPDATE statement to change the values of columns on any view that
is not a read-only view. Such a view is referred to as an updatable view.

You can use the INSERT statement on updatable views in either of two cases:

• The view includes all columns of the underlying table.


• All columns from the underlying table that are not included in the view either have
a default clause or allow null values.

You can use the DELETE statement on updatable views that include all columns of the
underlying table.

Column Names in Views


The column names do not have to be the same as the names in the SELECT clause.
You can rename a selected column or give a name to the result of a calculation, as in
the following example:

CREATE VIEW my_cut


(house_number, commission)
AS SELECT hno, price * 0.06
FROM houses

7–14 7830 8160–027


CREATE VIEW

UREP Considerations
The definition of the view stored in the repository consists of the CREATE VIEW
statement text. Since the view syntax is saved in the repository in 80-character
segments, you can improve the readability of UREP reports on view definitions by
segmenting the statement into 80-character lines.

The following example illustrates a CREATE VIEW statement formatted into


80-column segments in a COBOL program:

01 COMMAND.
02 FILLER PIC X(80) VALUE IS
'CREATE VIEW V1_HOUSE ' .
02 FILLER PIC X(80) VALUE IS
'(VHNO,VLOC) ' .
02 FILLER PIC X(80) VALUE IS
AS SELECT HNO, LOC FROM houses ' .
02 FILLER PIC X(80) VALUE IS
'WHERE PRICE > 150000;' .

Owned Schemas, Unowned Tables/Views


You cannot create a view in an owned schema that refers to an unowned table or
view, or vice versa.

Recompilation Errors
A recompilation error is returned at execution time for views that are referenced by
programs that use portable ESQL, if the view was not also created according to the
rules of portable ESQL.

Joined-Table
CREATE VIEW cannot include any joined-table.

WITH CHECK OPTION Clause


The WITH CHECK OPTION clause on the view declaration instructs RDMS to verify
that any updated or inserted values satisfy the view's WHERE clause. This feature
allows the enforcement of domain constraints that logically exist on columns in a
table.

For example, suppose table ORDERS contains the column MONTH that is defined to
contain a 2-digit decimal value in the range 1 to 12. MONTH is declared as a 2-digit
decimal number with no digits after the decimal point. You can enforce the constraint
by building the following view:

CREATE VIEW verified_orders AS SELECT *


FROM orders
WHERE month BETWEEN 1 AND 12
WITH CHECK OPTION

7830 8160–027 7–15


CREATE VIEW

By using view VERIFIED_ORDERS instead of table ORDERS, you force all values of the
column MONTH to be in the range 1 to 12.

Suppose table ORDERS also contains a column PRICE that is defined to contain a
7-digit decimal value with 2 digits after the decimal point. Creating the following view
illustrates how CHECK OPTION works:

CREATE VIEW verified_orders_1 AS SELECT *


FROM verified_orders
WHERE price > 1000.00 ;

The view VERIFIED_ORDERS_1 is built on top of view VERIFIED_ORDERS, on which


CHECK OPTION is specified. If PRICE has a value smaller than 1000.00, view
VERIFIED_ORDERS_1 does not reject it, because this view has no WITH CHECK
OPTION specified. However, if MONTH has a value not between 1 and 12, view
VERIFIED_ORDERS_1 rejects the row.

Suppose table ORDERS also contains a column QUANTITY that is defined to contain a
4-digit numeric value. Another view is created as follows:

CREATE VIEW verified_orders_2 AS SELECT *


FROM verified_orders_1
WHERE quantity BETWEEN 3 AND 6
WITH CHECK OPTION ;

The view VERIFIED_ORDERS_2 is built on top of view VERIFIED_ORDERS_1, which is


built on top of view VERIFIED_ORDERS. If data is inserted into view
VERIFIED_ORDERS_2, the WITH CHECK OPTION clause of view VERIFIED_ORDERS_2
enforces all three conditions:

• The month must be between 1 and 12.


• The price must be greater than $1,000.00.
• The quantity must be between 3 and 6.

It makes no difference that the view VERIFIED_ORDERS_1 has no WITH CHECK


OPTION clause, as the WITH CHECK OPTION clause of a view applies to the WHERE
clauses of the views on which it is based.

View Security
View security provides an effective way to control access to a distinct subset of a
table's rows and columns. For example, you can create a view that lets managers see
personnel records, but only for employees in their own departments.

To activate view security for unowned schemas, use the WITH ACCESS CONTROL
clause on the CREATE VIEW statement. After activating view security, use the GRANT
and REVOKE statements to control view access.

You can also activate view security by creating the view within a CREATE SCHEMA
statement, in which case data access control is implicitly active. View security is also
implicitly activated when you create a view within an existing owned schema.

7–16 7830 8160–027


CREATE VIEW

View security is similar to table security, but with the following differences:

• No view equivalent of ALTER TABLE exists. This means that the only way to
activate view security for unowned schemas is to use the WITH ACCESS
CONTROL clause of the CREATE VIEW statement. If you omit the WITH ACCESS
CONTROL clause and later wish to activate security on that view, you must drop
the view and create it again.
• You cannot create a view unless you have SELECT privileges on all tables and
views named in the CREATE VIEW statement. This privilege cannot be obtained
from a role to which the user-id creating the view is a member. It must be
explicitly granted to the user-id creating the view or explicitly granted to PUBLIC,
or the creator of the view must be the owner of the table.
• RDMS automatically drops a view if its owner loses SELECT privileges to any of its
underlying tables or views.
• RDMS automatically drops a view if any of its underlying tables or views is
dropped. For further information about automatically dropping views, see 7.11.3.
• If a view is updatable, the owner's access rights to the underlying tables and
views at view creation determine the owner's access rights to the view. For
example, if you have INSERT and UPDATE but not DELETE privileges over one of
the underlying tables or views, you also have INSERT and UPDATE but not DELETE
privileges over the view you created. If you later acquire DELETE privileges, you
must drop the view and create it again to obtain DELETE privileges for it.
• If a view was created using the WITH ACCESS CONTROL clause, the view owner
can grant any privileges the owner held under the WITH GRANT OPTION clause
when the view was created. For example, if you have DELETE privileges without
the WITH GRANT OPTION privilege on one of the underlying tables or views at the
time you create a view, you cannot grant DELETE privileges on the view to other
users. If you later obtain DELETE privileges with the WITH GRANT OPTION
privilege, you must drop the view and create it again before you can grant DELETE
privileges to other users.
• If the view being created is in an owned schema, the underlying tables and views
must also be created within an owned schema.
• If a view is read-only, no one, not even the owner, can have INSERT, UPDATE, or
DELETE privileges over it.
• If someone creates a view and does not specify WITH ACCESS CONTROL, all
users get all privileges the owner held under the WITH GRANT OPTION clause at
the time the view was created. For example, if the owner held SELECT and
UPDATE privileges, but had the grant option only on the SELECT privileges, all
other users can fetch from the view, but only the owner can update it.
• If a view is in an unowned schema, the owner of the view is always the user-id
that created the view. If a view is in an owned schema, the owner of the view is
the owner of the schema. You cannot transfer ownership to any other user-id.
• Only the owner of an owned schema can create a view in that schema.

7830 8160–027 7–17


DEBUG

7.3. DEBUG
Use the DEBUG statement to check the syntax of SQL statements without actually
executing them, or to dump internal information to help you to evaluate problems.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes* Yes* Yes* No X

* For more information, see 7.3.3.

7.3.1. RDMS Extended Syntax


DEBUG { DUMP dump-option │ NODUMP dump-option │ STUB │ NOSTUB │

PARSE │ EXECUTE }

where:

DUMP
instructs RDMS to dump the named data structure specified in the dump
option on all subsequent statements until a DEBUG NODUMP statement
instructs RDMS to stop.

NODUMP
instructs RDMS to stop dumping the named data structure specified in the
dump option.

dump-option
is the name of an internal RDMS data structure:

COMMAND MODULE
DATA PACKET
REQUEST PACKET
RDMCA
RSP PACKET
WORK AREA
ALL Dumps (or quits dumping) all of these data structures.
SIZES Valid only for the interpreter interface, produces a
report of D-bank space allocation for the RSA work
area for Universal Compiling System (UCS) programs.
This information is useful when using the RSA$INIT
subroutine. For more information about RSA$INIT, see
the reference manual for the programming language
you are using.

7–18 7830 8160–027


DEBUG

INPUT Produces an octal dump of all parameters passed to


RDMS.
ECHO Produces an ASCII dump of the command string sent
to RDMS.
BDIS Dumps the octal value for the RSA subsystem BDI.
This information is required when using the hardware
monitor to evaluate RDMS performance.

NOPRINT Inhibits the printing of debug information by RSA


without preventing the writing of this information to
the UDS trace file (see 7.3.4 for more information).
PRINT Starts or resumes the printing of debug information by
RSA.

STUB
instructs RDMS only to parse the statements. Use STUB to check syntax
without executing the statements.

NOSTUB
cancels DEBUG STUB. When you use DEBUG STUB, keep in mind that some
statements depend upon execution of other statements. For example, if you
begin a thread, execute DEBUG STUB and then execute an END THREAD
statement, the thread is still active. You must execute DEBUG NOSTUB before
the END THREAD statement if you want the thread to terminate normally.

PARSE
is equivalent to the following three statements:

DEBUG STUB
DEBUG DUMP COMMAND MODULE
DEBUG DUMP REQUEST PACKET

EXECUTE
is equivalent to the following three statements:

DEBUG NOSTUB
DEBUG NODUMP COMMAND MODULE
DEBUG NODUMP REQUEST PACKET

7830 8160–027 7–19


DEBUG

7.3.2. Examples
You can use the DEBUG STUB statement to test the syntax of a statement without
executing it.

The following statements test the syntax of the FETCH statement:

DEBUG STUB
FETCH NEXT cursor5 INTO $p1, $p2

RDMS returns error status 0000 (no errors) without returning data from the database.
No error is returned for fetching from an undeclared cursor because the FETCH
statement was only parsed, not executed.

Assume the following statement where you forget to separate FETCH and NEXT:

FETCHNEXT cursor5 INTO $p1, $p2

RDMS returns error status 0400 (unknown statement) and error column 1.

7.3.3. Rules and Guidelines


Read the following rules and guidelines before using the DEBUG statement.

Threads
You can execute the DEBUG statement when no thread is active.

Dynamic ESQL
You can use the DEBUG statement in dynamic ESQL only in the EXECUTE IMMEDIATE
statement. You cannot use a PREPARE statement to prepare and execute it.

Tracing Execution
The DEBUG DUMP statements print information about the compilation of SQL
statements.

To trace the actual execution of SQL statements, use the UDS Control trace control
(TRCCTL) program. For more information, see the Universal Data System
Administration and Support Reference Manual.

Tracing with Static and Dynamic ESQL Statements


To trace ESQL during program compilation, use the static ESQL form of the statement:

EXEC SQL DEBUG DUMP ECHO


END-EXEC.

This form of the statement has no effect during program execution.

7–20 7830 8160–027


DEBUG

To trace SQL statement compilation that occurs during program execution (for
example, interpreter interface or dynamic ESQL statements), use the dynamic form:

EXEC SQL EXECUTE IMMEDIATE 'DEBUG DUMP ECHO'


END-EXEC.

DEBUG SIZES
Information produced by this option is valid only for UCS interpreter interface
programs.

DEBUG DUMP BDIS


This can only be accessed using the RSA driver, RSAC-COIVP.

7.3.4. DEBUG and the UDS Trace File


The debug information usually appears in the user’s PRINT$ file. If the UDS trace
component “RSA” is set, then some of this debug information also appears in the
current UDS trace file. Refer to Universal Data System Administration and Support
Reference Manual for more information.

The following DEBUG commands, with the noted exceptions, produce entries in the
UDS trace file in this situation:

DEBUG DUMP ECHO (not the embedded SQL interface)


DEBUG DUMP COMMAND MODULE (not thread control commands)
DEBUG DUMP WORK AREA (not the RSAC-COIVP interface)
DEBUG DUMP INPUT (not the ACOB, FTN, IPF, or embedded SQL
interfaces)
DEBUG DUMP RDMCA (not the IPF or the embedded SQL interfaces)
DEBUG DUMP REQUEST PACKET (not the IPF or the embedded SQL interfaces)
DEBUG DUMP DATA PACKET (not the IPF interface)
DEBUG DUMP ALL (all stated commands: ECHO, COMMAND
MODULE, WORK AREA, INPUT, RDMCA,
REQUEST PACKET, DATA PACKET)

An explicit BEGIN THREAD statement is required in order for debugging information to


be sent to the UDS trace file.

The use of DEBUG STUB will not result in debug information being written to the UDS
trace file.

To write debug information to the UDS trace file, but not to the user’s PRINT$ file,
issue DEBUG DUMP NOPRINT.

Within a multi-activity program, the first DEBUG DUMP statement must be DEBUG
DUMP NOPRINT. The reason is, the writes of DEBUG DUMP information to PRINT$ are
not synchronized and can cause the program to abort.

7830 8160–027 7–21


DECLARE CURSOR

7.4. DECLARE CURSOR


Use the DECLARE CURSOR statement to define a set of data for later retrieval from
the database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes Yes E/F/X

7.4.1. Syntax
SQL 92 Syntax (Entry Level)
DECLARE cursor-name CURSOR

FOR query-expression

[ ORDER BY sort-specification-list ]

RDMS Extended Syntax


{ DECLARE cursor-name [ cursor-sensitivity ] CURSOR |

DEFINE CURSOR cursor-name [ cursor-sensitivity ] }

[ FOR { SEQUENTIAL | RANDOM | DIRECT } [ ACCESS] ]

[ [ FOR ] RETENTION | { WITH | WITHOUT } HOLD ]

[ FOR ] query-expression

[ ORDER BY sort-specification-list ]

[ FOR { READ ONLY | UPDATE [ OF column-name-list ] } ]

[ FETCH FIRST m ROWS ONLY ]

[ OPTIMIZE FOR p ROWS ]

[ WITH DESCRIPTION ]

7–22 7830 8160–027


DECLARE CURSOR

Syntax When Used in Routines or Triggers


DECLARE cursor-name [cursor-sensitivity] CURSOR

[ FOR { SEQUENTIAL │ RANDOM │ DIRECT } [ ACCESS ] ]

[ FOR ] query-expression

[ { [ FOR ] RETENTION | WITH HOLD } WITH RETURN

| [ WITHOUT HOLD ]

| [ WITHOUT RETURN ]

[ ORDER BY sort-specification-list ]

[ FOR { READ ONLY | UPDATE [ OF column-name-list ] } ]

[ FETCH FIRST m ROWS ONLY ]

[ OPTIMIZE FOR p ROWS]

Note: The DEFINE CURSOR form is not allowed in ESQL, routines, or triggers.

where:

cursor-name
is the name for the cursor. It must be a valid name as defined in 2.2.1.

query-expression
is a query, which can include query specifications, the set operators
UNION and UNION ALL, and query terms, in the form

{ query-term │ query-expression UNION [ALL] query-term }

where:

query-term
is a separate query specification or a subexpression in parentheses of the
query expression, in the form

{ query-specification │ (query-expression-order-fetch) }

Where:

query-specification

is as defined in 2.7.

7830 8160–027 7–23


DECLARE CURSOR

query-expression-order-fetch

is a query expression which also allows ORDER BY and FETCH FIRST


m ROWS ONLY.

query-expression
[ORDER BY sort-specification-list]
[FETCH FIRST m ROWS ONLY]

UNION [ALL]
lets you derive a result table by combining two other result tables. The
result of a UNION operation is the set of all selected rows in either table
with duplicate rows eliminated. Two rows are duplicates if each value in
the first is equal to the corresponding value in the second. Two null values
are considered equal. The result of a UNION ALL operation contains all
selected rows from both tables.
Set operations cannot be nested by parentheses deeper than 10 levels.
The select list of a UNION operand can contain column-specifications or
all columns of the table in their defined order (table-specification.*
[see 2.7]), constants, arithmetic expressions, and functions. Corresponding
columns in UNION operands must have identical data types, lengths, and
precision (if applicable). UNION operands do not have to be identical with
respect to whether they allow NULL values.
The select list of a UNION operand can also contain constants, arithmetic
expressions, and functions. Select lists of UNION operands are usually
homogeneous, which means that all corresponding positions contain the
same expression and that all items in the expressions have the same data
type, length, and precision (if applicable).
Heterogeneous select lists are allowed, provided that corresponding
positions in the UNION operands have identical internal RDMS data types.
The description of the GET DESCRIPTION statement (see 8.9) describes
external, not internal, data types, length, and precision (if applicable).
It is frequently not possible to create nonhomogeneous select lists that
meet these criteria. An attempt to use nonhomogeneous select lists can
result in an error regarding a data type mismatch, even though the GET
DESCRIPTION statements of the select lists are identical.
UNION operands of type CHARACTER must have identical character set
and collation definitions to be mutually comparable. The resulting columns
have no associated column names; therefore, ORDER BY clauses must
specify unsigned integers.
The result of a DECLARE CURSOR statement is a read-only table if UNION
[ALL] is specified. The cursor cannot contain the UNION [ALL] operator
and a FOR UPDATE OF clause.

7–24 7830 8160–027


DECLARE CURSOR

sort-specification-list
are the sort specifications, separated by commas, in the form

{ column-specification │ unsigned-integer │ scalar-bif reference }

[ COLLATE collation-name ]

[ ASCENDING │ DESCENDING ]

where:

column-specification
must reference columns contained in tables listed in the FROM clause
or be the name given to a selected expression by the AS title-name
clause.

unsigned-integer
specifies the position of the element in select-list if one of the
columns to sort is not a column specification but an expression (like
MAXPRICE * 1.1), or if the column is the result of a UNION operation.

collation-name
is the collation to use for ordering the values. The collation here is
independent of the column definition. The column’s character set must
match the collation's character set. This clause applies only to columns
with data type CHARACTER.

ASCENDING (default) or DESCENDING (or abbreviation ASC or DESC)


sorts in ascending or descending order. For CHARACTER columns, the
column definition's implicit or explicit collation order is used unless
you override it with a COLLATE clause.

scalar-bif-reference
is a reference to a scalar built-in-function. A column must be
referenced in each scalar-bif-reference in the ORDER BY clause.

cursor-sensitivity
defines whether updates made by this thread, after the cursor is opened, are
to be included as part of this cursor.

{ ASENSITIVE | INSENSITIVE | SENSITIVE }

ASENSITIVE means the cursor may or may not include updates made by this
thread. The default sensitivity is ASENSITIVE.
INSENSITIVE means the cursor does not include any updates made by this
thread after the cursor was opened. An INSENSITIVE cursor is always
read-only and nonscrollable.
SENSITIVE means the cursor includes all updates made by this thread,
provided the cursor’s currency has not already passed the updated record.

7830 8160–027 7–25


DECLARE CURSOR

SEQUENTIAL
(default) lets you access the rows only in their defined sequence.

RANDOM or DIRECT
lets you retrieve rows sequentially and at random. (RANDOM and DIRECT are
synonymous.) If you specify RANDOM, you can use the LOCATE statement to
position the cursor on a particular row by specifying its primary key. You can
then execute a FETCH CURRENT statement to retrieve the row.
You cannot specify RANDOM or DIRECT if the cursor contains a joined-table
specification, INSENSITIVE, FETCH FIRST m ROWS ONLY, or OPTIMIZE FOR p
ROWS.

FOR READ ONLY


makes the cursor read-only. This means it may not be referenced within an
UPDATE or DELETE statement when updating or deleting the current row of
the cursor. Omitting FOR READ ONLY may or may not make the cursor
updatable.

FOR UPDATE
indicates that the cursor is positional. The following conditions apply to
positional cursors:

• The FOR UPDATE clause cannot be used if the cursor is random access or
read-only.
• RDMS applies currency safeguards to the rows as they are fetched. This
means that when the cursor definition includes the FOR UPDATE clause
and a row is fetched using the cursor, RDMS automatically locks the row
until a different row is fetched.
• The positional cursor UPDATE or DELETE statement can be used without
the FOR UPDATE clause, but currency safeguards are not enforced when a
fetch is performed. RDMS does not require the use of the FOR UPDATE
clause when you use the positional UPDATE or DELETE statement;
however, its use is recommended to improve performance.
For information on performance with positional statements, refer to the
Relational Database Server for ClearPath OS 2200 Administration Guide.

For information on how to reference the cursor in DELETE and UPDATE


statements, see 7.5 and 10.3.

column-name-list
is a list of the column names that can be updated using the UPDATE
statement with the WHERE CURRENT OF CURSOR clause. The list is
composed of column specifications.
• The columns listed in the FOR UPDATE clause must also be listed in the
query specification.

7–26 7830 8160–027


DECLARE CURSOR

FETCH FIRST m ROWS ONLY


m specifies the maximum number of rows that can be retrieved. It must be
an unsigned integer >=1 and <= 34359738367. An attempt to fetch the m+1
row results in a no-find/end of cursor status (SQLCODE + 100, SQLSTATE
02000, error-code ‘6001’) being returned.
In addition to controlling the maximum number of records that are returned,
RDMS uses the information to more efficiently execute the statement. A
cursor containing this clause is read-only, asensitive, sequential, and
nonscrollable. To improve readability, the keyword ROW may be used instead
of ROWS (for example, when m = 1).

OPTIMIZE FOR p ROWS


p specifies the expected number of rows to be retrieved. It must be an
unsigned integer >= 1 and <= 34359738367. An attempt to fetch the p+1 row
returns that row, if it exists. RDMS uses this information to more efficiently
execute the statement. A cursor containing this clause is read-only, asensitive,
sequential, and nonscrollable. To improve readability, the keyword ROW may
be used instead of ROWS (for example, when p = 1).

Note: FETCH PRIOR, FETCH LAST, and LOCATE cannot be executed against a
nonscrollable cursor. Therefore, cursors containing FETCH FIRST m ROWS ONLY or
OPTIMIZE FOR p ROWS may only be used by FETCH FIRST, FETCH NEXT, and
FETCH NEXT n statements.

WITH DESCRIPTION
informs RDMS that you want information about the cursor you are declaring.
Retrieve this information with the GET DESCRIPTION statement. The
information includes

• The fully qualified table and column name of each item in the select list
unless it is an arithmetic expression or constant, or if the cursor is a
UNION operation. RDMS returns blanks if it encounters an arithmetic
expression. RDMS does not return a fully qualified table and column name
for an item specified with a title name. Instead, it returns only the title
name.
• The data type of each item.
• The size of each item: number of characters for a CHARACTER or
NCHARACTER column; the total size (including one character for the sign),
and number of fractional digits for a DECIMAL column; the size (number of
digits plus 1 for sign), scale, and binary precision for a NUMERIC column;
and the number of bytes of storage for an INTEGER, SMALLINT, REAL,
FLOAT, or DOUBLE PRECISION column.
• A flag indicating whether nulls are allowed in each item.
• A flag indicating whether each item is part of the table’s primary key.

7830 8160–027 7–27


DECLARE CURSOR

7.4.2. Examples
Example 1
The following example defines a set of rows by joining selected columns from tables
CUSTOMERS and HOUSES. The cursor is restricted to rows in which the asking price
of the house does not exceed the maximum price a customer is willing to pay.

DECLARE matchprice CURSOR


SELECT cno, maxprice, hno, price
FROM customers, houses
WHERE houses.price <= customers.maxprice

Example 2
The preceding example is for an inner join operation. The following examples illustrate
the use of outer join with two tables.

The first example shows all the customers and the houses that are available in the
desired locations, if any.

DECLARE c1 CURSOR
SELECT cname, maxprice, desiredloc, price, description
FROM customers LEFT OUTER JOIN houses
ON customers.desiredloc = houses.location

CNAME MAXPRICE DESIREDLOC PRICE DESCRIPTION

Thompson 150000 Woodbury 130000 2-bedroom condominium


Thompson 150000 Woodbury 40000 Handyman’s special
Owen 70000 New London (NULL) (NULL)
Johnson 90000 Woodbury 130000 2-bedroom condominium
Johnson 90000 Woodbury 40000 Handyman’s special
Jones 100000 Greenville (NULL) (NULL)
Smith 120000 Westchester 90000 Duplex

7–28 7830 8160–027


DECLARE CURSOR

The second example shows all the houses and the customers who are interested in
living in those locations, if any.

DECLARE c1 CURSOR
SELECT cname, maxprice, location, price, description
FROM customers RIGHT OUTER JOIN houses
ON customers.desiredloc = houses.location

CNAME MAXPRICE LOCATION PRICE DESCRIPTION

Thompson 150000 Woodbury 130000 2-bedroom condominium


Johnson 90000 Woodbury 130000 2-bedroom condominium
Thompson 150000 Woodbury 40000 Handyman’s special
Johnson 90000 Woodbury 40000 Handyman’s special
Smith 120000 Westchester 90000 Duplex
(NULL) (NULL) Parkway Heights 85000 3-bedroom town house
(NULL) (NULL) Turtle Creek 110000 4-bedroom house

Example 3
An outer join is defined as a binary operation only (that is, one that involves only two
tables). Therefore, performing an outer join operation on three or more tables may
need the parentheses to represent the nesting of such binary operation. Without the
parentheses, the outer join operation is performed from left to right as the tables are
defined in the query specification (FROM clause).

Here are examples of a three-table outer join. To do this we need a third table:

Realtors

RNAME LOCATION PHONE

Benson Turtle Creek 4432634


Doyle Westchester 5870784
Jefferson Woodbury 8721324
Miller Turtle Creek 4419305
Murray New London 3397745
Parker Westchester 5859231
Skater New London 3376470
Winter Appleville 9356886

7830 8160–027 7–29


DECLARE CURSOR

Joining the tables in the LOCATION column results in a table of both realtors and
available housing in the customer’s desired location, if any.

SELECT CNAME, MAXPRICE, REALTORS.LOCATION, PRICE, DESCRIPTION, RNAME,


PHONE
FROM (CUSTOMERS LEFT OUTER JOIN HOUSES
ON CUSTOMERS.LOCATION = HOUSES.LOCATION)
RIGHT OUTER JOIN REALTORS
ON CUSTOMERS.LOCATION = REALTORS.LOCATION

CNAME MAXPRICE LOCATION PRICE DESCRIPTION RNAME PHONE

(NULL) (NULL) Turtle Creek 110000 4-bedroom house Benson 4432634

Smith 120000 Westcheste 90000 Duplex Doyle 5870784


r

Thompson 150000 Woodbury 130000 2-bedroom condominium Jefferson 8721324

Thompson 150000 Woodbury 40000 Handyman’s special Jefferson 8721324

Johnson 90000 Woodbury 130000 2-bedroom condominium Jefferson 8721324

Johnson 90000 Woodbury 40000 Handyman’s special Jefferson 8721324

(NULL) (NULL) Turtle Creek 110000 4-bedroom house Miller 4419305

Owen 70000 New (NULL) (NULL) Murray 3397745


London

Smith 120000 Westcheste 90000 Duplex Parker 5859231


r

Owen 70000 New (NULL) (NULL) Skater 3376470


London

(NULL) (NULL) Appleville (NULL) (NULL) Winter 9356886

The next query specifies the WHERE condition in addition to the previous query
example. The WHERE clause condition is to choose records that satisfy either that the
house price is no more than the customer’s maximum price, or that the customer
name is non-null (the house may or may not exist for the customer).

SELECT CNAME, MAXPRICE, REALTORS.LOCATION, PRICE, DESCRIPTION, RNAME,


PHONE
FROM (CUSTOMERS LEFT OUTER JOIN HOUSES
ON CUSTOMERS.DESIREDLOC = HOUSES.LOCATION)
RIGHT OUTER JOIN REALTORS
ON CUSTOMERS.DESIREDLOC = REALTORS.LOCATION
WHERE CUSTOMERS.MAXPRICE > = HOUSES.PRICE AND CUSTOMERS.CNAME IS NOT
NULL

7–30 7830 8160–027


DECLARE CURSOR

The FROM clause operation takes place first, after which the WHERE clause condition
is evaluated against the result of the FROM clause operation.

CNAME MAXPRICE LOCATION PRICE DESCRIPTION RNAME PHONE

Thompson 150000 Woodbury 130000 2-bedroom condominium Jefferson 8721324

Smith 120000 Westchester 90000 Duplex Doyle 5870784

Thompson 150000 Woodbury 40000 Handyman’s special Jefferson 8721324

Johnson 90000 Woodbury 40000 Handyman’s special Jefferson 8721324

Smith 120000 Westchester 90000 Duplex Parker 5859231

Joining the tables in the LOCATION column results in a table of all realtors residing in
the location with houses for sale, together with customers interested in that location,
if any.

SELECT CNAME, MAXPRICE, REALTORS.LOCATION, PRICE, DESCRIPTION,


RNAME, PHONE
FROM (CUSTOMERS RIGHT OUTER JOIN HOUSES
ON CUSTOMERS.DESIREDLOC = HOUSES.LOCATION)
RIGHT OUTER JOIN REALTORS
ON CUSTOMERS.DESIREDLOC = REALTORS.LOCATION

CNAME MAXPRICE LOCATION PRICE DESCRIPTION RNAME PHONE

(NULL) (NULL) Turtle Creek 110000 4-bedroom house Benson 4432634

Smith 120000 Westchester 90000 Duplex Doyle 5870784

Thompson 150000 Woodbury 130000 2-bedroom condominium Jefferson 8721324

Johnson 90000 Woodbury 130000 2-bedroom condominium Jefferson 8721324

Thompson 150000 Woodbury 40000 Handyman’s special Jefferson 8721324

Johnson 90000 Woodbury 40000 Handyman’s special Jefferson 8721324

Smith 120000 Westchester 90000 Duplex Parker 5859231

(NULL) (NULL) Turtle Creek 110000 4-bedroom house Miller 4419305

(NULL) (NULL) New London (NULL) (NULL) Murray 3397745

(NULL) (NULL) New London (NULL) (NULL) Skater 3376470

(NULL) (NULL) Appleville (NULL) (NULL) Winter 9356886

Example 4
This example illustrates the use of a title name and position specification in the
ORDER BY clause:

DECLARE c1 CURSOR
SELECT cno, cname, maxprice AS cost
FROM customers
ORDER BY cost

7830 8160–027 7–31


DECLARE CURSOR

Example 5
This example illustrates how to select house numbers, their locations, and
commissions. The rows are sorted in ascending order of commissions and
alphabetically by order of location.

DECLARE by CURSOR
SELECT hno, price * 0.06, location
FROM houses
ORDER BY 2, location

Example 6
This example uses the UNION operator to select all combinations of prices and cities
(without duplicates) from the first 200 rows of both tables, CUSTOMERS and HOUSES.
The rows are sorted alphabetically by order of the name of the city.

DECLARE pl CURSOR
(SELECT maxprice, desiredloc FROM customers
WHERE cno < 'C201') UNION
(SELECT price, location FROM houses
WHERE hno < 'H201')
ORDER BY 2

Example 7
This example illustrates an invalid union because the corresponding columns PRICE
and DESIREDLOC are different data types:

DECLARE c1 CURSOR
(SELECT cno, desiredloc FROM customers) UNION
(SELECT hno, price FROM houses)

Example 8
This example illustrates how to create more comprehensible output by using
constants:

DECLARE okhouses CURSOR


(SELECT maxprice, desiredloc, 'buyer want' FROM customers) UNION
(SELECT price, location, 'seller offers' FROM houses)
ORDER BY 2

This example is matching the houses being offered for sale with what the buyer is
looking for by location. By adding a literal constant to each SELECT clause, the
resulting table treats the literal as if it were a column. You can easily determine the
origin of rows in the result. Both literals must have the same number of characters (in
this example, 13); otherwise, RDMS returns an error.

7–32 7830 8160–027


DECLARE CURSOR

Example 9
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The cursor is restricted to rows in which the asking
price of the house does not exceed the maximum price a customer is willing to pay,
but will not consider any houses that cost less than 350000.

DECLARE matchprice CURSOR


SELECT cno, maxprice, hno, price
FROM customers, houses
WHERE houses.price <= customers.maxprice AND houses.price > 350000

Example 10
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the view
expensive_houses. The cursor is restricted to rows in which the asking price of the
house does not exceed the maximum price a customer is willing to pay, but will not
consider any houses that cost less than 350000.

CREATE VIEW expensive_houses


(hno, price)
AS SELECT hno, price FROM houses
WHERE price > 350000
DECLARE matchprice CURSOR
SELECT cno, maxprice, hno, price
FROM customers, expensive_houses
WHERE expensive_houses.price <= customers.maxprice

Example 11
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the derived
table expensive_houses. The cursor is restricted to rows in which the asking price of
the house does not exceed the maximum price a customer is willing to pay, but will
not consider any houses that cost less than 350000.

DECLARE matchprice CURSOR


SELECT cno, maxprice, hno, price
FROM customers,
(SELECT hno,price
FROM houses
WHERE price > 350000) expensive_houses
WHERE expensive_houses.price <= customers.maxprice

7830 8160–027 7–33


DECLARE CURSOR

Example 12
This example shows how to write a subquery that returns only the top 10 rows. This
query uses a table called enquiry that contains questions from customers. The query
returns the questions posed by the customers who are willing to pay the most for
their house.

DECLARE return10 CURSOR


SELECT *
FROM enquiry
WHERE enquiry.cno IN (
SELECT cno
FROM customers
ORDER BY maxprice DESC
FETCH FIRST 10 ROWS ONLY)

Example 13
This example shows the illegal usage of ORDER BY within a query-expression. ORDER
BY and FETCH FIRST m ROWS ONLY may only be at the end of the DECLARE CURSOR
statement or as part of a query-expression that is enclosed within parentheses.

DECLARE badunion CURSOR


SELECT x FROM t1 ORDER BY x FETCH FIRST 5 ROWS ONLY
UNION
SELECT x FROM t2

The UNION is correctly written as follows:

DECLARE badunion CURSOR


(SELECT x FROM t1 ORDER BY x FETCH FIRST 5 ROWS ONLY)
UNION
SELECT x FROM t2

7.4.3. Rules and Guidelines


Read the following rules and guidelines before using the DECLARE CURSOR
statement.

Limits
The highest level (outermost) query expression can include up to 14 base or global
temporary tables. If a base or global temporary table is specified more than once,
each specification counts towards the maximum of 14.

If a view is specified in the query expression, it does not count towards this limit;
however, each of its underlying base tables does count.

7–34 7830 8160–027


DECLARE CURSOR

Performance
When you declare a cursor, RDMS analyzes the statement. Depending on the nature
and complexity of the query specification, this can require significant processing.
RDMS also allocates memory to the cursor that is not released until a DROP CURSOR
statement is executed. For more information, see 7.6.

The ORDER BY clause causes RDMS to sort all rows that satisfy the WHERE clause
when the cursor is opened. Opening a cursor with the ORDER BY clause takes longer
than opening a cursor without it.

In most cases, the ORDER BY clause requires RDMS to take a “snapshot” of the
cursor. This is a static image of the data when the cursor is opened. Rows retrieved
from the cursor come from the snapshot. Changes to the selected rows in the
database are not reflected in the snapshot.

If the sort specifications can be satisfied by using the primary key or secondary
indexes, RDMS does not take a snapshot.

Use the EXPLAIN statement to find out whether a snapshot was made for a given
cursor.

Use of the FETCH FIRST m ROWS ONLY and OPTIMIZE FOR p ROWS clauses
improves the performance of fetches.

See Section 5 of the Relational Database Server for ClearPath OS 2200


Administration Guide for additional performance considerations.

Random Access Cursors


RDMS does not optimize random access cursors and never uses a secondary index
search path when fetching from a random access cursor. Furthermore, random access
cursors are extensions of standard SQL. For these reasons, random access cursors
have limited application and should be used with discretion.

Multiple Cursors
More than one cursor can be opened at the same time. For more information about
opening a cursor, see 9.4.

Read-Only Cursors
A cursor is read-only if the DECLARE CURSOR statement includes at least one of the
following characteristics:

• The DISTINCT keyword


• A select list that has an entry with more than a column specification (for example,
an arithmetic operation or a function)
• A column specification that appears more than once in the select list
• A GROUP BY clause

7830 8160–027 7–35


DECLARE CURSOR

• A HAVING clause
• An ORDER BY clause
• A FROM clause that references more than one table or view
• A FROM clause that identifies a read-only view (a view that cannot be updated)
• A subquery
• A UNION operation
• Outer joined-table specification
• A FOR READ-ONLY clause
• The INSENSITIVE keyword
• A FETCH FIRST m ROWS ONLY or OPTIMIZE FOR p ROWS clause
• A cursor containing a derived table or CTE is read only.

FETCH FIRST m ROWS ONLY and OPTIMIZE FOR p ROWS


These clauses cannot be used with cursors declared FOR RANDOM ACCESS or FOR
UPDATE OF.

If these clauses are used together, the FETCH FIRST clause specifies the maximum
number of records that are returned, as usual. If the cursor is not a join, RDMS
optimizes for the minimum of m or p. If the cursor is a join, RDMS optimizes for p
records when searching the first table of the join.

Memory Usage
When a cursor is declared, RDMS allocates memory to retain the required information
about the cursor. When the cursor is opened, RDMS allocates more memory for any
additional required information.

To release this memory when a cursor does not need to be opened or even declared,
use the CLOSE or DROP CURSOR statement.

Nulls and the ORDER BY Clause


Nulls are considered to be greater than nonnulls when rows in a cursor are sorted.
That is, if the sort is on a column in ascending order, rows with null in that column
follow rows with nonnulls in that column.

Cursors Using Both FOR RETENTION and FOR UPDATE OF Clauses


When you fetch from a cursor declared with a FOR UPDATE OF clause, RDMS usually
places a retrieval lock on the fetched row until the cursor position is changed.
However, if you declare an updatable cursor with the FOR RETENTION clause and
commit the step, the cursor retains its position but the lock disappears. Row level
locks cannot exist past the end of the step.

7–36 7830 8160–027


DECLARE CURSOR

Incompatibility of ESQL DECLARE CURSOR Statement and DROP


CURSOR Statement
You cannot use the DROP CURSOR statement to drop a cursor that was declared with
the DECLARE CURSOR statement through ESQL.

Compilation Versus Execution


A static ESQL DECLARE CURSOR statement is not executed when the program is
executed. Consequently, it has no effect on run-time entities such as SQLCODE
(see C.3).

An interpreter interface DECLARE CURSOR statement, however, is executed.

Module Language Processing


If you declare a cursor but do not open the cursor in the same module, an error is
returned during SQL module language preprocessor (SMLP) processing.

Default Qualifiers and Version Names


In most statements, a table specification without a qualifier or version name
references the table with the default qualifier or version name. This is also true for the
DECLARE CURSOR statement, for qualifiers. Default version names are not used until
the cursor is opened, however. If the default version name is changed after the cursor
is declared but before it is opened, the cursor is based on the new default version
name.

In the following SQL sequence, the cursor that is opened contains rows from
RDMS.HOUSES:OUTSTATE. The qualifier RDMS and the version name PRODUCTION
are the default values at the beginning of the example.

DECLARE c1 CURSOR SELECT * FROM houses


USE DEFAULT VERSION outstate
USE DEFAULT QUALIFIER q1
OPEN c1

Note: In ESQL, a cursor's declaration (DECLARE CURSOR statement) must


textually precede any reference to it by another ESQL statement in the same
compilation unit. See 2.11 and also “Column Specifications Without Qualifiers or
Version Names” later in this subsection.

Updates and Cursor Result Sets


After a cursor has been opened, the same thread can perform other SQL statements
that alter the data in the tables referenced by the open cursor.

If the cursor is a sensitive cursor, the alterations can affect the contents of the result
set of the cursor.

7830 8160–027 7–37


DECLARE CURSOR

Inserted or updated rows can become part of the result set of the cursor, if the
inserted or updated rows still meet the conditions needed to be a member of the
result set. The position of the inserted or updated rows in the result set, relative to
the current cursor position at the time of the inserts or updates, is dependent on the
access path used by RDMS for the cursor. Deleted rows are removed from the result
set immediately and cannot be fetched again, no matter where the cursor is currently
positioned.

Any changes to tables that cause the access path to change could affect a thread that
opens a sensitive cursor and then modifies the tables used by the cursor. The
following operations could change the access path:

• Creating or dropping an index on the tables


• Updating RDMS statistics on the tables
• Adding or dropping unique constraints on the tables
• Altering the attributes of columns that are part of the primary key or secondary
indexes of the tables

For example, when you use the UPDATE Positioned statement to modify a row, and it
still meets the conditions of the cursor, the location of the row can move in the result
set so that the same row can be fetched again on a later FETCH NEXT performed
before the end of the result set is reached.

Dynamic Result Sets


Inside a stored procedure or stored function, the WITH RETURN clause specifies that
the cursor, if it is left open at the completion of the procedure's execution, is treated
as a dynamic result set. See 4.7 for more information about dynamic result sets.

WITH RETURN can only be specified on cursors declared in the outermost compound
statement of the routine. This means that cursors declared WITH RETURN must be
declared before any other executable statement. Cursors that specify WITH RETURN
are not updatable, and they must also explicitly specify FOR READ ONLY and FOR
RETENTION.

FOR RETENTION and WITH HOLD are synonymous; either one specifies that the
cursor is a retention cursor. WITHOUT HOLD is the default. It signifies that the cursor
is automatically closed whenever the thread is committed.

Routines and Triggers and the DECLARE CURSOR Statement


There is a limit of 16 cursor declarations within a routine or trigger.

Cursors declared within routines can reference any parameters of the routine as well
as any SQL variables declared within the same compound statement as the DECLARE
CURSOR or at an outer level of nesting. Cursors declared within triggers can reference
any correlation-name.column-name, as well as any SQL variables declared within the
same compound statement as the DECLARE CURSOR or at an outer level of nesting.
These references are resolved when the routine or trigger is created. Placeholder
variables and parameter markers are not allowed in the DECLARE CURSOR statement.

7–38 7830 8160–027


DECLARE CURSOR

The values that are used in place of parameter, correlation-name.column-name, SQL


variable, and system variable references are determined at the time that the cursor is
opened. The cursor continues to use these values until the cursor is closed. Although
the value of the parameters, correlation-name.column-names, and SQL variables may
change, through the use of SET, SELECT, or FETCH statements, the cursor continues
to use the value that was in effect when the cursor was opened.

If either the OLD TABLE or NEW TABLE alias-name of a trigger is the target table of a
cursor declaration, then the cursor must be a read-only cursor. Further, the cursor may
not be declared with the RANDOM or DIRECT keywords.

Note:
The following are nonstandard RDMS syntax extensions:
• [ FOR ] query-expression (that is, optional FOR),
• FOR RANDOM ACCESS
• FOR DIRECT ACCESS

Routines and Triggers and the DROP CURSOR Statement


You cannot use the DROP CURSOR statement to drop a cursor that was declared with
the DECLARE CURSOR statement in a routine or trigger. All cursors declared within a
compound statement are automatically dropped when the END statement of that
compound statement is executed.

Routines and Triggers and Default Version Names and Default


Qualifiers
RDMS does not support the USE DEFAULT statement within a routine or trigger. The
default qualifier in effect when a routine or trigger is created is used to resolve all
unqualified table and column references in the routine or trigger. The default version in
effect at execution time is used to resolve all implicit table version names in the
routine or trigger.

Outer Joined-Table
When a cursor contains outer joined-tables, then the following rules are applied:

• The cursor is read-only and cannot have FOR UPDATE clause.


• RANDOM ACCESS clause is not allowed.

7830 8160–027 7–39


DECLARE CURSOR

Column Specifications Without Qualifiers or Version Names


If a column reference in a select list, WHERE clause, GROUP BY clause, or HAVING
clause contains a column specification that includes a table specification having no
qualifier or version name, the following rules determine which table it references:

1. The default qualifier in effect when the DECLARE CURSOR statement is processed
is implied for any column specification or table specification having no explicit
qualifier.
2. The table specifications in the FROM clause are scanned from left to right for the
first table specification that matches the table specification in the column
specification and that names a table that contains a column of the same name.
A table specification is a match if it is at least as specific as the column
specification's table specification and the explicit names (along with the implied
qualifier) match. For example, Q1.R1 matches Q1.R1 and Q1.R1:V1, but does not
match R1 or R1:V1 unless the default qualifier is Q1.
3. When the cursor is opened, the default version name in effect in any table
specification that lacks an explicit version name is used.

Example
The following is a step-by-step example of how these rules work.

USE DEFAULT QUALIFIER rdms


USE DEFAULT VERSION production
DECLARE example CURSOR
SELECT cno, rdms.customers.cname, houses:production.price
FROM rdms.houses:production, customers, houses:outstate
WHERE houses:outstate.price <= maxprice
AND hno > 'H'
USE DEFAULT VERSION outstate
OPEN example

After applying rule 1, the query specification becomes the following:

SELECT cno, rdms.customers.cname, rdms.houses:production.price


FROM rdms.houses:production, rdms.customers, rdms.houses:outstate
WHERE rdms.houses:outstate.price <= maxprice
AND hno > 'H'

Rule 2 changes the query specification to the following:

SELECT rdms.customers.cno, rdms.customers.cname,


rdms.houses:production.price
FROM rdms.houses:production, rdms.customers, rdms.houses:outstate
WHERE rdms.houses:outstate.price <= rdms.customers.maxprice
AND rdms.houses:production.hno > 'H'

7–40 7830 8160–027


DECLARE CURSOR

Finally, when the OPEN statement is executed, rule 3 applies. This yields the
following:

SELECT rdms.customers:outstate.cno, rdms.customers:outstate.cname,


rdms.houses:production.price
FROM rdms.houses:production, rdms.customers:outstate,
rdms.houses:outstate
WHERE rdms.houses:outstate.price <= rdms.customers:outstate.maxprice
AND rdms.houses:production.hno > 'H'

Since other statements that can contain a query specification (SELECT INTO, CREATE
VIEW, and UNLOAD) are not opened, rule 3 is applied when the statement is
executed, so the following two sequences are equivalent:
Sequence 1:
USE DEFAULT QUALIFIER rdms
USE DEFAULT VERSION production
SELECT cno, rdms.customers.cname, houses:production.price
INTO :v1, :v2, :v3
FROM rdms.houses:production, customers, houses:outstate
WHERE houses:outstate.price <= maxprice
AND hno > 'H'

Sequence 2:
USE DEFAULT QUALIFIER rdms
USE DEFAULT VERSION production
SELECT rdms.customers:production.cno, rdms.customers:production.cname,
rdms.houses:production.price
INTO :v1, :v2, :v3
FROM rdms.houses:production, rdms.customers:production,
rdms.houses:outstate
WHERE rdms.houses:outstate.price <= rdms.customers:production.maxprice
AND rdms.houses:production.hno > 'H'

Note that the rows are taken from a version of table CUSTOMERS that is different
from the version in the example that uses the DECLARE CURSOR statement.

Placeholder Variables
When you are using placeholder variables in an OPEN statement, the following rules
apply:

• If a placeholder variable (for example, $P1) occurs in the WHERE clause of a


DECLARE CURSOR, it must also occur in the corresponding OPEN statement.
For example, the $P1 in the DECLARE CURSOR statement must correspond to the
$P1 in the OPEN statement. The order in which $P1 appears in the DECLARE
CURSOR statement does not have to be the order in which $P1 appears in the
OPEN statement. In addition, you can use a placeholder variable more than once in
DECLARE CURSOR, but that variable name does not occur more than once in the
OPEN statement.
• The size and data type of the host program variables in the OPEN statement must
match those of variables in the DECLARE CURSOR statement and the application
program.

7830 8160–027 7–41


DECLARE CURSOR

For example, the application program variable associated with $P1 in the DECLARE
CURSOR statement’s WHERE clause must match the type and size of $P1 in the
OPEN statement. You should usually use the same application program variables
in both the DECLARE CURSOR and OPEN statements. For character value
assignment considerations, see 2.8.1.
• Before you use the OPEN statement, you must initialize the program variables
associated with the placeholder variables.

An OPEN CURSOR statement is not required in cases like the following:

DECLARE cursor-name CURSOR FOR select * from table where column = value
FETCH INTO $p1, $p2

An OPEN CURSOR statement is required in cases like the following:

DECLARE cursor-name CURSOR FOR select * from table where column = $p1
OPEN cursor-name USING $p1
FETCH INTO $p1, $p2

7–42 7830 8160–027


DELETE

7.5. DELETE
Use the DELETE statement to delete one or more rows from a table or view in the
database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes Yes Yes E/X

7.5.1. Syntax
SQL 92 Syntax (Entry Level)
DELETE FROM table-specification

[ WHERE { Boolean-expression │ CURRENT OF cursor-name } ]

RDMS Extended Syntax


DELETE [ FROM ] table-specification

[ ALL [ ROWS ] │ WHERE { Boolean-expression │ CURRENT OF cursor-name } ]

Syntax When Used in Routines or Triggers


DELETE [ FROM ] table-specification

[WHERE { Boolean-expression │ CURRENT OF cursor-name } ]

where:

table-specification
is a table name as defined in 2.2.1.

WHERE
defines the rows to delete. If the WHERE clause is not used, RDMS deletes all
rows of the table. Therefore, you should always use a WHERE clause if you do not
want to delete all of the rows in the table.

Boolean-expression specifies the row or rows to delete. If the Boolean


expression contains one or more subqueries, the table referred to cannot be the
table from which rows are being deleted. For more information on Boolean
expressions, see 2.4.2.

CURRENT OF cursor-name deletes the row in the table that corresponds to the
row in the cursor cursor-name where the cursor pointer is currently positioned.

7830 8160–027 7–43


DELETE

The rules for using the positional DELETE statement are as follows:

• You cannot specify a read-only cursor. For a description of read-only cursors,


see 7.4.
• The cursor cannot be a random access type cursor.
• The table specification in the DELETE statement must be the same as the table
specification in the cursor’s FROM clause.
• A FETCH statement executed before the DELETE statement must successfully
fetch a row from the cursor specified in the DELETE statement.
• You do not have to declare the cursor with the FOR UPDATE OF clause, but if
you do, RDMS locks the current row when it is fetched. This means that no
other user can update or delete that row until the currency of the cursor is
changed.
• If FETCH NEXT n is used on the cursor, positional DELETE statements are not
allowed and are rejected.

ALL [ROWS]
deletes every row in the table.

7.5.2. Examples
Example 1
The following two statements delete all rows from a table:
DELETE houses ALL

DELETE customers

Example 2
The following statement removes a specific row from a table:

DELETE houses
WHERE hno = 'H102'

Example 3
You can also delete rows that meet certain conditions. For example, to eliminate all
customers who are unable to spend at least $40,000 for a house from the database,
enter either one of the following statements:

DELETE customers
WHERE maxprice < 40000

DELETE customers
WHERE maxprice - 40000 < 0

7–44 7830 8160–027


DELETE

Example 4
The following example deletes only those rows where the value of the PRICE column
is greater than $100,000:

DELETE houses
WHERE price > 100000

Example 5
In the following example, the first FETCH statement returns data on house H101, the
second data on house H102, and the third data on house H103; the DELETE statement
deletes the row for house H103:

DECLARE b CURSOR SELECT * FROM houses


FETCH FIRST B...
FETCH NEXT B...
FETCH NEXT B...
DELETE houses WHERE CURRENT OF B

7.5.3. Rules and Guidelines


Read the following rules and guidelines before using the DELETE statement.

Permanent Changes, NONE Recovery Option


Permanent database changes can occur any time after a DELETE statement is
executed if the NONE recovery option is used on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently delete rows from the database until the
program executes a COMMIT or END THREAD statement.

Default Locks, RETRIEVAL Mode


The default table lock is the step-duration UPDATE mode, and the default row lock is
step-duration EXCLUSIVE UPDATE mode. See the Relational Database Server for
ClearPath OS 2200 Administration Guide.

If you lock a table in one of the RETRIEVAL modes, RDMS rejects the DELETE
statement.

DELETE ALL
The DELETE ALL statement implicitly locks an entire table in exclusive update mode if
you do not explicitly lock the table with a LOCK statement. If RDMS can lock the table
in exclusive update mode and the deferred recovery option is used and this is the only
table in the storage area, the DELETE ALL statement is very fast and the UDS retention
file space is not exceeded. This is because in this case, RDMS executes the DELETE
ALL statement by reinitializing the file control information. SET AUXINFO OFF further
improves performance. Refer the Relational Database Server for ClearPath OS 2200
Administration Guide for more information.

7830 8160–027 7–45


DELETE

When you execute a DELETE ALL statement, the UDS retention file (a file maintained
by UDS Control for recovery purposes) might overflow. To prevent this, perform one
of the following actions:

• Enlarge the retention files.


• Instead of executing one DELETE ALL statement, consider using several
DELETE . . . WHERE statements with COMMIT statements in between.
• Turn off recovery for the storage area before executing the DELETE ALL
statement, remaining mindful at the same time of the perils of not using recovery
(see 6.11.14).
• Use the QUICKLOOKS recovery option in the BEGIN THREAD statement instead of
DEFERRED if you plan to delete many rows during a thread. QUICKLOOKS uses
fewer system resources than DEFERRED.

When the table contains a GENERATED AS IDENTITY column, DELETE ALL causes the
IDENTITY sequence to restart with the START/RESTART value. When the table
contains a GENERATED AS partition_id() column, DELETE ALL causes the sequence of
the left-most partition to restart with 1 and all other partitions to restart with their
lowest possible value.

Number of Rows Deleted Returned


RDMS returns the number of rows deleted through the auxiliary information variable.
For more information, see the manual for the programming language you are using.

In routines and triggers, the RDMSAUXINFO system variable can be used to obtain this
information (see 4.9.1).

Foreign Keys
When you are deleting rows from a parent table involved in a foreign key constraint,
RDMS checks to ensure that no rows exist in the child table that are related to the
rows being deleted from the parent table:

For DELETE ALL or DELETE with no WHERE clause (that is, deleting all rows from
parent table), RDMS checks to ensure that if rows do exist in the child table before the
deletion, all such rows contain null values for the foreign key columns.

On deleting rows from a table that is the object of a self-referencing foreign key (that
is, a table that is both the parent and child table for the same foreign key constraint),
RDMS checks the foreign key after the deletion.

Because of performance considerations and the manner in which self-referencing


foreign keys function, an RDMS error returned for a violation of foreign key integrity
may or may not cause a rollback.

7–46 7830 8160–027


DELETE

Routines and Triggers and the DELETE Statement


Any cursor referenced in a DELETE statement must be declared within the same
compound statement as the DELETE statement or at an outer level of nesting.

The cursor must be opened using the OPEN statement and positioned on a row by a
FETCH statement prior to the execution of the DELETE statement.

7830 8160–027 7–47


DROP CURSOR

7.6. DROP CURSOR


Use the DROP CURSOR statement to remove a previously defined cursor from RDMS
internal tables and release the memory RDMS allocated to the cursor when it was
declared.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No X

7.6.1. RDMS Extended Syntax


DROP CURSOR cursor-name

where cursor-name is the name of a cursor previously defined by a DECLARE


CURSOR statement.

7.6.2. Example
The following example drops the cursor MATCHPRICE:

DROP CURSOR matchprice

7.6.3. Rules and Guidelines


Read the following rules and guidelines before using the DROP CURSOR statement.

Redeclaring Cursor After Dropping


Use the DROP CURSOR statement in an application program when you no longer need
information from a particular cursor. After dropping a cursor, you must define it again
with a DECLARE CURSOR statement before using it in a program.

Performance
You can drop cursors when they are no longer needed again during a thread.
Dropping cursors frees space used by the thread, which in turn improves the
performance of statements that use cursors (for example, the FETCH statement).

Incompatibility with ESQL DECLARE CURSOR Statement


You cannot use the DROP CURSOR statement to drop a cursor that was declared with
the DECLARE CURSOR statement through ESQL.

7–48 7830 8160–027


DROP INDEX

7.7. DROP INDEX


Use the DROP INDEX statement to remove an index from a table definition.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No X

7.7.1. RDMS Extended Syntax


DROP INDEX index-name-list

FROM [ TABLE ] table-specification

where:
index-name-list
is a list of the names of indexes and unique constraints to be dropped, separated
by commas.
table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.

7.7.2. Example
The following example removes index IX5 from table HOUSES:

DROP INDEX ix5 FROM TABLE houses

7.7.3. Rules and Guidelines


Read the following rules and guidelines before using the DROP INDEX statement.

Nonpartitioned Tables and DROP INDEX


When an index is dropped from a nonpartitioned table, the records of the index are
removed from the storage area. If the deferred recovery option is used and the index
being dropped is the only index in the storage area, the DROP INDEX statement is very
fast and the UDS retention file space is not exceeded. This is because, in this case,
RDMS executes the DROP INDEX statement by reinitializing the file control
information. Otherwise, RDMS removes the index from the storage-area page by
page.

7830 8160–027 7–49


DROP INDEX

Partitioned Tables and DROP INDEX


There is no different syntax for partitioned tables for the DROP INDEX command. The
semantics for the drop of an index that is part of a partitioned table are different from
those of a nonpartitioned table. In partitioned tables, every index must be in its own
storage area and remain in the storage area after the execution of the DROP INDEX
command. Therefore, you must issue PROCESS STORAGE-AREA … DELETE and
PROCESS STORAGE-AREA … INSTALL commands before you reuse the storage area.

Partitions of the index being dropped can be in attached, detached, or hidden states.

Effect on Triggers
The DROP INDEX statement causes triggers to be implicitly dropped if the trigger
references the table. The implicit dropping of triggers can be prevented by using the
UREP configuration attribute RDMS-TRIGGER-DROPPING. RDMS-TRIGGER-DROPPING
is set to CASCADE by default. CASCADE allows RDMS to drop any triggers associated
with the dropped index table. Setting RDMS-TRIGGER-DROPPING to RESTRICT causes
any DROP INDEX statement to fail if it would cause the implicit dropping of a trigger.

Effect on Compiled Programs


Changes made by the DROP INDEX statement may invalidate previously compiled
programs, requiring these programs to be recompiled (without any logic changes).

Changes made by the DROP INDEX statement have no effect on previously compiled
interpreter interface programs (aside from performance during execution). For more
information, see 2.11.2.

Table Ownership
You must be the owner of the table from which you are removing an index.

7–50 7830 8160–027


DROP PROCEDURE/FUNCTION

7.8. DROP PROCEDURE/FUNCTION


Use the DROP PROCEDURE or DROP FUNCTION statement to remove a defined
stored procedure or function from the database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* No No No No P

* Not IPF SQL

7.8.1. SQL Syntax


DROP { PROCEDURE │ FUNCTION } [schema-name.]routine-name { CASCADE │ RESTRICT }

where:
schema-name
is the name of the schema containing the table routine. If you omit the schema
name, RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user-id of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information, see the Repository for
ClearPath 2200 Administration Guide.
routine-name
is the name of the routine. Schema and routine names must be valid names as
defined in 2.2.1.
CASCADE
all routines or triggers that reference the dropped stored procedure or function
are also dropped.
RESTRICT
if the dropped stored procedure or function is referenced by any other routine or
trigger, then the drop fails.

7.8.2. Examples
The first example drops function HOUSES_SCHEMA.SELECT_HOUSES and all other
routines that reference HOUSES_SCHEMA.SELECT_HOUSES:

DROP FUNCTION houses_schema.select_houses CASCADE;

The second example attempts to drop function HOUSES_SCHEMA.SELECT_HOUSES.


If HOUSES_SCHEMA.SELECT_HOUSES is referenced by any other routine, the drop
will fail.

DROP FUNCTION houses_schema.select_houses RESTRICT;

7830 8160–027 7–51


DROP PROCEDURE/FUNCTION

7.8.3. Rules and Guidelines


Read the following rules and guidelines before using the DROP PROCEDURE or DROP
FUNCTION statement.

Effect on Triggers When the CASCADE Option Is Used on the DROP


PROCEDURE or DROP FUNCTION Statement
These statements can cause triggers to be implicitly dropped if the trigger directly or
indirectly references the routine. The implicit dropping of triggers can be prevented by
using the UREP configuration attribute RDMS-TRIGGER-DROPPING.
RDMS-TRIGGER-DROPPING is set to CASCADE by default. CASCADE allows RDMS to
drop any triggers associated with the routine being dropped. Setting
RDMS-TRIGGER-DROPPING to RESTRICT causes any drop routine statement to fail if it
would cause the implicit dropping of a trigger.

Ownership
To remove a stored procedure or function from the database, you must own the
schema in which the procedure or function resides.

Threads
The thread in which this statement executes must be update recoverable.

Object Type
Use DROP PROCEDURE to drop a stored procedure. Use DROP FUNCTION to drop a
stored function.

7–52 7830 8160–027


DROP ROLE

7.9. DROP ROLE


DROP ROLE destroys a role. When a role is destroyed, all privileges granted to the
role are removed and all the users in that role lose the privileges granted to them by
the role.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No X

7.9.1. Syntax
DROP ROLE role-name

7.9.2. Examples
DROP ROLE “ROLE-PROGRAMMER”

7.9.3. Rules and Guidelines


The value of aux-info, following successful execution of DROP ROLE, is the number of
roles dropped plus the number of users who had been members of the dropped role.
When aux-info is returned as zero, but the DROP ROLE statement executed
successfully, the role being dropped did not exist. The number of privileges associated
with the dropped role is not added to the aux-info value. This is because knowing the
number of users who are affected by the DROP ROLE statement is considered more
important than knowing how many privileges had been granted to that role. The
theory being that if there are no users associated with a role then there is no impact
to the production system, regardless of how many privileges the role has.

The DROP ROLE statement cannot be included as part of a CREATE SCHEMA


statement, and it cannot be executed within a routine or trigger.

The DROP ROLE statement must be able to get exclusive use of all table and views
for which the role has privileges. No cursors can be declared over these tables.

Only the creator of the role can drop the role.

7830 8160–027 7–53


DROP TABLE

7.10. DROP TABLE


Use the DROP TABLE statement to remove a table definition from a database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No I/X*

* The illustrated syntax is referred to as “RDMS extended syntax” because RDMS extensions
are included in the intermediate level SQL 92 syntax.

7.10.1. RDMS Extended Syntax


DROP [ PERMANENT ] TABLE table-list [ INCLUDING CONTENTS ]

where table-list is the table specification (see 2.2.2) indicating which table definitions
to drop, separated by commas. Table specifications cannot include versions. RDMS
drops tables in the order listed.

INCLUDING CONTENTS instructs RDMS to remove any records the table might contain
and then remove the table definition.

7.10.2. Example
The following example drops definitions for tables REALESTATE.HOUSES and
HOUSE-SCHEMA.HOUSES:

SET DEFAULT SCHEMA house-schema


DROP TABLE realestate.houses, houses

7.10.3. Rules and Guidelines


Read the following rules and guidelines before using the DROP TABLE statement.

Effect on Triggers
The DROP TABLE statement causes triggers to be implicitly dropped if the trigger
references the table. If there are a large number (several hundred) such triggers
referencing the same table, this process of dropping all the triggers in a single thread
may run into D-bank space limitations. See the Relational Database Server for
ClearPath OS 2200 Administration Guide for more information regarding this
situation.

The implicit dropping of triggers can be prevented by using the UREP configuration
attribute RDMS-TRIGGER-DROPPING. RDMS-TRIGGER-DROPPING is set to CASCADE
by default. CASCADE allows RDMS to drop any triggers associated with the dropped
table. Setting RDMS-TRIGGER-DROPPING to RESTRICT causes any DROP TABLE
statement to fail if it would cause the implicit dropping of a trigger.

7–54 7830 8160–027


DROP TABLE

Partitioned and Nonpartitioned Tables and DROP TABLE


The syntax of DROP TABLE is the same for a partitioned or nonpartitioned table. The
semantics of DROP TABLE are different for partitioned and nonpartitioned tables. A
nonpartitioned table in an unowned schema cannot be dropped if it contains records.
A partitioned table can be dropped if it contains records; however, the records are not
deleted by the DROP TABLE command and remain in the storage area following the
DROP TABLE command.

RDMS implementation of DROP TABLE for nonpartitioned tables in unowned schemas


is nonstandard because the standard allows a table containing records to be dropped.
Nonpartitioned tables require all records to be deleted before the table is dropped
because multiple tables may be located in the same storage area. Records are deleted
to reclaim the file space before the table is deleted. Partitioned tables avoid this
problem by allowing only one table per file.

Prerequisites When INCLUDING CONTENTS Is Not Specified


If the table being dropped is partitioned, RDMS removes the table definition
regardless of whether the table contains records. The records are not removed from
the partitions when the table definition is removed. If the table being dropped is not
partitioned but is in an owned schema, RDMS first removes the records from the table
and then removes the table definition. If the table being dropped is nonpartitioned and
is in an unowned schema, it must be empty for the DROP TABLE to succeed.
Therefore, before you drop a table definition of a nonpartitioned table in an unowned
schema, ensure that all rows of all table versions are deleted with the DELETE
statement.

Foreign Keys
If you wish to drop a table that is the parent of a foreign key, you must first drop the
foreign key or drop the child table. If you are dropping a table in order to redefine it,
you can drop the foreign key relationship instead of dropping the child table or tables.
When the table is redefined and reloaded, you can reestablish the relationship. You
should ensure that the child table is not updated during this process.

Effect on Views (Cascading)


When you drop a table definition, RDMS automatically drops any view that is
dependent on that table (this is called “cascading”). All grants on these views are
revoked by RDMS.

Cursors
You cannot drop a table on which a cursor is declared.

Ownership Security
If a table has an owner, only the owner can drop it. All grants on the table are revoked
by RDMS.

7830 8160–027 7–55


DROP TABLE

Effect on Compiled Programs


Some changes made by the DROP TABLE statement may invalidate previously
compiled ESQL programs. For more information, see 2.11.2.

Effect on Table Contents


The effect on the contents of a table depends on the table type and whether
INCLUDING CONTENTS was specified, as follows.

When INCLUDING CONTENTS


Table Type Default Is Specified

Unowned The table must contain zero The records are deleted as part
nonpartitioned records in order to be dropped. of the DROP TABLE operation.
Records are thus not deleted as
part of the drop.
Owned The records are deleted as part The records are deleted as part
nonpartitioned of the DROP TABLE operation. of the DROP TABLE operation.
Partitioned The records remain in the The records are deleted as part
storage area after the DROP of the DROP TABLE operation.
TABLE operation.
Temporary DROP TABLE must be the DROP TABLE must be the
thread’s first reference to the thread’s first reference to the
temporary table. The table is temporary table. The table is
thus not materialized before the thus not materialized before the
DROP TABLE, and no delete is DROP TABLE, and no delete is
necessary. necessary.

The following SQL statement sequence could provide better performance than
DROP table-name INCLUDING CONTENTS:

SET AUXINFO OFF


DELETE table-name ALL
DROP table-name

These statements could perform better because DELETE ALL might only initialize the
file control information, while DROP TABLE removes the records one page at a time.

Effect on Global Temporary Tables


It is not necessary to use a DELETE statement to delete records from a temporary
table before you drop the table.

A global temporary table cannot be dropped by a thread that has referenced that table.

7–56 7830 8160–027


DROP TRIGGER

7.11. DROP TRIGGER


Use the DROP TRIGGER statement to remove a trigger from the database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* No No No No P

* Not IPF SQL

7.11.1. Syntax
DROP TRIGGER [schema.]trigger-name

where trigger-name is the optionally qualified name of the trigger defined in the
database.

7.11.2. Example
The following example drops DROP TRIGGER not_production in the default schema.

DROP TRIGGER not_production;

7.11.3. Rules and Guidelines


Read the following rules and guidelines before using the DROP TRIGGER statement.

Commit
If you commit the thread, the trigger is removed from the database.

Cursors
You cannot drop a trigger if there is an open cursor on the target table of the trigger.

Ownership
You can drop a trigger only if you are the owner of that trigger.

Rollback
If you issue a rollback command, the trigger is retained in the database and remains
active.

Threads
The thread in which this statement operates must be update recoverable.

7830 8160–027 7–57


DROP VIEW

7.12. DROP VIEW


Use the DROP VIEW statement to remove a view definition from a database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No I/X*

* The illustrated syntax is referred to as “RDMS extended syntax” because RDMS extensions
are included in the intermediate level SQL 92 syntax.

7.12.1. RDMS Extended Syntax


DROP VIEW [schema-name.] view-name [ , [schema-name.] view-name ]...

where schema-name.view-name is the name of the view to drop and follows the
same rules as for table names (see 2.2.2), except that version names are not allowed.

7.12.2. Example
The following example drops definitions for views V1 and V2 under schema S1, and for
view VX under schema S2:

USE DEFAULT SCHEMA s1


DROP VIEW v1, v2, s2.vx

7.12.3. Rules and Guidelines


Read the following rules and guidelines before using the DROP VIEW statement.

Effect on Triggers
The DROP VIEW statement causes triggers to be implicitly dropped if the trigger
directly or indirectly references the view. The implicit dropping of triggers can be
prevented through the use of the UREP configuration attribute
RDMS-TRIGGER-DROPPING. RDMS-TRIGGER-DROPPING is set to CASCADE by
default. CASCADE allows RDMS to drop any triggers associated with the dropped
view. Setting RDMS-TRIGGER-DROPPING to RESTRICT causes any DROP VIEW
statement to fail if it would cause the implicit dropping of a trigger.

Ownership Security
Only the person who created the view can drop it. All grants on the view are
automatically revoked by RDMS.

7830 8160–027 7–58


DROP VIEW

Automatic Dropping of Views (Cascading)


RDMS automatically drops view definitions; this is called “cascading.” RDMS does not,
drop table definitions automatically, however.

RDMS drops views when any of the following occurs:

• You drop any column in an underlying base table. (This includes base table
columns that are not part of the view.)
• You drop an underlying view or base table.
• The owner of the view loses SELECT access privileges to any underlying base
table through a REVOKE or ALTER TABLE statement.
• Access control is activated for any underlying base table that has an owner
different from that of the view.
• You change the owner of an access-controlled underlying base table, and the
view’s owner is the former owner of the table.

Any other kinds of modifications to the definition of an underlying base table do not
cause the view to be dropped.

Cursors
You cannot drop a view on which a cursor is declared.

Effect on Compiled Programs


Some changes made by the DROP VIEW statement may invalidate previously
compiled ESQL programs. For more information, see 2.11.2.

7830 8160–027 7–59


DROP VIEW

7–60 7830 8160–027


Section 8
SQL Statements END DECLARE
Through INSERT

This section contains reference information about the following SQL statements:

• END DECLARE (8.1)


• END THREAD (8.2)
• EXECUTE (8.3)
• EXECUTE IMMEDIATE (8.4)
• EXPLAIN (8.5)
• FETCH (8.6)
• FETCH NEXT n (8.7)
• FUNCTION (8.8)
• GET DESCRIPTION (8.9)
• GETERROR (8.10)
• GET PARAMETERS (8.11)
• GET RESULTS CURSOR NAME (8.12)
• GRANT (8.13)
• INSERT (8.14)

7830 8160–027 8–1


END DECLARE

8.1. END DECLARE


Use the END DECLARE statement to mark the end of the SQL data definition portion
of the WORKING STORAGE SECTION of an ESQL COBOL program or the equivalent
declaration in a C program.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No No No N/A No E

8.1.1. SQL 92 Syntax (Entry Level)


END DECLARE SECTION

8.1.2. Example
In the following example, the variables HNO, LOC, and XTALLY can be used in ESQL
statements:

EXEC SQL BEGIN DECLARE SECTION END-EXEC.


01 HNO PIC X(4).
01 LOC PIC X(32).
EXEC SQL END DECLARE SECTION END-EXEC.
01 XTALLY PIC 9(10).

8.1.3. Rules and Guidelines


Read the following rules and guidelines before using the END DECLARE statement.

Use with BEGIN DECLARE Statement


The BEGIN DECLARE statement is optional in RDMS. If you do not use the BEGIN
DECLARE statement, you cannot use the END DECLARE statement. If you do use the
BEGIN DECLARE statement, you must use the END DECLARE statement.

Extension to Standard SQL


Standard SQL requires variables declared in the DECLARE SECTION to be either 01 or
77 level items. RDMS allows variables to be of any level and to be subscripted.

As an extension to standard SQL, RDMS allows variables declared outside the BEGIN
DECLARE to END DECLARE section in ESQL statements.

If the UCS COBOL LEVEL/SQL FLAGGER is turned on, the compiler issues warnings for
variables declared outside the BEGIN DECLARE to END DECLARE section that are used
in ESQL statements.

8–2 7830 8160–027


END THREAD

8.2. END THREAD


Use the END THREAD statement to disconnect a thread from UDS Control and write
any updates to the database.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes* Yes No X

* See 8.2.3 on implicit threads.

8.2.1. RDMS Extended Syntax


END THREAD [ ADVANCE │ TERMINATE ]

where ADVANCE and TERMINATE are Step Control options and cause the operating
system to advance or terminate its current Integrated Recovery step. In any case,
RDMS assumes that an END THREAD statement terminates the thread’s step.

• ADVANCE advances the system Integrated Recovery step counter but does not
end the Integrated Recovery step, even though RDMS considers the thread's step
ended.
• TERMINATE ends the current Integrated Recovery step.

If you do not specify ADVANCE or TERMINATE, the run’s VALTAB parameter for
programs is the default Step Control option. For all other programs, TERMINATE is the
default option, unless the program was connected to TIP before the start of the
current step. In this case, specify the default option when connecting to TIP.

8.2.2. Examples
The following example ends the current thread:

END THREAD

The following END THREAD statement, with its TERMINATE step counter option, ends
the current thread as well as the current step recovery counter:

END THREAD TERMINATE

8.2.3. Rules and Guidelines


Read the following rules and guidelines before using the END THREAD statement.

Effect Compared with COMMIT Statement


The END THREAD statement has the same effect as a COMMIT statement but cancels
the working storage and environment for the thread and its registration with
UDS Control.

7830 8160–027 8–3


END THREAD

Implicit END THREAD Statement


If the ESQL program has no explicit BEGIN THREAD statement, an explicit END
THREAD statement is not required; the termination of the program serves as an
implicit END THREAD statement.

If the thread has uncommitted changes when an implicit END THREAD statement is
executed, the thread is rolled back and a contingency (ER ERR$) is forced. If all
changes made by the thread are already committed when the implicit END THREAD
statement is executed, then the thread terminates normally.

Effect on Prepared Statements


Any statements prepared (see 9.5) before an END THREAD statement are no longer
available after the END THREAD statement.

Implicit Threads and Prepared END THREAD Statements


You can prepare and execute an END THREAD statement only from an implicit thread
(see 6.4).

Use with DMS and SFS


If DMS is active in the thread, the END THREAD statement causes an automatic
departure from all imparted schemas. You do not have to use a DMS DEPART
command.

If SFS files are opened in the thread, you must close them before executing the END
THREAD statement.

For More Information


For further information on recovery steps and the Integrated Recovery step counter,
consult with your database administrator and see the Integrated Recovery Utility
Operations Guide, the Exec Administration Reference Manual, and the Exec
Installation and Configuration Guide.

8–4 7830 8160–027


EXECUTE

8.3. EXECUTE
Use the EXECUTE statement to execute a dynamic ESQL statement already prepared
with the PREPARE statement.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No Yes No I

8.3.1. SQL 92 Syntax (Intermediate Level)


EXECUTE statement-name [ USING host-variable-list ]

where:

statement-name
is the name of the prepared statement to be executed.

USING host-variable-list
imports the values of host program variables into a prepared statement, where
host-variable-list specifies a one-to-one relationship between parameter markers
in the prepared statement and the host program variables.

8.3.2. Example
The following example prepares and executes a DELETE statement:

EXEC SQL PREPARE deltbl


FROM 'DELETE FROM houses WHERE hno = ''H101'''
END-EXEC.
EXEC SQL EXECUTE deltbl END-EXEC.

8.3.3. Rules and Guidelines


Read the following rules and guidelines before using the EXECUTE statement.

Use PREPARE Statement First


Before using the EXECUTE statement, you must use the PREPARE statement to
compile and name the statement.

Repeated Use
You can use the EXECUTE statement zero or more times for each statement you
prepare.

7830 8160–027 8–5


EXECUTE

USING Clause
If the prepared statement contains parameter markers, you must use the USING
clause. If the prepared statement does not contain parameter markers, you must omit
the USING clause.

Naming
If the prepared statement is a query specification for the ALLOCATE CURSOR
statement, its name cannot be the same as statement-name in an EXECUTE
statement.

8–6 7830 8160–027


EXECUTE IMMEDIATE

8.4. EXECUTE IMMEDIATE


Use the EXECUTE IMMEDIATE statement to prepare and execute a statement that you
do not intend to use again.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No Yes No I

8.4.1. SQL 92 Syntax (Intermediate Level)


EXECUTE IMMEDIATE { :embedded-variable │ string-literal }

where:

embedded-variable
is a CHARACTER type host program variable that contains one of the following
SQL statements:

DEBUG LOCK UNLOCK


DELETE SET AUXINFO UPDATE
INSERT SET STATISTICS USE DEFAULT
LOCATE

string-literal
is a string literal that contains one of the SQL statements just listed.

8.4.2. Example
The following example drops a row from table HOUSES:

EXEC SQL EXECUTE IMMEDIATE


'DELETE FROM houses WHERE hno = ''H101'''
END-EXEC.

8.4.3. Rules and Guidelines


Read the following rules and guidelines before using the EXECUTE IMMEDIATE
statement.

No EXEC Prefix or Terminator


The EXECUTE IMMEDIATE statement cannot include the EXEC SQL prefix or the
END-EXEC terminator.

No Comments
The EXECUTE IMMEDIATE statement cannot contain a comment.

No Other Variables
The EXECUTE IMMEDIATE statement cannot contain other variables (host program,
embedded, parameter marker, or placeholder).

7830 8160–027 8–7


EXPLAIN

8.5. EXPLAIN
Use the EXPLAIN statement to direct RDMS to explain the access path it plans to use
for a declared cursor.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No X

8.5.1. RDMS Extended Syntax


EXPLAIN cursor-name

where cursor-name is the name of the cursor.

8.5.2. Examples
Example 1
The following sequence of SQL statements yields the text that follows in the program
variables associated with $P1, $P2, and $P3:

DECLARE xyz CURSOR


SELECT * FROM houses
WHERE price > 100000
EXPLAIN xyz
GETERROR INTO $p1, $p2, $p3, $p4

The access path for cursor XYZ is shown below:


The relation is S1.HOUSES:PRODUCTION.
Using 1 of 1 column from secondary index ix1 : PRICE(>).
-----------------------------------------------------------

The program variable associated with $P4 is blank-filled, which means that no further
text is to be returned.

8–8 7830 8160–027


EXPLAIN

Example 2
In the next example, this cursor declaration places the text that follows in the program
variables associated with $P1, $P2, $P3, $P4, and $P5:

DECLARE abc CURSOR


SELECT * FROM houses, customers
WHERE price <= maxprice
EXPLAIN abc
GETERROR INTO $p1, $p2, $p3, $p4, $p5
The access path for cursor ABC is shown below:
Relation no. 1 is S1.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PKC.
Relation no. 2 is S1.HOUSES:PRODUCTION.
Using 1 of 1 column from secondary index ix1 : PRICE(<=).
-----------------------------------------------------------

In this case, the WHERE clause has no constants or program variables to help limit the
number of rows that must be retrieved to determine whether they meet the search
condition. RDMS must therefore perform a "brute force search," using each record
from table CUSTOMERS to search table HOUSES, based on the secondary index on
PRICE where PRICE >= the value of MAXPRICE, supplied from the record in table
CUSTOMERS.

Example 3
The next example illustrates the use of additional comparisons:

DECLARE def CURSOR


SELECT * FROM customers
WHERE cno >'6000' AND maxprice > 100000;
EXPLAIN def;
The access path for cursor DEF is shown below:
The relation is S1.CUSTOMERS:PRODUCTION.
Using 1 of 1 column from primary key PKC : CNO(>).
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
-----------------------------------------------------------

In this example, table CUSTOMERS is searched using the primary key WHERE
CNO > ‘6000’. The relational storage manager (RSM) performs one additional
comparison on each record (MAXPRICE > 100000) in order to decide whether to return
that record to RDMS.

7830 8160–027 8–9


EXPLAIN

Example 4
The next example illustrates how the EXPLAIN statement reveals to you whether a
cursor is to be formed by a snapshot. Assume you execute this SQL statement
followed by the EXPLAIN and GETERROR statements:

DECLARE oby CURSOR


SELECT * FROM houses
ORDER BY description
EXPLAIN oby;
The access path for cursor OBY is shown below:
The relation is S1.HOUSES:PRODUCTION.
Brute force search applied to primary key K1.
A snap shot is taken.
-----------------------------------------------------------

Example 5
A cursor can sometimes be defined using subqueries. The following example, which
selects all customers who can afford at least three houses, illustrates this:

DECLARE subq CURSOR


SELECT * FROM customers
WHERE 3 <= (SELECT COUNT(*) FROM houses
WHERE customers.maxprice >= houses.price)
EXPLAIN subq;
The relation is S1.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PK.
Additional comparisons --> RSM PK : 0, RSM SI : 0, RDM : 1
-----------------------------------------------------------
The relation is S1.HOUSES:PRODUCTION.
Using 1 of 1 column from secondary index ix1 : PRICE(<=).
All columns projected from secondary index b-tree.
-----------------------------------------------------------

To understand why the secondary index PRICE is used in an index search for HOUSES,
you must examine the overall retrieval strategy for this cursor. Whenever an outer
reference is made from within a subquery (in this case, CUSTOMERS.MAXPRICE is the
outer reference), a record that satisfies the outer query must be retrieved. This record
is then used to evaluate the subquery. When the subquery is evaluated, the reference
to column CUSTOMERS.MAXPRICE is replaced by a constant from the outer query’s
record. This allows HOUSES.PRICE to be used in an indexed search.

8–10 7830 8160–027


EXPLAIN

Example 6
A cursor can sometimes be defined by a single group query. The following example,
which finds the average price of the houses on the market, illustrates this:

DECLARE avg_house CURSOR


SELECT AVG(houses.price)
FROM houses
EXPLAIN avg_house;
The access path for cursor AVG_HOUSE is shown below:
The relation is S1.HOUSES:PRODUCTION.
Brute force search applied to secondary index IX.
All columns projected from secondary index b-tree.
The summary record of the single group is accumulated in RSM.
-----------------------------------------------------------

Example 7
The next example illustrates how RDMS uses an accelerated method to compute the
maximum and minimum housing prices, assuming price is a secondary index. The last
two lines in this example provide the explanation of the record fetch.

DECLARE max_min_house CURSOR


SELECT MIN(houses.price), MAX(houses.price)
FROM houses
EXPLAIN max_min_house;
The access path for cursor MAX_MIN_HOUSE is shown below:
The relation is S1.HOUSES:PRODUCTION.
All columns projected from secondary index b-tree.
The summary record of the single group is accumulated in RSM.
The maximum or the minimum is found by FETCH FIRST or FETCH LAST.
-----------------------------------------------------------

Example 8
The next example illustrates how to use the EXPLAIN statement to see whether one
of the fast search methods was used. The cursor must be opened and RDMS must
have fetched records from the cursor in order for this text to be returned.

LOCK houses in PROTECTED RETRIEVAL MODE


DECLARE fis CURSOR
SELECT COUNT(*) FROM houses
WHERE description LIKE 'D%'

The EXPLAIN statement issued before the cursor is opened yields the following text:

EXPLAIN fis;
The access path for cursor FIS is shown below:
The relation is MF.HOUSES:PRODUCTION.
Brute force search applied to primary key K1.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
The summary record of the single group is accumulated in RSM.
-----------------------------------------------------------

7830 8160–027 8–11


EXPLAIN

After opening the cursor and fetching a record, one additional line of text appears in
the output as follows:

EXPLAIN fis;
The access path for cursor FIS is shown below:
The relation is MF.HOUSES:PRODUCTION.
Brute force search applied to primary key K1.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
The summary record of the single group is accumulated in RSM.
The fast indexed search method is used.
-----------------------------------------------------------

Example 9
The following cursor uses the hybrid hash join and yields one EQUIJOIN and one
NON-EQUIJOIN predicate:

DECLARE matchlocationandprice CURSOR


FOR SELECT cno,location,maxprice,hno,price
FROM customers,houses
WHERE houses.location = customers.desiredloc AND
houses.price <= customers.maxprice
ORDER BY cno ASC;
FETCH FIRST matchlocationandprice;
C101 Woodbury 150000 H102 40000.00
EXPLAIN matchlocationandprice;
The access path for cursor MATCHLOCATIONANDPRICE is shown below:
Relation no. 1 is S1.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PKC.
Hybrid hash join applied.

Relation no. 2 is S1.HOUSES:PRODUCTION.


Brute force search applied to primary key PKH.
Additional comparisons -->
RSM PK : 0, RSM SI : 0, EQUIJOIN : 1, NON-EQUIJOIN : 1, RDM
: 0
A snap shot is taken.
-----------------------------------------------------------

8–12 7830 8160–027


EXPLAIN

Example 10
The following two examples illustrate different settings of RSM PK and RSM SI:

DECLARE ind CURSOR


SELECT hno, price FROM houses
WHERE hno <> 'h103' AND price = 85000;
EXPLAIN ind;
The access path for cursor IND is shown below:
The relation is S1.HOUSES:PRODUCTION.
Using 1 of 1 column from secondary index IX : PRICE(=).
Additional comparisons --> RSM PK : 0, RSM SI : 1, RDM : 0
All columns projected from secondary index b-tree.
-----------------------------------------------------------

DECLARE indpky CURSOR


SELECT hno, price, location FROM houses
WHERE hno <> 'h103' AND price > 84999 AND location = 'Woodbury';
EXPLAIN indpky;
The access path for cursor INDPKY is shown below:
The relation is S1.HOUSES:PRODUCTION.
Using 1 of 1 column from secondary index IX : PRICE(>).
Additional comparisons --> RSM PK : 1, RSM SI : 1, RDM : 0
-----------------------------------------------------------

Example 11
The next example illustrates how a cursor uses nested joined-table and the EXPLAIN
command output:

DECLARE c1 CURSOR
SELECT t1.c1, t2.c2, t3.c3, t4.c4, t5.c5, t6.c6
FROM t1,
t5 LEFT OUTER JOIN ((t2 LEFT OUTER JOIN t3 ON t2.c1=t3.c1)
LEFT OUTER JOIN t4 ON t2.c1=t4.c1)
ON t5.t1=t2.c1,
T6
WHERE t1.c1=t5.c1 AND t1.c1=t6.c1 AND t5.c7='abc';

EXPLAIN c1;

The access path for cursor C1 is shown below:


Relation no. 1 is pseudo table no. 1.
Derived from LEFT OUTER JOIN.
Relation no. 2 is RDMS.T1:PRODUCTION.
Using 1 of 1 column from primary key PK : C1(=).
Nested loop join applied.
Relation no. 3 is RDMS.T6:PRODUCTION.
Using 1 of 1 column from primary key PK : C1(=).
The pseudo table no. 1 is derived from the following two tables:
Relation no. 1 is RDMS.T5:PRODUCTION.
Brute force search applied to primary key PK.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0

7830 8160–027 8–13


EXPLAIN

Relation no. 2 is pseudo table no. 2.


Derived from LEFT OUTER JOIN.
The pseudo table no. 2 is derived from the following two tables:
Relation no. 1 is pseudo table no. 3.
Derived from LEFT OUTER JOIN.
Relation no. 2 is RDMS.T4:PRODUCTION.
Using 1 of 1 column from primary key PK : C1(=).
The pseudo table no. 3 is derived from the following two tables:
Relation no. 1 is RDMS.T2:PRODUCTION.
Using 1 of 1 column from primary key PK : C1(=).
Relation no. 2 is RDMS.T3:PRODUCTION.
Using 1 of 1 column from primary key PK : C1(=).
-----------------------------------------------------------

Notice that RDMS transforms RIGHT OUTER JOIN to LEFT OUTER JOIN by exchanging
the left and the right table. Therefore, in an EXPLAIN command, it is reported as LEFT
OUTER JOIN.

Example 12
The next example illustrates how the EXPLAIN statement reveals whether a
correlation name is used for the table.

DECLARE c3 CURSOR SELECT veg FROM seed1 t1 WHERE t1.veg <> 'bean';
EXPLAIN c3;

The access path for cursor C3 is shown below:


The relation is MYSCH172.SEED1:PRODUCTION. T1
Brute force search applied to secondary index INDEX_1.
Additional comparisons --> RSM PK : 0, RSM SI : 1, RDM : 0
All columns projected from secondary index b-tree.
-----------------------------------------------------------

Example 13
When ORDER BY is specified and the rows are fetched in the same order specified by
the ORDER BY statement, a snapshot may not be taken.

Cursor abc returns rows in customers.cno order, this order does not match the order
specified in the ORDER BY clause.

DECLARE abc CURSOR


SELECT * FROM houses, customers
WHERE price <= maxprice
ORDER BY hno ASC;
EXPLAIN abc
The access path for cursor ABC is shown below:
Relation no. 1 is S1.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PKC.
Relation no. 2 is S1.HOUSES:PRODUCTION.
Using 1 of 1 column from secondary index ix1 : PRICE(<=).
A snap shot is taken.
-----------------------------------------------------------

8–14 7830 8160–027


EXPLAIN

Cursor def returns rows in customers.cno order, this order matches the order
specified in the ORDER BY clause.

DECLARE def CURSOR


SELECT * FROM houses, customers
WHERE price <= maxprice
ORDER BY cno ASC;
EXPLAIN def
The access path for cursor DEF is shown below:
Relation no. 1 is S1.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PKC.
Relation no. 2 is S1.HOUSES:PRODUCTION.
Using 1 of 1 column from secondary index ix1 : PRICE(<=).
-----------------------------------------------------------

Example 14
RDMS takes snapshots for evaluation of ORDER BY, GROUP BY, and subquery, if
needed. Delimiters are used to clarify the reason for which the snapshot was taken.

DECLARE c1 CURSOR
SELECT desiredloc,max(maxprice) as mp FROM customers
GROUP BY desiredloc
HAVING max(maxprice) > (SELECT maxprice FROM customers
WHERE cname = 'Johnson'
FETCH FIRST 1 ROW ONLY)
ORDER BY mp
FETCH FIRST 5 ROWS ONLY;

The first snapshot is for the ORDER BY clause of the outer select statement. The text
following the delimiting dashed line shows that the second snapshot is for the
evaluation of the subquery:

The access path for cursor C1 is shown below:


The relation is S1.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PKC.
Additional comparisons --> RSM PK : 0, RSM SI : 0, RDM : 0
--> RDM IN : 0, HAVING : 1
Fetch First 5 Rows Only
A snap shot is taken.
-----------------------------------------------------------
The relation is S1.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PKC.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
Fetch First 1 Rows Only
A snap shot is taken.
-----------------------------------------------------------
Optimized for 5 rows

7830 8160–027 8–15


EXPLAIN

Example 15
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the derived
table expensive_houses. This derived table is implemented as a snapshot. The cursor
is restricted to only the most expensive 10 houses.

DECLARE matchprice10 CURSOR


SELECT cno, maxprice, hno, price
FROM customers,
(SELECT hno,price
FROM houses
ORDER BY price DESC
FETCH FIRST 10 ROWS ONLY) expensive_houses
WHERE expensive_houses.price <= customers.maxprice
EXPLAIN matchprice10;
The access path for cursor MATCHPRICE10 is shown below:
Relation no. 1 is RDMS.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PK1.
Nested loop join applied.
Relation no. 2 is RDMS.EXPENSIVE_HOUSES.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
A scan is performed.
The derived table RDMS.EXPENSIVE_HOUSES is accessed as follows:
The relation is RDMS.HOUSES:PRODUCTION.
Brute force search applied to primary key PK1.
Multi fetch is in use.
Fetch First 10 Rows Only
A snap shot is taken.
-----------------------------------------------------------
-----------------------------------------------------------

Derived table

A derived table contains the result of evaluating a query-expression. Derived


tables are either joined with the other tables in the FROM clause, as done for
views, or implemented as snapshot.

FETCH FIRST m ROWS ONLY

Reports the value of m from FETCH FIRST m ROWS ONLY clause. When there
was no such clause, this EXPLAIN text is not displayed.

8–16 7830 8160–027


EXPLAIN

Example 16
The following example defines a set of rows by joining selected columns from the
tables CUSTOMERS and HOUSES. The HOUSES table is filtered through the common
table expression expensive_houses. The cursor is restricted to rows in which the
asking price of the house does not exceed the maximum price a customer is willing to
pay, but will not consider any houses that cost less than 350000. It only considers the
top 10 most expensive houses. If the CTE is referenced only once, it is treated as a
derived table and this is reflected in the explain text.

DECLARE matchprice CURSOR


WITH expensive_houses (hno, price) AS
(SELECT hno,price FROM houses WHERE price > 350000
ORDER BY price DESC FETCH FIRST 10 ROWS ONLY)
SELECT cno, maxprice, hno, price
FROM customers, expensive_houses
WHERE expensive_houses.price <= customers.maxprice
The access path for cursor MATCHPRICE is shown below:
Relation no. 1 is RDMS.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PK1.
Relation no. 2 is RDMS.EXPENSIVE_HOUSES.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
A scan is performed.
The derived table RDMS.EXPENSIVE_HOUSES is accessed as follows:
The relation is RDMS.HOUSES:PRODUCTION.
Brute force search applied to primary key PK1.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
Fetch First 10 Rows Only
A snap shot is taken.
-----------------------------------------------------------
-----------------------------------------------------------

Example 17
Here, the CTE is referenced in the cursor more than once. Therefore, the CTE is
displayed at the beginning of the explain text.

DECLARE matchprice CURSOR


WITH expensive_houses (hno, price) AS
(SELECT hno,price FROM houses WHERE price > 350000
ORDER BY price DESC FETCH FIRST 10 ROWS ONLY)
SELECT cno, maxprice, hno, price
FROM customers, expensive_houses
WHERE expensive_houses.price <= customers.maxprice AND
EXISTS (SELECT hno FROM expensive_houses WHERE price > 500000);
The access path for cursor MATCHPRICE is shown below:
The CTE RDMS.EXPENSIVE_HOUSES is accessed as follows:
The relation is RDMS.HOUSES:PRODUCTION.
Brute force search applied to primary key PK1.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
Fetch First 10 Rows Only

A snap shot is taken.

7830 8160–027 8–17


EXPLAIN

-----------------------------------------------------------
Relation no. 1 is RDMS.CUSTOMERS:PRODUCTION.
Brute force search applied to primary key PK1.
Additional comparisons --> RSM PK : 0, RSM SI : 0, RDM : 1
Relation no. 2 is RDMS.EXPENSIVE_HOUSES.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
A scan is performed.
-----------------------------------------------------------
The relation is RDMS.EXPENSIVE_HOUSES.
Additional comparisons --> RSM PK : 1, RSM SI : 0, RDM : 0
A scan is performed.
-----------------------------------------------------------

8.5.3. Rules and Guidelines


Read the following rules and guidelines before using the EXPLAIN statement.

Use with Third-Generation Programming Languages


To review the access path RDMS chooses for a cursor, use this three-step process:

1. If you are using the interpreter interface, declare the cursor.


If you are using ESQL, declare and open the cursor.
2. In the interpreter interface, execute the EXPLAIN statement.
3. Use the GETERROR statement in the interpreter interface to retrieve the
information provided by the EXPLAIN statement.

The EXPLAIN statement returns only the error status and auxiliary information
variables.

The access path information is acquired as text using the GETERROR statement.

Use with IPF SQL Interface


Reviewing the access path RDMS chooses for a cursor is a two-step process:

1. Declare the cursor using the DECLARE CURSOR statement.


2. Execute the EXPLAIN statement.

The IPF SQL Interface provides the message retrieval function performed by the
GETERROR statement in the interpreter interface, so that you can see the access path
information immediately after the EXPLAIN statement is executed.

8–18 7830 8160–027


EXPLAIN

Compile-Time Reporting
The EXPLAIN statement causes RDMS to display access path information at execution
time. This can sometimes be too late to be useful (for example, with static ESQL
statements).

RDMS can also generate access path information for static ESQL at compile time. The
compile time report includes the same information as that produced by the EXPLAIN
statement for static ESQL statements such as DECLARE CURSOR, SELECT, UPDATE,
DELETE, UNLOAD, and INSERT ... SELECT. The method used to join tables and the
search method is not included in the compile time report, however. The report
appears as remarks in the UCS COBOL or UCS C source compilation listing.

To produce the report, include the REMARK keyword option or S, L, or E option on the
compiler call. You can suppress the report by including the NO-REMARK keyword
option or N option on the compiler call. For further information about these listing
options, see the COBOL Compiler Programming Reference Manual Volume 2 or the
C Compiler Programming Reference Manual Volume 2.

Explanations of Phrases in EXPLAIN Output


The following explains the meanings of phrases used in the text produced by the
EXPLAIN statement.

Additional comparisons --> RDM: n

RDMS is evaluating n predicates on each record after the record is returned by the
relational storage manager (RSM).

Additional comparisons --> RSM PK: n

RDMS is evaluating n predicates in the relational storage manager (RSM) directly


on the record in the primary key data page in cache memory before the record is
copied from the page.

Additional comparisons --> RSM SI: n

RDMS is evaluating n predicates in the relational storage manager (RSM) directly


on the record in the secondary index data page in cache memory, before the
record is copied from the page.

RSM SI predicates are more efficient than RSM PK predicates.

Additional comparisons --> RDM IN: n HAVING m

RDMS is evaluating n predicates before reading any records from the relation. In
many cases, the evaluation is performed when fetching the first record. The
result is saved and used in any subsequent fetches.

RDMS is also evaluating m predicates at the HAVING clause level.

If n and m are zero, this line is not displayed.

7830 8160–027 8–19


EXPLAIN

All columns projected from secondary index b-tree

RDMS is finding all projected values in a secondary index and does not have to
search the primary key.

A scan is performed
A temporary table is searched without using a primary key or a secondary index.

A snap shot is taken

A temporary table is created to hold the sorted or grouped records.

Brute force search applied

No primary key or secondary index can be used to accelerate the search. All rows
in the relation are read.

Fetch first m rows only

m specifies the maximum number of records fetched by RDMS during the


execution of the select clause that the FETCH FIRST clause is a part of.

Hash join applied

A temporary table is searched using a hash key.

Hybrid hash join applied

The outer table equally joins the inner table. The join criteria must contain at least
one equal predicate, but can also contain nonequal predicates. This method scans
both tables simultaneously, builds a hash table for the outer table, and then probes
the hash table from the inner table to match the join columns.

RDMS uses this method to join the two outermost tables when both tables
equally join on nonindexed columns or on nonleading index columns. The cursor
must not be scrollable (that is, the cursor can fetch in the forward direction only).
For RDMS to display the join method, the cursor must be opened and RDMS must
have fetched records from the cursor.

Additional text returned:

EQUIJOIN : n and NON-EQUIJOIN : m

where:

n
indicates the number of equal predicates (=) that join the two tables and must
be greater than 0 for hybrid hash join to be used,
m
is the number of nonequal predicates (<>, ^-, !=, >, >, <, <, BETWEEN) that join
the two tables and is greater than or equal to 0.

8–20 7830 8160–027


EXPLAIN

Merge join applied

RDMS uses this method to equally join the two outermost tables when

• The outer and inner table join columns are in the same sequence.
• The outer table has more than an RDMS internally defined number of hit
records.
• The inner table uses an index search on the join columns.
• An ACCESS lock for the inner table is not active in the session (see 9.3).
The cursor must not be scrollable (that is, the cursor can fetch in the forward
direction only). For RDMS to display the join method, the cursor must be opened
and RDMS must have fetched records from the cursor.

Multi fetch is in use

The cursor is opened and RDMS is using an internal buffer to fetch multiple rows
in a single call to its storage manager. For RDMS to display this text, the cursor
must be opened and RDMS must have fetched records from the cursor.

Nested loop join applied

The outer table joins the inner table. RDMS scans the outer table once and then
scans the inner table. The number of times it scans the inner table is equal to the
number of qualifying rows in the outer table.

RDMS uses this method for all joins after the first join, and for the first join if other
methods do not apply. For RDMS to display the join method, the cursor must be
opened and RDMS must have fetched records from the cursor.

Optimized for k rows

k specifies the number of records RDMS is internally optimizing for. If the cursor is
not a join, this is the minimum of the value from the FETCH FIRST clause and the
OPTIMIZE FOR clause, if they exist. Alternatively, it may be 1 if RDMS determines
from the WHERE clause that only a single record can be returned. (For example, all
columns of the primary key are specified using equality.) If the cursor is a join, it is
the value from the OPTIMIZE FOR clause.

Semi-join is applied

The last table in the join has no columns projected and a “global” DISTINCT is
specified in the select list (see 2.7.1).

RDMS does not have to identify more than one row in the last table for a given
combination of rows in the other tables, thereby reducing the number of duplicate
rows that need to be eliminated during the processing of DISTINCT.

Scrollable, Nonscrollable

Indicates whether the cursor is scrollable (whether fetch current, fetch last, fetch
prior, or locate can be done).

7830 8160–027 8–21


EXPLAIN

The fast indexed search method is used

RDMS is employing the fast indexed search to read the table. For RDMS to display
the search method, the cursor must be opened and RDMS must have fetched
records from the cursor.

The fast non-indexed search method is used

RDMS is employing the fast non-indexed search to read the table. For RDMS to
display the search method, the cursor must be opened and RDMS must have
fetched records from the cursor.

The maximum or the minimum is found by FETCH FIRST or FETCH LAST

RDMS is evaluating MIN or MAX by performing the equivalent of a FETCH FIRST or


FETCH LAST statement.

The summary record of the single group is accumulated in RSM

AVG, MAX, MIN, SUM, and COUNT are evaluated in RSM.

Trapeze fetch {active | not active}


Swings -> passed: n, failed: m

RDMS is determining that the query is a candidate for trapeze fetch and is
displaying the following results pertaining to its activity and success rate. The n
value refers to how many times trapeze fetch successfully skipped data pages by
doing a B-tree search. The m value refers to how many times trapeze fetch did not
skip any data pages when doing a B-tree search. If the query is a candidate but is
not using trapeze fetch, the EXPLAIN statement displays trapeze fetch as not
active. If the query is a candidate and is also implementing trapeze fetch, the
EXPLAIN statement displays fetch as active.

-----------------------------------------------------------
Used as a delimiter to improve readability by separating attributes of a SELECT
clause from those of the union and cursor. This is helpful when the cursor contains
subqueries, GROUP BY, ORDER BY, and/or FETCH FIRST m ROWS ONLY clauses.

8–22 7830 8160–027


FETCH

8.6. FETCH
Use the FETCH statement to retrieve one row from a cursor.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No E/I/F/X

8.6.1. Syntax
SQL 92 Syntax (Entry Level)
FETCH cursor-name INTO variable-specification-list

SQL 92 Syntax (Intermediate Level) with RDMS Extension CURRENT


FETCH [ NEXT | FIRST | PRIOR | LAST | CURRENT |
ABSOLUTE n | RELATIVE n ]
[ FROM ] cursor-name INTO variable-specification-list

Syntax When Used in Routines or Triggers


FETCH [ NEXT | FIRST | PRIOR | LAST | CURRENT
[ FROM ] cursor-name INTO variable-specification-list

where:

NEXT
(default) retrieves the next row of the cursor, relative to the pointer. If you
execute a FETCH NEXT statement immediately following an OPEN statement, you
retrieve the first row of the cursor.

FIRST
retrieves the first row of the cursor.

PRIOR
retrieves the preceding row of the cursor, relative to the current position. If you
execute a FETCH PRIOR statement immediately following an OPEN statement, you
retrieve the same row you retrieve when you execute a FETCH LAST statement.
FETCH PRIOR uses slightly more computer resources than FETCH NEXT.

LAST
retrieves the last row of the cursor.

CURRENT
(an RDMS extension; not allowed by any level of SQL 92) retrieves the current row
in the cursor. The FETCH CURRENT statement is usually used in conjunction with a
LOCATE statement.

7830 8160–027 8–23


FETCH

ABSOLUTE n
retrieves the nth row from the first row of a cursor and sets the current cursor
position to the returned row. If n is zero, an error is returned.

Note: n must be a positive integer constant or a host program variable. A host


program variable must be a positive INTEGER or NUMERIC RDMS type with the
scale set to zero. Refer to the COBOL Compiler Programming Reference Manual
Volume 2: Compiler and System Interface and the C Compiler Programming
Reference Manual Volume 2: Compiler and System Interface for more
information.

RELATIVE n
retrieves the nth row from the current cursor position and sets the current cursor
position to the returned row. If n is zero, RDMS returns the current row. This is the
same as the FETCH CURRENT statement.

Note: n must be an unsigned integer constant or a host program variable. A


host program variable must be a positive INTEGER or NUMERIC RDMS type
with the scale set to zero. Refer to the COBOL Compiler Programming Reference
Manual Volume 2: Compiler and System Interface and C Compiler Programming
Reference Manual Volume 2: Compiler and System Interface for more
information.

cursor-name
is the name of the cursor from which a row is to be retrieved.

variable-specification-list
is a list of placeholder or embedded variable pairs in the form shown in 2.9.
Separate list entries with commas.

The number of embedded variables in ESQL must equal the number of columns in
the cursor. For character value assignment considerations, see 2.8.1.

In a routine, the variable-specification-list is a list of parameter and SQL variable


names (see 4.12.7).

8–24 7830 8160–027


FETCH

8.6.2. Example
In the following example, the third FETCH statement can retrieve rows with nulls.

DECLARE matchprice CURSOR


SELECT cno, maxprice, hno, price
FROM houses, customers
WHERE price <= maxprice
FETCH FIRST matchprice INTO $p1,$p2,$p3,$p4
FETCH matchprice INTO $p1,$p2,$p3,$p4
FETCH matchprice INTO $p1, $p2 $p5, $p3 $p6, $p4 $p7

Note the absence of commas between the last three pairs of placeholder variables.
The host program variables associated with placeholder variables $P1, $P2, $P3, and
$P4 is where RDMS returns the values of CNO, MAXPRICE, HNO, and PRICE. Variables
$P5, $P6, and $P7 contain the null indicator values for MAXPRICE, HNO, and PRICE.

The following examples show the usage of the FETCH ABSOLUTE and FETCH
RELATIVE statements:

DECLARE matchprice CURSOR


SELECT cno, maxprice, hno, price
FROM houses, customers
WHERE price <= maxprice;
OPEN CURSOR matchprice;
FETCH ABSOLUTE 10 FROM matchprice INTO $p1, $p2, $p3, $p4;
FETCH RELATIVE 5 FROM matchprice INTO $p1, $p2, $p3, $p4;

In ESQL using constants for the value of n

char cno [5] = ““;


int maxprice = 0;
char hno[5] = ” “;
int price = 0;
EXEC SQL DECLARE matchprice CURSOR
SELECT cno, maxprice, hno, price
FROM houses, customers
WHERE price <= maxprice;
EXEC SQL OPEN CURSOR matchprice;
EXEC SQL FETCH ABSOLUTE 10 FROM matchprice INTO :cno, :maxprice, :hno,
:price;
EXEC SQL FETCH RELATIVE 5 FROM matchprice INTO :cno, :maxprice, :hno,
:price;

7830 8160–027 8–25


FETCH

In ESQL using program variables for the value of n

int v_abs_off = 10;


int v_rel_off = 5;
char cno[5] = “ “;
int maxprice = 0;
char hno[5] = “ “;
int price = 0;

EXEC SQL DECLARE matchprice CURSOR


SELECT cno, maxprice, hno, price
FROM houses, customers
WHERE price <= maxprice;
EXEC SQL OPEN CURSOR matchprice;
EXEC SQL FETCH ABSOLUTE :v_abs_off FROM matchprice INTO
:cno, :maxprice, :hno, :price;
EXEC SQL FETCH RELATIVE :v_rel_off FROM matchprice INTO
:cno, :maxprice, :hno, :price;

In Interpretive Interface using program variables for the value of n

int v_abs_off = 10;


int v_rel_off = 5;
char cno[5] =" ";
int maxprice = 0;
char hno[5] =" ";
int price = 0;
char sqlcmd[90] = “DECLARE matchprice CURSOR SELECT cno, \

maxprice, hno, price \

FROM houses, customers WHERE price <= maxprice;”;

rsa(sqlcmd, error_code,&aux_info);
rsa( "OPEN CURSOR matchprice;",error_code,&aux_info);
rsa("FETCH ABSOLUTE $p1 FROM matchprice INTO $p2, $p3, $p4, $p5;",
error_code,&aux_info, &v_abs_off, &cno, &maxprice, &hno,
&price);

rsa(“FETCH RELATIVE $p1 FROM matchprice INTO $p2, $p3, $p4, $p5;",
error_code,&aux_info, &v_rel_off, &cno, &maxprice, &hno, &price);

8–26 7830 8160–027


FETCH

8.6.3. Rules and Guidelines


Read the following rules and guidelines before using the FETCH statement.

Cursors
Before you can use the FETCH statement to retrieve rows from a cursor, the cursor
must already be defined by a DECLARE CURSOR statement and activated by the OPEN
statement (if you used placeholder variables or declared the cursor through ESQL).
The normal use of the FETCH statement is in a program loop.

For ESQL FETCH statements, the cursor must be opened already either with an OPEN
statement or, for a cursor declared through the interpreter interface, opened implicitly
with a preceding FETCH statement through the interpreter interface.

The INTO clause must include one or two placeholders or embedded variables for
each column selected in the DECLARE CURSOR statement that defined the active
cursor.

You cannot fetch PRIOR or LAST from a cursor declared with any of the following:

• A GROUP BY, HAVING, DISTINCT or ORDER BY clause


• The UNION operator
• An aggregate function
• A subquery
• An OUTER JOIN
• INSENSITIVE
• OPTIMIZE FOR p ROWS
• FETCH FIRST m ROWS ONLY

There are special cases when RDMS has determined that the GROUP BY, ORDER BY,
UNION, or DISTINCT clause is redundant and has removed the redundant clause as
part of the optimization. Under these circumstances you might be permitted to use
the FETCH PRIOR, CURRENT, or LAST statements. For example, if the primary key is
specified in the select statement with a DISTINCT clause, RDMS can remove the
DISTINCT clause since the primary key is declared as distinct in the table definition.

If the cursor is positioned after the last row (for example, if after executing successive
FETCH NEXT statements, you eventually received the end-of-cursor status) and you
execute a FETCH NEXT statement, RDMS responds as follows:

• Repositions the cursor to the first row and returns that row to you if the cursor
was declared through the interpreter interface. It performs identically when you
execute a FETCH PRIOR from before the first row of the cursor.
• Returns the end-of-cursor status to you again if the cursor was declared through
ESQL. It performs identically when you execute a FETCH PRIOR from before the
first row of the cursor.

7830 8160–027 8–27


FETCH

In FETCH ABSOLUTE n if the value of n is larger than the number of rows in the cursor,
no row is returned, an error is returned, and the cursor is positioned after the last row.
If the value of n is zero, no row is returned, and an error is returned.

In FETCH RELATIVE n if the value of n, when added to the current cursor position,
causes it to be larger than the number of rows in the cursor, no row is returned, an
error is returned, and the cursor is positioned after the last row. If the value of n is
zero and the cursor is on a row, the current row is returned, otherwise no row is
returned.

Performance
In the interpreter interface, RDMS keeps track of the most recent FETCH NEXT
statement it received (up to 1500 characters altogether). If the next statement is the
same, RDMS bypasses parsing and re-executes the saved statement. This improves
performance considerably. See also 8.7.

Routines and Triggers and the FETCH Statement


Before you can use the FETCH statement to retrieve rows from a cursor, the cursor
must be defined by a DECLARE CURSOR statement specified within the same
compound statement as the FETCH statement or at an outer level of nesting. The
cursor must be opened using the OPEN statement prior to the execution of the FETCH
statement.

When FETCH is used in a routine, the INTO clause may only contain SQL variable
names, declared within the same compound statement as the FETCH statement or at
an outer level of nesting, or parameter names declared with the INOUT or OUT
attribute. The SQL variables and parameters must be of compatible data types and
sizes with the corresponding items in the cursor’s select list. There must be the same
number of variable names in the INTO list as there are columns in the cursor.

When used in a trigger, the INTO clause may also contain NEW ROW
correlation-name.column-name references in a Before Row Trigger. The NEW ROW
correlation-name.column-names must be of compatible data types and sizes with the
corresponding items in the cursor’s select list.

Note that when cursors are used in routines and triggers, they follow the same rules
as those specified for ESQL. If no data is returned by the FETCH statement, RDMS
returns an SQLSTATE value of 02000 (see 4.9.2).

FETCH ABSOLUTE and FETCH RELATIVE cannot be used within routines and triggers.

8–28 7830 8160–027


FETCH

FETCH and Dynamic Result Sets


See 4.7 for information about dynamic result sets. Before you can use the FETCH
statement to retrieve rows from a dynamic result set, you must know the name of the
cursor generated for the result set. You can only obtain this name by following these
steps:

1. Immediately after the CALL statement, issue this statement:


GET RESULT SET CURSOR NAME INTO $P1

This returns the cursor name on a temporary table that contains information about
all the return cursors left open at the end of the stored procedure. The table
format is described in 4.7.
2. Then issue this statement:
FETCH NEXT rs INFO $P1, $P2, $P3

If you are uncertain which returning cursor is first, you can issue the statement
GET DESCRIPTION FOR CURSOR $P1 and handle the results as you would for any
other GET DESCRIPTION statement.

BLOB Columns Not Supported for the IPF SQL Interface


With the IPF SQL interface, the FETCH statement fails if any columns contain BLOB
data. BLOB data is not supported with the IPF SQL interface.

7830 8160–027 8–29


FETCH NEXT n

8.7. FETCH NEXT n


Use the FETCH NEXT n statement to fetch multiple rows from a cursor through ESQL
from UCS COBOL and UCS C programs.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No N/A No X

8.7.1. RDMS Extended Syntax


FETCH NEXT number-of-rows [ FROM ] cursor-name

INTO variable-specification-list

where:

number-of-rows
is the number of rows you want to retrieve. This must be a positive integer
constant no greater than 510.

cursor-name
is the name of the cursor being fetched.

variable-specification-list
is a list of embedded variables in the form shown in 2.9. Separate list entries with
commas.

8.7.2. Example
The following example illustrates the PROCEDURE DIVISION and corresponding DATA
DIVISION of a UCS COBOL program that is fetching 10 rows of table HOUSES into an
array.

The following DATA DIVISION illustrates how the array can be declared:

01 RECA.
02 HNO OCCURS 10 PIC X(4).
02 LOCATION OCCURS 10 PIC X(28).
02 LOC-INDIC OCCURS 10 PIC S9(5).
02 PRICE OCCURS 10 PIC S9(12)V99
SIGN LEADING SEPARATE.
01 RECB.
02 PRICE-INDIC OCCURS 10 PIC S9(5).
01 RECF.
02 DESCRIPTION OCCURS 10 PIC X(40).
01 RECG.
02 DESC-INDIC OCCURS 10 PIC S9(5).

8–30 7830 8160–027


FETCH NEXT n

The following portion of the PROCEDURE DIVISION declares a cursor, opens the
cursor, and fetches the first 10 rows of table HOUSES:

EXEC SQL DECLARE c1 CURSOR SELECT * FROM houses END-EXEC.


EXEC SQL OPEN CURSOR c1 END-EXEC.
EXEC SQL FETCH NEXT 10 FROM c1 INTO :hno, :location
:loc-indic, :price :price-indic,
:description :desc-indic END-EXEC.
IF sqlcode = 100 AND aux-info = 0
DISPLAY 'No rows fetched - end of cursor' UPON PRINTER.

IF sqlcode = 100 AND aux-info > 0


DISPLAY 'Only',aux-info,'rows fetched - end of cursor'
UPON PRINTER.

8.7.3. Rules and Guidelines


Read the following rules and guidelines before using the FETCH NEXT n statement.

Use
You can use the FETCH NEXT n statement only in ESQL from UCS COBOL and UCS C
programs.

Cursors
The cursor must be already defined with a DECLARE CURSOR statement and activated
with the OPEN statement before you can use the FETCH NEXT n statement to retrieve
its rows. You need at least one embedded variable for each column selected in the
DECLARE CURSOR statement that defined the active cursor.

You cannot use the FETCH NEXT n statement with cursors declared FOR RANDOM
ACCESS or FOR UPDATE OF.

When using FETCH ABSOLUTE n in addition to FETCH NEXT n, declare the cursor with
OPTIMIZE FOR n ROWS syntax for better performance.

FETCH NEXT n Compared to FETCH


Use the FETCH NEXT n statement to fetch several rows of a cursor together. This
usually performs more efficiently than using several regular FETCH statements, unless
FETCH FIRST m ROWS ONLY or OPTIMIZE FOR p ROWS was specified. The presence
of these clauses in the cursor’s declaration allows RDMS to accelerate the regular
FETCH statements so their performance is comparable to that of FETCH NEXT n. You
can use FETCH NEXT n to fetch from cursors containing these clauses, but there is no
performance improvement if all records selected by the cursor are actually fetched.
Performance may improve if FETCH FIRST m ROWS ONLY causes only a subset of
rows selected by the cursor to be internally read by RDMS.

7830 8160–027 8–31


FETCH NEXT n

After fetching from a cursor with the FETCH NEXT n statement, you cannot use a
regular FETCH statement on the cursor until you close and reopen the cursor with the
CLOSE and OPEN statements. However, you can use the FETCH NEXT n statement
after a regular FETCH statement.

FETCH NEXT n and Sensitive Cursors


FETCH NEXT n cannot be used against a cursor explicitly declared as SENSITIVE. Thus,
use of FETCH NEXT n causes a sensitive cursor to become ASENSITIVE.

Arrays
A parameter passed in an embedded variable must be one-dimensional. See the
example in this subsection.

The size of the array must be able to accommodate the number of rows indicated by
number-of-rows.

The value returned by RDMS in the auxiliary information variable is the number of
rows returned by the FETCH NEXT n statement: from 0 to n after the FETCH NEXT n
statement is executed. The program should always check this parameter after it
executes a FETCH NEXT n statement. Ensure also that the program handles situations
where this parameter is zero or less than n.

RDMS returns a 6001 no-find error status and an SQLCODE of +100 (see C.3) if fewer
than n rows are fetched because the end of the cursor was reached, or if the cursor
has no rows. In this case, the auxiliary information variable contains a number less
than n.

If all rows of the cursor have already been fetched, a subsequent FETCH NEXT n
results in aux-info containing 0. If some rows are left in the cursor but the number is
less than n, a FETCH NEXT n results in aux-info containing the actual number of rows
fetched.

Performance
When using the ESQL interface to UCS COBOL or UCS C to fetch a large number of
rows, you can use the FETCH NEXT n statement to load an array of host program
variables in one operation. This operation improves performance two ways:

• The number of RDMS calls from the user program may be significantly reduced
since many rows can be passed in response to a single call.
• When FETCH NEXT n is used, RDMS uses internal buffering to optimize the
internal calls to the relational storage manager (RSM). You can realize this benefit
even if n is 1.

BLOB Data
You cannot use FETCH NEXT n if a selected column is of data type BLOB.

8–32 7830 8160–027


FUNCTION

8.8. FUNCTION
Use the FUNCTION statement to define a stored function.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No P

8.8.1. SQL Syntax


[ CREATE ] FUNCTION [schema-name.]routine-name
([parameter[,parameter]...])

[ DYNAMIC RESULT SETS [ max-result-sets ] ]

RETURNS data-type stored-procedure-statement

Note: The CREATE construct is optional. “CREATE FUNCTION . . .” is equivalent to


“FUNCTION...”

where:

schema-name
is the name of the schema to contain the function. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information see the Repository for
ClearPath OS 2200 Administration Guide.

routine-name
is the name of the function.

Schema and routine names must be valid names as defined in 2.2.1.

parameter
is the formal definition of a parameter for the function, in the form

[ IN │ OUT │ INOUT ] parameter-name data-type

where:

IN
means pass an initial value or values to the function. You can use the IN
parameter as the source for a value (for example, in a SET statement, a
WHERE clause, a values list, and so forth). You cannot use an IN parameter as
a target specification (for example, you cannot assign it a value using a SET or
a SELECT statement).

7830 8160–027 8–33


FUNCTION

When you use the nonstandard SET statement to invoke a function outside of
a routine or trigger, you can pass a host variable, a placeholder variable, a
literal, or the NULL keyword as an IN parameter. When you use the SET
statement to invoke a function within a routine or trigger, you can pass a
parameter name, an SQL variable, a literal, an arithmetic expression, a
datetime expression, a datetime system function, or the NULL keyword as an
IN parameter.

OUT
means return a value or values to the caller after the function finishes
executing. You can assign a value to the OUT parameter using a FETCH,
SELECT, or SET statement. You can also assign a value to the OUT parameter
by passing it as an OUT or an INOUT parameter of a nested stored procedure
or function invocation. You can use an OUT parameter as a source value in an
SQL statement. This is an RDMS extension to standard SQL. When you use
the nonstandard SET statement to invoke a function outside of a routine or
trigger, you can pass a host variable or placeholder variable as an OUT
parameter. When you use the SET statement to invoke a function within a
routine or trigger, you can pass an INOUT or OUT parameter name or an SQL
variable as an OUT parameter.

You cannot pass a literal as an OUT parameter. An OUT parameter has an


initial value of NULL and, if a value is not assigned to the OUT parameter, it
returns the value NULL.

INOUT
means pass values both ways, as a source or destination for a value. The
INOUT parameter combines the attributes of the IN and OUT parameters and
thus can be used wherever an IN or OUT parameter can be used. When you
use the nonstandard SET statement to invoke a function outside of a routine
or trigger, you can pass a host variable or placeholder variable as an INOUT
parameter. When you use the SET statement within a routine or trigger, you
can pass an INOUT or OUT parameter name or an SQL variable as an INOUT
parameter.

You cannot pass a literal as an INOUT parameter. If a value is not assigned to


the INOUT parameter, it returns the input value.

parameter-name
is the name of the parameter, which is then used in the body of the function.
The name must be a valid name as defined in 2.2.1. The name of each
parameter must be unique within the set of parameters.

DYNAMIC RESULT SETS max-result-sets


indicates that this function can return result set cursors. The max-result-sets
parameter is optional and specifies the maximum number of result sets that can
be returned from this function on any particular execution. If omitted,
max-result-sets is equal to the number of cursors declared WITH RETURN.

data-type
is any valid data type as defined in 2.8, except data type BLOB.

8–34 7830 8160–027


FUNCTION

stored-procedure-statement
is the statement that performs the activity for this stored function (see 4.11).
Normally this is a compound statement.

8.8.2. Examples
Example 1
Even though it is not required for functions with only one statement, functions should
start with the BEGIN keyword and end with the END keyword:

FUNCTION house_schema.minneapolis_houses( ) RETURNS INTEGER


BEGIN
DECLARE how_many INTEGER;
SELECT COUNT(*) INTO how_many FROM houses
WHERE location = "MINNEAPOLIS";
RETURN how_many;
END;

Example 2
This example returns the count of houses under a given maximum price. Note that the
data type of the variable that contains the return value is compatible with the data
type on the RETURNS clause.

FUNCTION house_schema.select_houses(IN max_price NUMERIC)


RETURNS NUMERIC
BEGIN
DECLARE how_many INTEGER;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

Example 3
This example accepts two input parameters (a new price and house identifier), and
then uses these two values when it executes the UPDATE statement. The return
value is a count of house with the new price. If the new price is invalid, the function
returns -1 for the house count.

FUNCTION house_schema.updateandcount(IN newprice INTEGER,


IN ident CHAR(20)) RETURNS INTEGER
BEGIN
DECLARE how_many INTEGER;
IF newprice > 0 THEN
UPDATE houses SET price = newprice WHERE hno = ident;
SELECT COUNT(*) INTO how_many FROM houses WHERE price =
newprice;
ELSE SET how_many = -1;
END IF;
RETURN how_many;
END;

7830 8160–027 8–35


FUNCTION

Example 4
This example keeps looping until at least 10 houses are found. It returns the count as
the function return value and returns the price threshold by updating the MAX_PRICE
parameter.

FUNCTION house_schema.find_houses(INOUT max_price NUMERIC) RETURNS


NUMERIC
BEGIN
DECLARE how_many NUMERIC;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
WHILE how_many < 10 DO
SET max_price = max_price + 10000;
SELECT COUNT(*) INTO how_many FROM houses WHERE price <
max_price;
END WHILE;
RETURN how_many;
END;

Example 5
This example sets a maximum price based on the input salary, and then selects
houses based on the maximum price:

FUNCTION house_schema.find_houses_from_salary(IN salary NUMERIC)


RETURNS NUMERIC
BEGIN
DECLARE how_many NUMERIC;
DECLARE max_price NUMERIC;
IF salary <= 20000 THEN SET max_price = 50000;
ELSE SET max_price = 2 * salary;
END IF;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

Example 6
The following example illustrates a case where the RETURN statement may not be
executed, depending on the value of MAX_PRICE:

FUNCTION house_schema.select_houses(IN max_price INTEGER) RETURNS


INTEGER
BEGIN
DECLARE how_many INTEGER;
IF max_price > 20000 THEN
SELECT COUNT(*) INTO how_many FROM houses WHERE price <
max_price;
RETURN how_many;
END IF;
END;

8–36 7830 8160–027


FUNCTION

RDMS returns an error if MAX_PRICE is less than 20,000 because the RETURN
statement was not executed before the end of the routine.

Example 7
This example shows the use of a nested invocation of a stored procedure. Whenever
a data modification occurs for the houses table, a comparable data modification occurs
for the house_backup table (this scenario can be used to maintain a backup for the
houses table).
First, create the stored procedure that is going to be invoked by other routines:

PROCEDURE replicate_ houses


(IN house_number INTEGER, IN modification CHAR(10), OUT status
CHAR(10))
BEGIN
DECLARE cost INTEGER;
DECLARE desc CHAR(20);
DECLARE loc CHAR(20);

SELECT price, description, location INTO cost, desc, loc


FROM houses WHERE hno = house_number;

SET status = ’NOT OK’;

IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;

IF modification = ’UPDATE’
THEN
BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;

IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
SET status = ’OK’;
END;
END IF;

END;

7830 8160–027 8–37


FUNCTION

Next, create the stored functions that make use of a nested stored procedure
invocation:

FUNCTION delete_ houses (IN house_number INTEGER) RETURNS CHAR(10)


BEGIN
DECLARE status CHAR(10);
DELETE FROM houses WHERE hno = house_number;
CALL replicate_houses (house_number, ’DELETE’, status);
RETURN status;
END;

FUNCTION insert_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20)) RETURNS CHAR(10)
BEGIN
DECLARE status CHAR(10);
INSERT INTO houses (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
CALL replicate_houses (house_number, ’INSERT’, status);
RETURN status;
END;

FUNCTION update_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20)) RETURNS CHAR(10)
BEGIN
DECLARE status CHAR(10);
UPDATE houses SET price = cost, description = desc, location = loc
WHERE hno = house_number;
CALL replicate_houses (house_number, ’UPDATE’, status);
RETURN status;
END;

8–38 7830 8160–027


FUNCTION

Example 8
The following example is the same as the previous example, except a nested
invocation of a stored function is used instead of a stored procedure:

First, create the stored function that is going to be invoked by other routines:

FUNCTION replicate_ houses


(IN house_number INTEGER, IN modification CHAR(10)) RETURNS CHAR(10)
BEGIN
DECLARE cost INTEGER;
DECLARE desc CHAR(20);
DECLARE loc CHAR(20);
DECLARE status CHAR(10);

SELECT price, description, location INTO cost, desc, loc


FROM houses WHERE hno = house_number;

IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;

IF modification = ’UPDATE’
THEN
BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;

IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
RETURN ’OK’;
END;
END IF;
RETURN ’NOT OK’;
END;

7830 8160–027 8–39


FUNCTION

Next, create the stored functions that make use of a nested stored function
invocation:

FUNCTION delete_ houses (IN house_number INTEGER) RETURNS CHAR(10)


BEGIN
DECLARE status CHAR(10);
DELETE FROM houses WHERE hno = house_number;
SET status = replicate_houses (house_number, ’DELETE’);
RETURN status;
END;

FUNCTION insert_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20)) RETURNS CHAR(10)
BEGIN
DECLARE status CHAR(10);
INSERT INTO houses (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
SET status = replicate_houses (house_number, ’INSERT’);
RETURN status;
END;

FUNCTION update_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20)) RETURNS CHAR(10)
BEGIN
DECLARE status CHAR(10);
UPDATE houses SET price = cost, description = desc, location = loc
WHERE hno = house_number;
SET status = replicate_houses (house_number, ’UPDATE’);
RETURN status;
END;

8.8.3. Rules and Guidelines


Read the following rules and guidelines before using the FUNCTION statement.

Ownership
You must own the schema in which the function will reside.

DECLARE Statements
All DECLARE statements must immediately follow the BEGIN keyword and precede
other statements. All DECLARE variable statements must precede any DECLARE
CURSOR statements.

8–40 7830 8160–027


FUNCTION

RETURNS Clause and RETURN Statement


The RETURNS clause must be included on the FUNCTION statement.

The RETURN statement (see 4.12.6) must be the last statement executed in the
function. If the function terminates without executing a RETURN statement, RDMS
returns an error.

The data type of the value on the RETURN statement must be compatible with the
data type on the RETURNS clause of the FUNCTION statement.

Committing
If you commit the run unit, RDMS stores the function in the database. You can
reference it later from any program.

Omitting
If you omit the run unit, the function definition is not written to the database.

Reporting
Use the GET PARAMETERS statement to retrieve information about the parameters of
an already defined function (see 8.11).

Dropping a Function
Use the DROP PROCEDURE/FUNCTION statement to remove a stored function from
the database. (See 7.8.)

Nested Invokes
A function can invoke other stored procedures or functions. The invoked stored
procedures and functions must have been successfully created prior to being
referenced in a CALL or SET statement within a function. Note that a function can
invoke itself (recursive reference).

Variables
Placeholder and host program variables are not allowed in functions.

Threads
The thread in which this statement executes must be update recoverable.

TIP
TIP Session Control must be active before you can create a stored function in a TIP
transaction. For information on establishing TIP Session Control, see the Exec
Installation and Configuration Guide.

7830 8160–027 8–41


FUNCTION

Parentheses ( ) and Semicolons ;


You must use parentheses on the FUNCTION statement, even if the function has no
parameters.

Do not use a semicolon on the FUNCTION or BEGIN statement. Refer to the examples
for the correct use of semicolons.

When using IPF SQL or JDBC, do not put a semicolon at the end of the final END
statement. (Note that the previous examples include the semicolon and, for this
reason only, would not be accepted by RDMS when submitted from an IPF SQL
thread.)

Default Qualifier and Version


Default qualifier (schema name): If any statement within the function specifies an
unqualified table or view name, the current default qualifier is used as the schema
name for the table or view (that is, the default qualifier at the time of function
definition).

Default version name: If any statement within the function specifies a table or view
without a version name, the version is not determined at function definition time.
Instead, it is determined from the current default version name at the time the
function is executed.

Security
Normal table security is in effect during the execution of a function.

Dynamic Result Sets


Dynamic result sets are not allowed within a trigger, nor can one routine call another
that specifies dynamic result sets. See 4.7 for a description of dynamic result sets.

Comments
When you submit a PROCEDURE/FUNCTION statement from an IPF SQL or JDBC
session, do not include SQL comments in the statement.

Saving Function Syntax


The FUNCTION statement saves the function syntax in the repository. To report the
syntax, use the following UREP command:

REPORT INCLUDE ATTRIBUTE SYNTAX SQL-ROUTINE routine-name FOR SCHEMA


schema-name.

8–42 7830 8160–027


GET DESCRIPTION

8.9. GET DESCRIPTION


Use the GET DESCRIPTION statement to retrieve information about each column of a
cursor that was declared by the DECLARE CURSOR statement with the WITH
DESCRIPTION clause.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* No No No No X

* Not IPF SQL

8.9.1. RDMS Extended Syntax


GET DESCRIPTION INTO placeholder-list

where placeholder-list must contain nine placeholder variables $P1 through $P9, as
follows:

$P1 The table’s qualifier name, up to 30 ASCII characters

$P2 The table’s name, up to 30 ASCII characters

$P3 The table’s version name, up to 30 ASCII characters

$P4 The column’s name or title name, up to 30 ASCII characters

$P5 The column’s data type, up to 16 ASCII characters, whose possible values are
as follows:

character
ncharacter
decimal
numeric
integer
smallint
real
float
double-precision
date
time
timestamp
blob

7830 8160–027 8–43


GET DESCRIPTION

$P6 $P6 returns the information described in the following table.

Data Type Information Returned

CHARACTER Number of characters in column (size)


NCHARACTER
DATE
TIME
TIMESTAMP
DECIMAL* Number of digits (plus 1 for the sign)
NUMERIC Decimal precision (plus 1 for the sign)
INTEGER Number of bytes used to store each data item
SMALLINT
REAL
FLOAT
DOUBLE PRECISION
BLOB Number of bytes in the column

* For DECIMAL columns defined in an owned schema, the number of decimal digits
is one greater than the number of decimal digits in the original definition. This is
because of the difference in the semantics of this value between the SQL
standard and RDMS.

$P7 $P7 returns the information described in the following table.

Data Type Information Returned

CHARACTER The number 0 (no information)


NCHARACTER
INTEGER
SMALLINT
REAL
DOUBLE PRECISION
DATE
DECIMAL Number of fractional digits (scale)
TIME
TIMESTAMP
NUMERIC Decimal precision of fractional portion
FLOAT Binary precision
BLOB The number 0 (no information)

8–44 7830 8160–027


GET DESCRIPTION

$P8 $P8 indicates whether nulls are allowed:

1 Allowed
0 Not allowed

$P9 $P9 returns the following information regarding primary key columns and
arithmetic expression results:

0 This column is not part of the table’s primary key.


1 This column is part of the table’s primary key.
2 This column is the result of an arithmetic expression.

8.9.2. Example
Enter the following statements:

DECLARE c1 CURSOR SELECT cname, price, maxprice-price,


price*.06 AS commission
FROM houses, customers
WHERE desiredloc = location AND maxprice = price
WITH DESCRIPTION

Next, execute the following statement five times:

GET DESCRIPTION INTO $p1,$p2,$p3,$p4,$p5,$p6,$p7,$p8,$p9

You get the following results.

Execution $P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8 $P9

First rdms customers production cname character 28 0 1 0

Second rdms houses production price decimal 14 2 1 0

Third decimal 15 2 1 2

Fourth commission decimal 16 4 1 2

Fifth*

* 6001 status returned; program variables not set.

8.9.3. Rules and Guidelines


Read the following rules and guidelines before using the GET DESCRIPTION
statement.

Scope
Each GET DESCRIPTION statement returns information about one cursor column.

7830 8160–027 8–45


GET DESCRIPTION

To obtain information for all columns, continue executing GET DESCRIPTION


statements until you get a 6001 (end-of-cursor) status.

The 6001 status tells you that the previous GET DESCRIPTION statement returned the
last column’s information.

When to Use GET DESCRIPTION


The GET DESCRIPTION statement must be the first statement executed after the
DECLARE CURSOR . . . WITH DESCRIPTION statement. Once another statement is
executed, however, the description is no longer available.

There is one exception to this rule. You can execute a GETERROR statement to
retrieve the cursor explanation error messages before you execute the GET
DESCRIPTION statement. Using the GETERROR statement for any other error
invalidates subsequent GET DESCRIPTION statements.

To get both the description of a cursor and the explanation of the cursor, you must
execute statements in the following order:

1. EXPLAIN ALL ON
2. DECLARE (cursor declaration)
3. GETERROR (EXPLAIN information)
4. GET DESCRIPTION (cursor description)

The GET DESCRIPTION statement can be used only for cursors declared through the
interpreter interface.

Columns That Use Arithmetic


When one of the columns given in the SELECT clause uses arithmetic or is a function,
a name is not appropriate. Instead, the first four parameters are returned with blanks.

Columns That Use Title Names


If a column has a title name, that name is returned in $P4. The other “name” variables
are blank-filled.

Columns That Use UNION [ALL] Operator


When the UNION [ALL] operator is used in the cursor declaration, column names are
not returned. Instead, the first four parameters are returned with blanks.

CHARACTER Columns
No information is returned about the character set or collation used with a column
definition.

8–46 7830 8160–027


GETERROR

8.10. GETERROR
Use the GETERROR statement to

• Retrieve the error message from an SQL statement and place this message into
an application program variable.
• Retrieve the cursor access path information compiled by the EXPLAIN statement.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes No Yes No X

* Not IPF SQL

8.10.1. RDMS Extended Syntax


GETERROR INTO variable-list

where variable-list is a list of variable specifications separated by commas.


Each variable specification must correspond to a host program variable that must hold
at least 132 ASCII characters. Indicator variables are not allowed.

8.10.2. Example
The following example uses the GETERROR statement in an ASCII COBOL program.
This example is set up to check whether an error condition occurred during the
processing of the GETERROR statement.

ERROR-PAR.
MOVE 0 TO ERR-END-FLAG.
MOVE Error-status TO cmd-status.
PERFORM DO-GETERROR UNTIL ERR-END-FLAG NOT EQUAL 0.
DO-GETERROR.
ENTER MASM 'ACOB$RDMR'
USING 'GETERROR INTO $p1, $p2, $p3, $p4;'
Error-status
Aux-info
Err-line(1)
Err-line(2)
Err-line(3)
Err-line(4).
IF Error-status NOT = 0
DISPLAY '*ERROR ', Error-status,
' on GETERROR request.' UPON PRINTER
MOVE 1 to ERR-END-FLAG.
PERFORM LOOK-FOR-RESULT-OF-GETERROR
VARYING i FROM 1 BY 1 UNTIL i > 4.
LOOK-FOR-RESULT-OF-GETERROR.
IF Err-line(i) NOT = SPACE
DISPLAY Err-line(i) UPON PRINTER

7830 8160–027 8–47


GETERROR

ELSE
MOVE 1 TO ERR-END-FLAG.

This segment of the program prints the SQL error messages after executing an SQL
statement.

8.10.3. Rules and Guidelines


Read the following rules and guidelines before using the GETERROR statement.

Retrieved Messages
The GETERROR statement retrieves error messages for all errors returned for one
statement. This includes those detected by RDMS, UREP, and UDS Control. If you
want the program to do something with this text, use a GETERROR statement before
executing the next SQL statement.

Number of Variables Passed


If you pass more variables than needed, RDMS fills the unused variables with blanks.
Therefore, the first blank line indicates the end of the message. In many cases, ten
variables retrieve the complete message. Therefore, it is reasonable to call GETERROR
passing ten parameters. It is very important to code the error handling routine so it
will call geterror repeatedly until all error message text is returned. This is because
sometimes it is the last line of the message that provides the critical information (for
example, table name.)

If you pass too few or just enough variables for the message, you do not see the
blank line. If this blank line does not appear, call GETERROR again. This returns
message lines beginning at the point you left off on the previous call. Repeat this step
until a blank line appears.

If you are calling GETERROR from a UCS C program, you receive a zero-length string
instead of a blank string.

SQLCODE, SQLSTATE, ERROR-STATUS, AUX-INFO


SQLCODE, SQLSTATE, ERROR-STATUS, and AUX-INFO are not updated on the
GETERROR call.

Selecting an Interface
If an error occurs in the execution of an ESQL statement, you must execute the
GETERROR statement through ESQL also.

Similarly, you must execute the GETERROR statement following an erring interpreter
interface SQL statement through the interpreter interface.

8–48 7830 8160–027


GET PARAMETERS

8.11. GET PARAMETERS


Use the GET PARAMETERS statement to retrieve information about the number and
type of parameters for a routine.

GET PARAMETERS is available only through the RDMS interpreter interface.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No X

8.11.1. RDMS Extended Syntax


GET PARAMETERS FOR [schema-name.]routine-name INTO placeholder-list

where:

schema-name
is the name of the schema that contains the routine.

routine-name
is the name of the routine.

Schema and routine names must be valid names as defined in 2.2.1.

placeholder-list
is a list of placeholder variables to receive the parameter or function result
information, as follows:

$P1 Routine’s owner-id, up to 30 ASCII characters. ($P1 is not currently


activated.)

$P2 Name of the parameter, up to 30 ASCII characters. The first parameter


of a function is the name of the function itself.

Note: For a function, the first invocation of GET PARAMETERS returns the
name of the function and the return value's attributes in $P1 through $P10. On
the second and succeeding iterations, $P1 and $P2 return information on actual
parameters.

$P3 A number that indicates the parameter type, returned as an ASCII value:

1 Input (IN)
2 Output (OUT)
3 Input/Output (INOUT)
4 Function Result

7830 8160–027 8–49


GET PARAMETERS

$P4 A number that indicates the parameter’s data type, returned as an ASCII
value:

01 DECIMAL
02 CHARACTER
03 REAL
04 DOUBLE PRECISION REAL
05 INTEGER
06 LONG CHARACTER
07 DOUBLE PRECISION INTEGER
08 FLOAT
09 SMALLINT
10 (Not used)
11 NUMERIC
12 DATE
13 TIME
14 TIMESTAMP
63 Unknown

$P5 Name of the parameter’s data type, up to 16 ASCII characters:

CHARACTER
NCHARACTER
DECIMAL
NUMERIC
INTEGER
SMALLINT
REAL
FLOAT
DOUBLE PRECISION
DATE
TIME
TIMESTAMP

$P6 Precision, returned as an ASCII value:

Numeric Maximum number of digits used by the data type


Nonnumeric Maximum or defined length of the parameter

8–50 7830 8160–027


GET PARAMETERS

$P7 Size of the value, returned as an ASCII value, as in the following table.

Data Type Information Returned

CHARACTER Number of characters in parameter (size)


NCHARACTER
DATE
TIME
TIMESTAMP
DECIMAL* Number of digits (plus 1 for the sign)
NUMERIC Decimal precision (plus 1 for the sign)
INTEGER Number of bytes used to store each data
SMALLINT item (9-bit bytes)
REAL
FLOAT
DOUBLE PRECISION

* For DECIMAL items defined in an owned schema, the number of decimal


digits is one greater than the number of decimal digits in the original
definition. See 2.8.2 for more information about numeric data types.

$P8 Auxiliary scaling information, returned as ASCII characters, as in the


following table.

Data Type Information Returned

CHARACTER The number 0 (no information)


NCHARACTER
INTEGER
SMALLINT
REAL
DOUBLE PRECISION
DATE
DECIMAL Number of fractional digits (scale)
TIME
TIMESTAMP
NUMERIC Decimal precision of fractional portion
FLOAT Binary precision

$P9 Radix of the number (always 10).

7830 8160–027 8–51


GET PARAMETERS

$P10 Number that indicates whether nulls are allowed, returned as an ASCII
value:

0 Not allowed
1 Allowed
2 Unknown

The following steps illustrate how a calling program can retrieve parameter
information for a routine:

1. The calling program issues the following command to RDMS to determine


whether the routine exists and to retrieve the associated parameters:

GET PARAMETERS FOR routine-name


INTO $p1,$p2,$p3,$p4,$p5,$p6,$p7,$p8,$p9,$p10;

RDMS populates the RDMCA with the parameter information. RSA returns
information on the first parameter or function result, if one is present, or it returns
a 6001 status (last parameter) or an error condition.
2. The calling program continues by issuing the following call until a 6001 status is
returned or an error occurs:

GET PARAMETERS FOR routine-name


INTO $p1,$p2,$p3,$p4,$p5,$p6,$p7,$p8,$p9,$p10;

Each call returns information about the next parameter.

8–52 7830 8160–027


GET PARAMETERS

8.11.2. Example
The following example returns information about the parameters for function
HOUSE_SCHEMA.SELECT_HOUSES:

FUNCTION house_schema.select_houses(IN max_price NUMERIC) RETURNS


NUMERIC;
GET PARAMETERS FOR house_schema.select_houses
INTO $p1,$p2,$p3,$p4,$p5,$p6,$p7,$p8,$p9,$p10;

You get the following results on the first three executions:

$P1 $P2 $P3 $P4 $P5 $P6 $P7 $P8 $P9 $P10

rdms select_houses 4 11 numeric 11 12 0 10 1


rdms max_price 1 11 numeric 11 12 0 10 1
*

* 6001 status returned; program variables not set.

8.11.3. Rules and Guidelines


Read the following rules and guidelines before using the GET PARAMETERS
statement.

First and Succeeding Calls for Parameter Information


Issue this statement from the calling program the first time with the FOR
routine-name clause. RDMS returns information on the first parameter or function
result.

Continue issuing the command until information about all parameters is returned.

Once all information is retrieved, RDMS returns a 6001 error status.

No Parameters
For routines without parameters, RDMS returns a 6001 error status.

No Stored Procedure
If the routine does not exist, RDMS returns a 6007 error status.

7830 8160–027 8–53


GET RESULTS CURSOR NAME

8.12. GET RESULTS CURSOR NAME


The GET RESULTS CURSOR NAME statement retrieves the name of the cursor RDMS
created to describe the dynamic result sets returned by a call to a stored procedure.
Use the GET RESULTS CURSOR NAME statement immediately after a procedure call
to obtain the name of the cursor.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No X

8.12.1. RDMS Extended Syntax


GET RESULTS CURSOR NAME INTO placeholder-variable

where placeholder-variable is the placeholder variable ($P1) that will hold the name of
the result set cursor.

8.12.2. Example
The following example returns the name of the result set cursor that was just created
by a stored procedure, assuming that the procedure was created to produce dynamic
result sets.

SET RESULT SET CURSOR ON

CALL PROC_1( )

IF SQLSTATE = '0100C' OR '0100E' THEN GET RESULTS CURSOR NAME INTO $P1

8.12.3. Rules and Guidelines


Read the following rules and guidelines before using the GET RESULTS CURSOR
NAME statement.

When to Use
The GET RESULTS CURSOR NAME statement is only available through the interpreter
interface and must be the first statement executed after a call to a stored procedure
or stored function. Once another statement has been executed, the cursor name is no
longer available.

Scope
Each stored procedure that returns dynamic result sets, sets SQLSTATE to 0100C, if
the SET RESULT SET CURSOR ON statement was issued prior to the procedure call.

8–54 7830 8160–027


GET RESULTS CURSOR NAME

Naming Protocol
The result set cursor name can generally be anticipated, as can the names of the
return cursors. The result set cursor name consists of the characters “RS” followed
by the number of procedure executions that have returned result sets since the start
of the thread. For the first procedure invoked, the result set cursor name is RS1. The
individual return cursor names take the result set cursor name as a prefix; they
append an underscore and the original cursor name from the procedure definition (for
example, RS1_C1).

See 4.7 for a complete description of dynamic result sets.

7830 8160–027 8–55


GRANT

8.13. GRANT
Use the GRANT statement to control access by other users to a table and its data. For
tables that are owned, the GRANT statement cannot be used to give users other than
the owner the ability to perform commands such as ALTER TABLE, DROP TABLE, and
CREATE INDEX. Only the owner can execute such commands.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No E/X

8.13.1. Syntax
SQL 92 Syntax (Entry Level)
GRANT { ALL PRIVILEGES │ privilege-list }

ON table-specification

TO user-id-list

[ WITH GRANT OPTION ]

RDMS Extended Syntax


GRANT {

{ALL PRIVILEGES | privilege-list} ON table-specification

| role-name

TO user-id-list

{WITH GRANT OPTION}

where:

ALL PRIVILEGES has one of the following effects:


• If the table is a base table or global temporary table with specific version or a
view, grants the specified users FETCH, UPDATE, INSERT, and DELETE
privileges on rows in the named table.
• If the table is a base table or global temporary table without version, grants
the specified users FETCH, UPDATE, INSERT, DELETE and REFERENCES
privileges on rows in the named table.

8–56 7830 8160–027


GRANT

privilege-list
is a list that contains any combination of the following privileges:

DELETE
FETCH
INSERT
REFERENCES [ (column-name-list) ]
SELECT
UPDATE [ (column-name-list) ]

where column-name-list is one or more simple column names from the table
named in the GRANT statement, separated by commas.

Use commas to separate items in the privilege list or column name list.

FETCH and SELECT are synonymous (FETCH is an extension to standard SQL).

RDMS requires that users privileged to use the DELETE and UPDATE statements
must also have SELECT statement privileges. DELETE ALL does not require the
SELECT statement privilege.

If security is enforced, RDMS requires that the REFERENCES privilege on the


parent table or on columns of the parent table be granted to the child table owner
of a foreign key before the foreign key is created.

table-specification
is a table name as defined in 2.2.2. The version name, if used, cannot be passed by
a variable.

user-id-list
is a list of user IDs allowed to access the table. Include the keyword PUBLIC in the
list to grant the listed privileges to all system users.

user-id [ ,user-id ] ...

A user ID can also be a role-name. All the names in the user ID list must be either
user IDs or role-names. You cannot mix user IDs and role-names in the same
statement.

If a user ID starts with a number, express it as a delimited uppercase identifier, as


illustrated in the following examples:

"1BIG" "2NOR" "3NOT"

RDMS converts lowercase user IDs to uppercase, regardless of whether it is


undelimited or delimited.

Role-name
is a role-name as defined in section 2.2.6.

7830 8160–027 8–57


GRANT

WITH GRANT OPTION


allows the users named to execute the GRANT statement and thereby pass along
the listed access privileges to other users. Even if a user has all privileges granted
with the GRANT option, other constraints can exist on which privileges the user
can grant. For more information, see 7.2.

8.13.2. Examples
The following example illustrates how to grant all privileges and the GRANT option on
table MASTER.PERSONNEL to users Jacques and Jack:

GRANT ALL PRIVILEGES


ON TABLE master.personnel
TO Jacques, Jack
WITH GRANT OPTION

The next example grants SELECT and INSERT privileges on table HOUSES to John:

GRANT SELECT, INSERT


ON TABLE houses
TO John

The next example grants the SELECT privilege to all users on table HOUSES:

GRANT SELECT
ON TABLE houses
TO PUBLIC

The next example grants the UPDATE privilege with a column name list on
CUSTOMERS to user 5XYZ:

GRANT UPDATE(maxprice,desiredloc)
ON TABLE customers
TO "5XYZ"

The next example grants the fetch privilege, on table houses, to the role named
“ROLE-PROGRAMMER”. Note that when granting privileges to a role, the role-name is
treated as a user ID.

GRANT fetch ON houses to “ROLE-PROGRAMMER”

The next example places user ID JIM in the role named “ROLE-PROGRAMMER”.

GRANT “ROLE-PROGRAMMER” TO Jim

8–58 7830 8160–027


GRANT

8.13.3. Rules and Guidelines


Read the following rules and guidelines before using the GRANT statement.

Version Names
Although the GRANT statement uses the thread default qualifier name the same way
any other statement uses it, it does not use the default version name in the same
way. The GRANT statement ignores default version names.

When you use a version name on the table specification in a GRANT statement, you
grant privileges on one version of the table. If you omit a version name, you grant
privileges on all versions of the table.

Since the REFERENCES privilege applies to all versions of a table, you cannot specify a
version name when granting this privilege.

The REFERENCES privilege controls the establishment of foreign keys. Foreign keys
apply to all versions of the related tables, thus guaranteeing integrity among all
versions of two tables on the system.

For example, two versions of table HOUSES exist, PRODUCTION and OUTSTATE. The
following GRANT statement grants privileges for both versions of the table:

GRANT SELECT ON houses TO PUBLIC

On the other hand, if you use the following statement, all users can look at
HOUSES:PRODUCTION, but only the owner can look at HOUSES:OUTSTATE:

GRANT SELECT ON houses:production TO PUBLIC

If you grant privileges to a specific table version, you must name that version when
you want to revoke privileges. Similarly, if you grant privileges without a version name,
the privileges can be revoked only by omitting the version name.

For example, you cannot grant privileges on HOUSES:PRODUCTION and revoke them
on HOUSES (without a version name). You also cannot specify a version when granting
the UPDATE privilege on columns.

Performance
Using table specifications without version names with the GRANT statement allows
faster execution.

Role Security: Granting privileges to a role


Privileges are granted to a role using the same syntax as for granting privileges to a
user ID.

7830 8160–027 8–59


GRANT

The REFERENCES privilege, privileges on columns, and table:version privileges cannot


be granted to a role. ALL PRIVILEGES does not include REFERENCES when granting to
a role.

A thread granting access to a role, on a table or view, must be able to get exclusive
access to the definition of that table or view (as also required by ALTER TABLE).

It is not possible to grant privileges to a role or to PUBLIC, on a table or view, when a


cursor is declared over that table or view.

A view cannot be created by a user whose privileges to underlying tables, or views,


were derived from role membership.

You cannot grant a role to a role.

Role Security: Placing a user ID in a role


A user ID is placed in a role using the following GRANT syntax:

GRANT role-name to user-id-list

Associating, or removing the association, of a user ID to a role, has no effect on active


threads of users that have already accessed the affected table. The committed grant
of privileges to a role is reflected in all new threads that access the affected table, and
by existing threads performing their first access to the table.

WITH GRANT OPTION cannot be specified when granting privileges to a role or


specifying a role-name.

A role cannot be granted to a role. A role cannot be granted to PUBLIC (because


PUBLIC is already a type of role).

Only the owner of the role can associate the user with a role, or remove the user from
a role.

8–60 7830 8160–027


INSERT

8.14. INSERT
Use the INSERT statement to add one or more rows to a new or existing table or
view.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes Yes Yes E/X

8.14.1. Syntax
SQL 92 Syntax (Entry Level)
INSERT INTO table-specification [ (column-name-list) ]

{ VALUES (value-list) │ query-specification }

RDMS Extended Syntax


INSERT [ INTO ] table-specification

{ [(column-name-list)] { VALUES (value-list) │ query-specification } │

COLUMNS (column-and-value) }

Syntax When Used in Routines or Triggers


INSERT INTO table-specification [ (column-name-list) ]

{ VALUES (value-list) │ query-specification }

where:

table-specification
is a table name as defined in 2.2.2.

column-name-list
is a list of column names in the table. The list can be omitted if the order and
number of data items in the value list correspond to the order and number of
columns defined when the table was created by the CREATE TABLE statement.

value-list
is a list of any combination of string literals, numeric constants, datetime literals,
CAST functions, variable specifications, the keywords NULL and USER, or the
datetime functions CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP.
Use commas to separate the data items in the value list.

The order of the data items is important. If you provide a column name list, the
data items in the value list must be specified in the corresponding order. If you do
not provide a column name list, the data items in the value list must correspond to
the columns for the table specified.

7830 8160–027 8–61


INSERT

In place of a value (for example, 1, NULL, ‘a’) in the value-list or value-specification,


you can specify the DEFAULT keyword. If a value of DEFAULT is specified for a
column, it works as follows:

• If the column contains a DEFAULT clause, the default is inserted.


• If the column is an IDENTITY column, the next value of the identity
sequence is inserted.
• If the column is GENERATED AS <expression> the expression following
the AS is evaluated and its value inserted.
• If none of the above, and NULL values are allowed, NULL is inserted.
Otherwise, an error is issued.
query-specification
is a query specification as defined in 2.7. If used, the values specified are identified
by this query specification. Items in the select list of the query specification must
correspond one to one, in order, with the columns in the column name list (or in
the table definition, if no column name list is specified).

column-and-value
is a list of column names from the table being updated and the data item for each
column.

The list is one or more entries, separated by commas, in the form

column-name=value-specification

You must enclose the list in parentheses. The value specification can include
string literals, numeric constants, datetime literals, CAST functions, variable
specifications, the keywords NULL and USER, or the datetime functions
CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP. For more
information, see 2.8.

8.14.2. Examples
The first three examples insert the same row in table HOUSES; only the format of the
INSERT statement is different.

Example 1
The following example specifies the values to be inserted with the VALUES clause:

INSERT INTO houses


VALUES ('H106', 'Anoka', 95000, 'Duplex')

Example 2
The following example provides the values to be inserted with the COLUMNS clause:

INSERT INTO houses


COLUMNS(hno = 'H106', price = 95000,
location = 'Anoka', description = 'Duplex')

8–62 7830 8160–027


INSERT

Example 3
The following example uses the SQL format:

INSERT INTO houses


(hno, price, location, description)
VALUES ('H106', 95000, 'Anoka', 'Duplex')

Example 4
To insert a row with nulls, use the NULL keyword or indicator variables:

INSERT INTO houses (hno, price, location, description)


VALUES('H107', NULL, 'Hibbing', NULL)

Example 5
In this example, $P3, $P5, and $P7 indicate whether $P2, $P4, and $P6, respectively,
contain a non-null:

INSERT INTO houses (hno, price, location, description)


VALUES($p1, $p2 $p3, $p4 $p5, $p6 $p7)

For more information on indicator variables, see 2.10.4.

Example 6
In this example, two versions of table HOUSES exist, one for PRODUCTION and one
for OUTSTATE. All houses in the Chicago neighborhood are listed incorrectly in the
outstate district and must now be moved to production houses. You can do this with
the following INSERT and DELETE statements.

INSERT INTO houses:production SELECT * FROM houses:outstate


WHERE location = 'Chicago'
DELETE houses:outstate WHERE location = 'Chicago'

Example 7
In the remaining examples, assume default clause values are defined for columns
LOCATION, PRICE, and DESCRIPTION of table HOUSES. (For more information about
default clauses, see 6.11.)

The following example inserts a row with default values for columns PRICE and
LOCATION:

INSERT INTO houses COLUMNS (hno = 'H108', description = 'split')

Example 8
This example inserts a row with default values for PRICE and DESCRIPTION:

INSERT INTO houses (hno, location) VALUES ('H109', 'Roseville')

7830 8160–027 8–63


INSERT

Example 9

This example shows inserts of the same record as example 8, but uses the DEFAULT
keyword.

INSERT INTO houses (hno, price, location, description)


VALUES ('H109', DEFAULT, 'Roseville', DEFAULT)

Example 10
Examples 9 and 10 assume another table, HOUSES2, exists with three columns
defined as HNUM, LOC, and PRICE. An insertion from table HOUSES2 into table
HOUSES results in default values for DESCRIPTION:

INSERT INTO houses SELECT * FROM houses2

Example 11
This example inserts default values for PRICE and DESCRIPTION:

INSERT INTO houses (hno, location) SELECT hnum, loc FROM houses2

8.14.3. Rules and Guidelines


Read the following rules and guidelines before using the INSERT statement.

Prerequisites
The table or view may or may not already contain rows of data. However, it must have
been created by the CREATE TABLE or CREATE VIEW statement. Use the first form
(VALUES) when you are certain of the order of the columns; otherwise, use the
second form (COLUMNS).

Default Values, Nulls


RDMS inserts the default value specified for each column for which you do not specify
a value. If the column has no default clause defined and the column allows nulls,
RDMS inserts a null in the column. If you do not specify a value for a NOT NULL
column and a default value is not explicitly defined for the column, RDMS returns an
error.

Read-Only Views
You cannot insert data into a read-only view.

Permanent Changes
Permanent database changes can occur any time after an UPDATE statement is
executed if the NONE recovery option is used on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently insert rows into the database until the
program executes a COMMIT or END THREAD statement.

8–64 7830 8160–027


INSERT

Row Locking Inserted by RDMS


RDMS locks inserted rows so that other threads cannot access them until these rows
are committed to the database.

The default table lock is step-duration UPDATE mode, and the default row lock is
step-duration EXCLUSIVE UPDATE mode. See the Relational Database Server for
ClearPath OS 2200 Administration Guide.

If the table is locked in one of the RETRIEVAL modes, RDMS rejects the INSERT
statement.

Column/Table Constraints
If one of the values you are inserting violates a column or table constraint, RDMS
returns an error.

Thread Rollbacks
Some errors during the insert operation do not cause a thread rollback unless the
INSERT statement includes a query specification. These errors include duplicate
primary key violations, column length or size violations, and constraint and referential
integrity violations.

If the INSERT statement contains a query specification and QUICKLOOKS or


DEFERRED recovery is used, these errors result in a thread rollback. To prevent the
thread from rolling back, use COMMANDLOOKS recovery.

FROM List
The FROM list in a query specification or subquery may contain the table identified in
the table specification. If the table contains a primary key or unique constraints, the
INSERT statement may terminate with a duplicate key error.

To avoid duplicate keys, use the SELECT statement to change the value of at least one
column of the primary key and at least one column of each unique constraint, as in the
following example:

INSERT INTO x
SELECT pk+1000,...unique1+1000,...
FROM x

7830 8160–027 8–65


INSERT

Inserting Multiple Rows


You can insert multiple rows with a single INSERT statement only by using a query
specification. Other forms of the INSERT statement insert only one row per
statement.

It is recommended that you specify DISTINCT in the SELECT clause of the query
specification to avoid encountering a duplicate primary key error. DISTINCT is not
required, however, if you know that the query specification is selecting only rows with
unique primary keys for the table being inserted.

Numeric Data Types


The data types of numeric items must be compatible with the data types of the
columns being inserted, as described in 2.8.2.

Subqueries
If query-specification contains a subquery and a character column is being inserted,
the values returned by a subquery must have the same character set as the column
into which the values are being inserted, unless either the source or destination
column is defined with the RDMS_TEXT character set. For character value assignment
considerations, see 2.8.1.

Number of Rows Inserted Returned


RDMS returns the number of rows inserted through the auxiliary information variable.
For more information, see the manual for the programming language you are using.

In routines, the RDMSAUXINFO system variable can be used to obtain this information.
See 4.9.1.

No Finds
If no rows are specified by the query specification, RDMS returns an OK status of
0000 or an SQLCODE of +100 (see C.3).

8–66 7830 8160–027


Section 9
SQL Statements LEVEL Through SET
STATISTICS

This section contains reference information about the following SQL statements:

• LEVEL (9.1)
• LOCATE (9.2)
• LOCK (9.3)
• OPEN (9.4)
• PREPARE (9.5)
• PROCEDURE (9.6)
• REVOKE (9.7)
• ROLLBACK (9.8)
• SELECT Multirow (9.9)
• SELECT Single Row (9.10)
• SET (9.11)
• SET AUXINFO (9.12)
• SET RESULT SET (9.13)
• SET SKIPGENERATED (9.14)
• SET STATISTICS (9.15)

7830 8160–027 9–1


LEVEL

9.1. LEVEL
Use the LEVEL statement to determine the internal level number of RDMS and its RSA
component.

The level number returned by the LEVEL statement corresponds to the system
number used by COMUS when RDMS was generated.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* No No No No X

* Not IPF SQL

9.1.1. RDMS Extended Syntax


LEVEL [ RSA │ RDMS ] INTO placeholder

where:

RSA
(default) returns the system level number of the RSA component of RDMS.

RDMS
returns the system level number of RDMS.

placeholder
represents a CHARACTER type host program variable.

9.1.2. Example
The following UCS FORTRAN statement returns the level number of the version of
RDMS in the application group being used in variable RLEVEL:

CALL F$RDMR('LEVEL RDMS INTO $p1;' errcod,auxinf,rlevel)

After the statement is executed, the variable RLEVEL contains a character string
similar in form to

RDMS LEVEL 10-1-12-2

9–2 7830 8160–027


LOCATE

9.2. LOCATE
Use the LOCATE statement to position the pointer in a cursor. The LOCATE statement
does not retrieve data.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes Yes Yes No X

* Not IPF SQL

9.2.1. Syntax
RDMS Extended Syntax
LOCATE cursor-name ON table-specification

USING VALUES (primary-key-value)

Syntax When Used in Routines or Triggers


LOCATE cursor-name ON table-specification

USING VALUES (primary-key-value)

where:

cursor-name
is an opened cursor. You can use the LOCATE statement on an opened cursor only
if you specified RANDOM or DIRECT ACCESS in its DECLARE CURSOR statement.
The cursor cannot be allocated (declared) from a prepared query specification. The
cursor cannot include a subquery.

table-specification
is a table name as defined in 2.2.2, except that version names are not allowed.

primary-key-value
is the value of the primary key for the row you want to locate. The primary key
value is a list of values of the column or columns of the table's primary key
separated by commas. The values can be any combination of string literals,
numeric constants, datetime literals, CAST functions, variable specifications, the
keywords NULL and USER, or the datetime functions CURRENT_DATE,
CURRENT_TIME, and CURRENT_TIMESTAMP. The values must be listed in the
same order as the columns in the PRIMARY KEY clause of the CREATE TABLE
statement.

7830 8160–027 9–3


LOCATE

9.2.2. Example
The following example locates the row in table CUSTOMERS that contains customer
number C101 in the CUST cursor:

DECLARE cust CURSOR


FOR RANDOM ACCESS
SELECT * FROM customers
LOCATE cust
ON customers
USING VALUES ('C101')

9.2.3. Rules and Guidelines


Read the following rules and guidelines before using the LOCATE statement.

Random Access Cursors


Specify the row’s primary key to locate a row in the cursor. The use of the LOCATE
statement is limited by the restrictions placed on random access cursors (see 7.4).

Pointer Position
If the primary key value does not exist in the table, the cursor does not have a current
row. However, RDMS positions the cursor where the primary key value would be
located if it existed. This means, in effect, that a FETCH CURRENT does not retrieve a
row but that a FETCH NEXT or FETCH PRIOR retrieves a row if a row exists after or
before the cursor's position.

If you execute a LOCATE statement on a table using a nonexistent primary key value,
a subsequent FETCH CURRENT statement always returns a 6001 no-find error status;
however, a FETCH NEXT statement returns the row following the cursor's new
position, if such a row exists.

The LOCATE statement only positions a cursor. RDMS does not return a 6001 no-find
error status on a LOCATE statement. If a row that contains the primary key value does
not exist, however, RDMS returns a no-find SQLCODE of +100 (see C.3).

Auxiliary Information
After executing the LOCATE statement, RDMS sets the auxiliary information variable
to 1 if the row specified in the USING clause does not exist. If the row does exist,
RDMS sets the auxiliary information variable to 0.

In routines, the RDMSAUXINFO system variable can be used to obtain this information.
See 4.9.1.

9–4 7830 8160–027


LOCATE

Routines and Triggers and the LOCATE Statement


Any cursor referenced in a LOCATE statement must be declared within the same
compound statement as the LOCATE statement or at an outer level of nesting.

The cursor must be opened using the OPEN statement prior to the execution of the
LOCATE statement.

Note that LOCATE is a nonstandard RDMS extension.

7830 8160–027 9–5


LOCK

9.3. LOCK
Use the LOCK statement to specify a lock on one or more tables during a step.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes Yes No X

9.3.1. RDMS Extended Syntax


LOCK [ TABLE ] table-specification-list

[ IN lock-specification [ MODE ] ]

[PARTITION IN lock-specification [MODE]]

[ ON CONFLICT { RETURN │ QUEUE } ]

where:

table-specification-list
is one or more table specifications, separated by commas. This list specifies the
base tables you want to lock. You cannot lock a view. If you need locking
protection while accessing a view, you must lock each of the base tables on which
the view depends. Locks on global temporary tables are ignored, because RDMS
implicitly locks global temporary tables in EXCLUSIVE UPDATE MODE.

lock-specification
is in the form

[mode] [usage]

where:

mode
is SHARE or SHARED (synonymous), PROTECTED, or EXCLUSIVE.

usage
is RETRIEVAL (default), ACCESS, or UPDATE.

A mode value is not allowed with the ACCESS clause.

For more information about mode and usage, refer to 9.3.2.

9–6 7830 8160–027


LOCK

PARTITION IN
specifies how to lock partitions of partitioned tables.

When PARTITION IN is specified, the only allowed values for the


lock-specification following the table-specification-list are UPDATE and
RETRIEVAL. If UPDATE is specified, the only allowable values following
PARTITION IN are PROTECTED UPDATE and EXCLUSIVE UPDATE. If RETRIEVAL is
specified, the only allowable values following PARTITION IN are PROTECTED
RETRIEVAL and EXCLUSIVE RETRIEVAL.

PARTITION IN can be used to specify a partition lock, both in the XTC and the
local-host environments. Partition lock is implemented to allow multiple threads
to EXCLUSIVE UPDATE or PROTECTED UPDATE to lock the partitions where they
are working. This capability improves performance in an XTC environment where
it takes time (approximately one millisecond) to call XPC-L to get a lock. Placing a
PROTECTED UPDATE lock on the partition eliminates the need to place any page
or record locks in the partition. Use of this feature does not greatly affect
performance in the single-host environment. For more information on locking and
partitions, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

ON CONFLICT
along with one of the following two keywords, instructs RDMS on how to handle a
locking conflict:

RETURN Return an error and then return control to the application


program.
QUEUE (Default) Queue the application program until the locking
conflict is resolved.

7830 8160–027 9–7


LOCK

9.3.2. Types of Locks


The following table describes the types of locks.

Lock /
Lock and Mode Description

RETRIEVAL When you place a RETRIEVAL lock on a table, you cannot update
the table. Other users cannot place an EXCLUSIVE RETRIEVAL or
EXCLUSIVE UPDATE lock on the table; they can, however, update
the table. You therefore risk reading the same row twice and
obtaining different data values each time if another user updated
the row and committed the changes between retrievals. You
cannot retrieve a row if another user has updated it but has not
committed or rolled back the change.
SHARED Your SHARED RETRIEVAL lock is similar to a RETRIEVAL lock
RETRIEVAL except that other users cannot change retrieved rows until a
COMMIT, ROLLBACK, or END THREAD statement is executed.
This guarantees the return of identical data values if the same
row is read twice.
PROTECTED Your PROTECTED RETRIEVAL lock prevents you and other users
RETRIEVAL from making changes to the table. Other users can place only a
nonexclusive RETRIEVAL type lock. Since RDMS does not lock
individual rows in this case, you can retrieve data faster by
imposing a PROTECTED RETRIEVAL lock than by using a
RETRIEVAL, UPDATE, SHARED RETRIEVAL, or SHARED UPDATE
lock.
EXCLUSIVE Your EXCLUSIVE RETRIEVAL lock allows only you to access the
RETRIEVAL table but not to update it. Since RDMS does not lock individual
rows in this case, you can retrieve data faster by using an
EXCLUSIVE RETRIEVAL lock than by using a RETRIEVAL, UPDATE,
SHARED RETRIEVAL, or SHARED UPDATE lock.
UPDATE Your UPDATE lock allows you and other users to retrieve data
from and update the table. Other users cannot place a
PROTECTED RETRIEVAL, PROTECTED UPDATE, EXCLUSIVE
RETRIEVAL, or EXCLUSIVE UPDATE lock on the table. As with
RETRIEVAL locks, you risk reading the same row twice and
getting different data values each time if another user updated
the row and committed the change between retrievals. If you
update a row, no other user can retrieve or update the row until
you commit or roll back the change.
SHARED UPDATE Your SHARED UPDATE lock is similar to an UPDATE lock, except
that other users cannot update your retrieved rows until a
COMMIT or ROLLBACK statement is executed. Other users who
also have the table locked in SHARED UPDATE mode cannot
retrieve your retrieved rows until you commit or roll back the
changes.

9–8 7830 8160–027


LOCK

Lock /
Lock and Mode Description

PROTECTED Your PROTECTED UPDATE lock allows only you to update the
UPDATE table. Other users can retrieve data from the table, but they can
place only RETRIEVAL and SHARED RETRIEVAL locks on the
table. Even though this protects the run from other users
attempting to update the table, you still cannot update a row
retrieved by another user who has a SHARED RETRIEVAL lock on
the table. Since RDMS does not lock individual rows for retrieval,
you can retrieve data faster by using a PROTECTED UPDATE lock
than by using a RETRIEVAL, UPDATE, SHARED RETRIEVAL, or
SHARED UPDATE lock.
EXCLUSIVE Your EXCLUSIVE UPDATE lock allows only you to retrieve data
UPDATE from the table and to update it. Since RDMS does not lock
individual rows in this case, you can retrieve data and update it
faster by using an EXCLUSIVE UPDATE lock than by using a
RETRIEVAL, SHARED RETRIEVAL, or any other UPDATE type lock.
ACCESS (Use only if the fast search feature is enabled.) Your ACCESS lock
prevents you from updating the table. Other users cannot place
an EXCLUSIVE RETRIEVAL or EXCLUSIVE UPDATE lock on the
table. Since you may be reading data that is currently being
updated by a transaction, you might see such data
inconsistencies as missing records, duplicate records, and
uncommitted records.

9.3.3. Examples
The following two examples lock table CUSTOMERS in different modes:

LOCK TABLE customers IN UPDATE MODE

LOCK TABLE customers IN EXCLUSIVE RETRIEVAL MODE ON CONFLICT RETURN

9.3.4. Rules and Guidelines


Read the following rules and guidelines before using the LOCK statement.

XTC
If an application group is configured for Extended Transaction Capacity (XTC), the
LOCK statement affects the entire storage area in which the table to be locked
resides. If one table in a storage area is locked, all other tables in the same storage
area (if any are present) are locked.

To prevent the LOCK statement from affecting multiple tables, it is recommended that
you place only one table in each storage area.

7830 8160–027 9–9


LOCK

Duration of Lock
Locks created with the ACCESS, RETRIEVAL, SHARED RETRIEVAL, PROTECTED
RETRIEVAL, and EXCLUSIVE RETRIEVAL clauses are immediately unlocked when you
issue the UNLOCK statement.

For UPDATE, SHARED UPDATE, PROTECTED UPDATE, and EXCLUSIVE UPDATE locks,
the UNLOCK statement does not take effect until you enter a COMMIT, ROLLBACK, or
END THREAD statement.

Changing a Table Lock


If you lock a table using the LOCK statement and later wish to change the mode or
usage, you must first unlock the table and then lock it again with the desired mode and
usage.

You can change the ON CONFLICT behavior without performing an UNLOCK.

Subsequent use of this attribute includes the new value. OPEN cursors reflect the ON
CONFLICT behavior in force at the time they are opened.

The ON CONFLICT behavior of STATIC ESQL statements, executed multiple times


within a loop, is difficult to determine if the ON CONFLICT behavior changes with the
loop. This change is therefore useful when the ESQL program is structured as follows:

a) LOCK ... ON CONFLICT ...


b) SQL statements that use the ON CONFLICT behavior a) ...
c) LOCK ... ON CONFLICT ...
d) SQL statements that use the ON CONFLICT behavior c), where these SQL
statements are physically different lines of program compared to the
statements of b).

Table and Row Locking


The LOCK statement places explicit locks on tables. You cannot place locks on
individual rows; only RDMS can lock rows.

Use of EXCLUSIVE UPDATE with Many Updates


If a program makes many updates to the database, use EXCLUSIVE UPDATE on the
LOCK statement. In this case, RDMS does not lock individual rows, and the speed of
processing thereby increases. Other users, however, cannot access the table while it
is locked.

RDMS-SERIALIZABLE Configuration Attribute


If the configuration attribute RDMS-SERIALIZABLE is set to YES, RDMS implicitly locks
the tables you reference. If the BEGIN THREAD syntax specifies UPDATE, RDMS
places an EXCLUSIVE UPDATE lock on each table referenced.

9–10 7830 8160–027


LOCK

For BEGIN THREAD syntax that specifies READ or RETRIEVE, RDMS places a
PROTECTED RETRIEVAL lock on each table referenced. Other users cannot update a
table that is referenced until the changes are committed or rolled back.

Use of Separate LOCK Statements for Individual Tables


Use a separate LOCK statement for each table you wish to lock. If you lock more than
one table with a single LOCK statement and the statement returns an RDMS error
(error status in the 6000 range), some of the tables might have been locked
successfully before RDMS detected the error.

A lock request can also become queued after some of the tables are locked. You can
avoid this potentially confusing situation by locking only one table per LOCK
statement.

You cannot lock a table if the thread has an opened cursor that refers to that table.

Lock Mode and Usage


You can specify nine types of locks. Each type includes a mode and usage:

• Mode establishes how strong a lock you want on a table and its rows. EXCLUSIVE
is the strongest lock, followed by PROTECTED and SHARED.
A mode value is not allowed with the ACCESS clause.
• Usage establishes whether you are retrieving or updating data, or in the case of
the ACCESS clause, the method of data retrieval.
If you are retrieving data with the DECLARE CURSOR statement or a FETCH
statement, a RETRIEVAL lock is appropriate.
If you are altering data with the UPDATE or the INSERT statement, for example, an
UPDATE lock is necessary.

Locks and Commit Processing


The technical details regarding table locks during commit processing are complex:

• Explicit table locks are retained.


• Implicit table locks are released if no opened cursors are active on the tables being
accessed.
• Implicit table locks with all other locks except ACCESS are reduced to a basic
RETRIEVAL lock on the table whenever cursors remain opened at the commit
point. It follows that implicit table locks for a RETRIEVAL lock are retained
unchanged with opened cursors on a table.

To demote an implicit table lock, RDMS performs an implicit UNLOCK command


followed by an implicit LOCK command of RETRIEVAL.

The Relational Database Server for ClearPath OS 2200 Administration Guide contains
an entire section devoted to locking. You are urged to read this section.

7830 8160–027 9–11


OPEN

9.4. OPEN
Use the OPEN statement to activate a cursor defined with a DECLARE CURSOR or
ALLOCATE CURSOR statement.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes No Yes No E/X

* Not IPF SQL

9.4.1. Syntax
SQL 92 Syntax (Entry Level)
OPEN cursor-name

RDMS Extended Syntax


{ OPEN │ READY [ CURSOR ] } cursor-name

[ USING variable-list ]

Syntax When Used in Routines or Triggers


OPEN cursor-name

where:

cursor-name
is the name of the cursor being opened.

variable-list
is a list of variables separated by commas.

Note: The READY [CURSOR] form is not allowed in ESQL, routines, or triggers.

9–12 7830 8160–027


OPEN

9.4.2. Examples
Example 1
The following example uses the OPEN statement with a DECLARE CURSOR statement
in a UCS FORTRAN program:

CALL F$RDMR('DECLARE cx CURSOR SELECT hno FROM houses '//


$ 'WHERE price >= $p2 AND location = $p1;',
$ Errstat, Auxinf, p1, p2)
p1 = 'Woodbury'
p2 = 65000
CALL F$RDMR('OPEN cx USING $p1, $p2;',
$ Errstat, Auxinf, p1, p2)
CALL F$RDMR('FETCH FIRST cx INTO $p1;',Errstat, Auxinf,
$ Hnum)
p1 = 'Turtle Creek'
p2 = 100000
CALL F$RDMR('OPEN cx USING $p1, $p2;',
$ Errstat, Auxinf, p1, p2)
CALL F$RDMR('FETCH FIRST cx INTO $p1;',Errstat, Auxinf,
$ Hnum)

This example declares a cursor to retrieve certain house numbers from table HOUSES.
Use placeholder variables in the WHERE clause to change the selection criteria from
time to time.

After declaring the cursor, you must open it. Opening the cursor fills in the blanks left
by the variables in the DECLARE CURSOR statement. The first OPEN statement places
all rows for houses in Woodbury priced at $65,000 or more in the cursor. You can then
fetch those rows.

You can use the same cursor to retrieve a different set of rows. In the same example,
the second OPEN statement modifies the cursor to retrieve rows for houses in Turtle
Creek priced at or above $100,000.

Example 2
The following example declares a cursor with a parameter marker; the OPEN
statement opens the cursor and supplies a value for the parameter marker:

MOVE 'SELECT * FROM houses WHERE price > ?' TO sqlsource.


EXEC SQL PREPARE cstmt_1 FROM :sqlsource END-EXEC
EXEC SQL ALLOCATE c1 CURSOR FOR cstmt_1 END-EXEC.
MOVE 90000.00 TO prog-price.
EXEC SQL OPEN c1 USING :prog-price END-EXEC.

7830 8160–027 9–13


OPEN

9.4.3. Rules and Guidelines


Read the following rules and guidelines before using the OPEN statement.

When to Use the OPEN Statement


Use the OPEN statement if the cursor is declared (or allocated, in dynamic ESQL):

• By the interpreter interface


You must open a cursor with the OPEN statement if the cursor declaration
includes placeholder variables. You must have a USING clause on the OPEN
statement. If the cursor contains no variables, RDMS automatically opens it the
first time you fetch from the cursor.
• Through static ESQL
You must use the OPEN statement with static ESQL. You cannot have a USING
clause on the OPEN statement.
• Through dynamic ESQL
You must use the static ESQL OPEN statement. The USING clause is required if
the prepared cursor specification has parameter markers.

Opening a Cursor Already Opened


In ESQL, if you attempt to open a cursor that is already opened, RDMS returns an error
as required by standard SQL.

If you are not using ESQL, RDMS does not return an error. Instead, RDMS
automatically closes the cursor and then reopens it. This is an extension to standard
SQL.

Allocation of Memory
When you open a cursor, RDMS allocates memory space to the cursor in addition to
that allocated when you declared the cursor.

When you close a cursor or when it is closed automatically by RDMS, the memory
space allocated upon opening is freed for other uses.

Avoiding Automatic Cursor Closure


Unless RETENTION is specified on the DECLARE CURSOR statement, RDMS closes a
cursor automatically if a COMMIT statement is executed.

Evaluating Datetime Functions


Whenever a cursor includes a datetime function such as CURRENT_DATE,
CURRENT_TIME, or CURRENT_TIMESTAMP, the function is evaluated only once during
the execution of the OPEN statement. The cursor keeps using the value until the
cursor is closed. If a cursor includes more than one datetime function, all of them are
evaluated simultaneously.

9–14 7830 8160–027


OPEN

Cursor Pointer
A cursor (referred to as an “active set” in some literature) is a set of rows in a
conceptual table. Each cursor includes a pointer. In some literature, this pointer is
called a “cursor.”The pointer indicates the current row of the cursor. This pointer
tracks a user’s progress through the cursor as rows are sequentially fetched or
randomly located in it.

After an OPEN statement, RDMS positions the pointer before the first row in the
specified cursor. Unless you change the current row with a LOCATE statement, a
FETCH NEXT statement at this time retrieves the first row in the cursor. Since RDMS
uses the pointer internally, you cannot actually see it. However, you can position the
pointer with the LOCATE statement if the cursor is a random access cursor.

The pointer is in one of the following positions:

• At the current row


• Before, but not at, a row
For example, the cursor does not move after the current row is deleted, yet it no
longer points to a row.
• After the last row of the cursor

A cursor declared through the interpreter interface “wraps around.” That is, if you go
past the last row of the cursor and get a no-find error status and then execute a
FETCH NEXT statement, you retrieve the first row of the cursor. This does not happen
for a cursor declared or allocated through ESQL, for once a no-find status is returned
for an ESQL cursor, no further retrievals are possible until the cursor is reopened.

Similarly, sequential FETCH PRIOR statements against a cursor declared through the
interpreter interface eventually retrieve the cursor’s first row, return the no-find
status, and then start again and retrieve the cursor’s last row. Again, an ESQL cursor
retrieves no rows after the nofind status until it is reopened.

Placeholder Variables
When you are using placeholder variables in an OPEN statement, the following rules
apply:

• If a placeholder variable (for example, $P1) occurs in the WHERE clause of a


DECLARE CURSOR, it must also occur in the corresponding OPEN statement.
For example, the $P1 in the DECLARE CURSOR statement must correspond to the
$P1 in the OPEN statement. The order in which $P1 appears in the DECLARE
CURSOR statement does not have to be the order in which $P1 appears in the
OPEN statement. In addition, you can use a placeholder variable more than once in
DECLARE CURSOR, but that variable name does not occur more than once in the
OPEN statement.

7830 8160–027 9–15


OPEN

• The size and data type of the host program variables in the OPEN statement must
match those of variables in the DECLARE CURSOR statement and the application
program.
For example, the application program variable associated with $P1 in the DECLARE
CURSOR statement’s WHERE clause must match the type and size of $P1 in the
OPEN statement. You should usually use the same application program variables in
both the DECLARE CURSOR and OPEN statements. For character value
assignment considerations, see 2.8.1.
• Before you use the OPEN statement, you must initialize the program variables
associated with the placeholder variables.

Routines and Triggers and the OPEN Statement


Before you can use the OPEN statement, the cursor must be defined by a DECLARE
CURSOR statement, specified within the same compound statement as the OPEN or
at an outer level of nesting.

If you attempt to open a cursor that is already opened, RDMS returns an error, as
required by standard SQL. This error terminates the execution of a routine or trigger.

The USING clause is not allowed on OPEN statements in routines or triggers, because
name resolution for the SQL variables and parameters used by a cursor takes place
when the routine or trigger is created. Consequently, placeholder variables and
parameter markers are not allowed in the query-expression portion of the DECLARE
CURSOR statement.

For more information, see “Cursor Pointer” earlier in this subsection. Note that when
cursors are used in routines or triggers, they follow the same rules as those specified
for ESQL.

9–16 7830 8160–027


PREPARE

9.5. PREPARE
Use the PREPARE statement to compile and name an SQL statement during program
execution.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No Yes No I

9.5.1. SQL 92 Syntax (Intermediate Level)


PREPARE statement-name

FROM { :embedded-variable │ string-literal }

where:

statement-name
is the name of the statement you are preparing.

embedded-variable
contains one of the following items:

• A cursor specification in the form


query-specification

[ ORDER BY sort-specification-list │ FOR UPDATE OF column-name-list ]

For the definition of a query specification, see 2.7; for the sort specification list
and column name list, see 7.4.
• One of the following SQL statements:
COMMIT (from an implicit thread only)
DELETE
END THREAD (from an implicit thread only)
INSERT
LOCATE
LOCK
ROLLBACK (from an implicit thread only)
SET AUXINFO
SET STATISTICS
UNLOCK
UPDATE
USE DEFAULT

7830 8160–027 9–17


PREPARE

string-literal
is a quoted character string that contains one of the SQL statements just listed.

9.5.2. Examples
The following example uses a string literal to pass the SQL statement to RDMS:

EXEC SQL PREPARE statement_one


FROM 'update houses all price = price * 1.1' END-EXEC.
EXEC SQL EXECUTE statement_one END-EXEC.

The next example uses an embedded variable that is assigned an SQL statement as its
values:

MOVE 'update houses all price = price * 1.1' TO source-statement.


EXEC SQL PREPARE statement_two FROM :source-statement END-EXEC.
EXEC SQL EXECUTE statement_two END-EXEC.

9.5.3. Rules and Guidelines


Read the following rules and guidelines before using the PREPARE statement.

Process
During program execution, the PREPARE statement compiles, optimizes, and names a
dynamic ESQL statement. This produces a named object statement that is saved for
later execution. Once prepared, a statement can be executed any number of times
using the EXECUTE statement.

Location
You can prepare a dynamic ESQL statement in one object module and execute it in a
different one.

During program compilation, it does not matter whether the PREPARE statement is
encountered before or after an EXECUTE statement referring to the same dynamic
ESQL statement.

The PREPARE statement for a particular dynamic ESQL statement, however, must be
executed before any EXECUTE statement for that statement.

List of PREPARE Statements


Prepared statements are stored in a list maintained by RDMS. The list of prepared
statements is deleted whenever RDMS executes a thread control statement. RDMS
also deletes the list when a thread is rolled back because of a run-time error.

9–18 7830 8160–027


PREPARE

Use and Reuse


If you use the same statement name in more than one PREPARE statement, the last
statement prepared is the only one with that name that actually appears on the list of
prepared statements kept by RDMS. You cannot reuse a statement name if that
statement is also the cursor specification of an opened cursor.

Dynamic ESQL Statement Restrictions


The following restrictions apply for the dynamic ESQL statement:

• It must contain an SQL statement.


• It cannot include either the EXEC SQL prefix or the END-EXEC terminator.
• It cannot include a parameter marker in any select list.
• It cannot include a parameter marker as both operands of a single arithmetic or
comparison operator. For example, ? = ? is invalid.

No EXECUTE Statement
If you use the PREPARE statement to prepare a cursor specification, you do not use
the EXECUTE statement on that statement.

The statement name of a prepared query specification can be used as the statement
name in the ALLOCATE CURSOR statement.

Availability After Execution


Prepared statements are available following the execution of a COMMIT statement
only when the prepared statement is of a query specification for a cursor allocated
with RETENTION specified. Prepared statements are available following the execution
of a rollback only when the prepared statement is of a query specification for a cursor
allocated with RETENTION specified and the thread is read-only.

Prepared statements are not available following the execution of an END THREAD
statement.

7830 8160–027 9–19


PROCEDURE

9.6. PROCEDURE
Use the PROCEDURE statement to define a stored procedure.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No P

9.6.1. SQL Syntax


[ CREATE ] PROCEDURE [schema-name.]routine-name ([parameter [,parameter]...])

[ DYNAMIC RESULT SETS [ max-result-sets ] ]

stored-procedure-statement

Note: The CREATE construct is optional. “CREATE PROCEDURE…” is equivalent


to “PROCEDURE…”

where:
schema-name
is the name of the schema to contain the procedure. If you omit the schema name,
RDMS uses the value you have specified on the USE DEFAULT SCHEMA
statement. If you have not established a default schema name, RDMS uses the
default schema name RDMS or the value of the user ID of the current run,
depending on the value of the UREP configuration attribute
RDMS-DEFAULT-QUALIFIER. For additional information, see the Repository for
ClearPath OS 2200 Administration Guide.

routine-name
is the name of the procedure.
Schema and routine names must be valid names as defined in 2.2.1.

parameter
is the formal definition of a parameter for the procedure, in the form

[ IN │ OUT │ INOUT ] parameter-name data-type

where:
IN
means pass an initial value or values to the procedure. You can use the IN
parameter as the source for a value (for example, in a SET statement, a
WHERE clause, a values list, and so forth). You cannot use an IN parameter as
a target specification (for example, you cannot assign it a value using a SET or
a SELECT statement).

9–20 7830 8160–027


PROCEDURE

When you use the CALL statement to invoke a procedure outside of a routine
or trigger, you can pass a host variable, a placeholder variable, a literal, or the
NULL keyword as an IN parameter. When you use the CALL statement to
invoke a procedure within a routine or trigger, you can pass a parameter name,
an SQL variable, a literal, an arithmetic expression, a datetime expression, a
datetime system function, or the NULL keyword as an IN parameter.

OUT
means return a value or values to the caller after the procedure finishes
executing. You can assign a value to the OUT parameter using a FETCH,
SELECT, or SET statement. You can also assign a value to the OUT parameter
by passing it as an OUT or an INOUT parameter of a nested stored procedure
or function invocation. You can use an OUT parameter as a source value in an
SQL statement. This is an RDMS extension to standard SQL. When you use
the CALL statement to invoke a procedure outside a routine or trigger, you can
pass a host variable or placeholder variable as an OUT parameter. When you
use the CALL statement to invoke a procedure within a routine or trigger, you
can pass an INOUT or OUT parameter name or an SQL variable as an OUT
parameter.

You cannot pass a literal as an OUT parameter. An OUT parameter has an


initial value of NULL and, if a value is not assigned to the OUT parameter, it
returns the value NULL.

INOUT
means pass values both ways, as a source or destination for a value. The
INOUT parameter combines the attributes of the IN and OUT parameters and
thus can be used wherever an IN or OUT parameter can be used. When you
use the CALL statement to invoke a procedure outside of a routine or trigger,
you can pass a host variable or placeholder variable as an INOUT parameter.
When you use the CALL statement to invoke a procedure within a routine or
trigger, you can pass an INOUT or OUT parameter name or an SQL variable as
an INOUT parameter.

You cannot pass a literal as an INOUT parameter. If a value is not assigned to


the INOUT parameter, it returns the input value.

parameter-name
is the name of the parameter, which is then used in the body of the procedure.
The name must be a valid name as defined in 2.2.1. The name of each
parameter must be unique within the set of parameters.

DYNAMIC RESULT SETS max-result-sets


indicates that this function can return result set cursors. The max-result-sets
parameter is optional and specifies the maximum number of result sets that can
be returned from this function on any particular execution. Its value may not
exceed 16. If omitted, max-result-sets is equal to the number of cursors declared
WITH RETURN.

data-type
is any valid data type as defined in 2.8 except data type BLOB.

7830 8160–027 9–21


PROCEDURE

stored-procedure-statement
is the statement that performs the activity for this stored procedure (see 4.12).
Normally this is a compound statement.

9.6.2. Examples
Example 1
Even though it is not enforced for procedures with only one statement, procedures
should start with the BEGIN keyword and end with the END keyword:

PROCEDURE house_schema.update_house_price( )
BEGIN
UPDATE houses SET price = 21000 WHERE price < 20000;
END;

Example 2
This example returns the count of houses under a given maximum price:

PROCEDURE house_schema.select_houses(IN max_price NUMERIC,


OUT how_many NUMERIC)
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;

This procedure contains only one statement and therefore does not have to be
enclosed in a BEGIN ... END pair.

Example 3
This example accepts two input parameters (an integer and a character value), and
then uses these two values when it executes the UPDATE statement. The return
value is a count of the rows in table HOUSES with a specific price.

PROCEDURE house_schema.updateandfindhouses
(IN newprice INTEGER, IN ident CHARACTER, OUT how_many
INTEGER)
BEGIN
UPDATE houses SET price = newprice WHERE hno = ident;
SELECT COUNT(*) INTO how_many FROM houses WHERE price = newprice;
END;

9–22 7830 8160–027


PROCEDURE

Example 4
The following example shows the use of a nested invocation of a stored procedure.
Whenever a data modification occurs for the houses table, a comparable data
modification occurs for the house_backup table.

First, create the stored procedure that is going to be invoked by other routines:

PROCEDURE replicate_ houses


(IN house_number INTEGER, IN modification CHAR(10), OUT status
CHAR(10))
BEGIN
DECLARE cost INTEGER;
DECLARE desc CHAR(20);
DECLARE loc CHAR(20);

SELECT price, description, location INTO cost, desc, loc


FROM houses WHERE hno = house_number;

SET status = ’NOT OK’;

IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;

IF modification = ’UPDATE’
THEN
BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
SET status = ’OK’;
END;
END IF;

IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
SET status = ’OK’;
END;
END IF;

END;

7830 8160–027 9–23


PROCEDURE

Next, create the stored procedures that make use of a nested stored procedure
invocation:

PROCEDURE delete_ houses (IN house_number INTEGER, OUT status CHAR(10))


BEGIN
DELETE FROM houses WHERE hno = house_number;
CALL replicate_houses (house_number, ’DELETE’, status);
END;

PROCEDURE insert_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20), OUT status CHAR(10))
BEGIN
INSERT INTO houses (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
CALL replicate_houses (house_number, ’INSERT’, status);
END;

PROCEDURE update_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20), OUT status CHAR(10))
BEGIN
UPDATE houses SET price = cost, description = desc, location = loc
WHERE hno = house_number;
CALL replicate_houses (house_number, ’UPDATE’, status);
END;

Example 5
This example is the same as the previous example, except a nested invocation of a
stored function is used instead of a stored procedure.

First, create the stored function that is going to be invoked by other routines:

FUNCTION replicate_ houses


(IN house_number INTEGER, IN modification CHAR(10)) RETURNS CHAR(10)
BEGIN
DECLARE cost INTEGER;
DECLARE desc CHAR(20);
DECLARE loc CHAR(20);
DECLARE status CHAR(10);

SELECT price, description, location INTO cost, desc, loc


FROM houses WHERE hno = house_number;

IF modification = ’DELETE’
THEN
BEGIN
DELETE FROM house_backup WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;
IF modification = ’UPDATE’
THEN

9–24 7830 8160–027


PROCEDURE

BEGIN
UPDATE house_backup SET price = cost, description = desc, location =
loc
WHERE hno = house_number;
RETURN ’OK’;
END;
END IF;

IF modification = ’INSERT’
THEN
BEGIN
INSERT INTO house_backup (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
RETURN ’OK’;
END;
END IF;
RETURN ’NOT OK’;
END;

Next, create the stored procedures that make use of a nested stored function
invocation:

PROCEDURE delete_ houses (IN house_number INTEGER, OUT status CHAR(10))


BEGIN
DELETE FROM houses WHERE hno = house_number;
SET status = replicate_houses (house_number, ’DELETE’);
END;

PROCEDURE insert_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20), OUT status CHAR(10))
BEGIN
INSERT INTO houses (hno, price, description, location)
VALUES (house_number, cost, desc, loc);
SET status = replicate_houses (house_number, ’INSERT’);
END;

PROCEDURE update_ houses (IN house_number INTEGER, IN cost INTEGER,


IN desc CHAR(20), IN loc CHAR(20), OUT status CHAR(10))
BEGIN
UPDATE houses SET price = cost, description = desc, location = loc
WHERE hno = house_number;
SET status = replicate_houses (house_number, ’UPDATE’);
END;

7830 8160–027 9–25


PROCEDURE

9.6.3. Rules and Guidelines


Read the following rules and guidelines before using the PROCEDURE statement.

Ownership
You must own the schema in which the procedure is to reside.

DECLARE Statements
All DECLARE statements must immediately follow the BEGIN keyword and precede
other statements. All DECLARE variable statements must precede any DECLARE
CURSOR statements.

No RETURNS Clause or RETURN Statement


The PROCEDURE statement (unlike the FUNCTION statement (see 8.8) has no
RETURNS clause. The RETURN statement is not allowed within the body of the
PROCEDURE statement.

Committing the Run Unit


If you commit the run unit, RDMS stores the procedure in the database. You can
reference it later from any program.

Omitting the Run Unit


If you omit the run unit, the procedure definition is not written to the database.

Reporting
Use the GET PARAMETERS statement to retrieve information about the parameters of
an already defined procedure (see 8.11).

Dropping a Procedure
Use the DROP PROCEDURE statement to remove a stored procedure from the
database (see 7.8).

Nested Invokes
A procedure can invoke other stored procedures or functions. The invoked stored
procedures and functions must have been successfully created prior to being
referenced in a CALL or SET statement. Note that a procedure can invoke itself
(recursive reference).

Variables
Placeholder and host program variables are not allowed in procedures.

9–26 7830 8160–027


PROCEDURE

Threads
The thread in which this statement executes must be update recoverable.

TIP
TIP Session Control must be active before you can create a stored function in a TIP
transaction. For information on establishing TIP Session Control. See the Exec
Installation and Configuration Guide.

Parentheses ( ) and Semicolons ;


You must use parentheses on the PROCEDURE statement, even if the procedure has
no parameters.

Do not use a semicolon on the PROCEDURE or BEGIN statement. Refer to the


examples for the correct use of semicolons.

When using IPF SQL or JDBC, do not put a semicolon at the end of the final END
statement. (Note that the previous examples include the semicolon and, for this
reason only, would not be accepted by RDMS when submitted from an IPF SQL
thread.)

Default Qualifier (Schema Name)


If any statement within the procedure specifies an unqualified table or view name, the
current default qualifier is used as the schema name for the table or view (that is, the
default qualifier at the time of procedure definition).

Default Version
If any statement within the procedure specifies a table or view without a version
name, the version is not determined at procedure definition time. Instead, it is
determined from the current default version name at the time the procedure is
executed.

Security
Normal table security is in effect during the execution of a procedure.

Dynamic Result Sets


Dynamic result sets are not allowed within a trigger, nor can one routine call another
that specifies dynamic result sets. See 4.7 for a description of dynamic result sets.

Comments
When you submit a PROCEDURE/FUNCTION statement from an IPF SQL or JDBC
session, do not include SQL comments in the statement.

7830 8160–027 9–27


PROCEDURE

Saving Procedure Syntax


The PROCEDURE statement saves the procedure syntax in the repository. To report
the syntax, use the following UREP command:

REPORT INCLUDE ATTRIBUTE SYNTAX SQL-ROUTINE routine-name FOR SCHEMA


schema-name.

9–28 7830 8160–027


REVOKE

9.7. REVOKE
Use the REVOKE statement to remove user privileges from a table.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No I/X

9.7.1. SQL 92 Syntax (Intermediate Level)


REVOKE { ALL [ PRIVILEGES ] │ privilege-list }

ON table-specification

FROM user-id-list

RDMS extended syntax


REVOKE {

{ALL PRIVILEGES | privilege-list} ON table-specification

| role-name

FROM user-id-list

where:

ALL PRIVILEGES
removes all previously granted privileges from all user IDs in the FROM clause.

privilege-list
is a list that contains any combination of the following privileges:
DELETE
FETCH
INSERT
REFERENCES
SELECT
UPDATE
Use commas to separate privileges in the list.
FETCH and SELECT are synonyms. FETCH is an extension to standard SQL.
table-specification
is a table name as defined in 2.2.2. The version name, if used, cannot be passed by
a variable.

7830 8160–027 9–29


REVOKE

user-id-list
is a list of user IDs that have access to the table. (The keyword PUBLIC removes
the listed access privileges granted to PUBLIC.)
user-id [ ,user-id ] ...

A user ID can also be a role-name. All the names in the user ID-list must be either
user IDs or role-names. You cannot mix user IDs and role-names in the same
statement.
If a user ID starts with a number, express it as a delimited uppercase identifier, as
illustrated in the following examples:
"1BIG" "2NOT" "3NOR""

RDMS converts lowercase user IDs without delimiters to uppercase.

Role-name
is a role-name as defined in 2.2.6.

9.7.2. Examples
The following example illustrates how to revoke UPDATE and DELETE privileges from
user Jacques on the MASTER.PERSONNEL table:

REVOKE UPDATE, DELETE


ON TABLE master.personnel
FROM Jacques

The following example illustrates how to revoke all privileges from all users (except
those granted privileges individually by user ID) on table HOUSES:

REVOKE ALL PRIVILEGES


ON TABLE houses
FROM PUBLIC

The next example removes user ID JIM from the role named “ROLE-PROGRAMMER”.

REVOKE “ROLE-PROGRAMMER” FROM Jim

The next example removes the fetch privilege, on table houses, from the role named
“ROLE-PROGRAMMER”. Note that when revoking privileges from a role, the
role-name is treated as a user ID.

REVOKE fetch ON houses FROM “ROLE-PROGRAMMER”

9–30 7830 8160–027


REVOKE

9.7.3. Rules and Guidelines


Read the information in this table before using the REVOKE statement.

A thread revoking privileges from a role, on a table or view, must be able to get
exclusive access to the definition of that table or view (as also required by ALTER
TABLE).

It is not possible to revoke privileges from a role, on a table or view, when a cursor is
declared over that table or view.

Qualifier and Version Names


The REVOKE statement uses the thread's default qualifier name, just as other
statements use the default qualifier name. The REVOKE statement ignores default
version names, however.

When you use a version name on the table specification in a REVOKE statement, you
revoke privileges on one version of the table. If you omit a version name, you revoke
privileges on all versions of the table. Note that the REFERENCES privilege applies to
all versions of a table. You cannot specify version names on the REFERENCES
privilege.

For example, suppose two versions of table HOUSES exist, PRODUCTION and
OUTSTATE. The following REVOKE statement revokes privileges for both versions of
the table:

REVOKE SELECT ON houses FROM PUBLIC

On the other hand, if you use the following statement, all system users can look at
HOUSES:OUTSTATE, but only the owner can retrieve from HOUSES:PRODUCTION:

REVOKE SELECT ON houses:production FROM PUBLIC

If you grant privileges to a specific table version, you must name that version when
you want to revoke privileges. Similarly, if you grant privileges without a version name,
the privileges can be revoked only by omitting the version name from the REVOKE
statement. For example, you cannot grant privileges on HOUSES:PRODUCTION and
revoke them on HOUSES (without a version name).

Performance
Using table specifications without version names with the REVOKE statement allows
faster execution.

Auxiliary Information
RDMS returns information to the program indicating whether any privileges were
actually revoked through the auxiliary information variable. For more information,
see the manual for the programming language you are using.

7830 8160–027 9–31


REVOKE

Relationship to GRANT Statement


Use the REVOKE statement to undo previous GRANT statements. Do not use REVOKE
to restrict access for particular users who individually were not given privileges with
the GRANT statement. That is, do not revoke a privilege that you never granted from a
user ID. You can revoke only those privileges granted to specific user IDs.

The only way to revoke privileges granted to many user IDs is to explicitly list those
user IDs in a REVOKE statement. A privilege granted to PUBLIC cannot be individually
revoked from a single user ID, or from a list of user IDs, but only from PUBLIC.

Revoking Privileges on Table with a New Owner


If the owner of a base table grants privileges (GRANT statement with or without the
GRANT OPTION) and later transfers ownership of the base table to another user, all
grantees retain their privileges.

GRANT ALL PRIVILEGES


ON table-specification
TO old-owner-id WITH GRANT OPTION

The new owner can revoke all privileges granted (even indirectly) by the original owner
by using the following statement format:

REVOKE ALL PRIVILEGES


ON table-specification
FROM old-owner-id

This does not apply to views because the ownership of views cannot be changed.

Table Privileges and Views


If you revoke the privileges on a table from the owner of a view based on that table,
the view is automatically dropped.

Table Privileges and Foreign Key


If you revoke the REFERENCES privilege from the owner of a child table of a foreign
key, the foreign key is automatically dropped.

Revoking Column Update Privileges


Update privileges on individual columns of a table are revoked by specifying UPDATE
in the REVOKE statement.

9–32 7830 8160–027


REVOKE

Revoking GRANT OPTION Privilege


You cannot revoke only the GRANT OPTION privilege. If you need to revoke the
GRANT OPTION privilege from a user, you must revoke the privileges that were
granted with the GRANT OPTION privilege.

If you then want the user to have the privileges (but not the GRANT OPTION privilege),
execute the appropriate GRANT statement without the WITH GRANT OPTION clause.

Cascading Privileges Revocation


Using the WITH GRANT OPTION clause can create complex hierarchies of grantees
and grantors for a table. For example, suppose you have users PRES, VPRES,
MANAGE, and SECRET, and that PRES owns the table and executes these statements:

GRANT ALL ON tbl1 TO vpres WITH GRANT OPTION


GRANT ALL ON tbl1 TO secret

Next, VPRES executes the following GRANT statement:

GRANT ALL ON tbl1 TO manage, secret

You now have this network of grants:

What happens if PRES revokes VPRES's privileges with the following REVOKE
statement?

REVOKE ALL ON tbl1 FROM vpres

Not only does VPRES lose privileges, but those privileges granted by VPRES are also
revoked. This means that MANAGE has no privileges to access the table. The
privileges granted by VPRES to SECRET are also revoked, but those granted by PRES
are unaffected. SECRET, therefore, still has full access to the table TBL1.

7830 8160–027 9–33


ROLLBACK

9.8. ROLLBACK
Use the ROLLBACK statement to undo any updates made to the database since the
last thread control statement or rollback.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes* Yes No E/X

* See 9.8.3 on implicit threads.

9.8.1. Syntax
SQL 92 Syntax (Entry Level)
ROLLBACK WORK

RDMS Extended Syntax


{ ROLLBACK [ WORK ] │ OMIT THREAD }

[ KEEP │ REQUEUE │ DISCARD ]

where:

KEEP
directs the operating system to resume its current Integrated Recovery step, even
though RDMS considers the current step finished. This option also directs the
system to keep the recoverable transaction message associated with the thread if
Message Control Bank (MCB) is being used.

REQUEUE
directs the operating system to terminate its current Integrated Recovery step
and requeue the recoverable transaction message associated with the thread if
MCB is being used.

DISCARD
directs the operating system to terminate its current Integrated Recovery step
and queue the recoverable transaction message to the application error program
queue if MCB is being used.

Note: The OMIT THREAD form is not allowed in ESQL.

If you do not specify KEEP, REQUEUE, or DISCARD, the operating system uses the
default Step Control option. For transaction programs, the default option is specified in
the program's VALTAB parameter. For all other programs, the default is REQUEUE
unless the program was connected to TIP before the start of the step, in which case,
the default option specified on the connection to TIP is in effect.

9–34 7830 8160–027


ROLLBACK

UDS Control passes the Step Control message option to ER DMRB$ as the rollback
indicator. For more information about Executive requests (ER), see the Exec
Administration Reference Manual. Unless you are using TIP with MCB, it may not be
relevant to specify this option.

9.8.2. Examples
The following ROLLBACK statement ends the thread’s current step and discards any
updates to the database made since the last thread control statement and begins a
new step. The operating system resumes the current Integrated Recovery step if the
KEEP option was specified or assumed.

ROLLBACK WORK

This ROLLBACK statement ends both the thread’s step and the operating system’s
current Integrated Recovery step and discards both its updates and any transaction
message:

ROLLBACK DISCARD

9.8.3. Rules and Guidelines


Read the following rules and guidelines before using the ROLLBACK statement.

Effect on Locks and Recovery


Rolling back a thread releases all locks except those set by LOCK statements. It also
ends the thread's current step and begins a new one. (In system integrated recovery
terminology, the step may actually be reset instead of terminated, depending on the
Step Control option specified.)

Effect on Cursors
Rolling back a thread closes all cursors except for RETENTION cursors in a read-only
thread. For more information about cursors, see the following:

• 6.1 (ALLOCATE CURSOR)


• 7.4 (DECLARE CURSOR)
• 7.6 (DROP CURSOR)
• 9.4 (OPEN)

Effect on Prepared Statements


Prepared statements are available following the execution of a rollback only when the
prepared statement is of a query specification for a cursor allocated with RETENTION
specified and the thread is read-only.

7830 8160–027 9–35


ROLLBACK

Global Temporary Tables


All records are removed from a global temporary table at rollback, unless the table
was created with ON ROLLBACK PRESERVE ROWS specified. If the rollback occurs
during an update of a temporary table, all records are removed from that table,
regardless of whether ON ROLLBACK PRESERVE ROWS was specified.

Implicit Threads and Prepared ROLLBACK Statements


You can prepare and execute a ROLLBACK statement only from an implicit thread
(see 6.4).

Indications for Use


You can use the ROLLBACK statement in application programs that use relational
statements in the following two situations:

• While several updates to the database are being performed, an unexpected error
occurs. You may want to commit the changes only if all of the changes can be
applied. If any updates are unsuccessful, you can use the ROLLBACK statement to
discard all updates the step makes.
• After making temporary updates to generate “what-if” reports, you can discard all
changes to the database with a ROLLBACK statement.

Errors
If an error occurs on a ROLLBACK statement, you must terminate the thread with an
END THREAD statement before submitting further SQL statements (whether the
thread is implicit or explicit).

9–36 7830 8160–027


SELECT Multirow

9.9. SELECT Multirow


Use the SELECT Multirow statement from the IPF SQL Interface to retrieve and display
zero, one, or more rows without having to declare, open, repeatedly fetch from, and
drop a cursor. For more information, see the RDMS and IPF SQL End Use Guide.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
IPF SQL only No No No No F/X

9.9.1. RDMS Extended Syntax


The syntax of the SELECT Multirow statement is a query specification with optional
clauses. See 2.7.1.

query-specification

[ ORDER BY sort-specification-list ]

[ FETCH FIRST m ROWS ONLY ]

[ OPTIMIZE FOR p ROWS ]

query-specification

is a query specification as defined in 2.7, except that it cannot contain an


embedded variable, parameter marker, or placeholder variable.
With the IPF SQL interface, the SELECT statement fails if any columns contain BLOB
data. BLOB data is not supported with the IPF SQL interface.

9.9.2. Example
In the following example, IPF SQL displays all rows in table HOUSES, where the house
is worth more than $50,000:

SELECT *
FROM houses
WHERE price > 50000

7830 8160–027 9–37


SELECT Single Row

9.10. SELECT Single Row


Use the SELECT Single Row statement to retrieve one row without having to declare,
open, fetch from, and drop a cursor.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes No Yes No E/X

* Not IPF SQL

9.10.1. Syntax
SQL 92 Syntax (Entry Level)
SELECT [ ALL │ DISTINCT ] { select-list │ * }

INTO variable-specification-list

FROM table-specification-list

[ WHERE Boolean-expression ]

RDMS Extended Syntax


SELECT [ ALL │ DISTINCT ] { select-list │ * }

FROM table-specification-list

[ WHERE Boolean-expression ]

[ GROUP BY group-by-item [, group-by-item]...

[ HAVING Boolean-expression ]

[ FETCH FIRST 1 ROW ONLY ]

INTO variable-specification-list

where:

group-by-item

is

{ column-specification | scalar-bif-reference }

ORDER BY

is allowed only in conjunction with FETCH FIRST 1 ROW ONLY.

9–38 7830 8160–027


SELECT Single Row

Syntax When Used in Routines or Triggers


SELECT [ ALL │ DISTINCT ] { select-list │ * }

INTO variable-specification-list

FROM table-specification-list

[ WHERE Boolean-expression ]

[ FETCH FIRST 1 ROW ONLY ]

ORDER BY is allowed only in conjunction with FETCH FIRST 1 ROW ONLY.

FETCH FIRST 1 ROW ONLY


The presence of this clause on the singleton select statement inhibits the ESQL
and Stored Procedure cardinality check. This improves performance, unless the
cardinality check was not being done (for example, the WHERE clause specified all
columns of the primary key with equality operators). Use of this clause means that
an error status is not returned if the evaluation of the FROM, WHERE, GROUP BY,
and HAVING clauses results in more than one record. The keyword ROWS can be
used in place of ROW.

See 2.7.1 for a description of the SELECT statement and its parameters and 2.10 for
details about variables. Use commas to separate variables in the list.

In a routine, the variable-specification-list is a list of parameter and SQL variable


names. See 4.12.7.

9.10.2. Examples
These examples use data from the CUSTOMERS and HOUSES tables in 1.2.2.

Example 1
In the following example, the host program variables receive the data items for house
H101:

EXEC SQL SELECT hno, location, price, description


INTO :house, :locn, :houseprice, :housedesc
FROM houses
WHERE hno = 'H101'
END-EXEC.

Example 2
The next example looks for a customer with a price range that matches listed house
prices:

SELECT cno, cname, maxprice


INTO $p1, $p2, $p3
FROM customers, houses
WHERE houses.price <= customers.maxprice

7830 8160–027 9–39


SELECT Single Row

You retrieve the following row, which is one of several that satisfies the WHERE
clause:

C101 Thompson 15000.

Example 3
To determine how many rows table HOUSES contains, you can execute this
statement:

SELECT COUNT(*)
INTO $p1
FROM houses

Because table HOUSES has five rows, $P1 receives the value 5.

9.10.3. Rules and Guidelines


Read the following rules and guidelines before using the SELECT Single Row
statement.

Indications for Use


The SELECT Single Row statement, like the DECLARE CURSOR statement, can specify
any combination of columns and tables. A typical use of the SELECT Single Row
statement is to select one row from one table using the primary key. If you want to
retrieve more than one row, use the DECLARE CURSOR and FETCH statements.

Relationship to Other Syntax


The SELECT, FROM, WHERE, GROUP BY, and HAVING clauses are the same as for the
query specification (see 2.7). The INTO clause is the same as for the FETCH statement
(see 8.6).

Handling Variables
If the expression in the WHERE clause includes placeholder or embedded variables,
you must first assign a value to the host program variables that correspond to the
placeholder variables.

This is different from the DECLARE CURSOR statement. With the DECLARE CURSOR
statement, you supply the values for a placeholder variable in a subsequent OPEN
statement.

9–40 7830 8160–027


SELECT Single Row

Interpreter Interface Compared to ESQL


In the interpreter interface, if the WHERE clause does not identify a single row (such
as WHERE CUSTOMERS.MAXPRICE > 1), the retrieved row is the first one found. If you
execute the same SELECT statement again, you always receive the same row.

However, if you execute a SELECT Single Row statement from ESQL, the evaluation of
the FROM, WHERE, GROUP BY, and HAVING clauses must result in 0 or 1 rows.
Otherwise, RDMS returns an error.

RDMS returns the following statuses for valid, nonerror conditions:

• When no rows are returned, RDMS returns a 6001 no-find error status or an
SQLCODE of +100 (see C.3).
• When one row is returned, RDMS returns an error status or an SQLCODE of zero.

SELECT Single Row Statement Compared to IPF SQL SELECT


Multirow Statement
Do not confuse the SELECT Single Row statement with the IPF SQL SELECT Multirow
statement, which can return multiple rows (see 9.9). You cannot use the SELECT
Multirow statement from a third-generation-language program.

7830 8160–027 9–41


SET

9.11. SET
Use the nonstandard SET statement to invoke a previously defined stored function
and assign values returned by the function to a host program variable, placeholder
variable, or (within a routine or trigger) an SQL variable.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes No X

9.11.1. Syntax
RDMS Extended Syntax
SET return-variable = [schema-name.]routine-name

([ parameter [ ,parameter ] ...]) [UPDATE COUNT OFF]

Syntax When Used in Routines or Triggers


SET return-variable = [schema-name.]routine-name

([ parameter [ ,parameter ] ...])

where:

return-variable
is a host program variable or placeholder variable into which the function writes
the return value. The data type of the return variable must be compatible with the
data type of the RETURNS clause of the function definition (see 8.8).
When used in a routine, the return-variable is an SQL variable or parameter.
When used in a trigger, the return-variable is an SQL variable. If used in a BEFORE
ROW trigger, the return-variable is a new row correlation-name.

schema-name
is the name of the schema that contains the function.

routine-name
is the name of the function. Schema and routine names must be valid names as
defined in 2.2.1.

parameter
is the parameter or parameters to pass to the function. The number and type of
parameters specified here must match the number and type of parameters on the
function declaration. When a SET statement is used outside of a routine or trigger,
you can use indicator variables as parameters for specifying or retrieving null
values. The use of indicator variables in a function invocation is identical to their
use in any other context. When a SET statement is used within a routine or trigger,
indicator variables may not be used. Valid values for parameters depend on the
type of formal parameter.

9–42 7830 8160–027


SET

The actual parameter passed from the calling program, routine, or trigger must be
as indicated for the parameter in the procedure declaration. For more information,
see 5.2.
UPDATE COUNT OFF
For this CALL or SET, the specification of UPDATE COUNT OFF on the CALL or SET
statement overrides a global SET RESULT SET UPDATE COUNT ON statement.
UPDATE COUNT OFF is not allowed in stored procedures or triggers or in ESQL.
You can refer to the function declaration or use the GET PARAMETERS statement to
determine the formal type of each parameter.

You must initialize the variables used as IN and INOUT parameters to valid values
before executing the SET statement. RDMS returns an error on an uninitialized input
parameter if its contents are not legal for its data type.

You must use the parentheses in all cases, even if the function has no parameters.

9.11.2. Example
In the following example, the function SELECT_HOUSES returns the number of houses
that meet the criteria in placeholder variable $P2 and places that value in the
placeholder variable $P1.

This is the function declaration:

FUNCTION house_schema.select_houses(IN max_price NUMERIC)


RETURNS NUMERIC
BEGIN
DECLARE how_many INTEGER;
SELECT COUNT(*) INTO how_many FROM houses WHERE price < max_price;
RETURN how_many;
END;

This is the function invocation:

SET $p1=house_schema.select_houses($p2);

9.11.3. Rules and Guidelines


Read the following rules and guidelines before using the SET statement.

Nested SET Statements


You can use a SET statement to invoke a function within a routine or trigger. The
invoked function must have been successfully created prior to its reference, or it must
be the same as the function being defined (recursive reference).

7830 8160–027 9–43


SET

Standard and Nonstandard SET Statements


Use this nonstandard SET statement in a host language program (such as COBOL) to
invoke a stored function.

Use the standard SET statement in a routine or trigger to invoke a stored function.

Use the standard SET statement (see 9.11) in a routine or trigger to assign a value to a
variable or parameter.

Invoking Functions and Procedures


Use this SET statement to invoke a stored function. Use the CALL statement to invoke
a stored procedure.

Errors
If an error occurs during the execution of a routine or trigger, control returns
immediately to the caller. The caller must examine the error variable for more
information (refer to Appendix B and Appendix D).

9–44 7830 8160–027


SET AUXINFO

9.12. SET AUXINFO


Use the SET AUXINFO statement to direct RDMS to return page and record count,
record count, or no count for UPDATE, DELETE, UNLOAD, REVOKE, LOCATE, and
INSERT statements.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No Yes No No X

9.12.1. RDMS Extended Syntax


SET AUXINFO { OFF | RECORD COUNT | PAGE COUNT }

where:

OFF
indicates no count returned in the auxiliary information parameter.

RECORD COUNT
requests only the record count returned in the auxiliary information parameter.
(This is the default.)

PAGE COUNT
requests the page count returned in H1 of the auxiliary information parameter and
record count returned in H2.

9.12.2. Example
The following example directs RDMS to return an auxiliary information parameter
value showing the page count and the record count returned on succeeding
statements where appropriate:

SET AUXINFO PAGE COUNT

9.12.3. Rules and Guidelines


SET AUXINFO provides a mechanism whereby an application can obtain the number of
updated pages. Knowing the number of updated pages allows for a more reliable
prediction of the appropriate commit processing points in order to remain under the
Audit Only Recovery (AOR) limit. It reduces the number of possible retention file I/Os
and allows the updating applications to reduce possible locking interaction with other
updating applications.

Use of SET AUXINFO in static ESQL has no worthwhile effect. In order to obtain the
desired count information, it must be used in either dynamic ESQL or the interpreter
interface.

7830 8160–027 9–45


SET AUXINFO

9.12.4. Host Language Examples for Declaring Aux-Info


When requesting page and record count (SET AUXINFO PAGE COUNT), it is necessary
to declare the auxinfo variable in such a way that each half can be accessed by your
program.

Note: Do not send AUXINFO as anything other than an elementary data item;
otherwise, RDMS rejects it.

UCS COBOL
01 aux-info PIC S9(9) BINARY
01 aux-inf REDEFINES aux-info.
02 aux-info-page-count PIC S9(5) USAGE BINARY.
02 aux-info-rec-count PIC S9(5) USAGE BINARY.

If you are using the ESQL interface, aux-info should be defined as follows:

01 RDMCA.
02 ERROR-STATUS PIC 9(4).
02 aux-info PICS9(9)BINARY.
02 aux-inf REDEFINES aux-info.
03 aux-info-page-count PIC S9(5)USAGE BINARY.
03 aux-info-rec-count PIC S9(5) USAGE BINARY.

ASCII COBOL
01 aux-info PIC S9(10) USAGE COMP.
01 aux-inf REDEFINES aux-info.
02 aux-info-page-count PIC S9(5) USAGE COMP.
02 aux-info-rec-count PIC S9(5) USAGE COMP.

UCS C
int aux_info=0;
int aux_pages=0;
int aux_recs=0;
long aux;
aux=aux_info;
aux_pages=aux_info>>18;
aux_recs=aux_info & 0777777;

UCS FORTRAN
INTEGER auxinfo, auxpgs, auxrec
auxpgs=BITS(auxinf,1,18)
auxrec=BITS(auxinf,19,18)

9–46 7830 8160–027


SET RESULT SET

9.13. SET RESULT SET


Use the SET RESULT SET statement to indicate whether you want to receive dynamic
result sets from stored procedure calls.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No No No No X

SET UPDATE COUNT ON can be overridden on the SET return-variable = ... and
CALL statements by including the syntax UPDATE COUNT OFF.

9.13.1. RDMS Extended Syntax


SET RESULT SET [ UPDATE COUNT ] { ON | OFF }

9.13.2. Examples
SET RESULT SET ON

SET RESULT SET UPDATE COUNT ON

9.13.3. Rules and Guidelines


Read the following rules and guidelines before using the SET RESULT SET statement.

Usage
See 4.7 for a description of dynamic result sets.

Scope
The SET RESULT SET statement is only available through the interpreter interface.

Restrictions
SET RESULT SET UPDATE COUNT ON can only be issued if SET RESULT SET ON has
already been issued.

If both SET RESULT SET and SET RESULT SET UPDATE COUNT have been turned on,
the statement SET RESULT SET OFF turns UPDATE COUNT off as well.

Update Counts
Callers may want to know how many records were affected by each insert, update, or
delete performed by a stored procedure. By turning on UPDATE COUNT, you are
requesting RDMS to insert a record into its temporary result set table that indicates
the line number and the number of records affected each time the stored procedure
performs an INSERT, UPDATE, or DELETE statement.

7830 8160–027 9–47


SET RESULT SET

For example, a result set could contain the following information.

line_ update_ return_cursor_ schema_


number count name name routine_name

22 55 SCH OUTER_PROC
27 1 SCH INNER_PROC

These results indicate that 55 records were affected by the statement at line 22 of the
procedure OUTER_PROC, and just one record was affected by the statement at line 27
of the nested procedure INNER_PROC.

If both update counts and return cursors are produced by a stored procedure
execution, all of the update count records are returned first.

9–48 7830 8160–027


SET SKIPGENERATED

9.14. SET SKIPGENERATED


Use the SET SKIPGENERATED statement to direct RDMS to enable individual programs
to have control over whether or not records inserted (for example, at the right-hand
side of the b-tree) into tables that contain generated default columns are to be
skipped by other transactions.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes No Yes No No X

9.14.1. RDMS Extended Syntax


SET SKIPGENERATED { ON | OFF }

9.14.2. Example
The table T contains an identity column. It is the value of the IDENTITY column that we
specify in the following examples. Runs are named A, B, and C.

DECLARE C1 CURSOR AS SELECT * FROM T.

The execution of runs A, B, and C were interleaved as shown in the following table.
The execution flows from left to right. Therefore, run A inserts value 1, followed by
run B which inserts value 2, followed again by run A which inserts value 3, and so on.

At this point, no run has committed.

1 2 3 4 5 6 7
A B A B C B A

The following table shows what is fetched from cursor C1, doing a brute force search
of the primary key b-tree that scans records from left to right starting from the record
with value 1. Given the specified value of SKIPGENERATED, ignore the deadlocks
caused by this fetching. Assume that fetching of each line of the table is independent
of every other.

Run SET OFF SET ON SET OFF. Lock on conflict return.


A 1; QUEUE on run B 1, 3, 7 1
B QUEUE on run A 2, 4, 6 Lock conflict
C QUEUE on run A 5 Lock conflict

7830 8160–027 9–49


SET SKIPGENERATED

Assume that run A has committed, but runs B and C are still uncommitted. * indicates
a record that is committed. The fact that run A has committed, does not change
anything with its own selects.

1 2 3 4 5 6 7
* B * B C B *

Run SET OFF SET ON SET OFF. Lock on conflict return.


A 1; QUEUE on run B 1, 3, 7 1, lock conflict
B 1, 2, 3, 4; queue on C 1,2,3,4, 6,7 1, 2, 3, 4, lock conflict
C 1; QUEUE on run B 1, 3, 5, 7 1, lock conflict

9.14.3. Rules and Guidelines


The default is ON. For example, records appended to the end of the b-tree are
skipped, if they have not yet been committed. OFF indicates that records must not be
skipped.

SKIPGENERATED ON is effective (skips records) only when

• the storage-area specifies LOCK-STRATEGY RECORD.


• the application group is a local application group (as opposed to a concurrent
application group using XPC).
To cause a search to terminate when it encounters an uncommitted record, inserted
by another thread, LOCK the table ON CONFLICT RETURN. This works only if the
cursor is scrollable (that is, only a single record is fetched at a time).

9–50 7830 8160–027


SET STATISTICS

9.15. SET STATISTICS


Use the SET STATISTICS statement to direct RDMS to use or stop using previously
collected statistics in determining cursor access paths.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes Yes No X

9.15.1. RDMS Extended Syntax


SET STATISTICS { ON │ OFF }

9.15.2. Example
The following example directs RDMS to use a previously collected set of statistics:

SET STATISTICS ON

9.15.3. Rules and Guidelines


Read the following rules and guidelines before using the SET STATISTICS statement.

Statistics On or Off?
Statistics use is on or off based on the value of the UREP configuration attribute
RDMS-SET-STATISTICS-DEFAULT. If that value is OFF, RDMS does not use statistics
unless you execute a SET STATISTICS ON statement.

When statistics is turned on, RDMS uses the most recently collected set of statistics
to optimize access paths (the frequency of collection is determined by the database
administrator).

When statistics is turned off, RDMS determines access paths by using a general set of
assumptions.

Suggested Use
The use of statistics on a query specification that refers to some tables for which
statistics were gathered and some for which statistics were not gathered can result in
a poorly chosen access path.

If you have not gathered statistics, use SET STATISTICS OFF. If you use SET
STATISTICS ON, RDMS must spend time looking up the statistics.

Obtaining Statistics
Statistics on table contents are gathered by the RUN STATISTICS statement of the
RDMUTL processor. For more information about the RDMUTL processor, see the
Relational Database Server for ClearPath OS 2200 Administration Guide.

7830 8160–027 9–51


SET STATISTICS

Scope
When used in the interpreter interface or dynamic ESQL, the SET STATISTICS
statement turns statistics use on or off for interpreter interface or dynamic ESQL
statements that are executed after the SET STATISTICS statement, until the thread is
ended or until another SET STATISTICS statement is executed, whichever occurs first.

When used in static ESQL, the SET STATISTICS statement turns statistics use on or off
for static ESQL statements that follow it in the source code but that precede any other
static ESQL SET STATISTICS statements in the source code.

The access path of a cursor is determined only when it is declared, not when it is
opened or fetched. This means that the SET STATISTICS statement, when used before
a DECLARE statement, affects all further use of that cursor, even if the use of
statistics is changed before the cursor is opened or fetched.

In ESQL, the access path of a statically declared cursor is determined during program
compilation, which means that interpreter or dynamic use of SET STATISTICS during
program execution has no effect on a static ESQL cursor.

9–52 7830 8160–027


Section 10
SQL Statements UNLOAD Through
WHENEVER

This section contains reference information about the following SQL statements:

• UNLOAD (10.1)
• UNLOCK (10.2)
• UPDATE ALL (10.3)
• UPDATE Positioned (10.4)
• UPDATE Searched (10.5)
• UPDATE SYNCHRONIZE (10.6)
• UPDATE VALUES (10.7)
• USE DEFAULT (10.8)
• WHENEVER (10.9)

7830 8160–027 10–1


UNLOAD

10.1. UNLOAD
Use the UNLOAD statement to dump selected rows into a system data format (SDF)
file.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes No Yes Yes X

10.1.1. RDMS Extended Syntax


UNLOAD TO [ SDF | PCIOS ] FILE file-name [ , file-name2 ]

[ USING { SDFO | IO } ] { FROM CURSOR cursor-name |

query-expression [ ORDER BY sort-specification-list ] }

[ FORMAT { EXTERNAL | [ position-and-null-list ] | INTERNAL |

MAPPER | TAB | COMMA | PIPE | CSV } ]

[ WITHOUT DESCRIPTION | WITH DESCRIPTION [ ONLY ] ]

where:
SDF
directs RDMS to create a file with SDF images and SDF control words. This is the
default. The SDF file type may be generated USING SDFO or USING IO.

PCIOS
directs RDMS to create a file with PCIOS images and PCIOS control words. The
PCIOS file type may be generated USING IO.

file-name
is an existing Exec mass storage or tape file name. (Since certain characters, like
the hyphen, are allowed in a file name but not in an RDMS name, enclose the file
name in quotation marks.) The file name should not be more than 30 characters. If
the file name is longer than 30 characters, attach a USE name (@USE) to the file
before executing this statement.

If the file is a tape file, you must use the USING SDFO clause.

file-name2
is an Exec large program file. (The same naming rules apply as for file-name
except that tape files are not allowed, no file cycle is allowed, and the implicit file
cycle must be 1.) RDMS stores BLOB data as omnibus elements in this file. This is
true regardless of the size of the BLOB or whether the BLOB is stored in the
record or in an RDMS LOB storage-area. A large program file has a limit of 26,146
elements. When performing an UNLOAD of a filename with the maximum of 12
characters, you must catalog the filename with 0 to 7 characters of your choice
and with the last 5 characters 00001.

10–2 7830 8160–027


UNLOAD

The format of the file name is as follows:

qualifier*0-to-7-character-file-name00001.

The following example names are valid for file-name2:

00001

A00001

OUTBLOB00001

ABCDEFG00001

The following example names are illegal for file-name2:

MYBLOBFILE00001 (too many characters)

A0001 (too few digits)

A00002 (last digit must be 1)

RDMS uses the numeric portion of the name as a counter.

When the BLOB data requires more than one program file, RDMS looks for a file
with the same name, ending with 00002, then 00003, and so on, up to a limit of
64000, the maximum number of files that can be cataloged in a system. You can
catalog as many files as are required to store the BLOB data.

RDMS first tries to @ASG the file. If it does not exist, RDMS then catalogs the file
using the maximum size of a large program file with no initial reserve. If you want
to set initial reserve, you must catalog the file yourself. When cataloging a file, you
must catalog the file using positions instead of tracks.

Each omnibus element can hold up to 29,360,016 bytes:

777,777 sectors * 28 words per sector * 4 bytes per word


8

RDMS creates multiple elements for a BLOB when required.

To calculate the number of files required to unload BLOB data, use the following
formula:

bytes-per-row Sum of the declared lengths of all the BLOB columns in


the table
bytes-per-table Number of data rows in the table times bytes-per-row
files-required-1 bytes-per-table divided by 120,258,625,536
files-required-2 (Number of data rows in the table times the number of
BLOB columns) divided by 26,136

The larger of files-required-1 and files-required-2 is the total number of files


needed to UNLOAD the BLOB data in the table.

7830 8160–027 10–3


UNLOAD

If the result of the division has any fractional part, round the value up to the next
whole number. The end result is the number of files required to store the BLOB
values for the table.

SDFO
directs RDMS to use the SLIB routine SDFO to write the images to the file. SDFO
can only generate an SDF file type. You must use this clause for a tape file.

IO
directs RDMS to use ER IO$ to write images to the file. This is the default. IO can
generate either SDF or PCIOS file types.

cursor-name
is the name of a declared cursor (see 7.4).

query-expression
is a query that can include query specifications, the set operators UNION and
UNION ALL, and query terms, in the form

{ query-term │ query-expression UNION [ ALL ] query-term }

where:
query-term
is a separate query specification, or a subexpression in parentheses, of the
query expression in the form

{ query-specification │ (query-expression) }

where query-specification is as defined in 2.7.

UNION [ALL]
lets you derive a result table by combining two other result tables. The result
of a UNION operation is the set of all rows in either tables with duplicate rows
eliminated. Two rows are duplicates if each value in the first is equal to the
corresponding value in the second. Two null values are considered equal. The
result of a UNION ALL operation contains all rows from both tables.

Set operations cannot be nested by parentheses deeper than 10 levels. The


select lists of the UNION operands can contain only column names; arithmetic
or function expressions are not allowed. Descriptions of UNION operands
must be identical. Corresponding columns in the UNION operands must have
matching data types and must both allow or not allow nulls, as the case may
be. UNION operands of type CHARACTER must have identical character set
and collation definitions to be mutually comparable.

The resulting columns have no associated column names; therefore,


ORDER BY clauses must use unsigned integers.

sort-specification-list
is a list of column-specifications or ordinal numbers (see 7.4).

10–4 7830 8160–027


UNLOAD

EXTERNAL
(default) directs RDMS to convert retrieved items into ASCII display format. RDMS
places the data items of each column in the file according to how you specify
them in the position-and-null list.

External files are suitable for transfer to other systems. RDMS tables can be
loaded from EXTERNAL format files; however, the INTERNAL format is more
efficient.

position-and-null-list
specifies how to format the output file. A position-and-null statement specifies
the range of print columns into which RDMS places a data value in an SDF output
file and also explains how to represent nulls in that file. The list is a sequence of
positions-and-null specifications separated by commas.

Each position-and-null specification corresponds to one data column named in the


SELECT clause, in the form

[ start-column [ :end-column ] [ NULL IS string-literal ] ]

where:

start-column and end-column


are print column numbers which delimit the portion of the output line into
which the item's value is to be written. The values for start-column and
end-column must be positive integers, expressed as either integer
constants or variable specifications.

Be careful not to overlap the item position of one data item with that of
another. You must allocate enough CHARACTER columns to accommodate
the longest possible value of the data item. For example, if you defined a
column to be 40 characters in the CREATE TABLE statement, you must
allocate at least 40 characters for it in the item position. If you do not
specify end-column, the end column is determined by the length of the
data item (plus 1 for the decimal point if the item is a decimal) as defined
in 6.10.

NULL IS string-literal
is the character string to place in the output file whenever nulls are
encountered in data columns. If omitted, blanks are inserted if nulls are
encountered.

If the NULL IS clause is for a BLOB column, the string-literal to place in the
output file must not start with a number.

List the item positions in the same order in which the columns are specified in the
SELECT clause of the UNLOAD or DECLARE CURSOR statement.

7830 8160–027 10–5


UNLOAD

INTERNAL
directs RDMS to format values in the file in a way that is internal to RDMS. The
section on the RDMUTL processor in the Relational Database Server for
ClearPath OS 2200 Administration Guide further describes this format.
INTERNAL format files can be used only as input to the RDMUTL LOAD statement.

MAPPER
directs RDMS to use the length of each data item to determine its CHARACTER
column range and to prefix each data item's value with a tab character. This makes
the output file suitable for input to the MAPPER RETRIEVE function (with the P
option).

TAB
directs RDMS to prefix each data item value with a tab character. The TAB
keyword is synonymous with MAPPER.

COMMA
directs RDMS to separate data item values with commas.

PIPE
directs RDMS to separate data item values with the pipe ( | ) character (vertical
bar).

WITHOUT DESCRIPTION
(default) directs RDMS not to place a description of the data into the output file.

WITH DESCRIPTION [ONLY]


directs RDMS to prefix the output file with a description of the data. If the ONLY
option is used, the output file has the description only; no data is unloaded to the
file.

Note: For DECIMAL columns defined in an owned schema, the number of


decimal digits is one greater than the number of decimal digits in the original
definition. This is because of the difference in the semantics of this value
between the SQL standard and RDMS. For more information, see 2.8.2.

For a description of the WITH DESCRIPTION clause output, see "WITH


DESCRIPTION clause" in 10.1.3.

CSV
comma-separated values; directs RDMS to separate data item values with
commas, removing any unnecessary leading and trailing spaces. Data item values
are delimited by double quotes if needed. CSV format only works with USING IO
(the default). If using PCIOS as the file type, up to three extra spaces may be
added following the last data item value of each record. If WITH DESCRIPTION is
specified, the column position of the data item values are the maximum values.

10–6 7830 8160–027


UNLOAD

10.1.2. Examples
Example 1
The following example does not specify a format. It unloads all columns from table
S1.CUSTOMERS to file CUSTOMERS2. RDMS uses the EXTERNAL format for the files
because the example does not specify a format.

UNLOAD TO FILE "customers2"


SELECT *
FROM s1.customers
WITH DESCRIPTION

The resulting output file is as follows:

>DESCRIPTION<
1 C4 1:4 S1.CUSTOMERS:PRODUCTION.CNO
2 C28 6:33 S1.CUSTOMERS:PRODUCTION.CNAME
3 D12.0 35:46 S1.CUSTOMERS:PRODUCTION.MAXPRICE
4 C40 48:87 S1.CUSTOMERS:PRODUCTION.DESIREDLOC
>END DESCRIPTION<
C101 Thompson 150000 Woodbury
C102 Owen 70000 New London
C103 Johnson 90000 Woodbury
C104 Jones 100000
C105 Smith 120000 Westchester

Customer C104 has no desired location; therefore, column DESIREDLOC is null. Since
the representation for nulls is not specified, all spaces is used by default.

Example 2
This example uses INTERNAL format with description:

UNLOAD TO FILE "customers1"


SELECT hno,location,price
FROM s1.houses
FORMAT INTERNAL
WITH DESCRIPTION

The resulting output file is as follows:

>DESCRIPTION<
1 C4 1:4 S1.HOUSES:PRODUCTION.HNO
2 C28 5:32 S1.HOUSES:PRODUCTION.LOCATION
3 D14.2 33:46 S1.HOUSES:PRODUCTION.PRICE
0 C3 47:49 NULL INDICATOR BYTES
>END DESCRIPTION<
H101Woodbury +0000013000000~~~
H102Woodbury +0000004000000~~~
H103Westchester +0000009000000~~~
H104 +0000008500000~N~
H105Turtle Creek +0000011000000~~~

7830 8160–027 10–7


UNLOAD

The values in the price columns do not contain a decimal point because RDMS does
not explicitly format decimal points in INTERNAL format. In addition, a plus sign and
leading zeros are explicit in INTERNAL format.

The characters in columns 47 to 49 of the file are null indicator bytes. The location
column for house H104 contains a null.

Example 3
This example selects columns MAXPRICE, CNAME, and DESIREDLOC from table
CUSTOMERS in the illustrated format:

UNLOAD TO FILE "customers3"


SELECT maxprice,cname,desiredloc
FROM s1.customers
FORMAT EXTERNAL 3:15,18:46,49:90 NULL IS 'XXXXXXXX'
WITH DESCRIPTION

The resulting output file is as follows:

>DESCRIPTION<
1 D12.0 4:15 S1.CUSTOMERS:PRODUCTION.MAXPRICE
2 C28 18:45 S1.CUSTOMERS:PRODUCTION.CNAME
3 C40 49:88 S1.CUSTOMERS:PRODUCTION.DESIREDLOC
>END DESCRIPTION<
150000 Thompson Woodbury
70000 Owen New London
90000 Johnson Woodbury
100000 Jones XXXXXXXX
120000 Smith Westchester

Customer Jones has no desired location; therefore, column DESIREDLOC is null. The
null is represented by XXXXXXXX, as specified in the UNLOAD statement.

Example 4
This example unloads a join of tables HOUSES and CUSTOMERS. It lists all houses for
each customer where the price of the house is not more than the customer’s
maximum price and the house itself is located in the customer's desired location.

Since the bank currently requires a minimum down payment of 6.85 percent, this
example also includes the minimum down payment to purchase each house. To
unload this information into a file, enter the following DECLARE CURSOR and UNLOAD
statements:

DECLARE join CURSOR


SELECT cname AS "Customer Name", hno AS "House #", location, price,
price * 0.0685 AS "Min Down Pymt"
FROM customers c, houses h
WHERE h.price <= c.maxprice AND h.location = c.desiredloc
ORDER BY cname

UNLOAD TO FILE "customers4"

10–8 7830 8160–027


UNLOAD

FROM CURSOR join


FORMAT EXTERNAL
WITH DESCRIPTION

The resulting output file is as follows:

>DESCRIPTION<
1 C28 1:28 Customer Name
2 C4 30:33 House #
3 C28 35:62 RDMS.HOUSES:PRODUCTION.LOCATION
4 D15.2 64:78 RDMS.HOUSES:PRODUCTION.PRICE
5 D20.6 80:99 Min Down Pymt
>END DESCRIPTION<
Johnson H102 Woodbury 40000.00
2740.000000
Smith H103 Westchester 90000.00
6165.000000
Thompson H102 Woodbury 40000.00
2740.000000
Thompson H101 Woodbury 130000.00
8905.000000

This example also illustrates how a title name appears in the description portion of the
output.

Example 5
This example contains an additional BLOB column ‘picture’ in table HOUSES. The
UNLOAD statement selects HNO, LOCATION, PRICE, and PICTURE from table
HOUSES. See the Relational Database Server for ClearPath OS 2200 Administration
Guide for the content of an SDF file internal lob-id and an SDF file external lob-id.

UNLOAD TO FILE "customers5", "bloba00001"


SELECT hno, location, price, picture
FROM s1.houses
FORMAT EXTERNAL 3:6, 8:35, 37:50, 52:75
WITH DESCRIPTION

7830 8160–027 10–9


UNLOAD

The resulting output file is as follows:

>DESCRIPTION<
1 C4 3:6 S1.HOUSES:PRODUCTION.HNO
2 C28 8:35 S1.HOUSES:PRODUCTION.LOCATION
3 D14.2 37:50 S1.HOUSES:PRODUCTION.PRICE
4 L35M 52:75 S1.HOUSES:PRODUCTION.PICTURE
>END DESCRIPTION<
H101 Woodbury 130000.00 200001 0021
H102 Woodbury 40000.00 200001 0022
H103 Westchester 90000.00 200001 0023
H104 Parkway Heights 85000.00 200001 0024
H105 Turtle Creek 110000.00 200001 0025

For clarity, here is a layout in a table form.

3 6 8 35 37 50 52 75
H101 Woodbury 130000.00 200001 0021 (Ext. lob-id)
H102 Woodbury 40000.00 200001 0022 (Ext. lob-id)
H103 Westchester 90000.00 200001 0023 (Ext. lob-id)
H104 Parkway Heights 85000.00 200001 0024 (Ext. lob-id)
H105 Turtle Creek 110000.00 200001 0025 (Ext. lob-id)
UNLOAD TO FILE "customers6", "blobb00001"
SELECT hno, location, price, picture
FROM s1.houses
FORMAT INTERNAL
WITH DESCRIPTION

The resulting output file is as follows:

>DESCRIPTION<
1 C4 1:4 S1.HOUSES:PRODUCTION.HNO
2 C28 5:32 S1.HOUSES:PRODUCTION.LOCATION
3 D14.2 33:46 S1.HOUSES:PRODUCTION.PRICE
4 L35M 47:70 S1.HOUSES:PRODUCTION.PICTURE
>END DESCRIPTION<
H101Woodbury +0000013000000100001~
H102Woodbury +0000004000000100001~
H103Westchester +0000009000000100001~
H104Parkway Heights +0000008500000100001~
H105Turtle Creek +0000011000000100001~

10–10 7830 8160–027


UNLOAD

For clarity, here is a layout in a table form.

1 4 5 32 33 46 47 70
H101 Woodbury +0000013000000 100001~ (Int. lob-id)
H102 Woodbury +0000004000000 100001~ (Int. lob-id)
H103 Westchester +0000009000000 100001~ (Int. lob-id)
H104 Parkway +0000008500000 100001~ (Int. lob-id)
Heights
H105 Turtle Creek +0000011000000 100001~ (Int. lob-id)

Example 6

This example selects columns MAXPRICE, CNAME, and DESIREDLOC from table

CUSTOMERS in CSV format:

UNLOAD TO FILE "customers4"


SELECT maxprice, cname, desiredloc
FROM s1.customers
FORMAT CSV;

The resulting output file is as follows:

150000,Thompson,Woodbury
70000,Owen,New London
90000,Johnson,Woodbury
100000,Jones,
120000,Smith,Westchester

Customer Jones has no desired location; therefore, DESIREDLOC is null. For CSV
format, no characters are printed for a null column.

10.1.3. Rules and Guidelines


Read the following rules and guidelines before using the UNLOAD statement.

Cursors
For ESQL UNLOAD statements, the cursor must already be opened either with an
OPEN statement or, for a cursor declared through the interpreter interface, opened
implicitly with a preceding FETCH statement through the interpreter interface.

If you are unloading data from a cursor declared through ESQL, you must first open
the cursor. If the cursor is positioned after its last row, no rows are unloaded.

If the cursor was declared through the interpreter interface and placeholders are
present in the cursor declaration, it must be opened. If the cursor is positioned after
its last row, all rows are unloaded.

7830 8160–027 10–11


UNLOAD

Regardless of how the cursor was declared, if it is positioned at or before the last
row, RDMS writes all rows following the current row to the output file. For example, if
you declare a cursor that has more than two rows and then execute two FETCH NEXT
statements before executing an UNLOAD statement, the file includes all but the first
two rows of the cursor.

Query Expressions
If you have a query expression in the UNLOAD statement, RDMS copies all selected
rows to the output file. The query expression can include up to 14 base tables or
global temporary tables. If a base table or global temporary table is specified more
than once, each specification counts towards the maximum of 14. If a view is specified
in the query expression, it does not count towards this limit; however, each of its
underlying base or global temporary tables does count.

Long Data Images


The UNLOAD statement can produce data images of up to 30,000 characters in length.
Some processors cannot handle images of this length. Most editors, for example,
truncate images at 132 or 256 characters. You can, therefore, lose data if you edit an
unloaded file with long images.

If the data image is greater than 8,188 characters in length, RDMS generates
continuation images. If the unload file type is PCIOS, RDMS generates PCIOS
continuation images, signaled by the segmentation flag in the PCIOS image control
word. If the unload file type is SDF, RDMS generates continuation control records
(051). See the Data Structures Programming Reference Manual for more information
about system data format. The OS 2200 editors do not handle continuation images.

When reading an unload file with a processor or program, see the applicable reference
manual to find how long images are handled. For example, to read an unload file from
a COBOL program, it is necessary to specify the device type DISC in the FILE
CONTROL paragraph to avoid truncation of long images.

Performance
When unloading many rows, you should lock the tables being loaded in PROTECTED
RETRIEVAL, EXCLUSIVE RETRIEVAL or EXCLUSIVE UPDATE mode (see 9.3).
Otherwise, RDMS locks each row or page you unload, significantly slowing execution
of the UNLOAD statement.

Including the USING IO clause on the UNLOAD statement improves the performance
of the UNLOAD command up to 40 percent, depending on the length of the RDMS
records. With longer records, you will see more improvement in performance.

Descriptions
The LOAD statement of the RDMUTL processor ignores the description.

10–12 7830 8160–027


UNLOAD

Auxiliary Information
The number of rows unloaded is returned to the program through the auxiliary
information parameter or the ESQL AUX-INFO variable.

EXTERNAL Clause
All information in the EXTERNAL clause position-and-null list is optional. The following
syntax is acceptable:

FORMAT EXTERNAL NULL IS '*',,41:43,

This is a list of four items, with no formatting information for the second or fourth
items. This list can be used when the select list contains four items, as there must be
one position-and-null statement for each item in the select list.

If the select and external lists do not match, an error status is returned. The above
FORMAT clause directs RDMS to place an asterisk ( * ) into the output file if it finds a
null in the first data column. All other columns either have no nulls or RDMS uses the
default representation (blanks). All values are placed into the output file according to
the table definition except the third value, which is placed in print columns 41 to 43.

If you want to control the format of even just one data column, you must provide a
position-and-null statement for each column selected.

No Finds
The UNLOAD statement never returns a 6001 no-find error status or an SQLCODE
of +100. If no records satisfy the query specification or remain in the cursor, RDMS
returns an OK status of 0000 or an SQLCODE of zero, and the auxiliary information
variable is set to zero.

7830 8160–027 10–13


UNLOAD

INTERNAL Format
When you use FORMAT INTERNAL, RDMS adds information about nulls at the end of
each line in the file. One character is added for each column that allows nulls. These
additional print columns are arranged in the same order as the columns in the select
list that allow nulls.

If a data item in a row is null, its corresponding null indicator character is N in the
row’s line in the file.

If the data item is not null, the null indicator character is a tilde ( ~ ).

The LOAD statement uses these bytes to determine whether any data values are null.
See the Relational Database Server for ClearPath OS 2200 Administration Guide.

WITH DESCRIPTION Clause


If you include the WITH DESCRIPTION clause, with or without ONLY, the output file
begins with a description of the rows unloaded. In particular, this description contains
the following:

• Each column's type


• Each column's size and, if appropriate, scale (number of digits to the right of the
decimal point)
• Which CHARACTER columns in the output file contain each data item's value and,
if possible, the data item’s name

The following example illustrates the first line of the output file with description:

>DESCRIPTION

The next example illustrates the last line

>END DESCRIPTION

Descriptions of each data item appear between DESCRIPTION and END DESCRIPTION.
Each column description fits on one line.

The format of a column description is described later in this subsection.

10–14 7830 8160–027


UNLOAD

Transferring Data from RDMS to MAPPER


You can move data to a MAPPER report by using the FORMAT MAPPER clause of the
UNLOAD statement, which causes RDMS to create a data file. You can easily load this
data file into the MAPPER system by using the MAPPER system RET P function.

When you specify FORMAT MAPPER, RDMS places the lines of data in the data file in
MAPPER tab type lines. This means that RDMS separates each data item with a tab
character.

If you specify WITH DESCRIPTION in addition to FORMAT MAPPER, RDMS places the
description lines in the file as MAPPER comment lines. This means that each line of
description text starts with a period in column 1.

The data files created by RDMS are not true MAPPER format files as used in a
MAPPER report. This means that you should place an N in the MAPPER FORMAT field
on the RET P function request screen when loading the file into a MAPPER report.

In addition, place a Y in the HEADERS field on the RET P function request screen;
RDMS does not place a header in the data field. By placing a Y in this field, you are
directing the MAPPER system to insert the standard header for the type of report
being loaded.

The following is an example of a MAPPER RETRIEVE file:

UNLOAD TO FILE "CUSTOMERS5"


SELECT cno,cname,maxprice
FROM s1.customers
FORMAT MAPPER;

The resulting file is as follows, where number signs ( # ) indicate the location of tab
characters:

#C101 #THOMPSON # 150000


#C102 #OWEN # 70000
#C103 #JOHNSON # 90000
#C104 #JONES # 100000
#C105 #SMITH 120000

Note: If a column with data type BLOB is projected, RDMS issues an error. You
cannot use the UNLOAD MAPPER command for tables with BLOB columns.

7830 8160–027 10–15


UNLOAD

file-name2
Use of file-name2 is optional. RDMS actions are as follows.

LOB Data file-name2


in Table? Specified? RDMS Action

No No RDMS unloads non-BLOB data.


No Yes RDMS issues an error because a BLOB output file was
specified, but there were no BLOBs.
Yes No RDMS issues an error to indicate the unload was not
executed because BLOB data was not unloaded.
Yes Yes RDMS unloads the table and BLOB data.
The element name where the BLOB data is stored is
generated by RDMS.
The BLOB indicator in UNLOAD EXTERNAL file format is a
24-character value SDF file external lob-id.
The BLOB indicator in UNLOAD INTERNAL file format is a
16-character value SDF file internal lob-id.

Note: If you want to unload to the same program file with two or more UNLOAD
commands, you must perform an End Thread after the previous UNLOAD is done,
then a Begin Thread before doing another UNLOAD to the same program file. This is
because UDS Control keeps the file assigned until the End Thread, and does not
allow the Exec to reassign the program file within the same thread after the
program file is freed.

Refer to PLE #17384937 if you want to unload the data from a table without unloading
the BLOB values.

Format of a Column Description


The format of a column description is as follows:

Column number
The ordinal number of the column as found in the SELECT clause of the
UNLOAD or DECLARE CURSOR statement. It is an integer in CHARACTER
columns 1 to 4, left-justified, and space-filled.

Column number 0 denotes the description of the null indicator characters, if


present.

10–16 7830 8160–027


UNLOAD

Column type
A single character in column 6 that indicates the type of data in the column:

A DATE
B NUMERIC
C CHARACTER
D DECIMAL
F FLOAT
I INTEGER
L BLOB
M TIMESTAMP
N NATIONAL CHARACTER
P DOUBLE PRECISION
R REAL
S SMALLINT
T TIME

Size and scale


One integer for CHARACTER columns and FLOAT columns, two integers for
NUMERIC and DECIMAL columns.

If the format is INTERNAL for datetime data types (DATE, TIME, and
TIMESTAMP), refer to Table 2-10.

If the format is EXTERNAL or MAPPER for datetime data types, see 2.7.3.

If the format is EXTERNAL or MAPPER, the size of a NUMERIC column is one


greater than the size specified in the CREATE TABLE statement; it is also one
greater if the scale is not zero.

If the format is INTERNAL, the size of a DECIMAL column is the same as the
size specified in the CREATE TABLE statement. Similarly, the scale is the same
scale specified in the CREATE TABLE statement.

If the format is EXTERNAL or MAPPER, the size of a DECIMAL column is one


greater than the size specified in the CREATE TABLE statement, if the scale is
not zero (since one character is added for the decimal point). The size is an
integer constant beginning in CHARACTER column 7 of the description. If the
data item is of type DECIMAL, the size is followed by a period and the scale.

For a BLOB column, the integer value must be between 1 and 4096M. If the
number is larger than 5 digits, it is rounded up to either K (1,024 bytes) or M
(1,048,576 bytes). Any number between 1 to 99999 is specified as it is. Any
number between 100,000 to 10,238,976 is rounded up as 98K to 9999K. Any
number between 10,238,977 to 4,294,967,296 is rounded up as 10M to 4096M.

7830 8160–027 10–17


UNLOAD

Output column range


The range of CHARACTER columns that contain the data item values. This
begins in CHARACTER column 13 and consists of two integers separated by a
colon.

Column name
The fully qualified name of the column in the form

qualifier-name.table-name:version-name.column-name

This begins in column 23. The column name does not appear in all cases. In
general, if a name can be deduced from the DECLARE CURSOR statement or
the SELECT clause in the UNLOAD statement (from a UNION operation, for
example), it is included in the description.

On the other hand, if a statement such as the following is used, no name can
be deduced for the single column selected:

UNLOAD TO FILE "EMP*MASTER-BASE"


SELECT YEARS_OF_SERVICE * PAY_RATE
FROM PERSONNEL_TABLE
.
.
.
;

Because no name can be deduced, no name appears in the column’s


description. This is true even if the SELECT clause is like the following
example:

SELECT PAY_RATE * 1.10

In such a case, the words “result of arithmetic expression” appear, rather than
the column name.

If INTERNAL format is used for columns allowing nulls, the last description line in this
item reads “null indicator bytes.”

10–18 7830 8160–027


UNLOCK

10.2. UNLOCK
Use the UNLOCK statement to release the locking protocol for one or more tables.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes Yes No X

10.2.1. RDMS Extended Syntax


UNLOCK table-specification-list

where table-specification-list is a list of table specifications separated by commas.

10.2.2. Example
The following example releases any explicit locks on tables HOUSES and
CUSTOMERS:

UNLOCK houses,customers

10.2.3. Rules and Guidelines


Read the following rules and guidelines before using the UNLOCK statement.

Release of UPDATE Locks


If the locking protocol is UPDATE, the unlock takes effect at the next commit or
rollback point.

Restrictions
The UNLOCK statement has the following restrictions:

• If the thread has an active cursor accessing a table, RDMS rejects the UNLOCK
statement.
• RDMS immediately releases any retrieval lock (RETRIEVAL, SHARED RETRIEVAL,
PROTECTED RETRIEVAL, or EXCLUSIVE RETRIEVAL).
• The UNLOCK statement releases only explicit table level locks created by the
LOCK statement. Row level locks in place when you execute the UNLOCK
statement are not affected.

Global Temporary Tables


An UNLOCK statement is ignored for a global temporary table, just as LOCK
statements are ignored. RDMS implicitly locks global temporary tables in EXCLUSIVE
UPDATE MODE.

7830 8160–027 10–19


UNLOCK

Errors with Multiple Tables


If you unlock more than one table with a single UNLOCK statement and the statement
returns an RDMS error (error status in the 6000 range), some of the tables may
already have been successfully unlocked before RDMS detected the error. To avoid
this potentially confusing situation, you should use a separate UNLOCK statement for
each table.

The following example releases any explicit locks on tables HOUSES and
CUSTOMERS, but avoids any confusion if RDMS encounters an error while executing
either UNLOCK statement:

UNLOCK houses
UNLOCK customers

XTC
If the application group is configured for Extended Transaction Capacity (XTC), the
UNLOCK statement affects the entire storage area in which the table to be unlocked
resides. If one table in a storage area is unlocked, all other tables in the same storage
area (if any exist) remain locked until they are unlocked individually.

To prevent conflicting interaction between locks on tables in a storage area, it is


recommended that you place only one table in each storage area.

10–20 7830 8160–027


UPDATE ALL

10.3. UPDATE ALL


Use the UPDATE ALL statement to change the content of columns within all existing
rows of a table.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes* Yes Yes X

* Except for the RETRIEVE INTO clause

10.3.1. RDMS Extended Syntax


UPDATE table-specification

[ CHANGE ] [ IN ] ALL [ ROWS ] change-specification-list

[ RETRIEVE INTO embedded-variable-specification-list ]

where:

table-specification
is a table name as defined in 2.2.2.

change-specification-list
is a list of column names and the values for each data item in a column. The list is
one or more entries in the form

[ ( ] column-name=value-specification
[ ,column-name=value-specification ] ...[ ) ]

The value specification can be a column name, an arithmetic expression, a string


literal, a numeric constant, a datetime literal, any scalar built-in function, a variable
specification, the keyword NULL or USER, or the datetime functions
CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP. If it contains the
name of a column that is being updated by the UPDATE statement, the value
denoted is the value of the column before the column is updated.

In place of a value (for example, 1, NULL, ‘a’) in the value-specification you can
now specify the DEFAULT keyword. If a value of DEFAULT is specified for a
column, it works as follows:

• If the column contains a DEFAULT clause, the default is inserted.


• If the column is an IDENTITY column, the next value of the identity sequence is
inserted
• If the column is GENERATED AS <expression> the expression following the
AS is evaluated and its value inserted.
• If none of the above, and NULL values are allowed, NULL is inserted.
Otherwise, an error is issued.

7830 8160–027 10–21


UPDATE ALL

embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated columns
are to be placed. The number of variables in the list must equal the number of
columns being updated.

If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.

This list is allowed in static ESQL only.

10.3.2. Example
The following example changes the price of all houses in table HOUSES to $150,000:

UPDATE houses
CHANGE ALL ROWS price = 150000

As a result, all rows in table HOUSES have a value of 150000 in column PRICE.

10.3.3. Rules and Guidelines


Read the following rules and guidelines before using the UPDATE ALL statement.

Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.

Default Table, Row Locks


The default table lock is step-duration UPDATE mode and the default row lock is
step-duration EXCLUSIVE UPDATE mode. For more information about locking and
concurrency, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

Rejection on Explicit Lock


If the table has an explicit lock (defined by a LOCK statement) in one of the RETRIEVAL
modes, RDMS rejects the UPDATE statement (see 9.3).

Permanent Changes, NONE Recovery Option


Permanent database changes may occur any time after you execute an UPDATE
statement if you used the NONE recovery option on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently delete rows from the database until the
program executes a COMMIT or END THREAD statement.

10–22 7830 8160–027


UPDATE ALL

Implicit Delete and Insert on Primary Key


When you update a table's primary key, it is treated as a DELETE statement followed
by an INSERT statement. If RDMS encounters a duplicate key, it rolls back any
updates. For more information about the DELETE and INSERT statements, see 7.5 and
8.14.

When you update the primary key of more than one row at a time, RDMS first deletes
all affected rows and then reinserts them.

Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.

Foreign Key Constraints


When you update either the columns of a primary key or a unique constraint for a
parent table (as defined by a foreign key constraint), the list of old values (that is, the
values of the updated columns that existed before the update) cannot exist as values
in foreign key columns of the associated child table. If such violations exist following
the update, RDMS returns an error and rolls back any updates. For more information
about foreign key constraints, see 6.11.

When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.

If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.

For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation.

Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.

Character String Too Long


If you send a character string that is larger than a table's definition, RDMS returns a
warning message and rejects the UPDATE statement. RDMS performs a statement
rollback or a thread rollback, depending on the recovery option being used.

7830 8160–027 10–23


UPDATE ALL

Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.

Embedded Variable Specification List


The embedded variable specification list is most useful when you use an arithmetic
expression to update a column and you want to know the result of the expression for
reporting purposes. For example, you can add a deposit to an account balance and
have the new balance reported automatically without having to retrieve it. For
character value assignment considerations, see 2.8.1.

10–24 7830 8160–027


UPDATE Positioned

10.4. UPDATE Positioned


Use the UPDATE Positioned statement to change the content of columns within the
current row of a cursor.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes Yes* Yes Yes E/X

* Except for the RETRIEVE INTO clause

10.4.1. Syntax
SQL 92 Syntax (Entry Level)

UPDATE table-specification

SET change-specification-list

WHERE CURRENT OF cursor-name

RDMS Extended Syntax

UPDATE table-specification

SET change-specification-list

WHERE CURRENT OF cursor-name

[ RETRIEVE INTO embedded-variable-specification-list ]

Syntax When Used in Routines or Triggers

UPDATE table-specification

[ CHANGE ] { SET │ COLUMNS } change-specification-list

WHERE CURRENT OF cursor-name

where:

table-specification
is a table name as defined in 2.2.2.

change-specification-list
is a list of column names and the values for each data item in a column. The list is
one or more entries in the form

column-name=value-specification
[ ,column-name=value-specification ] ...

7830 8160–027 10–25


UPDATE Positioned

The list can be enclosed in parentheses in RDMS extended syntax but not in
standard SQL syntax.

For a description of value-specification, see 10.3.

cursor-name
is the name of the cursor with the current row being updated.

To reference the cursor in an UPDATE statement, you must follow these rules:

• If the FOR UPDATE OF clause is used by the cursor definition, only those
columns listed by the cursor can be listed in the UPDATE statement change
specification.
• The table specification in the UPDATE statement must be the same as the
table specification in the cursor's FROM clause.
• A FETCH statement executed before the UPDATE statement must
successfully fetch a row from the cursor specified in the UPDATE statement.

If FETCH NEXT n is used on the cursor, positional UPDATE statements are not
allowed and are rejected.

embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated columns
are to be placed. The number of variables in the list must equal the number of
columns being updated.

If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.

This list is allowed in static ESQL only.

10.4.2. Example
The following example illustrates a positional cursor update:

DECLARE upcur CURSOR


SELECT *
FROM houses
WHERE location = 'WOODBURY'
FOR UPDATE OF price
FETCH FIRST upcur...
FETCH NEXT upcur...
UPDATE houses
SET price = 35000
WHERE CURRENT OF upcur

10–26 7830 8160–027


UPDATE Positioned

The FETCH FIRST statement returns data on house H101, the FETCH NEXT statement
returns data on house H102, and the UPDATE statement changes the price of house
H102 to $35,000.

For more information on the DECLARE CURSOR statement, see 7.4.

10.4.3. Rules and Guidelines


Read the following rules and guidelines before using the UPDATE Positioned
statement.

Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.

Default Table, Row Locks


The default table lock is step-duration UPDATE mode and the default row lock is
step-duration EXCLUSIVE UPDATE mode. For more information about locking and
concurrency, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

Rejection on Explicit Lock


If the table has an explicit lock (defined by a LOCK statement) in one of the RETRIEVAL
modes, RDMS rejects the UPDATE statement (see 9.3).

Permanent Changes, NONE Recovery Option


Permanent database changes may occur any time after you execute an UPDATE
statement if you used the NONE recovery option on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently delete rows from the database until the
program executes a COMMIT or END THREAD statement.

Update of Primary Key Columns


Exercise caution when updating a primary key column using an updatable cursor
unless you are only updating a single row. Changing the value of the primary key can
cause the same record to be fetched more than once. Instead of using the UPDATE
Positioned statement to update the primary key column, perform one of the following
alternative operations:

• First, fetch all the cursor records into your program and then issue an UPDATE
Searched statement for each record fetched.
• Perform an UNLOAD of all the cursor records and read the resulting file in your
program; issue an UPDATE Searched statement for each record read.
• Use the INSERT . . . SELECT statement to insert the records selected by the cursor
WHERE clause into a working table that you place in a storage area with AUDITED
FALSE and RECOVERED FALSE and that you lock in EXCLUSIVE UPDATE mode.

7830 8160–027 10–27


UPDATE Positioned

Declare a cursor to fetch records from this working table. For each record fetched,
issue an UPDATE Searched statement against the original table.
• If you have a UNIQUE constraint on the table and are not updating UNIQUE
columns, specify predicates against the leading columns of the UNIQUE constraint
in the WHERE clause so that the UNIQUE constraint is selected as the cursor
access path. Update of primary key columns WHERE CURRENT OF CURSOR using
a UNIQUE constraint as its access path does not cause records to be fetched
twice, unless UNIQUE columns are also updated.

Note: The same problem can occur if you fetch and update records from a cursor
one at a time even if the update is performed using the UPDATE Searched or
UPDATE VALUES statement.

Implicit Delete and Insert on Primary Key


When you update a table's primary key, it is treated as a DELETE statement followed
by an INSERT statement. If RDMS encounters a duplicate key, it rolls back any
updates. For more information about the DELETE and INSERT statements, see 7.5
and 8.14.

When you update the primary key, RDMS first deletes the row and then reinserts it
with its new primary key value.

Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.

Foreign Key Constraints


When you update either the columns of a primary key or a unique constraint for a
parent table (as defined by a foreign key constraint), the list of old values (that is, the
values of the updated columns that existed before the update) cannot exist as values
in foreign key columns of the associated child table. If such violations exist following
the update, RDMS returns an error and rolls back any updates. For more information
about foreign key constraints, see 6.11.

When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.

If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.

For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation. If a violation is encountered during
the update process, RDMS returns an error and rolls back any updates.

10–28 7830 8160–027


UPDATE Positioned

Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.

Character String Too Long


If you send a character string that is larger than a table's definition, RDMS returns a
warning message and rejects the UPDATE statement. RDMS performs a statement
rollback or a thread rollback, depending on the recovery option being used. For other
character value assignment considerations, see 2.8.1.

Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.

In routines, the RDMSAUXINFO system variable can be used to obtain this information.
See 4.9.1.

Routines and Triggers and the UPDATE Positioned Statement


Any cursor referenced in an UPDATE Positioned statement must be declared within
the same compound statement as the UPDATE Positioned statement or at an outer
level of nesting.

The cursor must be opened using the OPEN statement and positioned on a row by a
FETCH statement prior to the execution of the UPDATE statement.

7830 8160–027 10–29


UPDATE Searched

10.5. UPDATE Searched


Use the UPDATE Searched statement to change the content of columns within a
subset of the existing rows of a table.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes* Yes Yes* Yes Yes E/X

* Except for the RETRIEVE INTO clause

10.5.1. Syntax
SQL 92 Syntax (Entry Level)

UPDATE table-specification

SET change-specification-list

[ WHERE Boolean-expression ]

RDMS Extended Syntax

UPDATE table-specification

[ CHANGE ] { SET │ COLUMNS } change-specification-list

[ WHERE Boolean-expression ]

[ RETRIEVE INTO embedded-variable-specification-list ]

Syntax When Used in Routines

UPDATE table-specification

SET change-specification-list

[ WHERE Boolean-expression ]

where:

table-specification
is a table name as defined in 2.2.2.

change-specification-list
is a list of column names and the values for each data item in a column. The
list is one or more entries in the form

column-name=value-specification
[ ,column-name=value-specification ]...

10–30 7830 8160–027


UPDATE Searched

The list can be enclosed in parentheses in RDMS extended syntax but not in
standard SQL syntax. For a description of value-specification, see 10.3.

Boolean-expression
specifies the rows to be updated. If omitted, all rows are updated. For more
information on Boolean expressions, see 2.4.2.

embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated
columns are to be placed. The number of variables in the list must equal the
number of columns being updated.

If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.

This list is allowed in static ESQL only.

10.5.2. Examples
The following example changes the asking price for house number H101 in table
HOUSES to $150,000:

UPDATE houses
SET price = 150000
WHERE hno = 'H101'

The following example illustrates how to use one UPDATE statement to change the
asking price of two houses:

UPDATE houses
SET price = 150000
WHERE hno = 'H101' OR hno = 'H102'

The following example illustrates how to update the price of a house by an inflation
factor of 3 percent. It also uses an embedded variable specification to return the new
price into the embedded variable NEWPRICE. This eliminates the need to perform a
separate retrieval operation to find the updated value.

EXEC SQL UPDATE houses


SET price = price*1.03
WHERE hno = 'H101'
RETRIEVE INTO :newprice
END-EXEC.

7830 8160–027 10–31


UPDATE Searched

10.5.3. Rules and Guidelines


Read the following rules and guidelines before using the UPDATE Searched statement.

Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.

Default Table, Row Locks


The default table lock is step-duration UPDATE mode and the default row lock is
step-duration EXCLUSIVE UPDATE mode. For more information about locking and
concurrency, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

Rejection on Explicit Lock


If the table has an explicit lock (defined by a LOCK statement) in one of the RETRIEVAL
modes, RDMS rejects the UPDATE statement (see 9.3).

Permanent Changes, NONE Recovery Option


Permanent database changes may occur any time after you execute an UPDATE
statement if you used the NONE recovery option on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently delete rows from the database until the
program executes a COMMIT or END THREAD statement.

Implicit Delete and Insert on Primary Key


When you update a table's primary key, it is treated as a DELETE statement followed
by an INSERT statement. If RDMS encounters a duplicate key, it rolls back any
updates. For more information, see 7.5 (DELETE) and 8.14 (INSERT).

When you update the primary key of more than one row at a time, RDMS first deletes
all affected rows and then reinserts them.

Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.

Foreign Key Constraints


When you update either the columns of a primary key or a unique constraint for a
parent table (as defined by a foreign key constraint), the list of old values (that is, the
values of the updated columns that existed before the update) cannot exist as values
in foreign key columns of the associated child table. If such violations exist following
the update, RDMS returns an error and rolls back any updates. For more information
about foreign key constraints, see 6.11.

10–32 7830 8160–027


UPDATE Searched

When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.

If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.

For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation.

Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.

Character String Too Long


If you send a character string that is larger than a table's definition, RDMS returns a
warning message and rejects the UPDATE statement. RDMS performs a statement
rollback or a thread rollback, depending on the recovery option being used. For other
character value assignment considerations, see 2.8.1.

Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.

In routines, the RDMSAUXINFO system variable can be used to obtain this information
(see 4.9.1).

7830 8160–027 10–33


UPDATE SYNCHRONIZE

10.6. UPDATE SYNCHRONIZE


Use the UPDATE SYNCHRONIZE statement to change the content of columns within a
specific row of a table or insert the row if it does not exist in the table.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No Yes Yes X

10.6.1. RDMS Extended Syntax


UPDATE table-specification

[ CHANGE ] SYNCHRONIZE VALUES (value-list)

WHERE Boolean-expression

[ RETRIEVE INTO embedded-variable-specification-list ]

where:

table-specification
is a table name as defined in 2.2.2.

value-list
is a list that can contain any combination of

• String literals
• Numeric constants
• Datetime literals
• CAST functions
• Variable specifications
• The keywords NULL or USER
• The datetime functions CURRENT_DATE, CURRENT_TIME, or
CURRENT_TIMESTAMP

Arithmetic expressions are not allowed. Use commas to separate the values.

You must specify values for every column in the table. In addition, these values
must be listed in the same sequence in which the columns are defined in the
CREATE TABLE statement.

10–34 7830 8160–027


UPDATE SYNCHRONIZE

Indicator variables within the value-list have the following meanings:

-1 The value is NULL.


0 The variable contains a value. The value is to be used by both INSERT
and UPDATE.
1 The variable contains a value. The value is to be used only if the record
is inserted, but not if the record is updated (the column value is
therefore not changed).

For more information about usage of indicator variables, see 2.10.4.

Boolean-expression
specifies the row to be updated. For more information on Boolean expressions,
see 2.4.2.

embedded-variable-specification-list
is a list of variable pairs (see 2.9) into which the values of the updated columns are
to be placed. The number of variables in the list must equal the number of
columns being updated.

This list is allowed in static ESQL only.

10.6.2. Examples
Example 1
The following example calls UPDATE SYNCHRONIZE twice, with synchronization
turned on, for house number H106 in the HOUSES sample table. Assume that house
H106 does not exist for the first call to UPDATE SYNCHRONIZE, and that then the
house is sold and its row of data is obsolete and a new listing needs to be added. The
same HNO value (H106) can be retained and new values for the other columns
inserted.

The HNO column is the primary key. You are changing only the last three columns, but
you must include a data item for every column in the table. You must place the data
items in the same order in which the columns were originally defined.

UPDATE houses
SYNCHRONIZE VALUES ('H106', 'Big Town', 400000, '3000 sq ft overlooking
golf course')
WHERE hno = 'H106'

UPDATE houses
SYNCHRONIZE VALUES ('H106', 'Suburb', 80000, 'handyperson special')
WHERE hno = 'H106'

7830 8160–027 10–35


UPDATE SYNCHRONIZE

Example 2
The ESQL example that follows shows how the UPDATE SYNCHRONIZE statement
can be used in a C program. The example also demonstrates the use of indicator
variables.

#include <rsa.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <rsa$clib>
EXEC SQL BEGIN DECLARE SECTION;
char v_hno[5];
int ind_var_hno = 0;
char v_location[80];
int ind_var_location = 0;
int v_price = 400000;
int ind_var_price = 0;
char v_description[40];
int ind_var_description = 0;
EXEC SQL END DECLARE SECTION;
main(void)
{
/* This update will insert a new record into the houses table. */

strcpy( v_hno, "H106");


v_price = 400000;
strcpy(v_location, "Big Town");
strcpy(v_description, "3000 sq ft overlooking golf course");

printf("Insert the new record into the houses table using update with synchronize. \n");

EXEC SQL BEGIN THREAD FOR APPTWO;


EXEC SQL UPDATE houses_
SYNCHRONIZE VALUES( :v_hno :ind_var_hno,
:v_location :ind_var_location,
:v_price :ind_var_price,
:v_description :ind_var_description)
where HNO = ‘H106‘;
EXEC SQL COMMIT;
printf("insert committed\n");

/* This will update the record with HNO equal to H106 in the houses table. */

ind_var_hno = 0;
ind_var_location = 1; /* setting the indicator variable to 1 will not update this column */
ind_var_price = 0; /* the value in the PRICE column will be updated */
ind_var_description = -1; /* the value in DESCRIPTION will be set to null */

strcpy(v_location, “Suburb”);
v_price = 80000;
strcpy(v_description, “handyperson special”);

10–36 7830 8160–027


UPDATE SYNCHRONIZE

printf("Update the values in the houses table using UPDATE SYNCHRONIZE . \n");

EXEC SQL UPDATE houses_


SYNCHRONIZE VALUES( :v_hno :ind_var_hno,
:v_location :ind_var_location,
:v_price :ind_var_price,
:v_description :ind_var_description)
where HNO = ‘H106’;

EXEC SQL
END THREAD TERMINATE;
printf("end thread terminate\n");
return(0);

10.6.3. Rules and Guidelines


Read the following rules and guidelines before using the UPDATE SYNCHRONIZE
statement.

Locking, Committing
RDMS locks the updated row so that other threads cannot access it until the row is
committed to the database. UPDATE SYNCHRONIZE immediately XU locks the page
that contains the record to be updated, or where the record will be inserted. This
reduces the possibility of deadlocks, in comparison to using the UPDATE VALUES,
UPDATE SEARCHED, or INSERT statements, by eliminating lock upgrades. It also
improves performance in the XTC environment by eliminating at least one trip to the
RLP. If you have deadlocks caused by lock upgrades or performance issues caused by
the number of trips to the RLP, it could be beneficial to change your UPDATE
statements to UPDATE SYNCHRONIZE statements.

Default Table, Row Locks


The default table lock is step-duration UPDATE mode and the default row lock is
step-duration EXCLUSIVE UPDATE mode. For more information about locking and
concurrency, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

Rejection on Explicit Lock


If the table has an explicit lock (defined by a LOCK statement) in one of the RETRIEVAL
modes, RDMS rejects the UPDATE statement (see 9.3).

Permanent Changes, NONE Recovery Option


Permanent database changes can occur any time after you execute an UPDATE
statement, if you used the NONE recovery option on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently delete rows from the database until the
program executes a COMMIT or END THREAD statement.

7830 8160–027 10–37


UPDATE SYNCHRONIZE

Implicit Delete and Insert on Primary Key


When you update a table's primary key, it is treated as a DELETE statement followed
by an INSERT statement. If RDMS encounters a duplicate key, it rolls back any
updates. For more information about the DELETE and INSERT statements, see 7.5 and
8.14.

Unique Constraints
When you update any column defined as a unique constraint and the update results in
duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.

Foreign Key Constraints


When you update either the columns of a primary key or a unique constraint for a
parent table (as defined by a foreign key constraint), the list of old values (that is, the
values of the updated columns that existed before the update) cannot exist as values
in foreign key columns of the associated child table. If such violations exist following
the update, RDMS returns an error and rolls back any updates. For more information
about foreign key constraints, see 6.11.

When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table.

If a violation is encountered before any updates actually occur, RDMS returns an error
but no rollback occurs. If a violation is encountered during the update process, RDMS
returns an error and rolls back any updates.

For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. A rollback always
occurs for a self-referencing foreign key violation.

Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates. The Boolean expression cannot refer to a
subquery that contains the table being updated in its FROM clause.

Character String Too Long


If you send a character string that is larger than a table's definition, RDMS returns a
warning message and rejects the UPDATE statement. RDMS performs a statement
rollback or a thread rollback, depending on the recovery option being used.

10–38 7830 8160–027


UPDATE SYNCHRONIZE

Auxiliary Information
RDMS returns 1, the number of rows updated, through the auxiliary information
variable. For more information, see the reference manual for the programming
language you are using.

Embedded Variable Specification Lists


The embedded variable specification list is most useful when you use an arithmetic
expression to update a column and you want to know the result of the expression for
reporting purposes. For example, you can add a deposit to an account balance and
have the new balance reported automatically without having to retrieve it. For
character value assignment considerations, see 2.8.1.

Numeric Data Types


The data types of numeric items must be compatible with the data types of the
columns being inserted, as described in 2.7.2.

7830 8160–027 10–39


UPDATE VALUES

10.7. UPDATE VALUES


Use the UPDATE VALUES statement to change the content of columns within one or
more specific rows of a table.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes* Yes Yes X

* Except for the RETRIEVE INTO clause

10.7.1. RDMS Extended Syntax


UPDATE table-specification

[ CHANGE ] VALUES (value-list)

WHERE Boolean-expression

[ RETRIEVE INTO embedded-variable-specification-list ]

where:

table-specification
is a table name as defined in 2.2.2.

value-list
is a list of any combination of string literals, numeric constants, datetime literals,
CAST functions, variable specifications, the keywords NULL and USER, or the
datetime functions CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP.
Arithmetic expressions are not allowed. Use commas to separate the values.

You must specify values for every column in the table. In addition, these values
must be listed in the same sequence in which the columns are defined in the
CREATE TABLE statement.

Boolean-expression
specifies the rows to be updated. For more information on Boolean expressions,
see 2.4.2.

embedded-variable-specification-list
is a list of variable pairs (see 2.10) into which the values of the updated columns
are to be placed. The number of variables in the list must equal the number of
columns being updated.

If you update more than one row on the UPDATE statement, the embedded
variables contain the values of the columns in the last row updated.

This list is allowed in static ESQL only.

10–40 7830 8160–027


UPDATE VALUES

10.7.2. Example
The following example updates values for house number H101 in table HOUSES.
Assume that house H101 is sold and that its row of data is obsolete and a new listing
needs to be added. The same HNO value (H101) can be retained, and new values for
the other columns inserted.

The HNO column is the primary key. You are changing only the last three columns, but
you must include a data item for every column in the table. You must place the data
items in the same order in which the columns were originally defined.

UPDATE houses
CHANGE VALUES ('H101','Camden',40000,'Cottage')
WHERE hno = 'H101'

10.7.3. Rules and Guidelines


Read the following rules and guidelines before using the UPDATE VALUES statement.

Locking, Committing
RDMS locks updated rows so that other threads cannot access them until these rows
are committed to the database.

Default Table, Row Locks


The default table lock is step-duration UPDATE mode and the default row lock is
step-duration EXCLUSIVE UPDATE mode. For more information about locking and
concurrency, see the Relational Database Server for ClearPath OS 2200
Administration Guide.

Rejection on Explicit Lock


If the table has an explicit lock (defined by a LOCK statement) in one of the RETRIEVAL
modes, RDMS rejects the UPDATE statement (see 9.3).

Permanent Changes, NONE Recovery Option


Permanent database changes may occur any time after you execute an UPDATE
statement if you used the NONE recovery option on the BEGIN THREAD statement.
Otherwise, RDMS does not permanently delete rows from the database until the
program executes a COMMIT or END THREAD statement.

7830 8160–027 10–41


UPDATE VALUES

Implicit Delete and Insert on Primary Key


When you update a table's primary key, it is treated as a DELETE statement followed
by an INSERT statement. If RDMS encounters a duplicate key, it rolls back any
updates. For more information about the DELETE and INSERT statements, see 7.5 and
8.14.

When you update the primary key of more than one row at a time, RDMS first deletes
all affected rows and then reinserts them.

Unique Constraints
When you update any columns defined as a unique constraint and the update results
in duplicate values, RDMS returns an error and rolls back any updates. For more
information on unique constraints, see 6.11.

Foreign Key Constraints


When you update either the columns of a primary key or a unique constraint for a
parent table (as defined by a foreign key constraint), the list of old values (that is, the
values of the updated columns that existed before the update) cannot exist as values
in foreign key columns of the associated child table. If such violations exist following
the update, RDMS returns an error and rolls back any updates. For more information
about foreign key constraints, see 6.10.

When you update the columns of a foreign key for a child table (as defined by a
foreign key constraint), all new values being assigned to the foreign key columns must
exist as values in the referenced columns (that is, the columns of either the primary
key or a unique constraint) of the parent table. If a violation is encountered during the
update process, RDMS returns an error and rolls back any updates.

For a self-referencing foreign key constraint (that is, the same table is both the parent
and child), any check for violations is deferred until after the update. In any case, a
rollback always occurs with a foreign key violation. For more information about foreign
keys, see 6.11.

Check Constraints
If the column specified in the UPDATE statement is bound to a column or table check
constraint and the new value for the column violates the check constraint, RDMS
returns an error and rolls back any updates.

Character String Too Long


If you send a character string that is larger than a table’s definition, RDMS returns a
warning message and rejects the UPDATE statement. RDMS performs a statement
rollback or a thread rollback, depending on the recovery option being used. For other
character value assignment considerations, see 2.8.1.

10–42 7830 8160–027


UPDATE VALUES

Auxiliary Information
RDMS returns the number of rows updated through the auxiliary information variable.
For more information, see the reference manual for the programming language you
are using.

Performance
When the primary key does not need to be changed (as the example illustrates), it is
more efficient to use the UPDATE Searched statement (see 10.5).

Embedded Variable Specification Lists


The embedded variable specification list is most useful when you use an arithmetic
expression to update a column and you want to know the result of the expression for
reporting purposes. For example, you can add a deposit to an account balance and
have the new balance reported automatically without having to retrieve it. For
character value assignment considerations, see 2.8.1.

7830 8160–027 10–43


USE DEFAULT

10.8. USE DEFAULT


Use the USE DEFAULT statement to establish a new default qualifier or a new default
version name.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
Yes Yes Yes N/A No X

10.8.1. RDMS Extended Syntax


USE DEFAULT { { QUALIFIER │ SCHEMA } { schema-name │ placeholder } │

VERSION { version-name │ placeholder } }

where:

schema-name
is the schema name. The keywords QUALIFIER and SCHEMA are synonymous.
The terms schema-name and qualifier-name are used synonymously in RDMS.
See 2.2.2 for information on using the default schema name.

placeholder
is a placeholder for a host program variable that contains a name. Placeholders are
allowed only through the interpreter interface.

version-name
is the version name.

10.8.2. Examples
Example 1
The following example sets the default schema name to HOUSE_SCHEMA:

USE DEFAULT SCHEMA house_schema

Example 2
In the following example, the default schema name is the value of the application
program variable associated with the placeholder variable, $P1:

USE DEFAULT QUALIFIER $p1

Example 3
The following example sets the default version name to TUESDAY:

USE DEFAULT VERSION tuesday

10–44 7830 8160–027


USE DEFAULT

Example 4
When a cursor refers to a table without explicitly specifying a qualifier or version
(see 6.1 and 7.4), RDMS uses the default qualifier name when you declare the cursor
and the default version when you open the cursor. If an OPEN statement is not
required (see 9.4.3), RDMS implicitly opens the cursor when you first fetch it.

Consider the following code:

USE DEFAULT QUALIFIER east-side


USE DEFAULT VERSION test
DECLARE c1 CURSOR
SELECT *
FROM houses
FETCH FIRST c1
INTO $p1, $p2, $p3, $p4
USE DEFAULT QUALIFIER west-end
USE DEFAULT VERSION production
CLOSE c1
FETCH FIRST c1
INTO $p1, $p2, $p3, $p4

In the preceding code

• The first FETCH statement fetches from EAST-SIDE.HOUSES:TEST.


• The second FETCH statement fetches from EAST-SIDE.HOUSES: PRODUCTION.
• The new default qualifier name, WEST-END, was not used for the second fetch
because RDMS uses the default qualifier name, EAST-SIDE, when C1 is declared.
• The new default version name, PRODUCTION, is used for the second fetch
because RDMS applied the new version when it implicitly reopened C1 before the
second fetch.

10.8.3. Rules and Guidelines


Read the following rules and guidelines before using the USE DEFAULT statement.

active_version Function
The active_version function returns the current default version value.

Scope
A USE DEFAULT statement that is executed at run time (through either the interpreter
interface or dynamic ESQL) establishes a default qualifier or version name for all
interpreter interface and dynamic ESQL statements that execute after it, until another
run-time USE DEFAULT statement is executed.

A static ESQL USE DEFAULT statement establishes a default qualifier or version name
for all static ESQL statements that textually follow it in the source code until the next
static ESQL USE DEFAULT statement.

7830 8160–027 10–45


USE DEFAULT

For example, assume a portion of a UCS COBOL program looks like this:

EXEC SQL USE DEFAULT QUALIFIER stay END-EXEC.


ENTER MASM 'ACOB$RDMR' USING
'USE DEFAULT QUALIFIER trans ;',err, aux.
EXEC SQL DELETE x END-EXEC.
EXEC SQL EXECUTE IMMEDIATE DELETE x END-EXEC.

The first DELETE statement deletes rows from table STAY.X; the second DELETE
statement affects table TRANS.X.

Neither interactive nor dynamic embedded USE DEFAULT VERSION statements affect
the execution of static ESQL statements. To dynamically specify the version used by a
static ESQL statement, pass the version as a parameter to the static ESQL statement.
See 2.2.2 for more information.

Placeholders
A qualifier or version name contained in a placeholder is subject to the rules for
delimited identifiers (see 2.2.1). In particular, lowercase letters are not equivalent to
uppercase characters.

Qualifiers and Versions


If you omit the qualifier name from a table specification, RDMS uses the default name
you specified.

The default qualifier and version name remain in effect for the life of a thread, or until
you establish new default names.

The system configuration determines the thread default qualifier name for all tables
unless you establish a new default qualifier name.

The thread default version name for all tables is PRODUCTION unless you establish a
new default version name.

As with the qualifier name, RDMS uses the default version name when you omit the
version name on a table specification.

Use Restriction in Routines and Triggers


The USE DEFAULT statement is not allowed within a routine or trigger. For special
considerations on defaults for routines, see the following:

• Section 4
• 8.8 (FUNCTION)
• 9.6 (PROCEDURE)

10–46 7830 8160–027


WHENEVER

10.9. WHENEVER
Use the WHENEVER statement to direct a UCS COBOL or UCS C program of the action
to take if RDMS encounters an error while executing an SQL statement.

Interpreter Static Dynamic


Interface ESQL ESQL Module XREF Standard
No Yes No N/A No E

10.9.1. SQL 92 Syntax (Entry Level)


WHENEVER { SQLERROR │ NOT FOUND }

{ CONTINUE │ { GO TO │ GOTO } paragraph-name }

where:

SQLERROR
refers to an abnormal error status (negative value in SQLCODE).

NOT FOUND
refers to the SQLCODE no-find status of +100 on a retrieval statement
(see C.3).

CONTINUE
directs the program to execute the program statement following the ESQL
statement that generates the condition specified in this WHENEVER
statement.

GOTO or GO TO
directs the program to jump to the paragraph or label named if the ESQL
statement encounters the condition specified in this WHENEVER statement.

paragraph-name
is the name of a paragraph or label in the program.

10.9.2. Examples
The following example has the UCS COBOL program proceed without breaking its
normal flow of control if an ESQL statement encounters an error:

EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.

The next example directs a program to jump to a paragraph named NO-DATA on an


end-of-cursor or no-data status from RDMS:

EXEC SQL WHENEVER NOT FOUND GO TO no-data END-EXEC.

7830 8160–027 10–47


WHENEVER

10.9.3. Rules and Guidelines


Read the following rules and guidelines before using the WHENEVER statement.

Scope
A WHENEVER statement with either SQLERROR or NOT FOUND affects all ESQL
statements that textually come after it and before the next WHENEVER statement
with the same condition in the source code.

Code Suggestion
To avoid looping if an ESQL error occurs, place a WHENEVER statement in the
error-handling code.

10–48 7830 8160–027


Appendix A
Keywords

Keywords (called tokens in standard SQL) include reserved and nonreserved words.
Table A–1 lists reserved words and Table A–2 lists nonreserved words.

A keyword has a special meaning to RDMS. You cannot use RDMS reserved words as
names for identifiers managed by RDMS (for example, for tables and columns).

Avoid using SQL89, SQL92, and SQL99 reserved words as identifiers, because they
may become unavailable as new features are added to RDMS.

If SQL flagging is enabled when an application is compiled, RDMS returns a warning


message whenever SQL89, SQL92, and SQL99 reserved words are used as identifiers
even if they are not yet part of RDMS syntax. SQL flagging is enabled if the compiler
option LEVEL/SQL is set. For more information, see either of the following:

• COBOL Compiler Programming Reference Manual Volume 2


• C Compiler Programming Reference Manual Volume 2

The following RDMS synonyms are reserved words:

COLUMN, COLUMNS
INT, INTEGER
NULL, NULLS
QUALIFIER, SCHEMA

7830 8160–027 A–1


Reserved Words

A.1. Reserved Words


Table A–1 lists RDMS, SQL 89, SQL 92, and probable SQL 99 reserved words.

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

ABSOLUTE ABSOLUTE ABSOLUTE


ACTION ACTION
ADA
ADD ADD
ADMIN
AFTER AFTER
AGGREGATE
ALIAS
ALL ALL ALL ALL
ALLOCATE ALLOCATE
ALTER ALTER
AND AND AND AND
ANY ANY ANY ANY
ARE ARE ARE
ARRAY
AS AS AS
ASC ASC ASC
ASSERTION ASSERTION
AT AT
AUTHORIZATION AUTHORIZATION AUTHORIZATION AUTHORIZATION
AVG AVG AVG
BEFORE BEFORE
BEGIN BEGIN BEGIN BEGIN
BETWEEN BETWEEN BETWEEN
BINARY
BIT BIT
BIT_LENGTH
BLOB
BOOLEAN

A–2 7830 8160–027


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

BOTH BOTH
BREADTH
BY BY BY
CALL CALL
CASCADE CASCADE CASCADE
CASCADED CASCADED
CASE CASE
CAST CAST
CATALOG CATALOG
CHAR CHAR CHAR
CHARACTER CHARACTER CHARACTER
CHAR_LENGTH
CHARACTER_
LENGTH
CHECK CHECK CHECK CHECK
CLASS
CLOB
CLOSE CLOSE CLOSE
COALESCE
COBOL COBOL
COLLATE COLLATE COLLATE
COLLATION COLLATION
COLUMN COLUMN COLUMN
COLUMNS
COMMIT COMMIT COMMIT
COMPLETION
CONNECT CONNECT
CONNECTION CONNECTION
CONSTRAINT CONSTRAINT CONSTRAINT
CONSTRAINTS CONSTRAINTS
CONSTRUCTOR
CONTINUE CONTINUE CONTINUE CONTINUE

7830 8160–027 A–3


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

CONVERT
CORRESPONDING CORRESPONDING
COUNT COUNT COUNT
CREATE CREATE CREATE CREATE
CROSS CROSS
CUBE
CURRENT CURRENT CURRENT CURRENT
CURRENT_DATE CURRENT_DATE CURRENT_DATE
CURRENT_PATH
CURRENT_ROLE
CURRENT_TIME CURRENT_TIME CURRENT_TIME
CURRENT_ CURRENT_ CURRENT_
TIMESTAMP TIMESTAMP TIMESTAMP
CURRENT_USER CURRENT_USER
CURSOR CURSOR CURSOR CURSOR
CYCLE
DATA DATA
DATE DATE DATE
DAY DAY
DEALLOCATE DEALLOCATE
DEC DEC DEC
DECIMAL DECIMAL DECIMAL
DECLARE DECLARE DECLARE
DEFAULT DEFAULT DEFAULT DEFAULT
DEFERRABLE DEFERRABLE
DEFERRED DEFERRED
DELETE DELETE DELETE
DEPTH
DEREF
DESC DESC DESC
DESCRIBE DESCRIBE
DESCRIPTOR DESCRIPTOR

A–4 7830 8160–027


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

DESTROY
DESTRUCTOR
DETERMINISTIC
DIAGNOSTICS DIAGNOSTIC
DICTIONARY
DISCONNECT DISCONNECT
DISTINCT DISTINCT DISTINCT DISTINCT
DO
DOMAIN DOMAIN
DOUBLE DOUBLE DOUBLE DOUBLE
DROP DROP DROP
DYNAMIC
EACH
ELSE ELSE ELSE
ELSEIF
END END END END
ENDÄEXEC ENDÄEXEC
END IF
END WHILE
EQUALS
ESCAPE ESCAPE ESCAPE ESCAPE
EVERY
EXCEPT EXCEPT EXCEPT
EXCEPTION EXCEPTION
EXEC EXEC EXEC EXEC
EXECUTE EXECUTE
EXISTS EXISTS EXISTS
EXIT
EXPLAIN
EXTERNAL EXTERNAL
EXTRACT
FALSE FALSE

7830 8160–027 A–5


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

FETCH FETCH FETCH


FIRST FIRST FIRST
FLOAT FLOAT FLOAT FLOAT
FOR FOR FOR FOR
FOREIGN FOREIGN FOREIGN FOREIGN
FORMAT
FORTRAN FORTRAN
FOUND FOUND FOUND FOUND
FREE
FROM FROM FROM FROM
FULL FULL
FUNCTION FUNCTION
GENERAL
GET GET GET
GLOBAL GLOBAL
GO GO GO GO
GOTO GOTO GOTO GOTO
GRANT GRANT GRANT GRANT
GROUP GROUP GROUP GROUP
GROUPING
HAVING HAVING HAVING HAVING
HOST
HOUR HOUR
IDENTIFY IDENTITY
IF
IGNORE
IMM
IMMEDIATE IMMEDIATE IMMEDIATE
IN IN IN IN
INDEX
INDICATOR INDICATOR INDICATOR
INITIALIZE

A–6 7830 8160–027


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

INITIALLY INITIALLY
INNER INNER
INOUT INOUT
INPUT INPUT
INSENSITIVE
INSERT INSERT INSERT
INT INT INT INT
INTEGER INTEGER INTEGER INTEGER
INTERSECT INTERSECT INTERSECT
INTERVAL INTERVAL
INTO INTO INTO INTO
IPF
IS IS IS IS
ISOLATION ISOLATION
ITERATE
JOIN JOIN
KEY KEY KEY KEY
LARGE
LAST LAST LAST
LATERAL
LEADING LEADING
LEFT LEFT
LESS
LEVEL LEVEL
LIKE LIKE LIKE LIKE
LIMIT
LOCAL LOCAL
LOCALTIME
LOCALTIMESTAMP
LOCATOR
LOWER
MATCH MATCH

7830 8160–027 A–7


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

MAX MAX MAX


MIN MIN MIN
MINUTE MINUTE
MODIFIES
MODIFY
MODULE MODULE MODULE MODULE
MONTH MONTH
NAMES NAMES
NATIONAL NATIONAL
NATURAL NATURAL
NCHAR NCHAR
NCLOB
NEW
NEXT NEXT NEXT
NO NO
NONE
NOT NOT NOT NOT
NULL NULL NULL NULL
NULLIF
NULLS
NUMERIC NUMERIC NUMERIC NUMERIC
OBJECT
OCTET_LENGTH
OF OF OF OF
OFF
OLD
ON ON ON ON
ONLY ONLY
OPEN OPEN OPEN OPEN
OPERATION
OPTION OPTION OPTION
OR OR OR OR

A–8 7830 8160–027


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

ORDER ORDER ORDER ORDER


ORDINALITY
OUT OUT
OUTER OUTER
OUTPUT OUTPUT
OVERLAPS
PAD PAD
PARAMETER
PARAMETERS PARAMETERS
PARTIAL PARTIAL
PASCAL PASCAL
PATH
PENDANT
PLI PLI
POSITION
POSTFIX
PRECISION PRECISION PRECISION PRECISION
PREFIX
PREORDER
PREPARE PREPARE PREPARE
PRESERVE PRESERVE
PRIMARY PRIMARY PRIMARY
PRIOR PRIOR PRIOR
PRIVILEGES PRIVILEGES PRIVILEGES
PROCEDURE PROCEDURE PROCEDURE PROCEDURE
PUBLIC PUBLIC PUBLIC PUBLIC
QUALIFIER
RDMSAUXINFO
READ READ
READS
REAL REAL REAL REAL
RECURSIVE

7830 8160–027 A–9


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

REF
REFERENCES REFERENCES REFERENCES REFERENCES
REFERENCING
REFERS
RELATIVE RELATIVE RELATIVE
RENAME
RESTRICT RESTRICT RESTRICT
RESULT
RETURN RETURN
RETURNS RETURNS
REVOKE REVOKE
RIGHT RIGHT
ROLE
ROLLBACK ROLLBACK ROLLBACK
ROLLUP
ROUTINE
ROW
ROWS ROWS ROWS
SAVEPOINT
SCHEMA SCHEMA SCHEMA SCHEMA
SCOPE
SCROLL SCROLL SCROLL
SEARCH
SECOND SECOND
SECTION SECTION SECTION SECTION
SELECT SELECT SELECT SELECT
SEQUENCE
SESSION SESSION
SESSION_USER SESSION_USER
SET SET SET SET
SETS
SIZE SIZE

A–10 7830 8160–027


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

SMALLINT SMALLINT SMALLINT SMALLINT


SOME SOME SOME SOME
SPACE SPACE
SPECIFIC SPECIFIC
SPECIFICTYPE
SQL SQL SQL SQL
SQLCODE SQLCODE SQLCODE
SQLERROR SQLERROR SQLERROR
SQLEXCEPTION
SQLSTATE SQLSTATE SQLSTATE
SQLWARNING
START
STATE
STATEMENT STATEMENT
STATIC
STRUCTURE
SUBSTRING
SUM SUM SUM
SYSDATE
SYSTIMESTAMP
SYSTEM_USER SYSTEM_USER
TABLE TABLE TABLE TABLE
TEMPORARY TEMPORARY
TERMINATE
THAN
THEN THEN THEN
THREAD
TIME TIME TIME
TIMESTAMP TIMESTAMP
TIMEZONE_HOUR TIMEZONE_HOUR
TIMEZONE_ TIMEZONE_
MINUTE MINUTE

7830 8160–027 A–11


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

TO TO TO
TRAILING TRAILING
TRANSACTION TRANSACTION TRANSACTION
TRANSLATE
TRANSLATION TRANSLATION
TREAT
TRIGGER TRIGGER
TRIM
TRUE TRUE
UNDER
UNION UNION UNION UNION
UNIQUE UNIQUE UNIQUE UNIQUE
UNKNOWN UNKNOWN
UNNEST
UNOWNED
UPDATE UPDATE UPDATE
UPPER
USAGE USAGE
USER USER USER USER
USING USING USING
VALUE VALUE
VALUES VALUES VALUES
VARIABLE
VARYING VARYING
VIEW VIEW VIEW VIEW
VIEWS
WHEN WHEN
WHENEVER WHENEVER WHENEVER WHENEVER
WHERE WHERE WHERE WHERE
WHILE
WITH WITH WITH WITH
WITHOUT WITHOUT

A–12 7830 8160–027


Reserved Words

Table A–1. Reserved Words

RDMS SQL 89 SQL 92 SQL 99

WORK WORK WORK


WRITE WRITE WRITE
YEAR YEAR
ZONE ZONE

7830 8160–027 A–13


Nonreserved Keywords

A.2. Nonreserved Keywords


Table A–2 lists RDMS nonreserved keywords. Synonyms are separated by commas.
RDMS looks for nonreserved words when parsing and analyzing SQL statements. If a
nonreserved word appears in an SQL statement, RDMS returns a message stating
that this usage is illegal.

A–14 7830 8160–027


Nonreserved Keywords

Table A–2. RDMS Nonreserved Keywords

ABSOLUTE COMMIT GENERATED NO


CONFLICT NOCACHE
ACCESS HOUR
CONTENTS NOCYCLE
ACTIVE IDENTITY
ADD CONTROL NODUMP
INACTIVE
ADVANCE CYCLE NOMAXVALUE
INCLUDING
ALLOCATE D
NOMINVALUE
DAY INCREMENT
ALLOW NONE
DEBUG INDICATOR
ALLOWED NOSTUB
DEC, DECIMAL INNER
ALTER NUMBER
DEFERRED INPUT
ALWAYS OBJECT
DEFINE INSENSITIVE
AREA OFF
DELETE INSERT
AS OJ
DESC, DESCENDING INTERNAL
ASC, ASCENDING OMIT
DESCRIPTION INTERVAL
ASENSITIVE ONLY
DIRECT IO
ATOMIC OPTIMIZE
DISCARD ITEMMODFLAG
AUXINFO OPTION
DUMP JOIN
BDIS OUTER
DYNAMIC KEEP
BINARY OWNER
ECHO LARGE
BLOB PACKET
ERROR LEFT
BY PAGE
EXCLUSIVE LEVEL
CACHE PARSE
EXECUTE LOCAL
CAM PARTITION
EXPRESSION LOCATE
CAST PCIOS
EXTRACT LOCK
CHANGE PERMANENT
EXTERNAL LSS
CHAR, PRESERVE
CHARACTER, FETCH MANAGE
PRIMARY
CHARACTERS FILE MAPPER
PRIVILEGES
CHOOSE FN MAXVALUE
PROTECTED
CLOSE GETERROR MINUTE
QAD
COMMA GLOBAL MINVALUE
QUEUE
COMMAND HOLD MODE
QUICKLOOKS
COMMANDLOOK, MONTH
COMMANDLOOKS RANDOM
MULTIPLE
RDM
NAME
RDMCA
NCHAR
NCHARACTER

7830 8160–027 A–15


Nonreserved Keywords

Table A–2. RDMS Nonreserved Keywords

RDMS ROLE START UNLOAD


READ ROLLBACK STATISTICS UNLOCK
READY ROW STUB UPDATE
RECORD RSA T USE
RELATIVE RSM TAB VALUE, VALUES
RELEASE RSP TCL VERSION
REQUEST SDF TCS VARCHAR
REQUEUE SDFO TEMPORARY VARCHAR2
REQUIRE SECOND TERMINATE WORK
RESTART SENSITIVE TO YEAR
RESULTS SEQUENTIAL TRACE ZERO_LENGTH_
RETENTION STRING
SHARE TS
RETRIEVAL SHARED UDSMSG,
RETRIEVE SIGNAL UDSMESSAGE,
REVOKE UDSMESSAGES
SIZES
UNICODE
RIGHT SKIPGENERATED

A–16 7830 8160–027


Appendix B
RDMS Error Handling

This appendix discusses error messages returned by RDMS. It explains how to obtain
a list of current error messages from the release tape, categorizes the messages, and
suggests methods for correcting errors.

B.1. Obtaining Current Error Messages


RDMS error messages are in the RDMS file SYS$LIB$*RDMS in these elements:

RSAC-MSG
MCON-RDM
RDMS-UPMSPEC

7830 8160–027 B–1


Error Message Groups

B.2. Error Message Groups


The error statuses returned to a program by the interpreter interface are grouped as
follows:

1 - 16 Internal errors from the parser and lexical analyzer


50 - 99 Reserved for use by Unisys
100 - 299 Errors detected by the lexical analyzer
300 - 1999 Syntax errors detected by the RDMS parser
2000 - 5999 Semantic errors detected by RDMS
6000 - 6999 Statuses indicating errors detected by RDMS or UREP
7000 - 7100 Warning statuses from RDMS
8000 - 8999 Statuses indicating errors detected while trying to connect to UDS
9000 - 9999 RDMS internal errors

B–2 7830 8160–027


Checking Error Statuses

B.3. Checking Error Statuses


When RDMS returns a nonzero status, it is suggested that you follow these steps:

1. Check for the 6001 status if you use the FETCH or SELECT statement. The status is
not really an error, but means rather that no data (or no further data) is available to
retrieve.
2. Check to see whether the status is not in the 6000 to 6999 or 8000 to 8999 range.
Errors outside these ranges are RDMS errors, which usually mean that something
is wrong with the syntax, the parameters you are passing to RDMS, or the manner
in which you are passing the parameters. A program can print the status, auxiliary
information variable, and error messages (with the GETERROR statement). You
may then want to terminate the program and debug it.
3. You must handle errors in the 6000 to 6999 or 8000 to 8999 range. These
statuses represent errors detected by RDMS, the Data Definition Facility (DDF), or
some other component of UDS. When one of these statuses is returned, you can
check the rollback status in the auxiliary information variable and retrieve error
message text with the GETERROR statement.

IPF SQL users see error messages automatically. In IPF SQL, you can obtain more
information about an error message (if more information exists) by entering a question
mark (?) immediately after receiving the error message.

B.3.1. Error Message Text


If the status is 6009, a DDF error is returned. All DDF messages start with *ERROR in
column 1. Errors from other UDS components may also be returned.

Error messages returned by other UDS components (and some error messages by
RDMS) have the following form:

APP xx ccc yy zzzzz message-text

Other RDMS error messages have the form

*ERROR ZZZZ message-text

where:

xx
is the application group number in columns 5 and 6.

7830 8160–027 B–3


Checking Error Statuses

ccc
is the abbreviation for the UDS component in columns 8 to 10:

RDM Relational data manager (part of RDMS)


RSM Relational storage manager (part of UDS Control)
PCI Program-callable interface (part of UREP)
CAM Cache manager (part of UDS Control)
TCS Table control system (part of UDS Control)
LSS Locking subsystem (part of UDS Control)
DCS Data control system (part of UDS Control)
DMS Data Management System (DMS)

yy
is the message category in columns 13 and 14:

IN Informational (not an error)


EX External, usually caused by action or circumstance outside of UDS
RB Rollback; the error forced a rollback
IT Internal, caused by situation internal to UDS

zzzzz or ZZZZ
is the message number in columns 16 to 20, or 8 to 11, depending on the form of
the message.

Several messages may be returned at one time. The first message is usually the most
significant.

B.3.2. Errors and Rollbacks


An error in the range 6000 to 6999 may or may not cause a rollback. If a rollback
occurs, it is indicated in the auxiliary information variable. For ASCII COBOL programs,
see Appendix D. For ASCII FORTRAN programs, see Appendix E. For UCS compilers,
see the section on RDMS in the applicable programming reference manual.

The two types of rollbacks are thread rollbacks and command rollbacks:

• Thread rollbacks cause the current step to end and all changes made during the
step to be discarded. All step-duration locks are released and all cursors are
closed.
• Command rollbacks discard changes made from the beginning of the statement to
the point where the error was detected, but do not release locks or close cursors.
A command rollback can occur only when COMMANDLOOKS recovery is used.

B–4 7830 8160–027


Checking Error Statuses

RDMS performs command rollbacks only as required, and it performs them


transparently. From your perspective, errors that cause no rollback and errors that
cause a command rollback are no different from one other.

Whether a thread rollback occurs as the result of an RDMS error depends on several
factors:

• Message category
All rollback category errors (numbered 50000 to 69999) always cause a thread
rollback. IN and EX errors (numbered 0 to 49999) may or may not cause a thread
rollback, depending on other factors.
• Recovery option
Since command level recovery is available only when you specify the
COMMANDLOOKS recovery option, RDMS converts command rollbacks into
thread rollbacks for many errors when you specify QUICKLOOKS, DEFERRED, or
NONE as the recovery option.
• Error situation
In certain cases, one type of error may or may not cause a thread rollback,
depending on the situation in which the error was detected. For example, some
errors cause a thread rollback when detected during an update statement; they do
not, however, cause a rollback if detected during an insert statement.
• Status returned by RDMS
RDMS returns a status to the user program in the range 6000 to 6012 when an
error is detected. Certain statuses are associated with certain types of rollbacks.
For example, 6000 and 6002 do not accompany thread rollback; 6007 may or may
not accompany a thread rollback; and 6010 always accompanies a thread rollback.
Since certain error messages do not always accompany a rollback, you should
always check for the rollback status in the auxiliary information variable. This
variable returns one of three values:
0 The statement executed normally, and no rollback occurred.
1 The statement was not executed, and the thread was not rolled back.
2 The statement was not executed, and a thread rollback occurred.

7830 8160–027 B–5


Checking Error Statuses

B.3.3. RDMS Statuses 6000 to 6999


When RDMS or UDS encounters an error, RDMS generates a status in the range 6000
to 6999 and returns it to the user program. Table B–1 gives the meaning of each
status.

Note: For more information about an error status marked with an asterisk ( * ), see
the Relational Database Server for ClearPath OS 2200 Administration Guide.

Table B–1. Error Statuses 6000 to 6999

Status Meaning

6000 Warning. The statement was successfully executed.


6001 No data was found for a SELECT or FETCH statement. When fetching from a
cursor, it means that the end of the cursor was reached. This is not an error
and no rollback is performed.
6002 An error not serious enough to warrant a thread rollback occurred. No thread
rollback occurred. These errors are called "semantic" errors.
6003 An attempt was made to insert or update a primary key that is a duplicate of
an existing primary key. This error may or may not cause a thread rollback,
depending on various factors.
6004 A locking conflict occurred. This status can occur only if you lock (or attempt
to lock) a table while specifying ON CONFLICT RETURN on the LOCK
statement. A thread rollback may or may not result from this type of error.
6006 A table referred to by the statement does not exist. No rollback results from
this type of error.
6007 A catch-all status for most RDMS errors. This type of error may or may not
cause a thread rollback.
6009 An error was detected by DDF that is separate from RDMS. This status
should occur only on a statement that creates, modifies, or drops table, view,
or index definitions. This type of error almost always causes a thread
rollback.
6010 A deadlock occurred. A thread rollback always occurs for a deadlock. Status
6009 is returned instead of 6010 when a deadlock occurs in DDF.
6011 The command is redundant and was therefore not executed.
6012 An attempt was made to insert or update a unique column that is a duplicate
of an existing unique column. This error may or may not cause a thread
rollback, depending on various factors.
6013 A fast search could not be completed because of a lack of resources.
6014 * The program ran out of memory in RDMS.
6016 * Internal error. Possible database corruption of a recoverable file.
6017 * Internal error. Possible database corruption of a nonrecoverable file.
6018 Internal RDMS error.

B–6 7830 8160–027


Checking Error Statuses

Table B–1. Error Statuses 6000 to 6999

Status Meaning

6019 * An attempt was made to access a record in a primary key or secondary index
partition which is detached. The thread has been rolled back.
6020 * An attempt was made to retrieve, insert, update, or delete a record in a
primary key or secondary index partition which is hidden. Records in a hidden
partition are invisible to SQL commands. The thread has been rolled back.
6021 * An attempt was made to insert or move a record so that it is not within the
range of any partition. The thread has been rolled back.
6022 The called stored procedure returned dynamic result sets (see 4.7). AUXINFO
contains the number of result sets returned.
6023 The called stored procedure attempted to return more result sets than the
value of max-result-sets specified by the DYNAMIC RESULT SETS clause.
The number of result sets was limited to the specified value of
max-result-sets.
6024 Internal error in the interface between JDBC and RDMS. The size of the PCA
is too small. Please resubmit the request with a larger area. AUXINFO
contains the required size. The command was executed.
6025 Internal error in the interface between JDBC and RDMS. The section passed
to RDMS is out of date because it references a table whose definition has
been altered since the section was optimized. The command was not
executed.
6026 Internal error in the interface between JDBC and RDMS. The PCA is not large
enough to contain the section. The command was not executed. AUXINFO
contains the required size.
6027 Internal error in the interface between JDBC and RDMS. The statement
executed but was re-optimized. The description of the cursor is different
from that returned when the cursor was originally optimized. The previous
description should be discarded.
6028 Internal error in the interface between JDBC and RDMS. There is no PCA
available for this command. RDMS needs a PCA for the compiled section. The
command was not executed.
6029 Internal error in the interface between JDBC and RDMS. The OPEN CURSOR
failed because the size, or precision, of a program variable passed on the
OPEN is not compatible with the size, or precision, of that program variable
value passed on DECLARE CURSOR.

7830 8160–027 B–7


Checking Error Statuses

B.3.4. Resolving 6000 to 6999 Errors


After a program handles RDMS errors and the 6001 no-find/end-of-cursor error
statuses, take the following steps to deal with any remaining 6000 to 6999 errors:

1. Check for locking conflict status 6004 if you locked tables using the ON CONFLICT
RETURN specification. If this is not the case, 6004 should never occur and can be
grouped with the other error statuses. Status 6004 means that RDMS returned
control to you instead of queuing. The action the program should take depends on
the reason for inhibiting queuing; you may wish to go on to the next operation and
try again later.
Unless you are using COMMANDLOOKS recovery or read-only mode, the thread
was probably rolled back, in which case you must repeat any UPDATE, DELETE,
INSERT or OPEN statement in the step rolled back.
2. Check for deadlock status 6010. If more than one thread is attempting to access a
table at the same time, a deadlock is probable and the program should handle it.
One way to handle it is to wait one second and then repeat all the DELETE,
UPDATE, INSERT, and OPEN statements in the step rolled back by the deadlock.
If another deadlock occurs while repeating these statements, repeat the process
up to a determined reasonable limit to prevent infinite looping. If this is occurring
in several threads simultaneously, you may want to choose the wait time
randomly to reduce looping.
3. Handle all other error statuses in the same way. Use the GETERROR statement to
retrieve the error text. The program should print the message to inform the user
of the error situation. If the AUX-INFO variable indicates that a thread rollback
occurred, you may want to repeat the UPDATE, DELETE, and OPEN statements
before continuing or stopping the program.
Based on your experience with various errors, you may want to handle certain
errors in special ways. This requires that the program examine the text of the
message to extract the error number in columns 15 to 19 of the message and the
component (for example, RDM) in columns 7 to 9. Unisys reserves the right to
change, delete, add, or renumber errors in future releases.

B–8 7830 8160–027


COMMIT and ROLLBACK Statement Errors

B.4. COMMIT and ROLLBACK Statement Errors


If RDMS returns an error on a COMMIT, OMIT, or ROLLBACK statement, you must
terminate the thread with an END THREAD statement before executing further SQL
statements (whether the thread is implicit or explicit).

7830 8160–027 B–9


SQLSTATE

B.5. SQLSTATE
Using the SQLSTATE variable is the preferred SQL 92 standard method for checking
the successful completion of an SQL statement. SQLCODE, however, is still supported
by the standard and by RDMS (see C.3, “Using SQLCODE in an ESQL Program”).

SQLSTATE is returned to application programs compiled using a sufficiently high level


of C Compiler or COBOL Compiler software, or by client-based tools that support
SQLSTATE and that also call an interface that supports SQLSTATE.

The SQLSTATE variable consists of a 2-character class value followed by a 3-character


subclass value. Both are defined by the SQL 92 standard, Microsoft ODBC (a superset
of SQL 92), and RDMS.

The following criteria determine the return of an SQLSTATE value:

• If the error caused the transaction to roll back, an SQLSTATE value of class 40 is
returned regardless of any other possible SQLSTATE mapping.
• If the particular condition (such as “no data”) is defined by SQL 92, RDMS returns
the SQL 92 SQLSTATE value.
• If the particular condition (such as “base table not found”) is defined by ODBC,
RDMS returns the ODBC SQLSTATE value.
• If neither of the preceding two conditions is true, RDMS defines an SQLSTATE
value that consists of the character U followed by the RDMS error status, and
returns it. (Error status 6013 has an associated SQLSTATE value of U6013, for
example.) For information about RDMS error message groups, see B.2; for a
description of RDMS error statuses, see B.3.3.

The following table illustrates the mapping between the RDMS error status,
SQLCODE, and SQLSTATE.

SQLCODE Value SQLSTATE Value Error Status Meaning

0 00000 0000 Successful


completion
+100 02000 6001 No data
+6000 Various 6000 Warning
Negative error Not 00000 or Not 0000 or 6001 Error condition
status 02000

B–10 7830 8160–027


SQLSTATE

B.5.1. SQL 92 SQLSTATE Values


Table B–2 lists SQL 92 SQLSTATE values.

Table B–2. SQLSTATE Class and Subclass Values

Class Condition Subclass Subcondition

00 Successful completion 000 (no subclass)


01 Warning 000 (no subclass)
001 Cursor operation conflict
002 Disconnect error
003 Null value eliminated in set function
004 String data; right truncation
005 Insufficient item descriptor areas
006 Privilege not revoked
007 Privilege not granted
008 Implicit zero-bit padding
009 Search condition too long for
information schema
00A Query expression too long for
information schema
00C Dynamic result sets returned
00E Attempt to return too many result
sets
02 No data 000 (no subclass)
07 Dynamic SQL error 000 (no subclass)
001 Using clause does not match
dynamic parameter specifications
002 Using clause does not match target
specifications
003 Cursor specification cannot be
executed
004 Using clause required for dynamic
parameters
005 Prepared statement not a cursor
specification
006 Restricted data type attribute
violation
007 Using clause required for result
fields

7830 8160–027 B–11


SQLSTATE

Table B–2. SQLSTATE Class and Subclass Values

Class Condition Subclass Subcondition

008 Invalid descriptor count


009 Invalid descriptor index
08 Connection exception 000 (no subclass)
001 SQL client unable to establish SQL
connection
002 Connection name in use
003 Connection does not exist
004 SQL server rejected establishment
of SQL connection
006 Connection failure
007 Transaction resolution unknown
0A Feature not supported 000 (no subclass)
001 Multiple server transactions
21 Cardinality violation 000 (no subclass)
22 Data exception 000 (no subclass)
001 String data; right truncation
002 Null value; no indicator parameter
003 Numeric value out of range
005 Error in assignment
007 Invalid datetime format
008 Datetime field overflow
009 Invalid time zone displacement
value
011 Substring error
012 Division by zero
015 Internal field overflow
018 Invalid character value for cast
019 Invalid escape character
021 Character not in repertoire
022 Indicator overflow
023 Invalid parameter value
024 Unterminated C string
025 Invalid escape sequence

B–12 7830 8160–027


SQLSTATE

Table B–2. SQLSTATE Class and Subclass Values

Class Condition Subclass Subcondition

026 String data; length mismatch


027 Trim error
23 Integrity constraint violation 000 (no subclass)
24 Invalid cursor name 000 (no subclass)
25 Invalid transaction state 000 (no subclass)
26 Invalid SQL statement name 000 (no subclass)
27 Triggered data change violation 000 (no subclass)
28 Invalid authorization specification 000 (no subclass)
2A Syntax error or access rule 000 (no subclass)
violation in direct SQL statement
2B Dependent privilege descriptors 000 (no subclass)
still exist
2C Invalid character set name 000 (no subclass)
2D Invalid transaction termination 000 (no subclass)
2E Invalid connection name 000 (no subclass)
33 Invalid SQL descriptor name 000 (no subclass)
35 Invalid condition number 000 (no subclass)
37 Syntax error or access rule 000 (no subclass)
violation in dynamic SQL statement
3C Ambiguous cursor name 000 (no subclass)
3D Invalid catalog name 000 (no subclass)
3F Invalid schema name 000 (no subclass)
40 Transaction rollback 000 (no subclass)
001 Serialization failure (for example,
deadlock)
002 Integrity constraint violation
003 Statement completion unknown
U19 Partition inaccessible
U20 Partition hidden
U21 Partition does not exist
42 Syntax error or access rule 000 (no subclass)
violation

7830 8160–027 B–13


SQLSTATE

Table B–2. SQLSTATE Class and Subclass Values

Class Condition Subclass Subcondition

44 WITH CHECK OPTION violation 000 (no subclass)


HZ Remote database access (See ISO/IEC 9579-2 for the
definition of protocol subconditions
and subclass code values)

B.5.2. ODBC SQLSTATE Values and Errors


Table B–3 lists ODBC SQLSTATE values and errors.

Table B–3. ODBC Error Codes

SQLSTATE Error

S0001 Base table or view already exists


S0002 Base table not found
S0011 Index already exists
S0012 Index not found
S0021 Column already exists
S0022 Column not found
S1000 General error
S1001 Memory allocation failure
S1002 Invalid column number
S1003 Program type out of range
S1004 Std data type out of range
S1008 Operation canceled
S1009 Invalid argument value
S1010 Function sequence error
S1012 Invalid transaction operation code specified
S1015 No cursor name available
S1090 Invalid string or buffer length
S1091 Descriptor type out of range
S1092 Option type out of range
S1093 Invalid parameter number
S1094 Invalid scale value
S1095 Function type out of range

B–14 7830 8160–027


SQLSTATE

Table B–3. ODBC Error Codes

SQLSTATE Error

S1096 Information type out of range


S1097 Column type out of range
S1098 Scope type out of range
S1099 Nullable type out of range
S1100 Uniqueness option type out of range
S1101 Accuracy option type out of range
S1103 Direction option out of range
S1104 Invalid precision value
S1106 Fetch type out of range
S1107 Row value out of range
S1108 Concurrency option out of range
S1110 Invalid driver completion
S1C00 Driver not capable
S1DE0 No data at execution values pending
S1T00 Timeout expired

7830 8160–027 B–15


Routine and Trigger Compilation Errors

B.6. Routine and Trigger Compilation Errors


The definition of a routine or trigger typically is a lengthy set of characters that
consists of several individual RDMS statements. If an error is detected during the
compilation of the routine or trigger, RDMS attempts to determine the number of the
line and the column position within the line that is causing the problem. To this end,
RDMS assumes a command string of 80 characters per line. To enhance readability
and for accelerated error location, it is recommended that large definitions be blocked
out in 80-character segments.

For example, a procedure definition in UCS C can be written as follows:

rsa("PROCEDURE HOUSE_SCHEMA.RSA1080( OUT P01 CHAR(20) ) \


BEGIN \
LOCK HOUSE_SCHEMA.TB00; \
END; ",error-status,aux);-

The continuation character ( \ ) forms 80-character segments of the single command


string.

This procedure definition produces the following lines of error messages:

APP 3 RDM IN 6000 The following RDM messages were encountered while compiling
routine, HOUSE_SCHEMA.RSA1080 :

APP 3 RDM IN 6060 The following syntax error occurred at line 3,


column 10 :

APP 3 RDM IN 7010 *ERROR 1080: This command is not allowed within a stored
procedure, function, or trigger :

The technique for this kind of source formatting varies with the programming
language used to interface with RDMS.

B–16 7830 8160–027


Appendix C
Error Handling in ESQL

This appendix discusses tools and methods for handling ESQL errors during program
execution.

C.1. Tools for ESQL Error Handling


RDMS tools for handling errors in ESQL include

• The WHENEVER statement


• The SQLCODE variable
• The SQLSTATE variable (if the program is compiled using a sufficiently high level of
UCS C or UCS COBOL, or by client-based tools that support SQLSTATE and that
also call an interface that supports SQLSTATE)
• The GETERROR statement
• The relational data management communication area (RDMCA) variables
ERROR-STATUS and AUX-INFO

You can use these tools alone or in combination. For example, a program can use all of
the tools or just SQLSTATE, GETERROR, and AUX-INFO.

Error handling is not warranted for static ESQL statements that are processed entirely
during program compilation. These statements include the following:

USE DEFAULT QUALIFIER


USE DEFAULT VERSION
ALLOCATE CURSOR
DECLARE CURSOR
SET STATISTICS
WHENEVER
DEBUG

These statements warrant error-handling code if used dynamically, however.

7830 8160–027 C–1


Altering Program Flow with the WHENEVER Statement

C.2. Altering Program Flow with the WHENEVER


Statement
You can use the WHENEVER statement to change the flow of control in a program
when an SQL error occurs. The WHENEVER statement requires either an SQLERROR
or a NOT FOUND clause. The SQLERROR clause does not report not found conditions.

• A WHENEVER SQLERROR CONTINUE statement specifies that execution continue


after encountering an SQL error. You get the same result if you do not use a
WHENEVER SQLERROR statement in the program.
• A WHENEVER NOT FOUND CONTINUE statement specifies that execution
continue after encountering a not-found condition. You get the same result if you
do not use a WHENEVER NOT FOUND statement in the program.

C.2.1. Example Using the WHENEVER Statement


Suppose you want to insert some rows into a database and then fetch some or all of
the rows from the CUSTOMER.HOUSES table. You want to take a different course of
action, however, if no rows are found or if you encounter an error.

The following lines of code illustrate one approach to this problem:

EXEC SQL WHENEVER SQLERROR GO TO error-exit-para END-EXEC.


EXEC SQL INSERT INTO houses
VALUES('H108','St Paul',95000,'3-bedroom house') END-EXEC.
.
.
.
PERFORM fetch-para thru fetch-exit.
.
.
.
error-exit-para.
(do error processing, clean up, and stop run)

fetch-para.
EXEC SQL WHENEVER NOT FOUND GO TO fetch-exit END-EXEC.
(do fetch)
GO TO fetch-para.

fetch-exit.
EXIT.

C.2.2. Scope of the WHENEVER Statement


The scope of the WHENEVER statement is determined by the sequence of the source
statements in the program, not the execution sequence. Because of this, you should
use a WHENEVER SQLERROR CONTINUE statement at the beginning of the
error-handling paragraph. Otherwise, the error-handling paragraph falls under the
scope of the preceding WHENEVER statement, which can lead to infinite loops if you
encounter an SQL error while executing the error-handling paragraph.

C–2 7830 8160–027


Using SQLCODE in an ESQL Program

C.3. Using SQLCODE in an ESQL Program


You can use the special SQLCODE variable to expedite the development of error
handling code. SQLCODE is always a part of an embedded program, but you must
declare it if you want to use it. For the syntax of this declaration, see either

• COBOL Compiler Programming Reference Manual Volume 2


• C Compiler Programming Reference Manual Volume 2

The value in SQLCODE after an SQL statement is executed indicates the completion
status of that SQL statement.

The following table illustrates how to interpret the values in SQLCODE.

SQLCODE Interpretation Explanation

0 Successful completion No errors encountered. The SQL statement


has executed normally.
+100 No data No data or no more data. This status is
returned in all cases where the interpreter
interface returns “6001”. It is also returned
when a DELETE, INSERT, or UPDATE
statement does not affect a row.
+6000 Warning The SQL statement executed normally;
however, an accompanying message was
issued regarding a noncritical condition.
Än Error RDMS returns the negative of the error code
the interpreter interface (ENTER MASM)
would have returned. For example, for the
“deadlock” exception, RDMS sets SQLCODE
to -6010. The interpreter interface returns
6010 for the same error (see Appendix B).

7830 8160–027 C–3


Using SQLCODE in an ESQL Program

C.3.1. Migrating UCOB Programs to ESQL Without SQLCODE


You are not required to use SQLCODE in ESQL. Within a UCOB program, you can use
the RDMCA variables. For more information on declaring and using RDMCA variables,
see C.6 and the COBOL Compiler Programming Reference Manual Volume 2.

In some cases, this simplifies the migration to ESQL. To migrate an existing interpreter
interface program to ESQL without using SQLCODE, perform the following steps:

1. Replace the declaration of the variables passed as the second and third
parameters in the ENTER MASM ‘ACOB$RDMR’ statements with the following:
EXEC SQL BEGIN DECLARE SECTION END-EXEC.
01 RDMCA.
02 ERROR-STATUS PIC 9(4)
02 AUX-INFO PIC S9(9) BINARY.
EXEC SQL END DECLARE SECTION END-EXEC.

The variables within the RDMCA must appear within the DECLARE section and be
spelled ERROR-STATUS and AUX-INFO.
2. Modify the program to use RDMCA.ERROR-STATUS and RDMCA.AUX-INFO.
3. Change the ENTER MASM syntax in the program to ESQL syntax.

C.3.2. Migrating to ESQL with SQLCODE


To migrate from an existing interpreter interface program to ESQL using the SQLCODE
variable, make the following changes:

• Replace existing tests of ERROR-CODE, the error status variable used by the
program, with the WHENEVER statement where possible:
ᔭ “IF ERROR-CODE <> OK” can sometimes be replaced with “WHENEVER
SQLERROR GO TO <label>”.
ᔭ “IF ERROR-CODE = ‘6001’” (a not-found condition) can sometimes be replaced
with “WHENEVER NOT FOUND GO TO <label>”.
• Replace remaining comparisons of ERROR-CODE to zero with a comparison of
SQLCODE to zero.
• Replace remaining comparisons of ERROR-CODE to ‘6001’ with a comparison of
SQLCODE to +100.
• Replace remaining comparisons of ERROR-CODE to anything other than ‘6001’ (for
example, ‘nnnn’) with a comparison of SQLCODE to -nnnn.

An SQLCODE of +100 usually corresponds to an ERROR-CODE of '6001', except where


the UPDATE, INSERT, and DELETE statements affect zero records because the WHERE
clause did not select any records. In this case, ERROR-CODE should be ‘0000’ and
AUX-INFO should be 0; SQLCODE, however, should be +100.

C–4 7830 8160–027


Using SQLSTATE in an ESQL Program

C.4. Using SQLSTATE in an ESQL Program


You can use the special SQLSTATE variable to expedite the development of error-
handling code. Because SQLSTATE returns more standard values than SQLCODE, you
can use it for more precise error handling. For a description of SQLSTATE values and
their relationship to SQLCODE, see C.5. Unlike SQLCODE, SQLSTATE is not always part
of an embedded program. You must declare SQLSTATE if you want to use it.

7830 8160–027 C–5


Using the GETERROR Statement in ESQL

C.5. Using the GETERROR Statement in ESQL


You can use the GETERROR statement to retrieve error message text into an ESQL
program from RDMS when an exception occurs. The GETERROR statement functions
the same in ESQL as in the interpreter interface, but you must use embedded
variables instead of placeholders.

Examples
The following are valid examples of the GETERROR statement:

EXEC SQL GETERROR INTO :msg-text(1), :msg-text(2) END-EXEC.

GETERROR INTO :msg-text(1), :msg-text(2).

GETERROR INTO msg-text(1), msg-text(2).

All of these examples are acceptable syntax and retrieve text for ESQL, or for SQL
statements that are not embedded.

Note that the second and third examples do not have the embedded prefix and suffix,
and that the third example does not have the colon prefix for embedded variables.
The embedded prefix and suffix are optional on the GETERROR statement. The colon
prefix is also optional on embedded variables.

SQLCODE, ERROR-STATUS, and AUX-INFO are not changed on the GETERROR call.

Note: If an error occurs in the execution of an ESQL statement, you must execute
the GETERROR statement through ESQL also. Similarly, you must execute the
GETERROR statement following an erring interpreter interface SQL statement
through the interpreter interface.

C–6 7830 8160–027


Using UCOB RDMCA Variables ERROR-STATUS and AUX-INFO

C.6. Using UCOB RDMCA Variables ERROR-STATUS


and AUX-INFO
RDMS works with the Universal Compiling System (UCS) and the UCS Runtime
System to pass more detailed information back to a UCOB program.

By declaring RDMCA in the embedded declarative section of the DATA DIVISION, you
have access to the 4-digit RSA error status and auxiliary information. This includes the
rollback status and the number of records affected by an UPDATE, DELETE, INSERT, or
REVOKE statement.

For more information on declaring and using the RDMCA variables, see the COBOL
Compiler Programming Reference Manual Volume 2.

7830 8160–027 C–7


Using UCOB RDMCA Variables ERROR-STATUS and AUX-INFO

C–8 7830 8160–027


Appendix D
Using RDMS with ASCII COBOL

This appendix explains how to use SQL statements from an ASCII COBOL program. It
discusses only the interpreter interface. ESQL is not available from ASCII COBOL
programs.

D.1. SQL Statements in ASCII COBOL Programs


To use SQL statements in an ASCII COBOL program, place each statement in an
ENTER MASM statement:

ENTER MASM 'ACOB$RDMR'


USING sql-statement
error-status
auxiliary-information
program-variable-name1
program-variable-name2
.
.
.
program-variable-name28.

where:

sql-statement
is a literal or program variable containing an SQL statement.

error-status
is a PIC XXXX (or 9999 DISPLAY) item that, upon completion of the
ENTER MASM statement, contains the error status of that SQL statement. A
value of ‘0000’ means that the statement has no errors. Use a variable name
such as ERRSTAT to hold the error status value. For more information, see
Table D–1.

auxiliary-information
is a multipurpose 1-word numeric item that, upon completion of the ENTER
MASM statement, contains useful information about error-status. You must
declare this variable as S1(36) or S9(10) USAGE COMP. For more information,
see Table D–1.

7830 8160–027 D–1


SQL Statements in ASCII COBOL Programs

program-variable-name1, ... ,program-variable-name28


are application program variable names associated with placeholder variables.
You must declare at least one program variable in the application program.
The number of program variables should equal the number of distinct
placeholder variables in the SQL statement.

Table D–1. Error Status and Auxiliary Information in ASCII COBOL

ERROR-
STATUS Contents of AUXILIARY-INFORMATION

0000* For statement


• UPDATE, the number of updated rows.
• INSERT, the number of inserted rows.
• DELETE, the number of deleted rows.
• UNLOAD, the number of unloaded rows.
• REVOKE, the number of privileges removed.
• LOCATE, 0 if the specified row exists. 1 if the specified row does
not exist.
• DROP ROLE, the number of roles dropped plus the number of
users who had been members of the dropped role.
1 to 1999 The column number where the syntax error was encountered in the
statement.
6000 to The numbers 0, 1, and 2 have meanings as follows:
6999 0 RDMS did not roll back the thread. Unless ERROR-STATUS
indicates an end-of-cursor condition (6001), the statement was not
executed.
1 The statement was not executed to completion, and RDMS rolled
back any changes made by the statement before execution was
interrupted.
2 RDMS rolled back the thread. The statement was not executed.
Any changes made to the database since the last rollback or
commit are discarded. All cursors are closed.
7000 to 7999 RSA warning messages, usually generated by the SQL FLAGGER.
8000 to Not applicable.
8999
All other The column number indicating how much of the statement was parsed
values before the error was found. Note that a column number is not always
relevant.

* If the SET AUXINFO statement was not used, or SET AUXINFO RECORD COUNT
was used, then the contents for the auxiliary-information parameter will display
as indicated.

D–2 7830 8160–027


SQL Statements in ASCII COBOL Programs

For SET AUXINFO PAGE COUNT, the first half of aux-info gives the count of
modified pages; the second half gives the count of modified rows.

For SET AUXINFO OFF, a value of zero (0) is returned in aux-info.

Although RDMS allows up to 263 parameters (including sql-statement, error-status,


and auxiliary-information), ASCII COBOL limits an ENTER MASM statement to 31
parameters. This permits a maximum of 28 program variables because the first three
parameters are reserved for sql-statement, error-status, and auxiliary-information.
For information on how to overcome this ASCII COBOL limit, see Appendix G.

Example: The BEGIN THREAD Statement


To begin a work session, use the following call statement with the BEGIN THREAD
statement (application group and thread names are for this example only):

ENTER MASM 'ACOB$RDMR'


USING 'BEGIN THREAD T1 FOR APPLICATION UDSSRC READ;'
ERRSTAT
AUXINF.
IF ERRSTAT NOT ZERO PERFORM ERRCHK.

where:

ERRSTAT
is the program variable that receives the error status messages from RDMS.

AUXINF
is the program variable that contains any auxiliary information about the
statement.

Note: The variables ERRSTAT and AUXINF are program variables defined in the
application program.

If the value of ERRSTAT is not zero, the program branches to an error-handling


paragraph called ERRCHK.

7830 8160–027 D–3


Passing Data to RDMS

D.2. Passing Data to RDMS


Any program variable arguments that send data to RDMS can be any of the following
data types:

• COMP (signed or unsigned)


• COMP-1
• COMP-2
• COMP-3 (signed or unsigned)
• Numeric DISPLAY with a sign clause of SIGN LEADING SEPARATE, SIGN TRAILING
SEPARATE, or SIGN TRAILING. The recommended method, however, is to use a
leading sign as a separate character. This is because RDMS uses numeric DISPLAY
parameters with leading separate signs when it returns data to a program
(see D.3). For consistency, you may want to use the same form of numeric
DISPLAY variables for passing data to and receiving data from RDMS.
• Alphanumeric

Alphanumeric edited and USAGE DISPLAY-1 (Fieldata) characters are not supported.

An alphanumeric program variable argument, containing any alphabetic character,


must correspond to a CHARACTER value (that is, a column of type CHARACTER).

A CHARACTER program variable, containing only numeric characters (optionally


prepended with ‘+’ or ‘–‘) may correspond to a CHARACTER value or, in many cases,
may correspond to a numeric, date, time, or timestamp value. RDMS implicitly
converts, with proper conversion, character data to numeric, date, time, or timestamp
data when the character data is compared with (for example, WHERE clause) or
assigned to (for example, INSERT) a column of numeric, date, time, or timestamp.
Such character data may not be used as part of an arithmetic expression. For example,
you may insert the string ‘123’ into an integer column or compare an integer column to
the value ‘+456’. You can insert the string ‘2007-07-24’ into a date column. You cannot
divide the string ’789’ by 4.

A numeric program variable argument (for example, COMP) must correspond to a


numeric database value. RDMS performs the appropriate conversions.

A DECLARE CURSOR statement with placeholder variables must have a program


variable to match each placeholder variable. This gives RDMS the attributes of
variables for a subsequent OPEN statement. The DECLARE CURSOR statement uses
only the attributes of variables. The OPEN statement uses the values. Therefore, use
the same program variables in both the DECLARE CURSOR and OPEN statements.

D–4 7830 8160–027


Receiving Data from RDMS

D.3. Receiving Data from RDMS


RDMS returns data into application program variable arguments of the following types:

• COMP (signed or unsigned)


• COMP-1
• COMP-2
• COMP-3 (signed or unsigned)
RDMS allows retrieval into COMP-3 fields, with the following caveat: COBOL data
rules are observed. That is, for displayed COMP-3 fields, the number of places
displayed is based on the number of digits in the fields. Alignment is based on the
PICTURE clause. Truncation may therefore occur on most significant digits where
arithmetic results yield a value larger than the PIC size of the variable.
• Numeric DISPLAY. If the item receiving the data to be stored is signed, the sign
should be a separate, leading character. Use the SIGN LEADING SEPARATE clause
when declaring these variables.
• Alphanumeric

RDMS does not allow the following application program variable arguments:

• Numeric edited
• Alphanumeric edited
• USAGE DISPLAY-1 (Fieldata characters)
• Any attempt to store into a constant

If the application program variable argument is an unsigned numeric item, RDMS strips
any sign before storing a value into the application program variable argument.

You can store any data type into an alphanumeric program variable argument. RDMS
also stores numeric items as a string with a decimal point inserted at the proper
position. You can store only numeric values in numeric program variable arguments.
RDMS converts the different numeric data types as needed.

7830 8160–027 D–5


User Contingencies

D.4. User Contingencies


While the program has an active thread (after BEGIN THREAD and before END
THREAD), UDS Control is registered for contingency handling. RDMS does not register
for contingency handling. This means that if a contingency (for example, guard mode
interrupt) occurs in RDMS or the program, UDS Control receives control. The
information UDS Control displays may have nothing to do with the actual contingency.

You can take one of the following two steps to obtain the information you need. Both
require reexecuting the program.

• Register the program for contingency handling.


• If you think the contingency occurred in the program and not RDMS, end the
thread before the contingency is expected.

D–6 7830 8160–027


Collecting ASCII COBOL Programs That Contain SQL Statements

D.5. Collecting ASCII COBOL Programs That


Contain SQL Statements
Any ASCII COBOL program that uses SQL statements must include the following two
relocatable elements in its data bank (D-bank):

CBEP$$RSA
RDMR-ACOBDAT

Find these elements in the first of the two RDMS product files for a particular
application group. For the default application group, this file is SYS$LIB$*RSA. Ask the
database administrator for the name of the file in any other application groups.

Example
This example illustrates how to collect an ASCII COBOL program that has SQL
statements:

@MAP,I ,USER.PROGRAM/ABS
LIB COBOL*LIBRARY.
IN USER.PROGRAM/REL
IN SYS$LIB$*RSA.CBEP$$RSA
IN SYS$LIB$*RSA.RDMR-ACOBDAT
END

If the ASCII COBOL program also calls DMS or SFS, other steps are necessary. For
details, see the Universal Data System Configuration Guide.

Since RDMS uses the full 262K address window, UDS Control must transfer some of
the program's data to and from the UDS address space. The following data must be
transferred:

• The application program variable or parameter containing the command string


• The location counter zero portion of RDMR-ACOBDAT

This data must reside between 024000 (10K) and 0615000 (203K).

None of the program data banks should overlap the RSA basic mode common bank,
C$RDMRPLB4.

This bank resides between locations 01000 and 037777. If the program banks start
below 040000, an overlap may occur and the results are unpredictable. You may get
incorrect results, irrelevant error statuses, hangups, loops, or contingencies. RDMS
returns statement statuses to programs through a parameter in the program data
bank. An overlap may therefore make it impossible for RDMS to report any error
condition.

7830 8160–027 D–7


ASCII COBOL TIP Transactions

D.6. ASCII COBOL TIP Transactions


Whenever you execute an ASCII COBOL program in a TIP environment, add the
following command to the COBOL application program, and then execute it before
calling ACOB$RDMR in each TIP executable element.

CALL 'RSA$INIT'.

For programs registered with TIP as a reentrant, self-initializing, or high-volume


transaction, the RSA$INIT subroutine initializes (zero-fills) the portion of element
RDMR-ACOBDAT used by RDMS as its work area.

D–8 7830 8160–027


Example ASCII COBOL Program

D.7. Example ASCII COBOL Program


The program main routine

1. Establishes a thread (work session with UDS Control)


2. Declares a cursor on table CUSTOMERS
3. In a loop, fetches one row at a time and displays its contents
4. When the end of the cursor is encountered, closes the cursor and ends the thread

D.7.1. Data Handling


The example program declares the following variables:

• AUX-INFO
This variable receives the column position if RDMS detects an error. It also
receives information if an UPDATE, DELETE, REVOKE, INSERT, or LOCATE
statement is issued. None of these statements are in this program.
• ERROR-STATUS
This is the variable into which RDMS places the status of each statement. It must
be four ASCII characters.
• The following four variables correspond to the placeholder variables in the FETCH
statement. Each variable receives the value of the corresponding data column in
the fetched row. Variables must have data types compatible with their associated
column data types.
Hno
Locus
Price
Desc

The choice of names is unimportant. However, you must have COBOL program
variables for the error status, the error column, and the fetched values of each
column.
Since the BEGIN THREAD statement does not use the UDSMESSAGES option,
each call to ACOB$RDMR is followed by a check of the error status.

7830 8160–027 D–9


Example ASCII COBOL Program

D.7.2. Source Code


This is the code for the example program:

IDENTIFICATION DIVISION.
PROGRAM-ID. list-houses.
AUTHOR. DAA
DATE-WRITTEN. 1998 August 11
DATE-COMPILED.
*
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. UNIVAC-1100.
OBJECT-COMPUTER. UNIVAC-1100.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 aux-info PIC S9(10) USAGE COMP.
01 aux-inf redefines aux-info.
02 aux-page-count PIC S9(5)USAGE COMP.
02 aux-record-count PIC S9(5)USAGE COMP.
01 error-status PIC 9999.
01 result.
10 FILLER OCCURS 4.
15 error-line PIC X(132).
01 i PIC 9999.
01 err-end-flag PIC 9999.
01 hno PIC X(4).
01 locus PIC X(28).
01 price PIC S9(10) SIGN LEADING SEPARATE.
01 desc PIC X(40).
01 label-line.
04 FILLER PIC X(4) VALUE IS 'Hno'.
04 FILLER PIC X(1) VALUE IS ' '.
04 FILLER PIC X(28) VALUE IS 'Location'.
04 FILLER PIC X(1) VALUE IS ' '.
04 FILLER PIC X(10) VALUE IS 'Price'.
04 FILLER PIC X(1) VALUE IS ' '.
04 FILLER PIC X(40) VALUE IS 'Description'.
*
PROCEDURE DIVISION.
*
main-control SECTION.
*
go-to-it.
*

D–10 7830 8160–027


Example ASCII COBOL Program

DISPLAY label-line UPON PRINTER.


ENTER MASM 'ACOB$RDMR' USING
'BEGIN THREAD FOR APPLICATION udssrc READ ;',
error-status, aux-info.
IF error-status NOT = 0 GO TO error-par.
ENTER MASM 'ACOB$RDMR' USING
'USE DEFAULT QUALIFIER realty ;',
error-status, aux-info.
IF error-status NOT = 0 GO TO error-par.
*
*
* Dump the relation
*
*
*
* Define the cursor
*
*
ENTER MASM 'ACOB$RDMR' USING
'DECLARE dmprel CURSOR SELECT * FROM houses ;',
error-status, aux-info.
IF error-status NOT = 0 GO TO error-par.
*
*
* Loop to read and print the rows
*
*
PERFORM fetch-par THRU exit-fetch-par
UNTIL error-status NOT = 0 .
*
*
* End of relation found
*
*
DISPLAY SPACES UPON PRINTER.
DISPLAY 'End of relation.' UPON PRINTER.
ENTER MASM 'ACOB$RDMR' USING
'END THREAD ;',
error-status, aux-info.
IF error-status NOT = 0 GO TO error-par.
DISPLAY 'Normal end of program.' UPON PRINTER.
STOP RUN.
*
*
*
*
*
fetch-par.
ENTER MASM 'ACOB$RDMR' USING
'FETCH dmprel INTO $p1, $p2, $p3, $p4 ;',
error-status, aux-info, hno, locus,
price, desc.

7830 8160–027 D–11


Example ASCII COBOL Program

IF error-status = 6001 GO TO exit-fetch-par.


IF error-status NOT = 0 GO TO error-par.
DISPLAY hno, SPACE, locus, SPACE, price, SPACE, desc
UPON PRINTER.
exit-fetch-par.
EXIT.
*
*
* Check for error.
*
*
error-par.
MOVE 0 TO err-end-flag.
PERFORM do-geterror UNTIL err-end-flag NOT = 0 .
ENTER MASM 'ACOB$RDMR' USING
'END THREAD ;',
error-status, aux-info.
DISPLAY 'Abnormal end of program.' UPON PRINTER.
STOP RUN.
*
do-geterror.
*
ENTER MASM 'ACOB$RDMR' USING
'GETERROR INTO $p1, $p2, $p3, $p4 ;',
error-status, aux-info,
error-line(1), error-line(2),
error-line(3), error-line(4).
PERFORM look-for-result-of-geterror-pr
VARYING i FROM 1 BY 1 UNTIL i > 4 .
*
look-for-result-of-geterror-pr.
IF error-line(i) NOT = SPACE
DISPLAY error-line(i) UPON PRINTER
ELSE
MOVE 5 TO i.
MOVE 1 TO err-end-flag.

D.7.3. Output
After compilation, collection, and execution, this example COBOL program provides
the following output:

HNO LOCATION PRICE DESCRIPTION


H101 WOODBURY +0000130000 2-BEDROOM CONDOMINIUM
H102 WOODBURY +0000040000 HANDYMAN'S SPECIAL
H103 WESTCHESTER +0000090000 DUPLEX
H104 PARKWAY HEIGHTS +0000085000 3-BEDROOM TOWN HOUSE
H105 TURTLE CREEK +0000110000 4-BEDROOM HOUSE
END OF RELATION.
NORMAL END OF PROGRAM.

D–12 7830 8160–027


Appendix E
Using RDMS with ASCII FORTRAN

This appendix explains how to use SQL statements from an ASCII FORTRAN program.
It discusses only the interpreter interface. ESQL is not available from ASCII FORTRAN
programs.

E.1. SQL Statements in ASCII FORTRAN Programs


To submit an SQL statement from an ASCII FORTRAN program, place the SQL
statement in a CALL command to RDMS:

CALL F$RDMR(sql-statement, error-status,


$ auxiliary-information, program-variable-1,
$ program-variable-2,...,program-variable-n)

where:

F$RDMR
is the entry point into RDMS for ASCII FORTRAN.

sql-statement
is a CHARACTER item, a string or program variable containing a statement.

error-status
is a CHARACTER*4 item that, when it exits the CALL command, contains the
status of the statement. The value '0000' means that the statement did not
terminate in or cause an error. For more information, see Table E–1.

auxiliary-information
is a multipurpose INTEGER item that, when it exits the CALL command, contains
useful information, depending on the value of error-status or the type of
statement. For more information, see Table E–1.

program-variable-1,...,n
are application program variable names. Each application program variable is
associated with a placeholder variable ($P1, $P2, and so forth) in the statement.
You must declare at least one program variable in the program.

7830 8160–027 E–1


SQL Statements in ASCII FORTRAN Programs

Table E–1. Error Status and Auxiliary Information in ASCII FORTRAN

ERROR-STATUS Contents of AUXILIARY-INFORMATION

0000* For statement


• UPDATE, the number of updated rows.
• INSERT, the number of inserted rows.
• DELETE, the number of deleted rows.
• UNLOAD, the number of unloaded rows.
• REVOKE, the number of privileges removed.
• LOCATE, 0 if the specified row exists; 1 if the specified row
does not exist.
• DROP ROLE, the number of roles dropped plus the number
of users who had been members of the dropped role.
1 to 1999 The column number where the syntax error was encountered in
the statement.
6000 to 6999 The numbers 0, 1, and 2 have meanings as follows:
0 RDMS did not roll back the thread. Unless ERROR-STATUS
indicates an end-of-cursor condition (6001), the statement
was not executed.
1 The statement was not executed to completion, and RDMS
rolled back any changes made by the statement before
execution was interrupted.
2 RDMS rolled back the thread. The statement was not
executed. Any changes made to the database since the last
rollback or commit are discarded. All cursors are closed.
8000 to 8999 Not applicable.
All other values The column number indicating how much of the statement was
parsed before the error was found. Note that a column number
is not always relevant.

* If the SET AUXINFO statement was not used, or SET AUXINFO RECORD COUNT
was used, then the contents for the auxiliary-information parameter will display
as indicated.

For SET AUXINFO PAGE COUNT, the first half of aux-info will give the count of
modified pages; the second half will give the count of modified rows.

For SET AUXINFO OFF, a value of zero (0) is returned in aux-info.

Although RDMS allows up to 263 parameters (including sql-statement, error-status,


and auxiliary-information), ASCII FORTRAN can pass no more than 250 arguments.
Hence, it is the ASCII FORTRAN limit that applies. RDMS uses the term “parameter”
where ASCII FORTRAN uses the term “argument.”

E–2 7830 8160–027


SQL Statements in ASCII FORTRAN Programs

Example: The BEGIN THREAD Statement


This example illustrates a CALL command to RDMS that contains a BEGIN THREAD
statement in an ASCII FORTRAN program:

CALL F$RDMR('BEGIN THREAD T1 FOR UDSSRC READ;',


$ ERROR,AUXINF)
IF (ERROR .NE. '0000') GO TO 9000 @ ERROR-HANDLING CODE

ERROR is the variable that contains the error status. AUXINF is the application program
variable that contains additional information about the SQL statement.

7830 8160–027 E–3


Passing Data to RDMS

E.2. Passing Data to RDMS


All numeric data types are allowed as program variable arguments that pass data to
RDMS. However, if a program variable argument is COMPLEX, only the real portion is
used.

A numeric program variable argument must correspond to a numeric value or column.


If the application program variable argument and the value are both numeric but of
different data types, RDMS performs appropriate conversions.

RDMS treats LOGICAL program variable arguments as if they were type INTEGER.

A CHARACTER program variable argument, containing any alphabetic character, must


correspond to a CHARACTER value (that is, a column of type CHARACTER).

A CHARACTER program variable, containing only numeric characters (optionally


prepended with ‘+’ or ‘–‘) may correspond to a CHARACTER value or, in many cases,
may correspond to a numeric, date, time, or timestamp value. RDMS implicitly
converts, with proper conversion, character data to numeric, date, time, or timestamp
data when the character data is compared with (for example, WHERE clause) or
assigned to (for example, INSERT) a column of numeric, date, time, or timestamp.
Such character data may not be used as part of an arithmetic expression. For example,
you may insert the string ‘123’ into an integer column or compare an integer column to
the value ‘+456’. You can insert the string ‘2007-07-24’ into a date column. You cannot
divide the string ’789’ by 4.

CHARACTER strings that contain Fieldata characters cannot be used.

Hollerith constants (for example, 5H?><+*) are allowed as program variable


arguments, but the constant is assumed to have a length of 511 characters.
Otherwise, a Hollerith constant is treated as a CHARACTER program variable
argument.

Program labels and subprograms are not valid program variable arguments.

A DECLARE CURSOR statement with placeholder variables must have a program


variable to match each placeholder variable. This gives RDMS the attributes of
variables for a subsequent OPEN statement. The DECLARE CURSOR statement uses
only the attributes of variables. The OPEN statement uses the values. Therefore, use
the same program variables in both the DECLARE CURSOR and OPEN statements.

E–4 7830 8160–027


Receiving Data from RDMS

E.3. Receiving Data from RDMS


RDMS can store data in all types of numeric program variable arguments. However, if
a program variable argument is COMPLEX, RDMS can store a value only into its real
portion.

If you attempt to store a CHARACTER value in a numeric program variable argument,


an error is returned.

RDMS performs appropriate conversions before storing data in a numeric program


variable argument.

RDMS treats LOGICAL program variable arguments as if they were integers.

CHARACTER program variable arguments are allowed. If the value to be stored is


numeric, it is edited into the program variable argument using a suitable F-format. You
cannot store CHARACTER values into numeric program variable arguments.

Constants are not allowed as program variable arguments that are to receive data
from RDMS.

7830 8160–027 E–5


Calling F$RDMR

E.4. Calling F$RDMR


The ASCII FORTRAN application program module that calls F$RDMR must be compiled
in such a way that the argument type checking code is enabled. If the argument type
checking information is not part of the parameter list, F$RDMR aborts the program.

You can compile subprograms that do not call F$RDMR to ignore type checking for
arguments.

The F$RDMR procedure has no fixed number of parameters. This violates FORTRAN
conventions, and the compiler may issue warning messages as a consequence.
These warnings can be safely ignored.

F$RDMR does not accept banked data. The program aborts when you pass banked
data to F$RDMR.

E–6 7830 8160–027


User Contingencies

E.5. User Contingencies


While the program has an active thread (after BEGIN THREAD and before END
THREAD), UDS Control is registered for contingency handling. RDMS does not register
for contingency handling. This means that if a contingency (for example, guard mode
interrupt) occurs in RDMS or the program, UDS Control receives control. The
information it displays may have nothing to do with the actual contingency.

You can take one of the following two actions to obtain the information you need.
Both require re-executing the program.

• Register the program for contingency handling.


• If you believe the contingency occurred in the program and not RDMS, end the
thread before the contingency is expected.

7830 8160–027 E–7


Collecting ASCII FORTRAN Programs That Contain SQL Statements

E.6. Collecting ASCII FORTRAN Programs That


Contain SQL Statements
Any ASCII FORTRAN program that uses SQL statements must include the following
two relocatable elements in its D-bank:

CBEP$$RSA
RDMR-ACOBDAT

Find these elements in the first of the two RDMS product files for a particular
application group. For the default application group, this file is SYS$LIB$*RSA. Ask the
database administrator for the name of the file in any other application groups.

Example
This example illustrates how to collect an ASCII FORTRAN program that contains SQL
statements:

@MAP,I ,USER.PROGRAM/ABS
LIB FORTRAN*LIB.
IN USER.PROGRAM/REL
IN SYS$LIB$*RSA.CBEP$$RSA
IN SYS$LIB$*RSA.RDMR-ACOBDAT
END

Because RDMS uses the full 262K address window, UDS Control must transfer some
of the program’s data to and from the UDS address space. The following data must be
transferred:

• The host program variable that contains the command string


• The location counter zero portion of RDMR-ACOBDAT

This data must reside between 024000 (10K) and 0615000 (203K).

None of the program data banks should overlap the RSA common bank,
C$RDMRPLB4.

This bank resides between locations 01000 and 037777. If the program banks start
below 040000, an overlap may occur and the results are unpredictable. You may get
incorrect results, irrelevant error statuses, hangups, loops, or contingencies. RDMS
returns the status of statements to programs through a parameter in the program
data bank. An overlap may therefore make it impossible for RDMS to report any error
condition.

E–8 7830 8160–027


ASCII FORTRAN TIP Transactions

E.7. ASCII FORTRAN TIP Transactions


Whenever you execute an ASCII FORTRAN program in a TIP environment, add the
following command to the FORTRAN application program, and then execute it before
calling F$RDMR in each TIP executable element.

CALL RSA$IN

For programs registered with TIP as a reentrant, self-initializing, or high-volume


transaction, the RSA$IN subroutine initializes (that is, fills with zeros) the portion of
element RDMR-ACOBDAT used by RDMS as its work area.

7830 8160–027 E–9


Example FORTRAN Program

E.8. Example FORTRAN Program


The program main routine

• Establishes a thread (work session with UDS Control)


• Declares a cursor on table CUSTOMERS
• In a loop, fetches one row at a time and displays its contents
• Closes the cursor and ends the thread when it reaches the end of the cursor

E.8.1. Data Handling


The example program declares the following variables:

• auxinf
This variable receives the column position if RDMS detects an error. It also
receives information if an UPDATE, DELETE, or REVOKE statement is issued. None
of these statements are in this program.
• errcod
This is the variable into which RDMS places the status of each statement. It must
be four ASCII characters.
• The following four variables correspond to the placeholder variables in the FETCH
statement. Each variable receives the value of the corresponding data column in
the fetched row. Variables must have data types compatible with their associated
column data types.
cno
cname
maxpri
desloc

The choice of names is unimportant. However, you must have FORTRAN program
variables for the error status, the error column, and the fetched values of each
column.
Since the BEGIN THREAD statement does not use the UDSMESSAGES option,
each call to F$RDMR is followed by a call to a subroutine to check the error status
in errcod. This subroutine is passed to the error column, error status, the expected
status (if it is not 0000), and two return points, one to receive control if an
unexpected error is encountered, the other if the error status is expected.

E–10 7830 8160–027


Example FORTRAN Program

• Since the error checking subroutine, errchk, calls F$RDMR (to perform GETERROR
statements), it declares the following variables. (To avoid truncated error message
lines, each of these variables must be able to hold up to 80 characters.)

errloc Receives the RDMS status for the GETERROR statement.


Colloc Receives the column position should an error occur in a
GETERROR statement.
p1, p2, p3, and p4 Each receives one line of error message.

E.8.2. Source Code


This is the code for the example FORTRAN program:

C
C
C
C Main program to dump the relations CUSTOMERS
C ******************************************
C
C
C
INTEGER auxinf, auxpgs, auxrec
CHARACTER*4 errcod
CHARACTER*4 cno @ The first column (CNO)
CHARACTER*28 cname @ The second (CNAME)
REAL maxpri @ The third (Maxprice)
CHARACTER*40 desloc @ The fourth (DesiredLoc)
C
C
C Connect to UDS and submit a USE command
C
C
CALL F$RDMR('BEGIN THREAD FOR APPLICATION udssrc READ;',
$ errcod,auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
CALL F$RDMR(’SET AUXINFO PAGE COUNT;’,errcod, auxinf)
CALL F$RDMR('USE DEFAULT QUALIFIER realty;',
$ errcod,auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
CALL F$RDMR(’UPDATE houses SET price=150000 WHERE hno=$P1;’,errcod,auxinf,p1)
auxpgs=BITS(auxinf,1,18)
auxrec=BITS(auxinf,19,18)
CALL errchk(errcod,auxinf,' ',*90,*90)
C
C
C Dump the relation
C
C
C
C Define the cursor

7830 8160–027 E–11


Example FORTRAN Program

C
C
CALL F$RDMR('DEFINE CURSOR dmprel SELECT * FROM customers ;',
$ errcod, auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
C
C
C Open the relation
C
C
CALL F$RDMR('OPEN CURSOR dmprel;', errcod, auxinf)
CALL errchk(errcod,auxinf,' ',*90,*90)
C
C
C Loop to read and print the rows
C
C
10 CONTINUE
CALL F$RDMR('FETCH NEXT dmprel INTO $p1,$p2,$p3,$p4;',
$ errcod, auxinf, cno, cname, maxpri, desloc)
CALL errchk(errcod,auxinf,'6001',*90,*20)
PRINT '(1X,A,1X,A,F12.2,1X,A)', cno, cname, maxpri, desloc
GO TO 10
C
C
C End of relation found
C
C
20 CONTINUE
PRINT '(17H0End of relation)'
CALL F$RDMR('END THREAD;', errcod, auxinf)
CALL errchk(errcod, auxinf, ' ', *90, *90)
PRINT '(23H0Normal end of program.)'
STOP
90 CONTINUE
PRINT '(39H0***** Error status terminated program.)'
STOP
END
C
C
C
C Subroutine to check the status returned by RDMS
C **********************************************
C
C
SUBROUTINE errchk(errcod, auxinf, accept, *, *)
C
CHARACTER*4 accept @ Acceptable status for RETURN 2
INTEGER colloc,auxinf
CHARACTER*4 errcod,errloc
CHARACTER*132 p1,p2,p3,p4
IF (errcod.EQ.'0000') RETURN

E–12 7830 8160–027


Example FORTRAN Program

IF (errcod.EQ.accept) RETURN 2
PRINT '(31H0***** Unexpected error status ,A,11H at column
* ,I3)',
* errcod, auxinf
CALL F$RDMR('GETERROR INTO $p1,$p2,$p3,$p4;',
* errloc, colloc, p1, p2, p3, p4)
IF (errloc .NE. '0000') THEN
PRINT '(20H ***** Error status ,A,14H from GETERROR)',
* errloc
ELSE
CALL prres
END IF
RETURN 1
C
C
C Internal subroutine to print the result of a GETERROR statement
C
C
SUBROUTINE prres
IF (p1 .NE. ' ') PRINT '(1X,A)', p1
IF (p2 .NE. ' ') PRINT '(1X,A)', p2
IF (p3 .NE. ' ') PRINT '(1X,A)', p3
IF (p4 .NE. ' ') PRINT '(1X,A)', p4
RETURN
END

E.8.3. Output
After compilation, collection, and execution, this example FORTRAN program provides
the following output:

C101 THOMPSON 150000.00 WOODBURY


C102 OWEN 70000.00 NEW LONDON
C103 JOHNSON 90000.00 WOODBURY
C104 JONES 100000.00 GREENVILLE
C105 SMITH 120000.00 WESTCHESTER
END OF RELATION.
NORMAL END OF PROGRAM.

7830 8160–027 E–13


Example FORTRAN Program

E–14 7830 8160–027


Appendix F
HVTIP Restrictions for ASCII COBOL
and ASCII FORTRAN Programs

This appendix describes some restrictions when using RDMS from an HVTIP
environment.

In the HVTIP run-time environment, only the main program D-bank space remains
intact during the program’s entire execution. Space is allocated to subprograms when
they are called; it is deallocated when they return to their callers. Unpredictable results
can occur if the program includes calls to RDMS in different compilation units (where
each unit contains a copy of the RDMS D-bank space element RDMR-ACOBDAT,
which is collected with it), unless you take the precautions described in this appendix.

The following items require carryover of information in the RDMS D-bank area
between calls to RDMS:

• GETERROR statement
The GETERROR statement requires the last statement status, relational data
management communication area (RDMCA), and possibly various GETERROR
counters to be in place.
• GET DESCRIPTION statement
The data description packet must be available (from the DECLARE CURSOR
statement), and only one column description is available per call. Various counters
are retained between calls. If the GET DESCRIPTION statement is executed in the
same program module in which the DECLARE CURSOR statement appears, you
should have no problem.
• FETCH NEXT statement shortcut
To take advantage of the performance shortcut on FETCH statements, RDMS
must be able to retain information between FETCH statements. If FETCH NEXT
statements execute within a single program module, there should be no problem.
• DEBUG statement
DEBUG flags are set in the RSA work area. Debugging takes place only within the
program module in which the DEBUG statement is executed.

7830 8160–027 F–1


HVTIP Restrictions for ASCII COBOL and ASCII FORTRAN Programs

In summary, HVTIP user restrictions are as follows:

• A GETERROR statement must be in the program modules that contain the


statement receiving the error.
• A GET DESCRIPTION statement must be in the program module that contains its
corresponding DECLARE CURSOR statement.
• The FETCH NEXT statement shortcut operates only when the FETCH statement to
which it refers is in the same program module. If it is not, the FETCH statement
still works, but does not take the shortcut.
• A DEBUG statement must be in the program module in which debugging is to
occur.

F–2 7830 8160–027


Appendix G
Passing Many Variables to RDMS

Note: If you are programming in C, use the rsa function to call RDMS. The C
function for passing parameters is rsa_param.

This appendix explains how to use the RSA$PARAM subroutine to pass the maximum
number of parameters and indicators plus the three required parameters (statement
string, error status, and auxiliary information) to RDMS from a host language on an
ENTER MASM call.

All host languages have a limit on how many parameters can be passed on an
interpreter interface call. Use the RSA$PARAM subroutine to pass the maximum
number of parameters and indicators plus the three required parameters (command
string, error status, and auxiliary information).

Call RSA$PARAM to build a list of parameters, and then call it again as many times as
necessary to pass variables before calling ACOB$RDMR (or F$RDMR, as appropriate).

You can also pass variables on the ACOB$RDMR call itself:

ENTER MASM 'RSA$PARAM' USING list-of-program-variables.

You must pass the command string, error status variable, and auxiliary information
variable when you call ACOB$RDMR. If fewer than the maximum number of variables
remain to pass to RDMS for this statement, you can pass them when you call
ACOB$RDMR.

Example 1
In the following example, suppose you need to insert a row into a 90-column table
named BIG_TABLE:

ENTER MASM 'RSA$PARAM' USING p1, p2,...,p31.


ENTER MASM 'RSA$PARAM' USING p32, p33,...,p62.
STRING 'INSERT INTO BIG_TABLE VALUES',
'($p1,$p2,... , ', '... $p89,$p90);'
DELIMITED BY SIZE INTO COMMAND.
ENTER MASM 'ACOB$RDMR' USING COMMAND, ERR-STATUS, AUX-INFO,
p63, p64,... p90.

7830 8160–027 G–1


Passing Many Variables to RDMS

You cannot “reuse” parameters passed in this way. For each SQL statement of more
than the maximum number of placeholders, you must use a separate set of
RSA$PARAM calls, as illustrated in the following example:

ENTER MASM 'RSA$PARAM' USING p1, p2,..., p10.


ENTER MASM 'RSA$PARAM' USING p11, p12,..., p20.
ENTER MASM 'RSA$PARAM' USING p21, p22,..., p30.
ENTER MASM 'ACOB$RDMR' USING sql-statement,... .
ENTER MASM 'RSA$PARAM' USING p1, p2,..., p10.
ENTER MASM 'RSA$PARAM' USING p11, p12,..., p20.
ENTER MASM 'RSA$PARAM' USING p21, p22,..., P30.
ENTER MASM 'ACOB$RDMR' USING sql-statement,... .

C programs that use the interpreter interface may also need to pass more parameters
for one SQL statement than the UCS C compiler allows. These programs may call
function rsa_param in the same manner as a COBOL program calls RSA$PARAM.

Example 2
Suppose a cursor named cur_sor is declared, joining a 15-column table with a
30-column table. The following example illustrates the retrieval of one row from the
resulting 450-column cursor.

rsa param(p1, p2, ..., p150);


rsa_param(p151, p152, ..., p300);
rsa("FETCH NEXT cur_sor INTO $P1, $P2, ..., $P450;",
error_status, &auxiliary_info,
p301, p302, ..., p450);

G–2 7830 8160–027


Appendix H
Obtaining and Freeing Work Space for
UCS Programs

A work area with an initial default allocation of about 14,000 words is provided for UCS
programs (interpreted, module, and embedded SQL) that access RDMS databases. As
more space is needed, the system acquires it dynamically.

This dynamic or automatic acquisition of space has two drawbacks:

• It incurs high overhead.


• When multiactivity programs are closed, the area allocated is not freed
automatically.

This appendix explains how to overcome both of these problems.

7830 8160–027 H–1


Acquiring Additional Work Space

H.1. Acquiring Additional Work Space


To acquire additional work space for UCS programs, first determine the amount of
space your program requires and then set the work space:

1. To determine the size of the work area, enter a DEBUG DUMP SIZES command
immediately after the program's END THREAD command.

Table H–1. DEBUG DUMP SIZES Invocation Techniques

UCS Language Invocation

C #include <rsa.h>
...
rsa("DEBUG DUMP SIZES;",error_code,&aux_info);
COBOL ...
(embedded) EXEC SQL EXECUTE IMMEDIATE 'DEBUG DUMP SIZES '
END-EXEC. ....
COBOL ...
(interpreted) ENTER MASM 'ACOB$RDMR' USING
'DEBUG DUMP SIZES;' ERROR-STATUS AUX-INFO. ...
FORTRAN ...
CALL f$rdmr('DEBUG DUMP SIZES;' ,ERRM,AUXM) ...

Other UCS interfaces use similar syntax.

2. Execute the program and check the output of the DEBUG DUMP SIZES command,
which appears in the following format:

RSA D-bank size is 13,970 words.

3. Include a call to the RSA$INIT subroutine in the program that allocates the space
desired for the RDMS work area by setting the work area size parameter. This call
must precede the first RDMS command in the program and should be the only call
to RSA$INIT. Remove the DEBUG DUMP SIZES command from the program.
The following table illustrates the syntax for RSA$INIT for the available UCS
languages. The size of the work area is a 36-bit binary integer.

H–2 7830 8160–027


Acquiring Additional Work Space

Table H–2. RSA$INIT Invocation Techniques

UCS Language Invocation

C #include <rsa.h>
int work_area_size;
...
work_area_size = 20000;
rsa_init(&work_area_size);
COBOL work-area-size PIC 1(36) Usage Binary-1 .
...
MOVE 20000 to work-area-size.
call "rsa$init" using work-area-size.
FORTRAN INTEGER work_area_size
...
work_area_size = 20000
call rsa$init(work_area_size) .

7830 8160–027 H–3


Freeing Work Space

H.2. Freeing Work Space


RSA allocates its D-bank space on the UCS Runtime System heap once for each
activity. If an area has not been allocated, RSA calls the UCS Runtime System to
allocate the space from the heap area. The area allocated is not freed until activity
termination. If the activity still has processing other than RDMS processing to perform,
the allocated space remains attached to the activity.

You can avoid this problem by calling the RSA$FREE subroutine after issuing an END
THREAD statement.

Table H–3. RSA$FREE invocation techniques

UCS Language Invocation

C #include <rsa.h>
...
rsa$free();
...
COBOL ...
call "rsa$free"
....
FORTRAN ...
call rsa$free() .
...

H–4 7830 8160–027


TIP and HVTIP Considerations

H.3. TIP and HVTIP Considerations


TIP users should use the TIPMALLOC keyword option on the main program
compilation if they are concerned about losing sticking due to large d-bank usage.
Without this option, a create-bank may occur during execution to acquire more space
causing loss of sticking. The default bank is URTS$TABLES, a small bank (262K). With
the TIPMALLOC option, they will get a large TCA bank on the LINK.

HVTIP users cannot use the TIPMALLOC option, but can get more banks using valtab
settings and making LINK changes. The default bank is URTS$TABLES.

7830 8160–027 H–5


TIP and HVTIP Considerations

H–6 7830 8160–027


Appendix I
Using BLOB Data

Multimedia applications depend on storage of a variety of large data objects, such as


scanned documents, medical images, and audio messages. RDMS provides the binary
large object (BLOB) data type and corresponding RSM-Large Object format storage
areas to handle large data efficiently. Each BLOB column value can be from 1 byte to
4 gigabytes in length (232 -1).

An RDMS table can contain 510 columns. The primary key column cannot be a BLOB;
therefore, 509 columns in a table may be BLOB columns. The data for each BLOB
column may be stored in a different set of storage areas. Each set of storage areas
may contain up to 511 storage areas. The data inserted into BLOB storage areas can be
audited and recovered.

BLOBs are generically referred to as large objects. The terms BLOB and LOB are used
interchangeably throughout the RDMS documentation.

BLOB data is stored in the RDMS database as a structure (or, in COBOL terms, as a
record). The structure of the data is set by the structure of the host language variable
declared with the BLOB data type. See the following for more information:

• I.8 for information about UCS C


• I.9 for information on UCS COBOL

Note: Use of BLOB data is not supported for the IPF SQL interface.

7830 8160–027 I–1


Creating LOB Storage Areas in UREP

I.1. Creating LOB Storage Areas in UREP


For details on creating LOB storage areas, see the Relational Database Server for
ClearPath OS 2200 Administration Guide. The following general guidelines apply:

• The LOB storage areas are identified by the DATA-FORMAT value of RSM-LOB.
• LOB storage areas may be based on EXEC or TIP files and can be large files. Each
file can be as large as 120 gigabytes.
• The default page size is 112 (words), and using that page size is encouraged for
optimal use of the storage space. If you are auditing BLOB data (storage area
attribute LOB-AUDITED is TRUE), 112 may not be the optimal page size. Because
auditing is on a page basis, using a small page size such as 112 results in the
processing of more audit looks than would be required for a larger page size. The
optimal size depends on your system configuration, however.

For more detailed information on how BLOB data is arranged in the storage area,
see the Relational Database Server for ClearPath OS 2200 Administration Guide.

Also see I.7 for recovery considerations.

I–2 7830 8160–027


Creating LOB Columns Without Specifying a Storage Area

I.2. Creating LOB Columns Without Specifying a


Storage Area
When the IN storage-area-name clause is not specified as part of the LOB declaration,
the BLOB is stored as part of the record as LOB-id and LOB-data. The LOB-id is 24
bytes. The LOB-data is the size of the LOB inserted. The maximum size LOB is ~28000
bytes because the LOB must fit on a single page along with the rest of the record.

An in-record BLOB is excellent for storing short binary data such as encrypted credit
card numbers. This provides better performance than when the BLOB is stored in a
LOB storage area. Using a BLOB is the only way to insert binary data from a JAVA
program.

7830 8160–027 I–3


Creating LOB Columns in LOB Storage Areas

I.3. Creating LOB Columns in LOB Storage Areas


To store LOB data in a database, you create an RSM-LOB format storage area to hold
the LOB data. Then you create a table having a column with data type BLOB and
assign the storage of the column to the RSM-LOB format storage area. The following
is a part of the CREATE TABLE or ALTER TABLE syntax for creating a BLOB column
(see 2.7, “RDMS Data Types,” for more information):

column-name BLOB '(' n [K|M|G] ')' IN list-of-storage-area-names


[DEFAULT 'default-blob− value']

The following sample table is used throughout the examples below:

CREATE TABLE s1.houses IN s1.data_area1


COLUMNS ARE
hno :
CHAR(4) NOT NULL,
location :
CHAR(28),
price :
INTEGER,
description :
CHAR(40),
detail_description :
BLOB(20000) IN s1.house_long_desc_1,
house_photo :
BLOB(50K) IN (s1.house_photo_1,
s1.house_photo_2)
DEFAULT 'no house_photo available'
inspection_disclosure : BLOB(1M) IN s1.house_disclosure_1
PRIMARY KEY index_0 IS hno

where:

hno
identifies the property uniquely.

location
describes where the property is located.

price
is the asking price.

description
is a short description of the property.

detail_description
is a long textual description of the property. Since this description may exceed the
7000-byte limit of the CHAR data type, it is stored in a BLOB instead.

house_photo
is a GIF or JPEG photo of the property.

inspection_disclosure
contains a formatted inspection disclosure created by a word processing program.

I–4 7830 8160–027


Creating LOB Columns in LOB Storage Areas

Note: Each BLOB column has its own storage area or areas, up to 511 storage areas
per column. If you include more than one storage area, the names must be enclosed
in parentheses and separated by commas

The following comments pertain to sizes:

• When you fetch data from a column into your application program, you will need
to allocate a buffer big enough to hold the data. If you know that the data is limited
to, say, 50K bytes, you can allocate just the right amount of memory.
• When a LOB value is stored in a table, the table entry is actually a descriptor, or
LOB-id, that points to the LOB value in a RSM-LOB storage area corresponding to
the column. The length of the LOB-id is 24 bytes. In any given table, the total size
of all the column data, including the LOB-ids for each BLOB column, cannot exceed
7168 bytes. In order to store 259 BLOB columns plus a short (CHAR(4), INTEGER,
or SHORT) primary key, the page size for the storage area containing the table
data (in our example it is s1.data_area1) must be 7168. The page size for the
storage area is calculated in words with 4 bytes per word.
• When RDMS allocates space in the storage area for a BLOB value, it allocates the
declared size number of bytes. So if the value being inserted into the column is
40,000 bytes long and the column is declared to be 50K bytes long (51,200 bytes),
RDMS allocates 51,200 bytes of storage space in the storage area. The extra
space is inaccessible for any other use.

7830 8160–027 I–5


Limitations of the BLOB Data Type

I.4. Limitations of the BLOB Data Type


BLOB columns can be used in INSERT, UPDATE, and DECLARE CURSOR commands.

In a SELECT statement, a BLOB column must meet both of the following


requirements:

• It must be selected by name.


• It must be tested with an IS [NOT] NULL predicate.

A BLOB column cannot be used in any of the following:

• Arithmetic or Boolean expressions


• GROUP BY or ORDER BY clauses
• UNIQUE expression
• Indexing, either by itself or as part of a composite key
• A query-expression that also includes UNION or UNION ALL

I–6 7830 8160–027


Calculating Record Size and Page Size for Tables with BLOB Data

I.5. Calculating Record Size and Page Size for


Tables with BLOB Data
When you insert a row containing a BLOB value into a table, and the IN
storage-area-name clause is specified, RDMS writes a BLOB-id into the row in the
position of the BLOB column. The BLOB-id tells RDMS where the BLOB value for this
column of this row is stored in the corresponding set of BLOB storage areas. The
BLOB-id is 24 bytes long. You must take this into account when setting the page size
for the data storage area for the table. When IN storage-area-name was not specified,
the BLOB-id and the BLOB value are stored as part of the record. This means that you
need to include the BLOB-id (24 bytes) plus the size of the BLOB value as part of the
record size calculation.

7830 8160–027 I–7


Calculating BLOB Storage Area Sizes

I.6. Calculating BLOB Storage Area Sizes


When you create storage areas to hold BLOB data, you must observe the rules
described in the following.

I.6.1. Calculating Minimum File Size


Each storage area must be large enough to hold 8 BLOB values. The following
examples illustrate how to calculate the minimum file size.

Example 1
A BLOB column is declared as inspection_disclosure: blob(50K) and the page size is
224 words. The minimum file size calculation is as follows:

• ((50*1024)+3)/4 = 12,800 words per BLOB value, where K = 1024 times 50. Add 3
and divide by 4, and drop any fractional part of the result to change bytes into
whole words.
• 12,800 / 224 = 57.5 pages per BLOB value. RDMS rounds up to a whole number of
pages, so there are 58 pages per BLOB value.
• 58 * 224 = 12,992 words per page-granularity BLOB value.
• 12,992 / 1792 = 7.25 tracks per BLOB value. RDMS rounds up to a whole number
of tracks, so there are 8 tracks per BLOB value.
• Eight tracks * 8 BLOB values minimum = 64 tracks, which is the minimum size for
the file.
• Add 1 track for the file control information, so the minimum file size is 65 tracks.
• Set the maximum-pages attribute for the storage area to 65*1792/224 = 520
pages.

Example 2
A BLOB column is declared as inspection_disclosure: blob(500M) and the page size is
224 words. The minimum file size calculation is as follows:

• ((500 * 1,048,576)+3)/4 = 131,072,000 words per BLOB value, where M = 1,048,576


bytes. Add 3 and divide by 4, and drop any fractional part of the result to change
bytes into whole words.
• 131,072,000 / 224 = 585,142.85 pages per BLOB value. RDMS rounds up to a whole
number of pages, so there are 585,143 pages per BLOB value.
• 585,143 * 224 = 131,072,032 words per page-granularity BLOB value.
• 131,072,032 / 1792 = 73,142.87 tracks per BLOB value. RDMS rounds up to a whole
number of tracks, so there are 73,143 tracks per BLOB value.
• 73,143 tracks * 8 BLOB values minimum = 585,144 tracks, which is the minimum
size for the file.
• Add 1 track for the file control information, so the minimum file size is 585,145
tracks.

I–8 7830 8160–027


Calculating BLOB Storage Area Sizes

• Set the maximum-pages attribute for the storage area to


(585,145*1792) / 224 = 4,681,160 pages.

Example 3
A BLOB column is declared as inspection_disclosure: blob(2G) and the page size is
224 words. The minimum file size calculation is as follows:

• ((2 * 1,073,741,824)+3)/4 = 536,870,912 words per BLOB value.


G = 1,073,741,824 bytes. Add 3 and divide by 4, and drop any fractional part of the
result to change bytes into whole words.
• 536,870,912 / 224 = 2,396,745.14 pages per BLOB value. RDMS rounds up to a
whole number of pages, so there are 2,396,746 pages per BLOB value.
• 2,396,746 * 224 = 536,871,104 words per page-granularity BLOB value.
• 536,871,104 / 1792 = 299,593.25 tracks per BLOB value. RDMS rounds up to a
whole number of tracks, so there are 299,594 tracks per BLOB value. Since this is
greater than 262,143, we must convert tracks into positions by dividing by 64.
• 299,594 tracks * 8 BLOB values minimum = 2,396,752 tracks, which is the
minimum size for the file.
• Add 1 track for the file control information; thus, the minimum file size is
2,396,753 tracks. Because this is greater than 262,143, you must convert tracks
into positions by dividing by 64. The storage area file must be cataloged at least
37,450 positions in size.
• Set the maximum-pages attribute for the storage area to
(2,396,753*1792) / 224 = 19,174,024 pages.

I.6.2. Maximum File Size


The maximum size file allowed in OS 2200 is 120 gigabytes. This gives an upper limit to
the number of BLOBs that may be stored in a single storage area. For backup and
recovery, files this large are difficult to manage and should be avoided if possible.

I.6.3. Calculating MAXIMUM-PAGES


Using track granularity, the largest file you can create is 262,143 tracks. The following
examples illustrate how to calculate the number of BLOB values that can fit into a file
of this size.

Example 1
A BLOB column is declared as inspection_disclosure: blob(50K) and the page size is
224 words. The calculation is as follows:

• From the calculations in the preceding examples, each BLOB takes 58 pages or
12,992 words.
• 262,143 * 1792 = 469,760,256 words.
• 469,760,256 minus 448 words for the file control information = 469,759,808 words
for BLOB data.

7830 8160–027 I–9


Calculating BLOB Storage Area Sizes

• 469,759,808 / 12,992 = 36,157.62 BLOB values. Round down to a whole number of


BLOB values. 36,157 BLOB values can fit in the storage area.
• Set the maximum-pages attribute for the storage area to
(262,143*1792) / 224 = 2,097,144 pages.

Example 2
A BLOB column is declared as inspection_disclosure: blob(500M) and the page size is
224 words. The calculation is as follows:

• From a calculation in a preceding example, each BLOB takes 585,143 pages or


131,072,032 words.
• 469,759,808 words are available for BLOB data.
• 469,759,808 / 585,143 = 802.81 BLOB values. Round down to a whole number of
BLOB values. 802 BLOB values can fit in the storage area.
• Set the maximum-pages attribute for the storage area to
(262,143*1792) / 224 = 2,097,144 pages.

Example 3
A BLOB column is declared as inspection_disclosure: blob(2G) and the page size is
224 words. Because the minimum file size exceeds 262,143 tracks, this size file cannot
be used. You must use a large file to store BLOB values of this size.

I.6.4. Calculating Page Size


Choose page size carefully. The storage areas for BLOB values are allocated in page
granularity. Depending on the size of the BLOB values and the size of the pages, much
of the storage area space can be inaccessible. See the Relational Database Server for
ClearPath OS 2200 Administration Guide for information on how BLOB values are
stored in the database.

As an example, suppose you have 40,000 house_photo images to insert into the
house table, and each photo is between 40,000 and 45,000 bytes. The column size is
set in the table definition to 50K bytes (51,200 bytes), so RDMS allocates 51,200 bytes
of the storage area for each house_photo value inserted.

I–10 7830 8160–027


Calculating BLOB Storage Area Sizes

The following table illustrates the amount of space in the file that becomes
inaccessible, based on page size.

Pages
per Inaccessible
Page BLOB Inaccessible Space per Space for 40,000
Column Size Value Value in Words Values in Words

51,200 bytes 112 115 (115*112) - 12,800 = 80 3,200,000


12,800 words
12,800 words 224 58 (58*224) - 12,800 = 192 7,680,000
12,800 words 448 29 (29*448) - 12,800 = 192 7,680,000
12,800 words 896 15 (15*896) - 12,800 = 640 25,600,000
12,800 words 1796 8 (8*1796) - 12,800 = 1568 62,720,000

Smaller page sizes generally give the best storage area usage, with no impact on
performance.

I.6.5. Avoiding Addressing Errors


If the MAXIMUM-PAGES value computes to a file sector address greater than the
maximum size of the file, you may get an error like this:

APP 3 DCS RB 60140 Attempt to create a new page at sector 16640


in EXEC file UDS$$SRC*T1SA5.
It failed because the file is too small.

This can happen even on the first INSERT. The reason is that RDMS tries to spread the
BLOB values out across the file. This is to support multithread access to the BLOB
storage area. RDMS divides the storage area into eight pieces, with page allocation
controlled independently for each piece. When inserting a BLOB value into the file,
RDMS randomly chooses one of the eight pieces from which to allocate pages to
store the BLOB value. So even though it may be the first BLOB value to be inserted
into the database, RDMS may choose the eighth piece, whose page numbers are
beyond the end of the file.

To avoid this error, ensure that the MAXIMUM-PAGES value times the PAGE-SIZE
value is smaller than the maximum size of the file.

7830 8160–027 I–11


Backup and Recovery of BLOB Storage Areas

I.7. Backup and Recovery of BLOB Storage Areas


The data inserted into BLOB (RSM-LOB) storage areas is not audited by default. To
enable auditing of BLOB data, the following are required:

• You must have the storage area attribute AUDITED set to true. AUDITED is true by
default if RECOVERED is true.
• You must also have LOB-AUDITED set to true. This is false by default.

See the Repository for ClearPath OS 2200 Programming Reference Manual for more
details about storage area attributes.

Note: Auditing BLOB data when BLOBs are very large or numerous can
significantly increase audit volume and affect system performance. Also, because
each page within a BLOB is audited separately, you should avoid small page sizes if
BLOB data is audited.

If you use IRU to dump your BLOB areas, you should be aware that you may get many
messages from IRU indicating that I/O errors have occurred, because RSM-LOB areas
can contain unallocated areas of mass storage. If you want to avoid these messages
and increase the speed of the dump and reload, you should preallocate the entire file
using the IRU ALLOCATE command, or preallocate a large initial reserve when you
create the file.

If you do not audit BLOB data, you must manually back up and recover the BLOB
storage areas. For best results, use IRU to dump and reload the storage area as
needed. When you reload a BLOB storage area, you cannot recover the file after
reload, because there are no LOB page records on the audit trail for IRU to apply
(when LOB-AUDITED is false). For this reason, avoid dynamic dumps. At the same time
that you dump the BLOB storage area, dump the associated data storage area, to have
a consistent recovery point. When you restore a BLOB storage area from a dump,
you should also restore all associated storage areas to dumps from the same time.

I–12 7830 8160–027


Declaring Large Object Variables in UCS C

I.8. Declaring Large Object Variables in UCS C


To exchange BLOB data between RDMS and your C application program, you must
declare one or more variables of data type BLOB. These variables must be declared in
the SQL Declare Section with your other RDMS-related variables.

BLOB variables in a C program are actually structured data. When you declare a
variable with the data type BLOB, the UCS C compiler generates a structure to
describe the BLOB data item.

The declaration format is similar to other C variables, but with the SQL TYPE clause:

SQL TYPE IS BLOB(large-object-length) v1;

The UCS C compiler generates the following structure. Note that the name you give is
used as a prefix for each of the three parts of the structure:

struct v1_t {long v1_reserved;


unsigned long v1_length;
char v1_data[large-object-length]
}v1;

large-object-length
is the maximum length for the BLOB variable, in bytes. The value can be in the
range 1 to approximately 4 gigabytes. See Table I–1 for more information.

The maximum length can be specified as a simple integer representing the


number of bytes or as an integer followed by one of the following suffixes:

K Kilobytes (210 or 1,024 bytes)


M Megabytes (220 or 1,048,576 bytes)

If you use the K or M suffix in the declaration, they must be uppercase letters.

For the s1.houses table in this example, the following declarations could be made:

EXEC SQL BEGIN DECLARE SECTION;


char[4] v_hno;
char[28] v_location;
int v_price;
char[40] v_description;
SQL TYPE IS BLOB(20000) v_detail_description;
SQL TYPE IS BLOB(50K) v_house_photo;
SQL TYPE IS BLOB(1M) *v_inspection_disclosure;
EXEC SQL END DECLARE SECTION;

You can initialize BLOB variables using C structure initialization syntax. For example

SQL TYPE IS BLOB(20000) v_detail_description = {0, 24, "no description available"};


SQL TYPE IS BLOB(50K) v_house_photo = {0,1, 700}; /* end of image sentinel */

7830 8160–027 I–13


Declaring Large Object Variables in UCS C

I.8.1. Declaring BLOB Values Larger than 64 Megabytes in


UCS C
The UCS C compiler allocates program variables into data banks. The OS 2200
architecture supports the following data bank types:

• Small banks (218 words = 262,144 words or 1,048,576 bytes)


• Large banks (224 words = 16,777,216 words or 67,108,864 bytes)
• Very large banks (230 = 1,073,741,824 words or 4,294,967,296 bytes)

The UCS C compiler allocates automatic variables in a small bank and allocates static
variables in a small or large bank, depending on the size of the static data items.

The UCS Runtime System allocates a very large bank when you call the UCS C
memory management functions such as malloc( ) for a single storage request in
excess of 16,777,216 words (67,108,864 bytes).

The UCS C compiler generates code to access data references using a 24-bit index
register. The compiler-generated code is limited to addressing a single object (array or
structure) up to 16,777,216 words in size. A UCS C pointer is limited to addressing up
to 16,777,216 words. If you use pointer arithmetic or array indexing to access a word in
a very large bank that exceeds an address of 16,777,216 words, the data reference
wraps back to zero, the beginning of the bank. There are no diagnostics issued if you
attempt to access a word in a very large bank beyond the limit. It is your responsibility
to avoid using a C pointer or array index that exceeds the limit.

Table I–1 summarizes the kinds of data access available based on the size of the BLOB
variable. Yes indicates that you can use the technique for the given size of BLOB
variable. No indicates that you cannot.

I–14 7830 8160–027


Declaring Large Object Variables in UCS C

Table I–1. Creating and Referencing BLOB Variables in UCS C

BLOB Variable Size

Less Than 786,000 to Greater Than


786,000 67,108,852 67,108,852
Bytes Bytes Bytes
Declaring BLOB Variables
Automatic BLOB variable Yes1 No No
Static BLOB variable Yes Yes No
BLOB variable pointer with data space Yes Yes Yes2
created using, for example, malloc( )
BLOB variable pointer with data space Yes Yes Yes3
created using CREATE$BANK
Referencing Data in BLOB Variables
Directly (see examples in I.8.2, “Referencing Yes Yes No
BLOB Variables in UCS C”)
By incrementing a C pointer Yes Yes No
Using the UCS C functions char_poke and Yes Yes Yes
char_peek
Input/Output Access to Data in BLOB
Variables
Using standard UCS C functions fread( ), Yes Yes No
fwrite( )
Using low-level I/O functions fio( ), fiow( ) Yes No4 No
Using bulkio functions bulkio_read( ), Yes Yes Yes
bulkio_write( )

Notes on the table:


1. The maximum size of an automatic variable is approximately 785,000 bytes. This
size depends on how many other automatic variables are declared in the same
function and also on the execution path of the program. When a function begins
execution it allocates a storage frame on the automatic storage stack. As a
function completes execution, it frees the storage frame.
2. The maximum size allowed by malloc( ) is approximately 4,282,384,559 bytes.
This size depends on how many activity level banks have already been created.
Any subsequent malloc( ) requests may fail due to no memory being available.
3. To get the largest possible data space, you must use the Exec system service
CREATE$BANK documented in the System Services Programming Reference
Manual. This routine is callable from a UCS C program. See the C Compiler
Programming Reference Volume 2 for an example of an extended mode call
routine.

7830 8160–027 I–15


Declaring Large Object Variables in UCS C

4. The low-level I/O functions fio( ) and fiow( ) are limited to reading and writing a
maximum of 128 tracks or 917,504 bytes per function call.

For more information on these capabilities, see the C Compiler Programming


Reference Manual Volume 1.

I.8.2. Referencing BLOB Variables in UCS C


The following are examples of referencing data in BLOB variables:

detail_description.detail_description_data[45] = 'B';

v_house_photo.v_house_photo_data
[v_house_photo.v_house_photo_length] = '\n';

strcpy(v_detail_description.v_detail_description_data ,
"charming two story home in the prestigious Powderhorn neighborhood");

v_inspection_disclosure = malloc(sizeof(*v_inspection_disclosure)); /* 1M bytes */


v_inspection_disclosure-> v_inspection_disclosure_length =
sizeof(v_inspection_disclosure-> v_inspection_disclosure_data);
v_inspection_disclosure-> v_inspection_disclosure_data[0] = 'A';
v_inspection_disclosure-> v_inspection_disclosure_data[1048575] = 'B';

When you put data into a BLOB variable, before calling RDMS to insert the value into
the database you must set the length of the value in the xx_length area of the
generated BLOB variable structure.

strcpy(v_detail_description.v_detail_description_data ,
"charming two story home in the prestigious Powderhorn neighborhood");
v_detail_description.v_detail_description_length =
strlen(v_detail_description. v_detail_description_data);

The strcpy( ) function copies the string including the null terminator. The strlen( )
function returns the length of the string not including the null terminator. If you require
the null terminator as significant data in your BLOB, you must add one to the result of
strlen( ) (the null character has already been added by the strcpy( ) function):

v_detail_description.v_detail_description_length ++;

For automatic and static BLOB variables, the UCS C compiler always creates the
generated BLOB structure as whole words, that is, a whole multiple of 4 bytes. For
example, you could use the following declaration:

SQL TYPE IS BLOB(6) v_example_blob;

In this case, the UCS C compiler generates the following structure:

struct {long v_example_blob_reserved;


unsigned long v_exampleblob_length;
char v_example_blob_data[6];
} v_example_blob

I–16 7830 8160–027


Declaring Large Object Variables in UCS C

However, the computer allocates 8 bytes for the v_example_blob_data. When RDMS
copies data to and from the generated structure, it likewise copies whole words. In
this case, v_example_blob could be used on an RDMS INSERT statement:

strcpy(v_example_blob.v_example_blob_data, "nodata");
v_example_blob.v_example_blob_length = 6;
EXEC SQL INSERT INTO s1.houses (hno, house_photo)
VALUES (:v_hno, :v_example_blob) ;

RDMS would copy 16 bytes of data to the database:

• 4 bytes for v_example_blob_reserved


• 4 bytes for v_example_blob_length
• 6 significant bytes of v_example_blob_data
• 2 bytes of “filler” to make a whole number of words

As a result, up to 3 bytes of indeterminate data are written from the BLOB variable to
the database on an INSERT statement and are written from the database to the BLOB
variable on a FETCH statement. The xx_length field contains the true length of the
value, in bytes.

I.8.3. Declaring and Using BLOB Pointer Variables in UCS C


You can use pointer variables for BLOB data. There are three important
considerations:

• When you use a BLOB pointer variable on an INSERT statement or as an input


variable for an UPDATE statement, you must set the yourname_length field of the
BLOB variable structure to the length of the BLOB value in the yourname_data
field of the BLOB variable structure. This is the same as for static or automatic
BLOB variables.
• When you use malloc( ) for example to acquire space dynamically, you must take
into consideration both the size of the actual BLOB value you will put into the
yourname_data field of the generated BLOB structure, as well as the 8 bytes of
header information, yourname_reserved and yourname_length.
• When you use a BLOB pointer variable on a FETCH statement or on the RETRIEVE
INTO clause of an UPDATE statement, you must initialize the yourname_length
field of the BLOB variable structure to the size of the available yourname_data
space, in bytes, before calling RDMS. Since BLOB pointer variables do not have
any real space allocated to them at compile time, you must tell RDMS how much
space is available, at execution time.

7830 8160–027 I–17


Declaring Large Object Variables in UCS C

For example, suppose you want to acquire space for a BLOB value whose maximum
size is 20,000 bytes and fetch a value into it:

SQL TYPE IS BLOB(50K) *v_inspection_disclosure;

#define blob_header_size 8
bytes_to_read = 20000;
v_inspection_disclosure = malloc(bytes_to_read + blob_header_size);
v_inspection_disclosure-> v_inspection_disclosure_length =
bytes_to_read;

EXEC SQL
DECLARE curs1 CURSOR FOR SELECT hno, inspection_disclosure FROM
s1.houses;
EXEC SQL OPEN CURSOR curs1;
EXEC SQL FETCH NEXT curs1 INTO :v_hno, :v_inspection_disclosure ;

I.8.4. BLOB Data in C++


You cannot create BLOB variables in C++, nor can you access RDMS directly from
C++. You must create and call a C function that declares the BLOB variables and
references RDMS.

I–18 7830 8160–027


Declaring Large-Object Variables in COBOL

I.9. Declaring Large-Object Variables in COBOL


In order to exchange data between RDMS and your COBOL application program, you
must declare one or more variables of data type BLOB. These variables must be
declared in the SQL Declare Section with your other RDMS-related variables.

BLOB variables in a COBOL program are actually a record rather than a primitive data
item. When you declare a variable with the data type BLOB, the UCS COBOL compiler
generates a record to describe the BLOB data item.

The declaration format is similar to other COBOL variables, but with a new SQL TYPE
clause:

01 v-house-photo USAGE IS SQL TYPE IS BLOB(large-object-length).

The declaration can also be shortened:

01 v-house-photo SQL TYPE IS BLOB(large-object-length).

The UCS COBOL compiler generates the record

01 v-house-photo.
02 v-house-photo-reserved PIC S9(9) USAGE IS BINARY.
02 v-house-photo-length PIC S9(9) USAGE IS BINARY.
02 v-house-photo-data PIC X(large-object-length).

large-object-length
is the maximum length for the BLOB variable, in bytes. The value can be in the
range 1 to 67,108,852. The maximum length can be specified as a simple integer
representing the number of bytes or as an integer followed by one of the
following suffixes:
K Kilobytes (210 or 1,024 bytes)
M Megabytes (220 or 1,048,576 bytes)

For the house schema in our example, the following declarations could be made:

EXEC SQL BEGIN DECLARE SECTION END-EXEC.


01 v-hno PIC X(4).
01 v-location PIC X(28).
01 v-price PIC S9(9) USAGE IS BINARY.
01 v-description PIC X(40).
01 v-detail-description SQL TYPE IS BLOB(20000).
01 v-house-photo SQL TYPE IS BLOB(50K).
01 v-inspection-disclosure SQL TYPE IS BLOB.
EXEC SQL END DECLARE SECTION END-EXEC.

7830 8160–027 I–19


Declaring Large-Object Variables in COBOL

I.9.1. Declaring BLOB Values Larger than 64 Megabytes in


COBOL
In UCS COBOL, the maximum size allowed for a BLOB variable is 64 megabytes
(67,108,852 bytes). To use larger BLOB values, the UCS COBOL application program
must call a UCS C procedure.

Table I–2 summarizes the kinds of data access available based on the size of the
BLOB variable. Yes indicates that you can use the technique for the given size of BLOB
variable. No indicates that you cannot.

Table I–2. Creating and Referencing BLOB Variables in COBOL

BLOB Variable Size

Less Than 1,048,576 to Greater Than


1,048,576 67,108,852 67,108,852
Bytes Bytes Bytes

Declaring BLOB Variables


Static BLOB variable Yes Yes No
Referencing Data in BLOB Variables
Directly, for example Yes Yes No
MOVE 'B' TO detail-description-
data(45:1)

I/O Access to Data in BLOB Variables


Using standard COBOL READ and WRITE Yes Yes No
Using low level I/O functions Yes Yes No
Using bulkio functions bulkio_read( ), Yes Yes No
bulkio_write( )

For more information on the capabilities described in the preceding table, see either

• UCS COBOL Programming Reference Manual Volume 1


• COBOL Compiler Programming Reference Manual Volume 2

I.9.2. Referencing BLOB Variables in COBOL


The following are examples of referencing data in BLOB variables:

MOVE 'BC' TO v-detail-description-data(6:8).

MOVE 'charming two story home in the prestigious Powderhorn neighborhood'


TO v-detail-description-data.

MOVE v-detail-description TO v-example-blob.

I–20 7830 8160–027


Declaring Large-Object Variables in COBOL

When you put data into a BLOB variable, before calling RDMS to insert the value into
the database you must set the length of the value in your name-length area of the
generated BLOB variable structure.

MOVE 'charming two story home in the prestigious Powderhorn neighborhood'


TO v-detail-description-data.
MOVE 66 TO v-detail-description-length.

The UCS COBOL compiler always creates the generated BLOB record as whole
words, that is, a multiple of 4 bytes. For example, if you use the following
declaration:

01 v-example-blob SQL TYPE IS BLOB(6).

the UCS COBOL compiler generates the following structure:

01 v-example-blob.
02 v-example-blob-reserved PIC S9(9) USAGE IS BINARY.
02 PIC S9(9) USAGE IS BINARY.
02 v-example-blob-data PIC X(6).

Since v-example-blob is an 01 level item, UCS COBOL allocates 8 bytes for the
v-example-blob-data to make the record occupy a whole number of words. When
RDMS copies data to and from the generated record, it likewise copies whole words.
In this case, v-example-blob could be used on an RDMS INSERT statement:

MOVE 'nodata' TO v-example-blob-data.


MOVE 6 TO v-example-blob-length.
EXEC SQL
INSERT INTO s1.houses (hno, house-photo)
VALUES (:v-hno, :v-example-blob)
END-EXEC.

RDMS would copy 16 bytes of data to the database:

• 4 bytes for v-example-blob-reserved


• 4 bytes for v-example-blob-length
• 6 significant bytes of v-example-blob-data
• 2 bytes of filler to make a whole number of words

As a result, up to 3 bytes of indeterminate data are written from the BLOB variable to
the database on an INSERT statement and are written from the database to the BLOB
variable on a FETCH statement.

7830 8160–027 I–21


Example UCS C Program—Using Embedded SQL

I.10. Example UCS C Program—Using Embedded


SQL
The following example shows how to insert and retrieve BLOB data using the
embedded SQL interface in a UCS C program. You can mix embedded SQL with
interactive SQL as needed.

The following are the differences between the embedded SQL and interactive SQL
versions of the program. (See I.11 for the interactive SQL version.)

Action Embedded SQL Interactive SQL

Passing an EXEC SQL SQL- rsa("SQL-statement", error_code,


SQL statement statement; &aux_info);
to RDMS
Passing a :variable-name Variables are typically passed by reference, as
variable value follows:
to RDMS
&variable-name

The exceptions are the references to error_code,


which is a “pointer to character,” and
v_disclosure, which is a “pointer to BLOB.”
Because these data items are already pointers,
they are passed by value.
Detecting Use the WHENEVER clause. Check error_code directly, as in the example.
errors

Example Code
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sysutil.h>
5 #include <rsa.h>
6 #define NO_FIND_STATUS 6001
7 #define NO_DATA_STATUS "02000"
8 #define OK_STATUS "00000"
9 #define TRUNC_WARN "01004"
10 #define blob_header_size 8
11
12 int size_needed_in_bytes;
13 rsa_error_code_type error_code;
14 int aux_info = 0;
15 char SQLSTATE[6];
16
17 EXEC SQL BEGIN DECLARE SECTION;
18 char v_hno[5];
19 char v_location[80];
20 int v_price;
21 char v_description[40];
22 SQL TYPE IS BLOB (50K) v_detail_description;
23 SQL TYPE IS BLOB (30000) v_house_photo = { 0, 1, 700};
24 /* initialize with end of file sentinel */
25 SQL TYPE IS BLOB (500K) *v_disclosure;
26

I–22 7830 8160–027


Example UCS C Program—Using Embedded SQL

27 char d_hno[5];
28 char d_location[80];
29 int d_price;
30 char d_description[40];
31 SQL TYPE IS BLOB (40K) d_detail_description;
32 SQL TYPE IS BLOB (30000) d_house_photo;
33 SQL TYPE IS BLOB (500K) *d_disclosure;
34
35 int indicator1, indicator2, indicator3, indicator4;
36 int indicator5, indicator6, indicator7;
37 EXEC SQL END DECLARE SECTION;
38
39
40 main()
41 {
42 EXEC SQL WHENEVER SQLERROR goto:a_bad_end;
43
44 EXEC SQL
45 BEGIN THREAD FOR app014 UPDATE UDSMSG;
46
47 /* use malloc to get the maximum amount of space for the
48 inspection_disclosure and add 8 bytes for the BLOB header information.
49 */
50
51 size_needed_in_bytes = sizeof(v_disclosure -> v_disclosure_data);
52 v_disclosure = malloc(size_needed_in_bytes + blob_header_size);
53 v_disclosure -> v_disclosure_length = size_needed_in_bytes;
54
55
56 /* Assume that at this point we get the names of the files containing
57 the detail description, house photo, and inspection disclosure and
58 perform the I/O to read data into the variables v_detail_description,
59 v_house_photo, and v_disclosure. See the C Compiler Programming
60 Reference Manual Volume 2: Compiler and System Interface for an
61 example of Input and Output of BLOBs.
62
63 Also, assume that we get the values for hno, location, price, and
64 description from the user.
65
66 This example uses strcpy in place of the I/O to illustrate the
67 specific RDMS issues.
68 */
69
70 strcpy(v_hno, "H907");
71 strcpy(v_location, "123 Main Street Minneapolis");
72 v_price = 120000;
73 strcpy(v_description, "older home 4BR 2BA FP AC");
74
75 /* fill in detail description; set the length to the actual length,
76 in bytes. Note that the trailing NULL character in the string is
77 not included in the length. In this instance, the NULL is not
78 a significant character.
79 */
80
81 strcpy(v_detail_description.v_detail_description_data ,
82 "charming two story home in the prestigious Powderhorn neighborhood");
83 v_detail_description.v_detail_description_length = 66;
84 v_detail_description.v_detail_description_reserved = 0;
85
86 /* assume there is no house photo */
87
88 strcpy(v_disclosure -> v_disclosure_data , "no work orders required");

7830 8160–027 I–23


Example UCS C Program—Using Embedded SQL

89 v_disclosure -> v_disclosure_length = 23;


90 v_disclosure -> v_disclosure_reserved = 0;
91
92
93 /* There are several ways to tell RDMS that the house_photo column will
94 have a NULL value -- and thereby trigger the insertion of the
95 default value from the table definition:
96 - set the corresponding indicator to -1
97 - set v_house_photo.v_house_photo_length to 0
98 - include the keyword NULL in place of the variable :v_house_photo
99 */
100
101 v_house_photo.v_house_photo_length = 0;
102
103 EXEC SQL
104 INSERT INTO s1.house
105 VALUES (:v_hno, :v_location, :v_price, :v_description,
106 :v_detail_description, :v_house_photo, :v_disclosure);
107 EXEC SQL
108 COMMIT THREAD;
109
110 /* Now, fetch the records back again */
111
112 /* Since the variable d_disclosure is a pointer to BLOB, we malloc
113 the space and then must tell RDMS how big the size is by setting
114 d_disclosure_length
115 */
116
117 d_disclosure = malloc(size_needed_in_bytes + blob_header_size);
118 d_disclosure -> d_disclosure_length = size_needed_in_bytes;
119 d_disclosure -> d_disclosure_reserved = 0;
120
121 EXEC SQL
122 DECLARE curs301 CURSOR
123 FOR SELECT * FROM s1.house;
124
125 EXEC SQL
126 OPEN CURSOR curs301;
127
128 EXEC SQL
129 FETCH FIRST curs301 INTO :d_hno :indicator1, :d_location :indicator2,
130 :d_price :indicator3, :d_description :indicator4,
131 :d_detail_description :indicator5, :d_house_photo :indicator6,
132 :d_disclosure :indicator7;
133
134 /* Assume that at this point we write the three BLOB values to files for
135 transport to a display device.
136
137 This example uses printf to illustrate the specific RDMS issues
138 */
139
140
141
142 /* Since the trailing NULL character is not part of the actual data values,
143 insert one now to be able to display the values.
144 */
145
146 d_detail_description.d_detail_description_data
147 [d_detail_description.d_detail_description_length]= '\0';
148 d_house_photo.d_house_photo_data
149 [d_house_photo.d_house_photo_length]= '\0';
150 d_disclosure -> d_disclosure_data

I–24 7830 8160–027


Example UCS C Program—Using Embedded SQL

151 [d_disclosure -> d_disclosure_length]= '\0';


152
153
154 printf("hno: %s\n", &d_hno);
155 printf("location: %s\n", &d_location);
156 printf("price: %i\n", d_price);
157 printf("description: %s\n", &d_description);
158 printf("detail description: \n %s\n",
159 &d_detail_description.d_detail_description_data);
160 printf("house_photo: %s\n", &d_house_photo.d_house_photo_data);
161 printf("inspection disclosure: %s\n",
162 &d_disclosure -> d_disclosure_data);
163
164
165 /* Suppose the variable to hold the inspection disclosure is too small
166 to hold the value being fetched. RDMS returns the SOLSTATE warning '01004' and
167 sets the indicator variable value to the defined length of the variable in the
168 DECLARE. Note that it is the column's declared length, not the length of the
169 value being fetched.
170 */
171
172 d_disclosure -> d_disclosure_length = 20;
173 EXEC SQL
174 FETCH FIRST curs301 INTO :d_hno :indicator1, :d_location :indicator2,
175 :d_price :indicator3, :d_description :indicator4,
176 :d_detail_description :indicator5, :d_house_photo :indicator6,
177 :d_disclosure :indicator7;
178
179 printf("inspection disclosure length from indicator: %i\n", indicator7);
180
181 EXEC SQL
182 CLOSE curs301;
183
184 EXEC SQL
185 END THREAD TERMINATE;
186 return 0;
187
188 a_bad_end:
189 handle_sqlerror();
190 return 1;
191 }
192
193
194 void handle_sqlerror(void)
195 {
196 printf("PROGRAM TERMINATED IN ERROR *SQLSTATE = %s\n", SQLSTATE);
197 return;
198 }

7830 8160–027 I–25


Example UCS C Program—Using Embedded SQL

Output
Executing this program produces the following output:

@XQT file.example
hno: H907
location: 123 Main Street Minneapolis
price: 120000
description: older home 4BR 2BA FP AC
detail description:
charming two story home in the prestigious Powderhorn neighborhood
house_photo: no house photo available
inspection disclosure: no work orders required
inspection disclosure length from indicator: 1048576

I–26 7830 8160–027


Example UCS C Program—Using Interactive SQL

I.11. Example UCS C Program—Using Interactive


SQL
The following example shows how to insert and retrieve BLOB data using the
interactive SQL interface in a UCS C program. You can mix interactive SQL with
embedded SQL as needed.

These are differences to note between the interactive SQL and embedded SQL
versions of the program (see I.10 for the embedded SQL version of the program).

Action Embedded SQL Interactive SQL

Passing an SQL EXEC SQL SQL- rsa("SQL-statement", error_code,


statement to statement; &aux_info);
RDMS
Passing a variable :variable-name Variables are typically passed by reference, as
value to RDMS follows:
&variable-name

The exceptions are the references to error_code,


which is a “pointer to character,” and
v_disclosure, which is a “pointer to BLOB.”
Because these data items are already pointers,
they are passed by value.
Detecting errors Use the WHENEVER Check error_code directly, as in the example.
clause.

Example Code
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sysutil.h>
5 #include <rsa.h>
6 #define NO_FIND_STATUS 6001
7 #define NO_DATA_STATUS "02000"
8 #define OK_STATUS "00000"
9 #define TRUNC_WARN "01004"
10 #define blob_header_size 8
11
12 int size_needed_in_bytes;
13 rsa_error_code_type error_code;
14 int aux_info = 0;
15 char SQLSTATE[6];
16
17 EXEC SQL BEGIN DECLARE SECTION;
18 char v_hno[5];
19 char v_location[80];
20 int v_price;
21 char v_description[40];

7830 8160–027 I–27


Example UCS C Program—Using Interactive SQL

22 SQL TYPE IS BLOB (50K) v_detail_description;


23 SQL TYPE IS BLOB (30000) v_house_photo = { 0, 1, 700};
24 /* initialize with end of file sentinel */
25 SQL TYPE IS BLOB (500K) *v_disclosure;
26
27 char d_hno[5];
28 char d_location[80];
29 int d_price;
30 char d_description[40];
31 SQL TYPE IS BLOB (50K) d_detail_description;
32 SQL TYPE IS BLOB (30000) d_house_photo;
33 SQL TYPE IS BLOB (500K) *d_disclosure;
34
35 int indicator1, indicator2, indicator3, indicator4;
36 int indicator5, indicator6, indicator7;
37 EXEC SQL END DECLARE SECTION;
38
39
40 main()
41 {
42 1 rsa("BEGIN THREAD FOR app014 UPDATE UDSMSG;",
43 error_code, &aux_info);
44 1 if (atoi(error_code)) {
45 2 printf("Error on BEGIN THREAD\n");
46 2 goto a_bad_thing;
47 }
48
49
50 /* use malloc to get the maximum amount of space for the
51 inspection_disclosure and add 8 bytes for the BLOB header information.
52 */
53
54 1 size_needed_in_bytes = sizeof(v_disclosure -> v_disclosure_data);
55 1 v_disclosure = malloc(size_needed_in_bytes + blob_header_size);
56 1 v_disclosure -> v_disclosure_length = size_needed_in_bytes;
57
58
59 /* Assume that at this point we get the names of the files containing
60 the detail description, house photo, and inspection disclosure and
61 perform the I/O to read the data into the variables v_detail_description,
62 v_house_photo, and v_disclosure. See the C Compiler Programming
63 Reference Manual Volume 2: Compiler and System Interface for an
64 example of Input and Output of BLOBs.
65
66 Also, assume that we get the values for hno, location, price, and
67 description from the user.
68
69 This example uses strcpy in place of the I/O to illustrate the
70 specific RDMS issues.
71 */
72
73 1 strcpy(v_hno, "H907");

I–28 7830 8160–027


Example UCS C Program—Using Interactive SQL

74 1 strcpy(v_location, "123 Main Street Minneapolis");


75 1 v_price = 120000;
76 1 strcpy(v_description, "older home 4BR 2BA FP AC");
77
78 /* fill in detail description; set the length to the actual length,
79 in bytes. Note that the trailing NULL character in the string is
80 not included in the length. In this instance, the NULL is not
81 a significant character.
82 */
83
84 1 strcpy(v_detail_description.v_detail_description_data ,
85 "charming two story home in the prestigious Powderhorn neighborhood");
86 1 v_detail_description.v_detail_description_length = 66;
87 1 v_detail_description.v_detail_description_reserved = 0;
88
89 /* assume there is no house photo */
90
91 1 strcpy(v_disclosure -> v_disclosure_data , "no work orders required");
92 1 v_disclosure -> v_disclosure_length = 23;
93 1 v_disclosure -> v_disclosure_reserved = 0;
94
95
96 /* There are several ways to tell RDMS that the house_photo column will
97 have a NULL value -- and thereby trigger the insertion of the
98 default value from the table definition:
99 - set the corresponding indicator to -1
100 - set v_house_photo.v_house_photo_length to 0
101 - include the keyword NULL in place of the variable :v_house_photo
102
103 NOTE: In the list of arguments for the rsa call, the variable
104 v_disclosure is passed by value, not by reference. This is because
105 the variable is declared as a 'pointer to blob'.
106
107 */
108
109 1 v_house_photo.v_house_photo_length = 0;
110
111 1 rsa("INSERT INTO s1.house \
112 VALUES($p1, $p2 $p3, $p4 $p5, $p6, $p7, $p8 $p9, $p10);",
113 error_code, &aux_info, &v_hno, &v_location, &indicator1,
114 &v_price, &indicator2, &v_description,
115 &v_detail_description, &v_house_photo, &indicator3, v_disclosure);
116 1 if (atoi(error_code)) {
117 2 printf("Error on INSERT\n");
118 2 goto a_bad_thing;
119 }
120
121 1 rsa("COMMIT THREAD;", error_code, &aux_info);
122 1 if (atoi(error_code)) {
123 2 printf("Error on COMMIT THREAD\n");
124 2 goto a_bad_thing;
125 }

7830 8160–027 I–29


Example UCS C Program—Using Interactive SQL

126
127
128 /* Now, fetch the records back again */
129
130 /* Since the variable d_disclosure is a pointer to BLOB, we malloc
131 the space and then must tell RDMS how big the size is by setting
132 d_disclosure_length
133 */
134
135 1 d_disclosure = malloc(size_needed_in_bytes + blob_header_size);
136 1 d_disclosure -> d_disclosure_length = size_needed_in_bytes;
137 1 d_disclosure -> d_disclosure_reserved = 0;
138
139 1 rsa("DECLARE curs301 CURSOR FOR SELECT * FROM s1.house;",
140 error_code, &aux_info);
141 1 if (atoi(error_code)) {
142 2 printf("Error on COMMIT THREAD\n");
143 2 goto a_bad_thing;
144 }
145
146 1 rsa("OPEN CURSOR curs301;", error_code, &aux_info);
147 1 if (atoi(error_code)) {
148 2 printf("Error on OPEN CURSOR\n");
149 2 goto a_bad_thing;
150 }
151
152 /* NOTE: In the list of arguments for the rsa call, the variable
153 d_disclosure is passed by value, not by reference. This is because
154 the variable is declared as a 'pointer to blob'.
155 */
156
157 1 rsa("FETCH FIRST curs301 INTO $p1 $p2, $p3 $p4, $p5 $p6, \
158 $p7 $p8, $p9 $p10, $p11 $p12, $p13 $p14;",
159 error_code, &aux_info, &d_hno, &indicator1, &d_location, &indicator2,
160 &d_price, &indicator3, &d_description, &indicator4,
161 &d_detail_description, &indicator5, &d_house_photo, &indicator6,
162 d_disclosure, &indicator7);
163 1 if (atoi(error_code)) {
164 2 printf("Error on FETCH 1\n");
165 2 goto a_bad_thing;
166 }
167
168 /* Assume that at this point we write the three BLOB values to files for
169 transport to a display device.
170
171 This example uses printf to illustrate the specific RDMS issues
172 */
173
174
175
176 /* Since the trailing NUL character is not part of the actual data values,
177 insert one now to be able to display the values.

I–30 7830 8160–027


Example UCS C Program—Using Interactive SQL

178 */
179
180 d_detail_description.d_detail_description_data
181 1 [d_detail_description.d_detail_description_length]= '\0';
182 d_house_photo.d_house_photo_data
183 1 [d_house_photo.d_house_photo_length]= '\0';
184 d_disclosure -> d_disclosure_data
185 1 [d_disclosure -> d_disclosure_length]= '\0';
186
187
188 1 printf("hno: %s\n", &d_hno);
189 1 printf("location: %s\n", &d_location);
190 1 printf("price: %i\n", d_price);
191 1 printf("description: %s\n", &d_description);
192 1 printf("detail description: \n %s\n",
193 &d_detail_description.d_detail_description_data);
194 1 printf("house_photo: %s\n", &d_house_photo.d_house_photo_data);
195 1 printf("inspection disclosure: %s\n",
196 &d_disclosure -> d_disclosure_data);
197
198
199 /* Suppose the variable to hold the inspection disclosure is too small
200 to hold the value being fetched. RDMS returns a truncation warning
201 and puts the column length into the corresponding indicator variable.
202 Note that it is the column's declared length, not the length of the
203 value being fetched.
204
205 NOTE: In the list of arguments for the rsa call, the variable
206 d_disclosure is passed by value, not by reference. This is because
207 the variable is declared as a 'pointer to blob'.
208
209 */
210
211 1 d_disclosure -> d_disclosure_length = 20;
212 1 rsa("FETCH FIRST curs301 INTO $p1 $p2, $p3 $p4, $p5 $p6, \
213 $p7 $p8, $p9 $p10, $p11 $p12, $p13 $p14;",
214 error_code, &aux_info, &d_hno, &indicator1, &d_location, &indicator2,
215 &d_price, &indicator3, &d_description, &indicator4,
216 &d_detail_description, &indicator5, &d_house_photo, &indicator6,
217 d_disclosure, &indicator7);
218 1 if (atoi(error_code)) {
219 2 printf("Error on FETCH 2\n");
220 2 goto a_bad_thing;
221 }
222
223 1 printf("inspection disclosure length from indicator: %i\n", indicator7);
224
225 1 rsa("CLOSE curs301;", error_code, &aux_info);
226 1 if (atoi(error_code)) {
227 2 printf("Error on CLOSE\n");
228 2 goto a_bad_thing;
229 }

7830 8160–027 I–31


Example UCS C Program—Using Interactive SQL

230
231 1 rsa("END THREAD TERMINATE;", error_code, &aux_info);
232 1 if (atoi(error_code)) {
233 2 printf("Error on END THREAD\n");
234 2 goto a_bad_thing;
235 }
236 1 return 0;
237
238 a_bad_thing:
239 1 handle_sqlerror();
240 1 rsa("END THREAD TERMINATE;", error_code, &aux_info);
241 1 if (atoi(error_code)) {
242 2 printf("Error on END THREAD\n");
243 2 goto a_bad_thing;
244 }
245 1 return 1;
246 }
247
248
249 void handle_sqlerror(void)
250 {
251 1 printf("PROGRAM TERMINATED IN ERROR *error_code = %s, *aux_info = %d\n",
252 error_code, aux_info);
253 1 return;
254 }

I–32 7830 8160–027


Example UCS C Program—Using Interactive SQL

Output
Executing this program produces the following output:

@XQT OBJ$.do-house2zm
hno: H907
location: 123 Main Street Minneapolis
price: 120000
description: older home 4BR 2BA FP AC
detail description:
charming two story home in the prestigious Powderhorn neighborhood
house_photo: no house photo available
inspection disclosure: no work orders required
inspection disclosure length from indicator: 1048576

7830 8160–027 I–33


Example UCS COBOL Program—Using Embedded SQL

I.12. Example UCS COBOL Program—Using


Embedded SQL
The following example shows how to insert and retrieve BLOB data using the
embedded SQL interface in a UCS COBOL program. You can mix embedded SQL with
interactive SQL as needed.

These are differences to note between the embedded SQL and interactive SQL
versions of the program (see I.13 for the interactive SQL version of the program).

Action Embedded SQL Interactive SQL

Passing an SQL EXEC SQL SQL- ENTER MASM 'ACOB$RDMR' USING "SQL-
statement to statement statement", error_status, aux_info.
RDMS END-EXEC.
Detecting Use the WHENEVER Check error-status directly, as in the example.
errors clause.

Example Code
1 IDENTIFICATION DIVISION.
2 PROGRAM-ID. cobol-example.
3 AUTHOR. RDMS.
4 DATE-WRITTEN. 2000 Oct 31.
5 ENVIRONMENT DIVISION.
6 CONFIGURATION SECTION.
7 SOURCE-COMPUTER. UNISYS-2200-5600.
8 OBJECT-COMPUTER. UNISYS-2200-5600.
9 SPECIAL-NAMES.
10 PRINTER IS PRINTER.
11
12 DATA DIVISION.
13
14 WORKING-STORAGE SECTION.
15
16 EXEC SQL BEGIN DECLARE SECTION END-EXEC.
17
18 01 v-hno PIC X(4).
19 01 v-location PIC X(28).
20 01 v-price PIC 9(10) BINARY.
21 01 v-description PIC X(40).
22 01 v-detail-description SQL TYPE IS BLOB(20K).
23 01 v-house-photo SQL TYPE IS BLOB(30000).
24 01 v-disclosure SQL TYPE IS BLOB(500K).
25
26 01 d-hno PIC X(4).
27 01 d-location PIC X(28).
28 01 d-price PIC 9(10) BINARY.
29 01 d-description PIC X(40).
30 01 d-detail-description SQL TYPE IS BLOB(20K).

I–34 7830 8160–027


Example UCS COBOL Program—Using Embedded SQL

31 01 d-house-photo SQL TYPE IS BLOB(30000).


32 01 d-disclosure SQL TYPE IS BLOB(500K).
33 01 d-short-disclosure SQL TYPE IS BLOB(20).
34
35
36 01 SQLCODE PIC S9(9) USAGE COMPUTATIONAL.
37 01 SQLSTATE PIC X(5).
38 01 RDMCA.
39 02 ERROR-STATUS PIC 9(4).
40 02 AUX-INFO PIC S9(9) BINARY.
41
42
43 EXEC SQL END DECLARE SECTION END-EXEC.
44
45 01 indicator1 PIC S9(7) USAGE BINARY.
46 01 indicator2 PIC S9(7) USAGE BINARY.
47 01 indicator3 PIC S9(7) USAGE BINARY.
48 01 indicator4 PIC S9(7) USAGE BINARY.
49 01 indicator5 PIC S9(7) USAGE BINARY.
50 01 indicator6 PIC S9(7) USAGE BINARY.
51 01 indicator7 PIC S9(7) USAGE BINARY.
52
53 01 WORK-AREA-SIZE PIC 1(36) USAGE BINARY-1 VALUE 2000.
54
55 01 print-line1.
56 05 label1 PIC X(12).
57 05 indicator1-value PIC +9(7).
58 05 label2 PIC X(16).
59 05 hno-value PIC X(4).
60
61 01 print-line2.
62 05 label3 PIC X(12).
63 05 indicator2-value PIC +9(7).
64 05 label4 PIC X(16).
65 05 location-value PIC X(40).
66
67 01 print-line3.
68 05 label5 PIC X(12).
69 05 indicator3-value PIC +9(7).
70 05 label6 PIC X(16).
71 05 price-value PIC $ZZZ,ZZ9.99 .
72
73 01 print-line4.
74 05 label7 PIC X(12).
75 05 indicator4-value PIC +9(7).
76 05 label8 PIC X(16).
77 05 description-value PIC X(40).
78
79 01 print-line5.
80 05 label9 PIC X(12).
81 05 indicator5-value PIC +9(7).
82 05 label10 PIC X(21).

7830 8160–027 I–35


Example UCS COBOL Program—Using Embedded SQL

83 01 print-line5a.
84 05 filler PIC X(4).
85 05 detail-description-value PIC X(72).
86
87 01 print-line6.
88 05 label11 PIC X(12).
89 05 indicator6-value PIC +9(7).
90 05 label12 PIC X(16).
91 05 house-photo-value PIC X(40).
92
93 01 print-line7.
94 05 label13 PIC X(12).
95 05 indicator7-value PIC +9(7).
96 05 label14 PIC X(16).
97 05 disclosure-value PIC X(40).
98 *
99 *
100 PROCEDURE DIVISION.
101 Start-test.
102
103 init-rsa.
104 CALL 'RSA$INIT' USING WORK-AREA-SIZE.
105 EXEC SQL
106 WHENEVER SQLERROR GO TO :RDMS-ERROR-PARA
107 END-EXEC.
108
109 init-print-lines.
110 MOVE SPACES TO print-line1.
111 MOVE SPACES TO print-line2.
112 MOVE SPACES TO print-line3.
113 MOVE SPACES TO print-line4.
114 MOVE SPACES TO print-line5.
115 MOVE SPACES TO print-line5a.
116 MOVE SPACES TO print-line6.
117 MOVE SPACES TO print-line7.
118 MOVE 'indicator1: ' TO label1.
119 MOVE 'indicator2: ' TO label3.
120 MOVE 'indicator3: ' TO label5.
121 MOVE 'indicator4: ' TO label7.
122 MOVE 'indicator5: ' TO label9.
123 MOVE 'indicator6: ' TO label11.
124 MOVE 'indicator7: ' TO label13.
125 MOVE ' house number: ' TO label2.
126 MOVE ' location: ' TO label4.
127 MOVE ' price: ' TO label6.
128 MOVE ' description: ' TO label8.
129 MOVE ' detail description: ' TO label10.
130 MOVE ' house-photo: ' TO label12.
131 MOVE ' disclosure: ' TO label14.
132
133
134 do-the-work.

I–36 7830 8160–027


Example UCS COBOL Program—Using Embedded SQL

135 *
136 * Assume that at this point we get the names of the files containing
137 * the detail description, house photo, and inspection disclosure and
138 * perform the I/O to read the data into the variables v-detail-
description
139 * v-house-photo, and v-disclosure. See the COBOL Compiler Programming
140 * Reference Manual Volume 2: Compiler and System Interface for an
141 * example of Input and Output of BLOBs.
142 *
143 * Also, assume that we get the values for hno, location, price, and
144 * description from the user.
145 *
146 * This example uses MOVE in place of the I/O to illustrate the
147 * specific RDMS issues.
148 *
149 MOVE 'H907' TO v-hno.
150 MOVE '123 Main Street Minneapolis, MN' TO v-location.
151 MOVE 120000 to v-price.
152 MOVE 'older home 4BR 2BA FP AC' to v-description.
153 *
154 * fill in detail description; set the length to the actual length,
155 * in bytes. Note that trailing spaces in the string are
156 * not included in the length. In this instance, the trailing spaces
157 * are not significant characters.
158 *
159 STRING
160 'charming two story home in the prestigious '
161 DELIMITED SIZE,
162 'Powderhorn neighborhood'
163 DELIMITED SIZE
164 INTO v-detail-description-data.
165 MOVE 66 TO v-detail-description-length.
166 *
167 * assume there is no house photo
168 *
169 MOVE 'no work orders required' TO v-disclosure-data.
170 MOVE 23 TO v-disclosure-length.
171 *
172 * There are several ways to tell RDMS that the house_photo column will
173 * have a NULL value -- and thereby trigger the insertion of the
174 * default value from the table definition:
175 * - set the corresponding indicator to -1
176 * - set v-house-photo-length to 0
177 * - include the keyword NULL in place of the variable :v-house-photo
178 *
179 MOVE 0 TO v-house-photo-length.
180
181 EXEC SQL
182 INSERT INTO s1.house
183 VALUES (:v-hno, :v-location, :v-price, :v-description,
184 :v-detail-description, :v-house-photo,
185 :v-disclosure)

7830 8160–027 I–37


Example UCS COBOL Program—Using Embedded SQL

186 END-EXEC.
187
188 EXEC SQL
189 COMMIT THREAD
190 END-EXEC.
191
192 *
193 * Now, fetch the records back again
194 *
195 EXEC SQL
196 DECLARE curs301 CURSOR
197 FOR SELECT * FROM s1.house
198 END-EXEC.
199
200 EXEC SQL
201 OPEN CURSOR curs301
202 END-EXEC.
203 *
204 * Clear the BLOB destination variables
205 *
206 MOVE SPACES TO d-detail-description.
207 MOVE SPACES TO d-house-photo.
208 MOVE SPACES TO d-disclosure.
209
210 EXEC SQL
211 FETCH FIRST curs301 INTO :d-hno :indicator1,
212 :d-location :indicator2, :d-price :indicator3,
213 :d-description :indicator4,
214 :d-detail-description :indicator5,
215 :d-house-photo :indicator6,
216 :d-disclosure :indicator7
217 END-EXEC.
218 *
219 * Assume that at this point we write the three BLOB values to files
for
220 * transport to a display device.
221 *
222 * This example uses DISPLAY to illustrate the specific RDMS issues
223 *
224 MOVE indicator1 TO indicator1-value.
225 MOVE indicator2 TO indicator2-value.
226 MOVE indicator3 TO indicator3-value.
227 MOVE indicator4 TO indicator4-value.
228 MOVE indicator5 TO indicator5-value.
229 MOVE indicator6 TO indicator6-value.
230 MOVE indicator7 TO indicator7-value.
231
232 MOVE SPACES TO hno-value.
233 IF indicator1 IS >= ZERO
234 MOVE d-hno TO hno-value.
235 MOVE SPACES TO location-value.
236 IF indicator2 IS >= ZERO

I–38 7830 8160–027


Example UCS COBOL Program—Using Embedded SQL

237 MOVE d-location TO location-value.


238 MOVE ZERO TO price-value.
239 IF indicator3 IS >= ZERO
240 MOVE d-price TO price-value.
241 MOVE SPACES TO description-value.
242 IF indicator4 IS >= ZERO
243 MOVE d-description TO description-value.
244 MOVE SPACES TO detail-description-value.
245 IF indicator5 IS >= ZERO
246 MOVE
247 d-detail-description-data(1:d-detail-description-length)
248 TO detail-description-value.
249 MOVE SPACES TO house-photo-value.
250 IF indicator6 IS >= ZERO
251 MOVE d-house-photo-data(1:d-house-photo-length)
252 TO house-photo-value.
253 MOVE SPACES TO disclosure-value.
254 IF indicator6 IS >= ZERO
255 MOVE d-disclosure-data(1:d-disclosure-length)
256 TO disclosure-value.
257
258 DISPLAY print-line1 UPON PRINTER.
259 DISPLAY print-line2 UPON PRINTER.
260 DISPLAY print-line3 UPON PRINTER.
261 DISPLAY print-line4 UPON PRINTER.
262 DISPLAY print-line5 UPON PRINTER.
263 DISPLAY print-line5a UPON PRINTER.
264 DISPLAY print-line6 UPON PRINTER.
265 DISPLAY print-line7 UPON PRINTER.
266 *
267 * Suppose the variable to hold the inspection disclosure is too small
268 * to hold the value being fetched. RDMS returns a truncation warning
269 * and puts the column length into the corresponding indicator variable
270 * Note that it is the column's declared length, not the length of the
271 * value being fetched.
272 *
273 EXEC SQL
274 FETCH FIRST curs301 INTO :d-hno :indicator1,
275 :d-location :indicator2, :d-price :indicator3,
276 :d-description :indicator4,
277 :d-detail-description :indicator5,
278 :d-house-photo :indicator6,
279 :d-short-disclosure :indicator7
280 END-EXEC.
281
282 DISPLAY
283 'inspection disclosure length from indicator:'
284 UPON PRINTER.
285 DISPLAY indicator7 UPON PRINTER.
286
287 EXEC SQL
288 CLOSE curs301

7830 8160–027 I–39


Example UCS COBOL Program—Using Embedded SQL

289 END-EXEC.
290
291
292 PERFORM END-THREAD-TO-UDS.
293 PERFORM TERMINATION-PARA.
294 *
295 * other procedure paragraphs
296 *
297
298
299 END-THREAD-TO-UDS.
300 END THREAD.
301
302 TERMINATION-PARA.
303 DISPLAY 'END UCOB example'
304 UPON PRINTER.
305 STOP RUN.
306
307 RDMS-ERROR-PARA.
308 EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.
309 DISPLAY '*** SQLSTATE = ' SQLSTATE UPON PRINTER.

Output
Executing this program produces the following output:

@XQT OBJ$.EXAMPLE-UCOB
indicator1: +0000000 house number: H907
indicator2: +0000000 location: 123 Main Street Minneapolis,
indicator3: +0000000 price: $120,000.00
indicator4: +0000000 description: older home 4BR 2BA FP AC
indicator5: +0000000 detail description:
charming two story home in the prestigious Powderhorn neighborhood
indicator6: +0000000 house-photo: no house photo available
indicator7: +0000000 disclosure: no work orders required
inspection disclosure length from indicator:
+1048576
END UCOB example

I–40 7830 8160–027


Example UCS COBOL Program—Using Interactive SQL

I.13. Example UCS COBOL Program—Using


Interactive SQL
The following example shows how to insert and retrieve BLOB data using the
interactive SQL interface in a UCS COBOL program. You can mix interactive SQL with
embedded SQL as needed.

These are differences to note between the embedded SQL and interactive SQL
versions of the program (see I.12 for the embedded SQL version of the program).

Action Embedded SQL Interactive SQL

Passing an SQL EXEC SQL SQL-statement ENTER MASM 'ACOB$RDMR' USING "SQL-
statement to END-EXEC. statement", error_status, aux_info.
RDMS
Detecting Use the WHENEVER Check error-status directly, as in the example.
errors clause.

Example Code
1 1 IDENTIFICATION DIVISION.
2 PROGRAM-ID. cobol-example.
3 AUTHOR. RDMS.
4 DATE-WRITTEN. 2003 Oct 29.
5 ENVIRONMENT DIVISION.
6 CONFIGURATION SECTION.
7 SOURCE-COMPUTER. UNISYS-2200-5600.
8 OBJECT-COMPUTER. UNISYS-2200-5600.
9 SPECIAL-NAMES.
10 PRINTER IS PRINTER.
11
12 DATA DIVISION.
13
14 WORKING-STORAGE SECTION.
15
16 EXEC SQL BEGIN DECLARE SECTION END-EXEC.
17
18 01 v-hno PIC X(4).
19 01 v-location PIC X(28).
20 01 v-price PIC 9(10) BINARY.
21 01 v-description PIC X(40).
22 01 v-detail-description SQL TYPE IS BLOB(20K).
23 01 v-house-photo SQL TYPE IS BLOB(30000).
24 01 v-disclosure SQL TYPE IS BLOB(500K).
25
26 01 d-hno PIC X(4).
27 01 d-location PIC X(28).
28 01 d-price PIC 9(10) BINARY.
29 01 d-description PIC X(40).
30 01 d-detail-description SQL TYPE IS BLOB(20K).

7830 8160–027 I–41


Example UCS COBOL Program—Using Interactive SQL

31 01 d-house-photo SQL TYPE IS BLOB(30000).


32 01 d-disclosure SQL TYPE IS BLOB(500K).
33 01 d-short-disclosure SQL TYPE IS BLOB(20).
34
35
36 01 SQLCODE PIC S9(9) USAGE COMPUTATIONAL.
37 01 SQLSTATE PIC X(5).
38 01 RDMCA.
39 02 ERROR-STATUS PIC 9(4).
40 02 AUX-INFO PIC S9(9) BINARY.
41
42
43 EXEC SQL END DECLARE SECTION END-EXEC.
44
45 01 indicator1 PIC S9(7) USAGE BINARY.
46 01 indicator2 PIC S9(7) USAGE BINARY.
47 01 indicator3 PIC S9(7) USAGE BINARY.
48 01 indicator4 PIC S9(7) USAGE BINARY.
49 01 indicator5 PIC S9(7) USAGE BINARY.
50 01 indicator6 PIC S9(7) USAGE BINARY.
51 01 indicator7 PIC S9(7) USAGE BINARY.
52
53 01 COMMAND-AREA.
54 05 CM-LINE PIC X(60) OCCURS 15 TIMES.
55 01 print-line1.
57 05 label1 PIC X(12).
58 05 indicator1-value PIC +9(7).
59 05 label2 PIC X(16).
60 05 hno-value PIC X(4).
61
62 01 print-line2.
63 05 label3 PIC X(12).
64 05 indicator2-value PIC +9(7).
65 05 label4 PIC X(16).
66 05 location-value PIC X(40).
67
68 01 print-line3.
69 05 label5 PIC X(12).
70 05 indicator3-value PIC +9(7).
71 05 label6 PIC X(16).
72 05 price-value PIC $ZZZ,ZZ9.99 .
73
74 01 print-line4.
75 05 label7 PIC X(12).
76 05 indicator4-value PIC +9(7).
77 05 label8 PIC X(16).
78 05 description-value PIC X(40).
79
80 01 print-line5.
81 05 label9 PIC X(12).
82 05 indicator5-value PIC +9(7).
83 05 label10 PIC X(21).

I–42 7830 8160–027


Example UCS COBOL Program—Using Interactive SQL

84 01 print-line5a.
85 05 filler PIC X(4).
86 05 detail-description-value PIC X(72).
87
88 01 print-line6.
89 05 label11 PIC X(12).
90 05 indicator6-value PIC +9(7).
91 05 label12 PIC X(16).
92 05 house-photo-value PIC X(40).
93
94 01 print-line7.
95 05 label13 PIC X(12).
96 05 indicator7-value PIC +9(7).
97 05 label14 PIC X(16).
98 05 disclosure-value PIC X(40).
99 *
100 *
101 1 PROCEDURE DIVISION.
102 1 Start-test.
103
104 1 init-rsa.
105 1 EXEC SQL
106 WHENEVER SQLERROR GO TO RDMS-ERROR-PARA
107 END-EXEC.
108
109 1 init-print-lines.
110 1 MOVE SPACES TO print-line1.
111 1 MOVE SPACES TO print-line2.
112 1 MOVE SPACES TO print-line3.
113 1 MOVE SPACES TO print-line4.
114 1 MOVE SPACES TO print-line5.
115 1 MOVE SPACES TO print-line5a.
116 1 MOVE SPACES TO print-line6.
117 1 MOVE SPACES TO print-line7.
118 1 MOVE 'indicator1: ' TO label1.
119 1 MOVE 'indicator2: ' TO label3.
120 1 MOVE 'indicator3: ' TO label5.
121 1 MOVE 'indicator4: ' TO label7.
122 1 MOVE 'indicator5: ' TO label9.
123 1 MOVE 'indicator6: ' TO label11.
124 1 MOVE 'indicator7: ' TO label13.
125 1 MOVE ' house number: ' TO label2.
126 1 MOVE ' location: ' TO label4.
127 1 MOVE ' price: ' TO label6.
128 1 MOVE ' description: ' TO label8.
129 1 MOVE ' detail description: ' TO label10.
130 1 MOVE ' house-photo: ' TO label12.
131 1 MOVE ' disclosure: ' TO label14.
132
133
134 1 do-the-work.
135 *

7830 8160–027 I–43


Example UCS COBOL Program—Using Interactive SQL

136 * Assume that at this point we get the names of the files containing
137 * the detail description, house photo, and inspection disclosure and
138 * perform I/O to read the data into the variables v-detail-description
139 * v-house-photo, and v-disclosure. See the COBOL Compiler Programming
140 * Reference Manual Volume 2: Compiler and System Interface for an
141 * example of Input and Output of BLOBs.
142 *
143 * Also, assume that we get the values for hno, location, price, and
144 * description from the user.
145 *
146 * This example uses MOVE in place of the I/O to illustrate the
147 * specific RDMS issues.
148 *
149 1 MOVE 'H907' TO v-hno.
150 1 MOVE '123 Main Street Minneapolis, MN' TO v-location.
151 1 MOVE 120000 to v-price.
152 1 MOVE 'older home 4BR 2BA FP AC' to v-description.
153 *
154 * fill in detail description; set the length to the actual length,
155 * in bytes. Note that trailing spaces in the string are
156 * not included in the length. In this instance, the trailing spaces
157 * are not significant characters.
158 *
159 1 STRING
160 'charming two story home in the prestigious '
161 DELIMITED SIZE,
162 'Powderhorn neighborhood'
163 DELIMITED SIZE
164 INTO v-detail-description-data.
165 1 MOVE 66 TO v-detail-description-length.
166 *
167 * assume there is no house photo
168 *
169 1 MOVE 'no work orders required' TO v-disclosure-data.
170 1 MOVE 23 TO v-disclosure-length.
171 *
172 * There are several ways to tell RDMS that the house_photo column will
173 * have a NULL value -- and thereby trigger the insertion of the
174 * default value from the table definition:
175 * - set the corresponding indicator to -1
176 * - set v-house-photo-length to 0
177 * - include the keyword NULL in place of the variable :v-house-photo
178 *
179 1 MOVE 0 TO v-house-photo-length.
180 *
181 * do the begin thread statement
182 *
183 1 MOVE SPACES TO COMMAND-AREA.
184 1 MOVE 'BEGIN THREAD FOR app014 UPDATE UDSMSG;' TO CM-LINE(1).
185 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
186 ERROR-STATUS, AUX-INFO.
187 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO

I–44 7830 8160–027


Example UCS COBOL Program—Using Interactive SQL

188 1 DISPLAY 'Error on BEGIN THREAD' UPON PRINTER


189 1 PERFORM RDMS-ERROR-PARA
190 END-IF.
191 *
192 * do the insert statement
193 *
194 1 MOVE SPACES TO COMMAND-AREA.
195 1 MOVE 'INSERT INTO s1.house ' TO CM-LINE(1).
196 1 MOVE 'VALUES($P1, $P2, $P3, $P4, $P5, ' TO CM-LINE(2).
197 1 MOVE '$P6, $P7); ' TO CM-LINE(3).
198
199 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
200 ERROR-STATUS, AUX-INFO, v-hno, v-location, v-price,
201 v-description, v-detail-description, v-house-photo,
202 v-disclosure.
203 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
204 1 DISPLAY 'Error on INSERT' UPON PRINTER
205 1 PERFORM RDMS-ERROR-PARA
206 END-IF.
207
208 *
209 * commit the changes
210 *
211 1 MOVE SPACES TO COMMAND-AREA.
212 1 MOVE 'COMMIT THREAD;' TO CM-LINE(1).
213
214 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
215 ERROR-STATUS, AUX-INFO.
216
217 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
218 1 DISPLAY 'Error on COMMIT' UPON PRINTER
219 1 PERFORM RDMS-ERROR-PARA
220 END-IF.
221
222 *
223 * Now, fetch the records back again
224 *
225 1 MOVE SPACES TO COMMAND-AREA.
226 1 MOVE 'DECLARE curs301 CURSOR ' TO CM-LINE(1).
227 1 MOVE 'FOR SELECT * FROM s1.house; ' TO CM-LINE(2).
228
229 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
230 ERROR-STATUS, AUX-INFO.
231 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
232 1 DISPLAY 'Error on DECLARE CURSOR' UPON PRINTER
233 1 PERFORM RDMS-ERROR-PARA
234 END-IF.
235
236 1 MOVE SPACES TO COMMAND-AREA.
237 1 MOVE 'OPEN CURSOR curs301; ' TO CM-LINE(1).
238
239 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA

7830 8160–027 I–45


Example UCS COBOL Program—Using Interactive SQL

240 ERROR-STATUS, AUX-INFO.


241 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
242 1 DISPLAY 'Error on OPEN CURSOR' UPON PRINTER
243 1 PERFORM RDMS-ERROR-PARA
244 END-IF.
245
246 *
247 * Clear the BLOB destination variables
248 *
249 1 MOVE SPACES TO d-detail-description.
250 1 MOVE SPACES TO d-house-photo.
251 1 MOVE SPACES TO d-disclosure.
252
253 1 MOVE SPACES TO COMMAND-AREA.
254 1 MOVE 'FETCH FIRST curs301 ' TO CM-LINE(1).
255 1 MOVE 'INTO $p1 $p2,$p3 $p4,$p5 $p6, ' TO CM-LINE(2).
256 1 MOVE '$p7 $p8, $p9 $p10, $p11 $p12, $p13 $p14; '
257 TO CM-LINE(3).
258 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
259 ERROR-STATUS, AUX-INFO, d-hno, indicator1,
260 d-location, indicator2,
261 d-price, indicator3,
262 d-description, indicator4,
263 d-detail-description, indicator5,
264 d-house-photo, indicator6,
265 d-disclosure, indicator7.
266 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
267 1 DISPLAY 'Error on FETCH 1' UPON PRINTER
268 1 PERFORM RDMS-ERROR-PARA
269 END-IF.
270
271 *
272 * Assume that at this point we write the three BLOB values to files for
273 * transport to a display device.
274 *
275 * This example uses DISPLAY to illustrate the specific RDMS issues
276 *
277 1 MOVE indicator1 TO indicator1-value.
278 1 MOVE indicator2 TO indicator2-value.
279 1 MOVE indicator3 TO indicator3-value.
280 1 MOVE indicator4 TO indicator4-value.
281 1 MOVE indicator5 TO indicator5-value.
282 1 MOVE indicator6 TO indicator6-value.
283 1 MOVE indicator7 TO indicator7-value.
284
285 1 MOVE SPACES TO hno-value.
286 1 IF indicator1 IS >= ZERO
287 1 MOVE d-hno TO hno-value.
288 1 MOVE SPACES TO location-value.
289 1 IF indicator2 IS >= ZERO
290 1 MOVE d-location TO location-value.
291 1 MOVE ZERO TO price-value.

I–46 7830 8160–027


Example UCS COBOL Program—Using Interactive SQL

292 1 IF indicator3 IS >= ZERO


293 1 MOVE d-price TO price-value.
294 1 MOVE SPACES TO description-value.
295 1 IF indicator4 IS >= ZERO
296 1 MOVE d-description TO description-value.
297 1 MOVE SPACES TO detail-description-value.
298 1 IF indicator5 IS >= ZERO
299 1 MOVE
300 d-detail-description-data(1:d-detail-description-length)
301 TO detail-description-value.
302 1 MOVE SPACES TO house-photo-value.
303 1 IF indicator6 IS >= ZERO
304 1 MOVE d-house-photo-data(1:d-house-photo-length)
305 TO house-photo-value.
306 1 MOVE SPACES TO disclosure-value.
307 1 IF indicator6 IS >= ZERO
308 1 MOVE d-disclosure-data(1:d-disclosure-length)
309 TO disclosure-value.
310
311 1 DISPLAY print-line1 UPON PRINTER.
312 1 DISPLAY print-line2 UPON PRINTER.
313 1 DISPLAY print-line3 UPON PRINTER.
314 1 DISPLAY print-line4 UPON PRINTER.
315 1 DISPLAY print-line5 UPON PRINTER.
316 1 DISPLAY print-line5a UPON PRINTER.
317 1 DISPLAY print-line6 UPON PRINTER.
318 1 DISPLAY print-line7 UPON PRINTER.
319 *
320 * Suppose the variable to hold the inspection disclosure is too small
321 * to hold the value being fetched. RDMS returns a truncation warning
322 * and puts the column length into the corresponding indicator variable
323 * Note that it is the column's declared length, not the length of the
324 * value being fetched.
325 *
326 1 MOVE SPACES TO COMMAND-AREA.
327 1 MOVE 'FETCH FIRST curs301 ' TO CM-LINE(1).
328 1 MOVE 'INTO $p1 $p2,$p3 $p4,$p5 $p6, ' TO CM-LINE(2).
329 1 MOVE '$p7 $p8, $p9 $p10, $p11 $p12, $p13 $p14; '
330 TO CM-LINE(3).
331 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
332 ERROR-STATUS, AUX-INFO, d-hno, indicator1,
333 d-location, indicator2,
334 d-price, indicator3,
335 d-description, indicator4,
336 d-detail-description, indicator5,
337 d-house-photo, indicator6,
338 d-short-disclosure, indicator7.
339 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
340 1 DISPLAY 'Error on FETCH 2' UPON PRINTER
341 1 PERFORM RDMS-ERROR-PARA
342 END-IF.
343

7830 8160–027 I–47


Example UCS COBOL Program—Using Interactive SQL

344 1 DISPLAY
345 'inspection disclosure length from indicator:'
346 UPON PRINTER.
347 1 DISPLAY indicator7 UPON PRINTER.
348 *
349 * close the cursor
350 *
351
352 1 MOVE SPACES TO COMMAND-AREA.
353 1 MOVE 'CLOSE curs301; ' TO CM-LINE(1).
354
355 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
356 ERROR-STATUS, AUX-INFO.
357 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
358 1 DISPLAY 'Error on CLOSE CURSOR' UPON PRINTER
359 1 PERFORM RDMS-ERROR-PARA
360 END-IF.
361
362
363 1 PERFORM END-THREAD-TO-UDS.
364 1 PERFORM TERMINATION-PARA.
365 *
366 * other procedure paragraphs
367 *
368
369
370 1 END-THREAD-TO-UDS.
371 1 MOVE SPACES TO COMMAND-AREA.
372 1 MOVE 'END THREAD TERMINATE; ' TO CM-LINE(1).
373
374 1 ENTER MASM 'ACOB$RDMR' USING COMMAND-AREA
375 ERROR-STATUS, AUX-INFO.
376 1 IF ERROR-STATUS IS NOT EQUAL TO ZERO
377 1 DISPLAY 'Error on END THREAD' UPON PRINTER
378 1 PERFORM RDMS-ERROR-PARA
379 END-IF.
380
381 1 TERMINATION-PARA.
382 1 DISPLAY 'END UCOB example'
383 UPON PRINTER.
384 1 STOP RUN.
385
386 1 RDMS-ERROR-PARA.
387 1 EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.
388 1 DISPLAY '*** RDMCA AUX-INFO = ' AUX-INFO UPON PRINTER.
389 1 DISPLAY '*** ERROR STATUS = ' ERROR-STATUS UPON PRINTER.

I–48 7830 8160–027


Example UCS COBOL Program—Using Interactive SQL

Output
Executing this program produces the following output:

@XQT OBJ$.EX-UCOB2
indicator1: +0000000 house number: H907
indicator2: +0000000 location: 123 Main Street Minneapolis,
indicator3: +0000000 price: $120,000.00
indicator4: +0000000 description: older home 4BR 2BA FP AC
indicator5: +0000000 detail description:
charming two story home in the prestigious Powderhorn neighborhood
indicator6: +0000000 house-photo: no house photo available
indicator7: +0000000 disclosure: no work orders required
inspection disclosure length from indicator:
+1048576
END UCOB example

7830 8160–027 I–49


Example UCS COBOL Program—Using Interactive SQL

I–50 7830 8160–027


Index

A updatable cursors, 6-17


views, 6-17
examples, 6-12
abs function, 3-59
foreign key enforcement, 6-82
absval function, 3-59
restrictions
ACCESS lock, 9-9
cast function, 6-18
access path
global temporary tables, 6-19
determining
interval data type, 6-18
examples, 8-8
revoking privileges (REVOKE), 6-18
in IPF SQL interface, rules, 8-18
storage areas for tables, 6-12
good or poor, and statistics, 9-51
syntax, 6-4
retrieving cursor information, 8-47
user-id considerations, 6-17
acos function, 3-59
alternate based integers, 2-13
active_version function, 3-24
AND, binary operator, 2-27
ADD BLOB STORAGE edit specification,
ANY, universal quantifier, 2-25
ALTER TABLE, 6-5
application groups
ADD column edit specification, ALTER
MAXIMUM-AOR-UPDATES configuration
TABLE, 6-5
parameter, 3-146
ADD CONSTRAINT edit specification, ALTER
names, determining, 6-23
TABLE, 6-5
UDS Control, 1-10
ADD FOREIGN KEY edit specification, ALTER
application programs (See also ASCII
TABLE, 6-5
COBOL; ASCII FORTRAN; Universal
add_months function, 3-78
Compiling System)
addition rounding algorithm, 2-32
accessing RDMS, DMS, SFS
ADVANCE recovery step option, 6-33, 8-3
concurrently, 6-25
AFTER triggers, 7-6
host language variables, 2-109
aggregate functions, 2-48 (See also
placeholder variables, 2-112, 2-113
functions; scalar functions)
approximate numeric data types, 1-7, 2-83
aggregate operations with views, 2-67, 2-68
arithmetic expressions
ALL, universal quantifier, 2-25
datetime arithmetic expressions, 2-36
ALLOCATE CURSOR statement
evaluating, 2-31
example, 6-3
result types, 2-35
rules/guidelines for use, 6-3
rounding, 2-31
syntax, 6-2
arithmetic operators, precedence of
ALLOW MULTIPLE TABLE FILE edit
operations, 2-30
specification, ALTER TABLE, 6-5
arrays, FETCH NEXT n statement, 8-32
ALTER TABLE statement
ASCENDING/ASC sort order, 6-60, 6-61
adding constraints, 6-17, 6-18
ASCII COBOL
address conflicts, 6-17
BEGIN THREAD, D-3
dropping constraints, 6-18
collecting a program with SQL
edit specifications, 6-5
statements, D-7
effect on
example program, D-9
compiled programs, 6-18
GETERROR statement, 8-47
foreign keys, 6-18
kanji, 2-81, 2-108
triggers, 6-19

7830 8160–027 Index–1


Index

passing data to RDMS, D-4 examples, 6-23


programs that call DMS or SFS, D-7 explicit, required by IPF SQL, 6-25
receiving data from RDMS, D-5 implicit, example, 6-25
SQL statements, D-1 NONE recovery option, 6-22
TIP transactions, D-8 not supported in routines and
ASCII FORTRAN triggers, 4-27
BEGIN THREAD, E-3 options format/table, 6-22
calling R$RDMR, E-6 QUICKLOOKS recovery option, 6-22
collecting a program with SQL rules/guidelines for use, 6-23
statements, E-8 syntax, 6-21
example program, E-10 BETWEEN operator, 2-42
kanji, 2-81, 2-108 binary (bitwise) expressions and
passing data to RDMS, E-4 operators, 2-27
receiving data from RDMS, E-5 binary large objects (BLOB)
SQL statements, E-1 ADD BLOB STORAGE edit specification,
TIP environment, E-9 ALTER TABLE, 6-5
variable arguments, E-4 backup and recovery, I-12
ascii function, 3-55 COBOL programs
asin function, 3-60 declaring BLOB variables, I-19
atan function, 3-60 referencing BLOB variables, I-20
atan2 function, 3-60 columns, I-4
automatic recompilation, 1-15, 2-119 defined, 2-89
auxiliary information functions
rollback status, B-3, B-4 get_file, 3-163
rows lob_crc, 3-164
existence/nonexistence of, 9-4 lob_end_address, 3-164
returned, 8-32 lob_end_page, 3-165
updated, 10-33 lob_file, 3-165
AUX-INFO, COBOL programs, 9-46, C-4, C-7 lob_id, 3-166
AVG function lob_id_crc, 3-166
aggregate operation, 2-67 lob_start_address, 3-167
example, 2-50 lob_start_page, 3-167
format, 2-48 put_file, 3-168
limitations, I-6
not supported for C++, I-18
B not supported for IPF SQL, 8-29
overview, I-1
base tables, described, 1-8 page sizes, I-7
BEFORE triggers, 7-6 record sizes, I-7
BEGIN DECLARE statement RSM-LOB format storage areas, I-4
embedded variables, 2-110 sizes of BLOB values, I-5
rules/guidelines for use, 6-20 storage areas, I-2, I-8
syntax and examples, 6-20 UCS C programs
BEGIN statement, 4-30 declaring BLOB pointer variables, I-17
BEGIN THREAD statement declaring BLOB variables, I-13, I-14
accessing RDMS, DMS, and SFS example, embedded SQL, I-22
concurrently, 6-25 example, interactive SQL, I-27
application group name, determining, 6-24 referencing BLOB variables, I-16
ASCII COBOL, D-3 UCS COBOL programs
ASCII FORTRAN, E-3 declaring BLOB values larger than
COMMANDLOOKS recovery option, 6-22 64 MB, I-20
DEFERRED recovery option, 6-22 example, embedded SQL, I-34
example, interactive SQL, I-41

Index–2 7830 8160–027


Index

binding to a cursor, rules, 2-122 datalength, 3-42


bindings, program, 1-15 decode, 3-57
bitwise (binary) expressions and delesc, 3-27
operators, 2-27 difference, 3-43
blanks, trailing, 2-44, 3-5, 3-6 ifnull, 3-58
BLOB (See binary large objects) initcap, 3-27
Boolean expressions insert, 3-28
described, 2-23 insesc, 3-29
evaluating, 2-31 instr, 3-44
precedence of operations, 2-30 isalnum, 3-45
built-in functions (See scalar functions) isalpha, 3-45
iscntrl, 3-46
isdigit, 3-47
C isgraph, 3-47
islower, 3-48
CALL statement isprint, 3-49
examples, 6-29 ispunct, 3-49
rules/guidelines for use, 6-30 isspace, 3-50
syntax, 6-28 isupper, 3-51
cascading, dropping views isxdigit, 3-52
automatically, 7-59 lcase, 3-29
cast function, 3-79 left, 3-30
ceil function, 3-61 length, 3-42
ceiling function, 3-61 locate, 3-53
CHANGE COLUMN edit specification, ALTER lower, 3-29
TABLE, 6-5 lpad, 3-31
char function, 3-55 ltrim, 3-31
char_length function, 3-42 nspace, 3-32
CHARACTER data type nullif, 3-58
character value assignments, 2-93 nvl, 3-58
characteristics and usage, 3-4 octet_length, 3-54
collating sequence, 2-107 patindex, 3-54
pattern-matching (LIKE and NOT position, 3-41
LIKE), 2-43 posstr, 3-41
VARCHAR, comparison to, 3-4 repeat, 3-32
character data types replace, 3-33
character strings, 2-99 replicate, 3-32
format, 2-80 reverse, 3-33
introduced, 1-7 right, 3-34
character functions rpad, 3-35
active_version, 3-24 rtrim, 3-36
char_length, 3-42 soundex, 3-36
character functions that return character space, 3-37
values, 3-24 stuff, 3-28
character functions that return numeric substr, 3-37
values, 3-41 substring, 3-37
character_length, 3-42 ucase, 3-40
charindex, 3-41 upper, 3-40
coalesce, 3-56 value, 3-56
concat, 3-5, 3-25 character sets
concatrtrim, 3-5, 3-25 CHARACTER SET clause, 2-93, 2-98
concatstrim, 3-5, 3-26 implicit collation, 2-101
RDMS_TEXT, 2-101

7830 8160–027 Index–3


Index

character_length function, 3-42 recovery step, effect on, 6-34


charindex function, 3-41 rules/guidelines for use, 6-34
check constraints, defining (CREATE step control options, 6-33
TABLE), 6-59 syntax and examples, 6-33
chr function, 3-55 TERMINATE recovery step option, 6-33
CLOSE statement comparison operators
rules/guidelines for use, 6-31 IS [NOT] NULL, 2-41
syntax and examples, 6-31 precedence of operations, 2-30
two consecutive OPENs instead of compile time reports, 8-19
CLOSE, 6-31 composite key, described, 6-62
coalesce function, 3-56 concat function, 3-5, 3-6, 3-25
collating sequences concatenate ( | | ) operator, 3-5
CHARACTER data, 2-107 concatrtrim function, 3-5, 3-6, 3-25
COLLATE clause concatstrim function, 3-5, 3-6, 3-26
CREATE TABLE, 6-53 concurrency functions
DECLARE CURSOR, 7-25 identity_val_local function, 3-160
description and use, 2-99 partition _id function, 3-158
effects on character value conditions
assignments, 2-93 CHECK clause, 6-60
comparison of character strings, 2-99 EXISTS function, 2-56
NCHARACTER data, 2-107 query specifications, 2-60
columns search, LIKE operator, 2-43
column-definition clause, CREATE WHENEVER statement, 10-47
TABLE, 6-49 constraints
defined, 1-6 adding and dropping table constraints
dropping (ALTER TABLE), 6-5
example, 8-7 defining (CREATE TABLE), 6-59
restriction on, 6-7 multiple use of, 6-74
name specifications, 2-7 naming conventions, 2-3
naming conventions, 2-3 referential (foreign key), 6-53
nulls, designing for, 2-14 table-constraint-specification clause.
retrieving information about, 8-43 CREATE TABLE, 6-59
specifying column names in SQL, 2-7 conversions
UNLOAD statement, column binary-to-character, 3-55
descriptions, 10-16 character-to-binary, 3-55
updating convert function, 3-85
in a subset of rows (UPDATE to_char function, 3-134
Searched), 10-30 convert function, 3-85
in all rows (UPDATE ALL), 10-21 correlated query, 2-74
in current row (UPDATE correlation names, naming conventions, 2-3
Positioned), 10-25 cos function, 3-61
in one or more rows (UPDATE cosh function, 3-62
VALUES), 10-40 cot function, 3-62
widths of columns, 3-5 COUNT function
COMMANDLOOKS recovery option aggregate operation, 2-67
description of, 6-22 example, 2-50
updating with, 6-26 format, 2-48
comments in statements, 5-3 CRC (See cyclical redundancy checks)
COMMIT statement CREATE INDEX statement
ADVANCE recovery step option, 6-33 examples, 6-37
errors, B-9 large tables, performance with, 6-39
not supported in routines and QUICKLOOKS recovery option,
triggers, 4-27 performance issues, 6-39

Index–4 7830 8160–027


Index

syntax, 6-35 CURRENT_DATE function, 2-51, 2-53


CREATE ROLE statement CURRENT_TIME function, 2-51, 2-53
rules/guidelines for use, 6-41 CURRENT_TIMESTAMP function, 2-51, 2-53
syntax, 6-41 cursors
syntax and examples, 6-41 access path
CREATE SCHEMA statement determining, 9-51
example, 6-43 explanation, 8-8
rules/guidelines for use, 6-43 retrieving information, 8-47
syntax, 6-42 aggregate operations, restriction, 2-67
user-id considerations, 6-43 allocating (ALLOCATE CURSOR), 6-2
CREATE TABLE statement associating with prepared statement, 6-2
access specification clause, 6-64 binding to, rules, 2-122
check constraints, 6-80 closing, 6-31
column definition format, 6-49 declaring (DECLARE CURSOR), 7-22
default clauses, 6-81 declaring, example, 8-31
examples, 6-72 dropping (DROP CURSOR), 7-48
foreign keys dynamic result sets
enforcement of foreign keys, 6-82 cursor names, 4-17, 8-55
establishing foreign keys, 6-63, 6-81 fetching
global temporary tables, 6-46, 6-84 multiple rows from, 8-30
index specification clause, 6-61 one row from, 8-23
nulls in primary keys, 6-81 naming conventions, 2-3
owner specification clause, 6-64 opening
partition index specification clause, 6-71 OPEN statement, 9-12
partition-primary-key-specification opening, examples, 8-31
clause, 6-64 pointer, positioning, 9-3
restrictions read-only (DECLARE CURSOR), 7-35
cast function, 6-82 references, resolving, 2-122
interval data type, 6-82 releasing
security example, 6-31
MAPPER and TIP security, 6-83 retrieving
specifying access control, 6-83 access path information, 8-47
sort column list format, 6-60, 6-61, 6-62 multiple rows from, 8-30
storage area designations, 6-79 one row from, 8-23
syntax, 6-45 description of (example, 8-45
table-constraint-specification clause, 6-59 UPDATE statement, referencing
table-specification clause (table cursors, 10-26
name), 6-48 curtime function, 3-88
table-storage-area clause, 6-48 CUSTOMERS sample table (used in
user-ids, 6-79 examples), 1-5
CREATE TRIGGER statement cyclical redundancy checks (CRC)
BEFORE and AFTER triggers, 7-6 lob_crc function, 3-164
examples of triggers, 7-7 lob_id_crc function, 3-166
rules and guidelines, 7-10
syntax, 7-2
CREATE VIEW statement D
example, 7-13
query specification processing, 2-60 DATA ACCESS CONTROL edit specification,
rules and guidelines, 7-14 ALTER TABLE, 6-5
syntax, 7-12 data items, defined, 1-6
UREP considerations, 7-15 data types
WITH CHECK OPTION clause, 7-15 approximate numeric data types, 2-83
curdate function, 3-88

7830 8160–027 Index–5


Index

binary large object (BLOB), 2-89 DATE literals, 2-15


character data types, 2-80 dateadd function, 3-90
combinations for concatenation, 3-6 datediff function, 3-9, 3-92
datetime, 2-87 datename function, 3-9, 3-93
introduced, 1-7 datepart function, 3-9, 3-94
RDMS data types, 2-80 dates
scalar functions, input, 3-2 DATE literal format, 2-15
time zones, 2-89 date, time, and timestamp functions, 3-78
database storage areas, naming Gregorian calendar, 3-9
conventions, 2-3 Julian calendar, 3-9
datalength function, 3-42 datetime arithmetic expressions, 2-36
date, 3-12 datetime data types (See also DATE data
DATE data type type; TIME data type; TIMESTAMP
format, 2-87 data type)
introduced, 1-7 formats, 2-87
date Function, 3-89 in routines and triggers, 4-50
date functions introduced, 1-7
add_months, 3-78 memory usage, 2-88
cast, 3-79 ranges, 2-87
casting a value to an interval, 3-82 storing and retrieving values, 2-88
convert, 3-85 time zones, 2-89
curdate, 3-88 datetime literals, 2-15
dateadd, 3-90 day, 3-12
datediff, 3-92 day Function, 3-96
datename, 3-93 day of month, 3-12
datepart, 3-94 day of month (dayofmonth function), 3-97
dayname, 3-97 day of week (dayofweek function), 3-98
dayofmonth, 3-97 day of year
dayofweek, 3-98 dayofyear function, 3-100
dayofyear, 3-100 Julian day, 3-9
days, 3-101 julian_day function, 3-107
erdate_to_timestamp, 3-102 dayname function, 3-97
erdwtime_to_timestamp, 3-102 dayofmonth function, 3-97
ertdate_to_timestamp, 3-103 dayofweek function, 3-98
ertime_to_time, 3-103 dayofyear function, 3-100
extract, 3-103 days function, 3-9, 3-101
julian_day, 3-107 DEBUG DUMP SIZES command, determining
last_day, 3-108 syntax size, H-2
month, 3-112 DEBUG statement
monthname, 3-113 examples, 7-20
months_between, 3-114 HVTIP environment, F-1
next_day, 3-118 rules and guidelines, 7-20
quarter, 3-119 syntax, 7-18
round, 3-120 DECIMAL data type
strftime, 3-122 introduced, 1-7
strptime, 3-125 items defined in an owned schema, 2-31
timestamp, 3-129 DECLARE CURSOR statement
timestampadd, 3-130 COLLATE clause, 2-99
timestampdiff, 3-132 examples, 7-28
to_char, 3-134 ORDER BY clause, 2-99
trunc, 3-142 query specification processing, 2-60
week, 3-143 retrieving cursor information, 8-43
year, 3-144 rules and guidelines, 7-34

Index–6 7830 8160–027


Index

UNION and UNION ALL operators, 7-24 examples, 7-51


DECLARE statement, 4-40 rules and guidelines, 7-52
decode function, 3-57 syntax, 7-51
default qualifier and version names, 10-44 DROP ROE statement
DEFERRED recovery option rules and guidelines, 7-53
description of, 6-22 DROP ROLE statement
updating with, 6-26 example, 7-53
degree function, 3-62 syntax, 7-53
degrees function, 3-62 DROP TABLE statement
delesc function, 3-27 example, 7-54
DELETE statement global temporary tables, 7-56
DELETE ALL, 7-45 INCLUDING CONTENTS, 7-54, 7-55, 7-56
examples, 7-44 rules and guidelines, 7-54
foreign keys, 7-46 syntax, 7-54
NONE recovery option, 7-45 DROP TRIGGER statement, 7-57
number of rows deleted, 7-46 DROP VIEW statement, 7-58
positional deletion, 7-44 dropping
preparing and executing, 8-5 cursors (DROP CURSOR), 7-48
RETRIEVAL locks not allowed, 7-45 indexes (DROP INDEX), 7-49
routines and triggers, 7-47 roles (DROP ROLE), 7-53
syntax, 7-43 routines, 4-11
views, using with, 7-14 stored functions (DROP FUNCTION, 7-51
deleting stored procedures (DROP
indexes (DROP INDEX), 7-49 PROCEDURE, 7-51
positional deletion (DELETE), 7-44 tables (DROP TABLE), 7-54
roles (DROP ROLE), 7-53 triggers, 4-12
rows (DELETE), 7-43 DROP TRIGGER statement, 7-57
tables (DROP TABLE), 7-54 effects of DROP
views (DROP VIEW), 7-58 PROCEDURE/FUNCTION, 7-52
delimited identifiers, 2-4 effects of DROP TABLE, 7-54
DESCENDING/DESC sort order, 6-60, 6-61 effects of DROP VIEW, 7-58
difference function, 3-43 RDMS-TRIGGER-DROPPING, 7-2, 7-50,
direct access, DECLARE CURSOR, 7-26 7-52, 7-54
DISCARD step control option, ROLLBACK views
statement, 9-34 automatic (cascading), 7-59
DISTINCT keyword, 2-65, 2-67, 8-66 DROP VIEW statement, 7-58
division rounding algorithm, 2-33 effects of DROP TABLE, 7-55
DMS (See Network Database Server) dumping rows into files (UNLOAD), 10-2
double function, 3-77 dumps, DEBUG statement, 7-18
DOUBLE PRECISION data type dynamic ESQL, 1-18
format, 2-83 dynamic parameter markers, 2-109
introduced, 1-7 dynamic result sets
DROP column edit specification, ALTER cursor names, 8-55
TABLE, 6-5 described, 4-17
DROP CONSTRAINT edit specification, example, 4-19
ALTER TABLE, 6-5 FUNCTION statement, 8-34
DROP CURSOR statement GET RESULT SET CURSOR NAME, 8-54
syntax and examples, 7-48 PROCEDURE statement, 9-21
DROP FOREIGN KEY edit specification, result set information (temporary
ALTER TABLE, 6-5 table), 4-18
DROP INDEX statement SET RESULT SET statement, 9-47
syntax and examples, 7-49 update counts, 9-47
DROP PROCEDURE/FUNCTION statement

7830 8160–027 Index–7


Index

E erdwtime_to_timestamp function, 3-102


error messages
GETERROR statement, 8-47
ELSEIF clause, 4-41
groups, B-2
embedded SQL (ESQL)
handling, B-1
comments in statements, 2-2
location, B-1
compilation, determining application
retrieving, 8-47
group name, 6-24
status 6000 to 6999, B-6
compile-time statements, scope, 2-121
statuses, B-3
cursor resolution, 2-123
text, B-3
dynamic
UDS Control, 1-10
example, 2-124
errors
statements allowed, 2-126
error checking routines, 4-26
dynamic ESQL, 1-18
handling errors in ESQL, C-1
dynamic parameter markers, 2-109
SQLCODE variable, ESQL, C-3
embedded variables, 2-109, 2-110
SQLSTATE system variable, B-10
error handling, C-1
ERROR-STATUS variable, using in COBOL
expressions, 2-22
programs, C-4, C-7
GETERROR statement, using to retrieve
ertdate_to_timestamp function, 3-103
error messages, C-6
ertime_to_time function, 3-103
interface, introduction to, 1-13
escape characters, 2-44
introduction to, 2-118
ESQL (See embedded SQL)
LIKE operator in UCS COBOL
exact numeric data types, 1-7
program, 2-46
examples
marking statements for compiler, 2-120
ALTER TABLE, 6-12
migrating to, C-4
ASCII COBOL program, D-9
multiple rows, retrieving, 1-20
ASCII FORTRAN program, E-10
parameter markers, 2-111
BEGIN THREAD statement
recompilation, automatic, 1-15, 2-119
ASCII COBOL, D-3
scope of statements, 2-120
ASCII FORTRAN, E-3
SQLCODE variable, C-3
BLOB data
static
UCS C, I-22, I-27
considerations, 2-121
UCS COBOL, I-34, I-41
static ESQL, 1-16, 2-119
calculating BLOB storage area sizes, I-8
static ESQL, 2-118
collecting programs with SQL statements
UCS C example, with BLOB data, I-22
ASCII COBOL, D-7
UCS COBOL example, with BLOB
ASCII FORTRAN, E-8
data, I-34
creating
UCS COBOL indicator variable, 2-116
LOB columns, I-4
variable declarations, delimiting, 1-24
tables (CREATE TABLE), 6-72
version name
CUSTOMERS and HOUSES tables, 1-5
specifying, 2-7
debugging syntax (DEBUG), 7-20
embedded variables, 2-109
DECLARE CURSOR, 7-28
END DECLARE statement
deleting rows (DELETE), 7-44
embedded variables, 2-110
dropping
example, 8-2
cursors (DROP CURSOR), 7-48
rules/guidelines for use, 8-2
indexes (DROP INDEX), 7-49
syntax, 8-2
tables (DROP TABLE), 7-54
END IF clause, 4-41
triggers (DROP TRIGGER), 7-57
END statement, 4-30
views (DROP VIEW), 7-58
END THREAD statement, 8-3
dynamic result sets, 4-19
END WHILE clause, 4-48
inner join, 7-28
erdate_to_timestamp function, 3-102
outer join, 7-28, 7-29

Index–8 7830 8160–027


Index

passing many variables to RDMS, G-1 F


referencing BLOB variables
COBOL, I-20
FETCH NEXT n statement
UCS C, I-16
arrays, 8-32
stored functions (FUNCTION), 8-35
compared to FETCH, 8-31
tracing ESQL compilation and
example, 8-30
execution, 7-20
HVTIP environment, F-1
triggers (CREATE TRIGGER), 7-7
not supported for BLOB columns, 8-32
views, creating (CREATE VIEW), 7-13
performance, 8-32
WHENEVER statement, C-2
restrictions on use, 8-31
EXCLUSIVE RETRIEVAL lock, 9-8
sensitive cursors, 8-32
EXCLUSIVE UPDATE lock, 9-9
syntax, 8-30
EXECUTE IMMEDIATE statement
FETCH statement
example, 8-7
example, 8-25
restrictions, 8-7
performance, 8-28
rules/guidelines for use, 8-7
retrieving rows from a cursor, 8-27
syntax, 8-7
routines and triggers, 8-28
EXECUTE statement
syntax, 8-23
example, 8-5
FF, 3-136
rules/guidelines for use, 8-5
FLASH indexes, 6-35
syntax, 8-5
FLOAT data type
executing
format, 2-83
prepared ESQL statement, 8-5
introduced, 1-7
routines, 4-11
floor function, 3-63
stored procedures, 6-28
foreign keys
triggers, 4-12
CREATE TABLE
EXISTS function
foreign key considerations, 6-81
format and example, 2-56
foreign key specification clause, 6-63
in subqueries, 2-73, 2-77
deleting rows (DELETE), 7-46
exp function, 3-63
enforcement of foreign keys, 6-82
EXPLAIN statement
foreign key constraints, defining (CREATE
examples, 8-8
TABLE), 6-59
retrieving cursor access path
naming conventions, 2-3
information, 8-47
UPDATE ALL statement, 10-23
rules/guidelines for use, 8-18
format
syntax, 8-8
timestamp, 3-21
exponentiation (exp function), 3-63
varchar, 3-23
expressions
Function
arithmetic result types, 2-35
date, 3-89
bitwise expressions, 2-27
day, 3-96
Boolean expressions, 2-23
timestamp_format, 3-134
built-in functions, 2-38
to_date, 3-138
datetime arithmetic expressions, 2-36
to_timestamp, 3-141
defined, 2-22
varchar_format, 3-143
evaluation, 2-31
FUNCTION statement
IS NULL operator, 2-41
committing and omitting, 8-41
null values, 2-41
DECLARE statements, 8-40
operands and comparison operators, 2-39
default qualifier and version, 8-42
precedence of operations, 2-30
examples, 8-35
rounding arithmetic expressions, 2-31
nested invokes, 8-41
string and blob expressions, 2-37
parameter information (GET
extract function, 3-103
PARAMETERS), 8-41

7830 8160–027 Index–9


Index

recoverable threads, 8-41 ALTER TABLE, 6-12, 6-19


RETURNS clause and RETURN CREATE TABLE, 6-46, 6-84
statement, 8-41 described, 1-8
schema ownership required, 8-40 DROP TABLE, 7-56
security, 8-42 LOCK, 9-6
syntax, 8-33 ROLLBACK, 9-36
TIP transactions, 8-41, 9-27 UNLOCK, 10-19
variables, restrictions, 8-41 GRANT statement
functions (See also scalar functions; examples, 8-58
aggregate functions; stored rules/guidelines for use, 8-59
functions) syntax, 8-56
CURRENT_DATE, 2-51 Gregorian calendar, 3-9
CURRENT_TIME, 2-51 GROUP BY clause, aggregate operation, 2-67
CURRENT_TIMESTAMP, 2-51 grouping operations, 2-67
EXISTS, 2-56
expression operands, 2-38
qualified names, 2-8 H
referencing functions in SQL, 2-8
unqualified names, 2-8 HAVING clause
USER, 2-55 aggregate operation, 2-67
scalar functions, 3-3
with GROUP BY clause, 2-65
G with WHERE clause, 2-67
hex function, 3-64
generated_run_id function, 3-146 host language variables, 1-15, 2-109
GET DESCRIPTION statement host program variables, SET statement, 9-42
example, 8-45 hour function, 3-106
in HVTIP environment, F-1 HOUSES sample table (used in
rules/guidelines for use, 8-45 examples), 1-5
syntax, 8-43 HVTIP environment
using, 3-8 application group name, determining, 6-24
GET PARAMETERS statement restrictions, F-1
example, 8-53 TIPMALLOC compiler keyword
rules/guidelines for use, 8-53 option, H-5
syntax, 8-49
GET RESULT SET CURSOR NAME statement
examples, 4-19, 8-54 I
syntax, 8-54
get_file function, 3-163 identifiers, delimited, 2-4
getdate function, 3-105 IDENTITY, 2-57, 6-50, 6-54
GETERROR statement identity_val_local function, 3-160
COBOL example, 8-47 IF statement, 4-41
determining access path, use in, 8-8 ifnull function, 3-58
error message text, retrieving, C-6 IN operator, 2-47
ESQL statement errors, use for, C-6 INCLUDING CONTENTS clause, DROP TABLE
in HVTIP environment, F-1 statement, 7-56
rules/guidelines for use, 8-48 indexes
syntax, 8-47 adding a secondary index (CREATE
with implicit BEGIN THREAD INDEX), 6-35
statement, 6-25 CREATE TABLE
global DISTINCT keyword, 2-65 index specification clause, 6-61
global temporary tables

Index–10 7830 8160–027


Index

partition index specification isdigit function, 3-47


clause, 6-71 isgraph function, 3-47
dropping (DROP INDEX), 7-49 islower function, 3-48
dropping columns from a secondary isprint function, 3-49
index, restriction, 6-7 ispunct function, 3-49
naming conventions, 2-3 isspace function, 3-50
indicator variables, 2-110, 2-114 isupper function, 3-51
initcap function, 3-27 isxdigit function, 3-52
inner joins, examples, 7-28 items, data, defined, 1-6
insert function, 3-28
INSERT statement
examples, 8-62 J
foreign key enforcement, 6-82
rules/guidelines for use, 8-64 joins
syntax, 8-61 cursor restrictions (DECLARE
views, using with, 7-14 CURSOR), 7-39
insesc function, 3-29 inner joins, examples, 7-28
instr function, 3-44 introduced, 1-8
INTEGER data type LEFT and RIGHT, 2-64
introduced, 1-7 outer joins
integer function, 3-64 examples, 7-28, 7-29
integer literals, 2-12 Julian day
Integrated Recovery step counter, defined, 3-9
advancing/terminating, 6-33, 8-3 julian_day function, 3-9, 3-107
interactive SQL
introduced, 1-17
UCS C example, with BLOB data, I-27 K
UCS COBOL example, with BLOB
data, I-41
kanji
interfaces to RDMS
ASCII COBOL, 2-81, 2-108
described, 1-12
ASCII FORTRAN, 2-81, 2-108
tradeoffs of using different
NCHARACTER data type, 2-80, 2-108
interfaces, 1-14
restrictions, 2-109
interpreter interface, 1-12
UCS C, 2-108
interval function, 3-82
UCS COBOL, 2-108
interval literals
UCS FORTRAN, 2-108
format, 2-18
katakana, restrictions, 2-109
operands in expressions, 2-39
KEEP step control option, ROLLBACK
invoking
statement, 9-34
stored procedures, 6-28
keys (See foreign keys; primary key)
triggers, 4-12
keywords, A-1
IPF SQL Interface
error messages, B-3
explicit BEGIN THREAD statement
requirement, 6-25
L
introduced, 1-12
percent sign (%) special character, 2-44 Large Object format (See binary large objects)
SELECT Multirow statement use, 9-37 last_day function, 3-108
IS [NOT] NULL comparison operator, lcase function, 3-29
determining values with, 2-41 left function, 3-30
isalnum function, 3-45 LEFT, join type, 2-64
isalpha function, 3-45 length function, 3-7, 3-42
iscntrl function, 3-46 LETS-J character set, 2-97

7830 8160–027 Index–11


Index

LEVEL statement log10 function, 3-66


example, 9-2 lower function, 3-29
syntax, 9-2 lpad function, 3-31
LIKE operator, 2-43 ltrim function, 3-31
LINC access to data, 1-13
literal values
alternate based integers, 2-13 M
DATE literal format, 2-15
datetime literals, 2-15 MAPPER Relational Interface (MRI), 1-12
described, 2-11 MAPPER, unloading RDMS data, 10-15
integer literals, 2-12 mathematical and numerical conversion
interval literals, 2-18 functions
nulls, 2-14 abs, 3-59
numeric literals, 2-12 absval, 3-59
real literals, 2-12 acos, 3-59
string literals, 2-11 asin, 3-60
TIME literal format, 2-16 atan, 3-60
TIMESTAMP literal format, 2-16 atan2, 3-60
ln function, 3-65 ceil, 3-61
LOB (See binary large objects) ceiling, 3-61
lob_crc function, 3-164 cos, 3-61
lob_end_address function, 3-164 cosh, 3-62
lob_end_page function, 3-165 cot, 3-62
lob_file function, 3-165 degree, 3-62
lob_id function, 3-166 degrees, 3-62
lob_id_crc function, 3-166 exp, 3-63
lob_start_address function, 3-167 floor, 3-63
lob_start_page function, 3-167 hex, 3-64
LOCAL indexes, 6-35 integer, 3-64
locate function, 3-53 ln, 3-65
LOCATE statement log, 3-65
example, 9-4 log10, 3-66
rules/guidelines for use, 9-4 mod, 3-66
syntax, 9-3 octal, 3-66
LOCK statement pi, 3-67
ACCESS, 9-9 power, 3-67
examples, 9-9 radians, 3-68
EXCLUSIVE RETRIEVAL, 9-8 rand, 3-69
EXCLUSIVE UPDATE, 9-9 real, 3-69
lock specification format, 9-6 round, 3-70
PROTECTED RETRIEVAL, 9-8 sign, 3-71
PROTECTED UPDATE, 9-9 sinh, 3-72
RETRIEVAL, 9-8 smallint, 3-72
rules/guidelines for use, 9-9 sqrt, 3-73
SHARED RETRIEVAL, 9-8 str, 3-73
SHARED UPDATE, 9-8 tan, 3-75
syntax, 9-6 tanh, 3-75
UPDATE, 9-8 trunc, 3-76
locking truncate, 3-76
types of locks (LOCK), 9-8 MAX function
UPDATE ALL, 10-22 aggregate operation, 2-67
UPDATE Positioned, 10-27 DISTINCT keyword, 2-65
log function, 3-65

Index–12 7830 8160–027


Index

example, 2-51 null values


format, 2-48 in expressions, 2-41
max_aor_updates function, 3-146 in literals, 2-14
MAXIMUM-AOR-UPDATES, configuration nullif function, 3-58
parameter, 3-146 nulls
memory usage in primary key, 6-62
datetime data types, 2-88 in secondary indexes, 6-61
numeric data types, 2-85 NUMERIC data type
microsecond function, 3-109 introduced, 1-7
midnight_seconds function, 3-110 numeric data types
migrating to ESQL, C-4 approximate numeric data types, 1-7
MIN function exact numeric data types, 1-7
aggregate operation, 2-67 memory usage, 2-85
DISTINCT keyword, 2-65 ranges and precision, 1-7, 2-84
example, 2-51 storing numeric data, 2-86
format, 2-48 numeric literals, 2-12
minute function, 3-111 nvl function, 3-58
mod function, 3-66
module language programs
description of, 2-127 O
month function, 3-112
monthname function, 3-113 octal function, 3-66
months_between function, 3-114 octet_length function, 3-54
MRI (See MAPPER Relational Interface) OLD ROW correlation-name (CREATE
multiplication rounding algorithm, 2-32 TRIGGER), 7-4
OMIT THREAD (ROLLBACK)
not supported in ESQL, 9-34
N not supported in routines and
triggers, 4-27
naming conventions, 2-3 Open Distributed Transaction Processing
NCHARACTER data type interface, 1-12
character value assignments, 2-93 OPEN statement
collating sequence, 2-107 examples, 9-13
format, 2-80 rules/guidelines for use, 9-14
kanji, 2-80, 2-108 syntax, 9-12
pattern-matching (LIKE and NOT two consecutive OPENs instead of
LIKE), 2-43 CLOSE, 6-31
Network Database Server (DMS) opening a cursor (OPEN), 9-12
access to files, 6-25 operands, in expressions, 2-39
ASCII COBOL, D-7 operators
NEW ROW correlation-name (CREATE AND, 2-27
TRIGGER), 7-4 BETWEEN, 2-42
new_time function, 3-115 bitwise (binary), 2-27
next_day function, 3-118 concatenate ( | | ), 3-5
NONE recovery option IN, 2-47
DELETE, 7-45 LIKE, 2-43
description of, 6-22 OR, 2-27
updating with, 6-27 order of precedence for operations, 2-30
nonreserved words, A-14 UNION and UNION ALL, 7-24
NOT LIKE operator, 2-43 XOR, 2-27
now function, 3-105 options
nspace function, 3-32 ADVANCE recovery step, 6-33, 8-3

7830 8160–027 Index–13


Index

COMMANDLOOKS recovery, 6-22 position function, 3-41


DEFERRED recovery, 6-22 posstr function, 3-41
FETCH statement, 1-20 power function, 3-67
NONE recovery, 6-22 predicates
QUICKLOOKS recovery, 6-22 defined, 2-23
READ, 6-22 limit on total number of predicates in
recovery, BEGIN THREAD statement, 6-22 constraints, 6-80
RETRIEVE, 6-22 PREPARE statement
step control examples, 9-18
DISCARD, 9-34 EXECUTE statement, use with, 8-5
END THREAD statement, 8-3 preparing and executing DELETE
KEEP, 9-34 statement, 8-5
REQUEUE, 9-34 rules/guidelines for use, 9-18
Step Control syntax, 9-17
COMMIT statement, 6-33 primary key
TERMINATE recovery step, 6-33, 8-3 approximate numeric columns, 6-62
UDSMSG/UDSMESSAGE(S), 6-23 CREATE TABLE
UPDATE, 6-22 partition primary key specification, 6-64
OR, binary operator, 2-27 primary key specification clause, 6-62
ORDER BY clause dropping columns used in a primary key,
in SELECT Multirow statement, 9-37 restriction, 6-7
with a COLLATE clause, 2-99 naming conventions, 2-3
outer joins nulls in primary keys, 6-62, 6-81
examples, 7-28, 7-29 primary key constraints, defining (CREATE
owned schemas, security, 6-44 TABLE), 6-59
OWNER IS edit specification, ALTER privileges
TABLE, 6-5 granting (GRANT), 8-56
revoking (REVOKE), 9-29
PROCEDURE statement
P examples, 9-22
rules/guidelines for use, 9-26
pages_updates function, 3-154 syntax, 9-20
parameter markers, 2-109, 2-111 procedures
parameters referencing procedures in SQL, 2-8
routines, 4-16 program variable arguments, ASCII
scalar functions, 3-3 FORTRAN, E-4
parentheses program variables, values, 2-117
controlling evaluation of expressions, 2-31 program_type function, 3-150
required with functions (FUNCTION), 8-42 projection, relational operation, defined, 1-8
partition _id function, 3-158 PROTECTED RETRIEVAL lock, 9-8
patindex function, 3-54 PROTECTED UPDATE lock, 9-9
percent sign (%), IPF SQL, 2-44 public tables, 6-83
permuted_id function, 3-147 put_file function, 3-168
pi function, 3-67
placeholder variables
assigning values from stored functions Q
(SET), 9-42
defined, 2-109 qualified names, functions, 2-8
in application programs, 2-113 qualifiers
names in placeholder variables, 2-112 DECLARE CURSOR, 7-40
usage and naming, 2-111 default qualifier (USE DEFAULT), 10-44
pointer, cursor, 9-3 GRANT statement, 8-59

Index–14 7830 8160–027


Index

naming conventions, 2-3 step


quantifiers, universal, 2-25 advancing, 6-33, 8-3
quarter function, 3-119 terminating, 6-33, 8-3
Query Language Processor (QLP) type, specifying, 6-21
interface, 1-13 UDS Control, 1-10
query specifications relational calculator, 1-6
DISTINCT keyword, 2-65 relational database model
examples, 2-59 introduced, 1-4
execution sequence, 2-71 tables, 1-6
order of rows, 2-65 terminology, 1-8
SELECT statement processing, 2-60 views, 1-8
use and form, 2-59 Relational Database Server (RDMS)
QUICKLOOKS recovery option RDMS command module, 1-16
CREATE INDEX performance issues, 6-39 RDMS environment, 1-10
defined, 6-22 RDMS interfaces, 1-12
updating with, 6-26 Relational Definition Table (RDT), 1-16
quotation marks, use in names, 2-4 RENAME COLUMN edit specification, ALTER
TABLE, 6-5
repeat function, 3-32
R replace function, 3-33
replicate function, 3-32
radians function, 3-68 Repository for ClearPath OS 2200 (UREP)
rand function, 3-69 RDMS environment, 1-11
random access, DECLARE CURSOR, 7-26 views, UREP considerations, 7-15
RDMCA variables ERROR-STATUS and AUX- REQUEUE step control option, ROLLBACK
INFO, C-4 statement, 9-34
RDMS (See Relational Database Server) REQUIRE SINGLE TABLE FILE edit
RDMS_DUMMY table, 1-6 specification, ALTER TABLE, 6-5
RDMS_TEXT character set, 2-101 reserved words, A-1
rdms_thread_stat function, 3-155 resolving cursor references, 2-122
RDMS_TRIGGER_DROPPING, UREP restrictions, relational operations, 1-8
configuration attribute, 7-50 result sets, described, 4-17
RDMSAUXINFO system variable, 4-22 RETRIEVAL lock, 9-8
RDMS-TRIGGER-DROPPING, UREP RETRIEVE option, BEGIN THREAD
configuration attribute, 7-52, 7-54, statement, 6-22
7-58 retrieving
READ option, BEGIN THREAD access path information, 8-47
statement, 6-22 error messages, 8-47
READY CURSOR statement, 9-12 information about columns, 8-43
REAL data type information about routine
format, 2-83 parameters, 8-49
introduced, 1-7 rows
real function, 3-69 examples, 9-37, 9-39
real literals, 2-12 from cursor, 8-23, 8-30
recompilation, automatic, 1-15, 2-119 SELECT Multirow statement, 9-37
recovery SELECT Single Row statement, 9-38
COMMANDLOOKS option, 6-22 RETURN statement, 4-43
COMMIT statement effect on, 6-34 reverse function, 3-33
DEFERRED option, 6-22 REVOKE statement
NONE option, 6-22 rules/guidelines for use, 9-31
DELETE, 7-45 syntax, 9-29
QUICKLOOKS option, 6-22 revoking user privileges (REVOKE), 9-29
right function, 3-34

7830 8160–027 Index–15


Index

RIGHT, join type, 2-64 SET statement (standard), 4-44


roles standard SQL statements, 4-29
dropping roles (DROP ROLE), 7-53 statements, allowed, 4-28
ROLLBACK statement terminating execution (SIGNAL), 4-46
DISCARD step control option, 9-34 variable references, 4-33
errors, B-9 version names, 4-9
examples, 9-35 WHILE statement, 4-48
KEEP step control option, 9-34 row triggers, 4-6
not supported in routines and rows
triggers, 4-27 defined, 1-6
REQUEUE step control option, 9-34 deleting (DELETE), 7-43
rules/guidelines for use, 9-35 fetching
Step Control options, 9-34 FETCH, 8-23
syntax, 9-34 FETCH NEXT n, 8-30
rollbacks inserting (INSERT), 8-61
ON ROLLBACK PRESERVE ROWS, ALTER rpad function, 3-35
TABLE, 6-45 rsa function, G-1
rollbacks caused by errors, B-4 RSA$FREE subroutine, H-4
rolling back a thread (ROLLBACK), 9-34 RSA$IN subroutine, E-9
round function, 3-8, 3-70, 3-120 RSA$INIT subroutine, 7-18, D-8, H-2
rounding RSA$PARAM subroutine, G-1
evaluating expressions, 2-31 rsa_param function, G-1
with program variables, 2-34 RSM-LOB format storage areas, I-4
routines and triggers rtrim function, 3-7, 3-36
assigning value to parameter/SQL run_id function, 3-150
variable, 4-44
compound statements, 4-30
conditional execution, 4-41 S
control statements, 4-28
creating variables, 4-40 Saving Procedure Syntax, 9-28
datetime values, 4-50 scalar functions (See also aggregate
DECLARE CURSOR, 7-38 functions; functions)
DECLARE statement, 4-40 abs, 3-59
defining a stored function absval, 3-59
(FUNCTION), 8-33 acos, 3-59
defining a stored procedure active_version, 3-24
(PROCEDURE), 9-20 add_months, 3-78
DELETE, 7-47 ascii, 3-55
ELSEIF clause, 4-41 asin, 3-60
END IF clause, 4-41 atan, 3-60
END statement, 4-30 atan2, 3-60
END WHILE clause, 4-48 binary-to-character, 3-55
error checking, 4-26 BLOB functions, 3-163
execution within transaction context, 4-27 cast, 3-79
IF statement, 4-41 ceil, 3-61
invoking a stored function (SET), 9-42 ceiling, 3-61
invoking a stored procedure (CALL), 6-28 char, 3-55
naming conventions, 2-3 char_length, 3-42
parameters, 4-16 character functions that return character
parameters information (GET values, 3-24
PARAMETERS), 8-49 character functions that return numeric
repeated conditional execution, 4-48 values, 3-41
routines, defined, 4-1

Index–16 7830 8160–027


Index

character_length, 3-42 isalnum, 3-45


character-to-binary, 3-55 isalpha, 3-45
charindex, 3-41 iscntrl, 3-46
chr, 3-55 isdigit, 3-47
coalesce, 3-56 isgraph, 3-47
concat, 3-5, 3-6, 3-25 islower, 3-48
concatrtrim, 3-5, 3-6, 3-25 isprint, 3-49
concatstrim, 3-5, 3-6, 3-26 ispunct, 3-49
convert, 3-85 isspace, 3-50
cos, 3-61 isupper, 3-51
cosh, 3-62 isxdigit, 3-52
cot, 3-62 julian_day, 3-9, 3-107
curdate, 3-88 last_day, 3-108
curtime, 3-88 lcase, 3-29
datalength, 3-42 left, 3-30
date, time, and timestamp functions, 3-78 length, 3-7, 3-42
dateadd, 3-90 list and summary of scalar functions, 3-10
datediff, 3-9, 3-92 ln, 3-65
datename, 3-9, 3-93 lob_crc, 3-164
datepart, 3-9, 3-94 lob_end_address, 3-164
dayname, 3-97 lob_end_page, 3-165
dayofmonth, 3-97 lob_file, 3-165
dayofweek, 3-98 lob_id, 3-166
dayofyear, 3-100 lob_id_crc, 3-166
days, 3-9, 3-101 lob_start_address, 3-167
decode, 3-57 lob_start_page, 3-167
defined, 3-1 locate, 3-53
degree, 3-62 log, 3-65
degrees, 3-62 log10, 3-66
delesc, 3-27 lower, 3-29
difference, 3-43 lpad, 3-31
erdate_to_timestamp, 3-102 ltrim, 3-31
erdwtime_to_timestamp, 3-102 mathematical and numerical conversion
ertdate_to_timestamp, 3-103 functions, 3-59
ertime_to_times, 3-103 max_aor_updates, 3-146
exp, 3-63 microsecond, 3-109
expression operands, 2-38 midnight_seconds, 3-110
extract, 3-103 minute, 3-111
floor, 3-63 mod, 3-66
generated_run_id, 3-146 month, 3-112
get_file, 3-163 monthname, 3-113
getdate, 3-105 months_between, 3-114
HAVING clauses, 3-3 naming conventions, 2-3
hex, 3-64 nested functions, 3-3
hour, 3-106 new_time, 3-115
ifnull, 3-58 next_day, 3-118
initcap, 3-27 now, 3-105
input data types, 3-2 nspace, 3-32
insert, 3-28 nullif, 3-58
insesc, 3-29 nvl, 3-58
instr, 3-44 octal, 3-66
integer, 3-64 octet_length, 3-54
introduction, 3-1 pages_updates function, 3-154

7830 8160–027 Index–17


Index

parameters, 3-3 unique_id, 3-151


patindex, 3-54 upper, 3-40
permuted_id, 3-147 user, 3-154
pi, 3-67 value, 3-56
position, 3-41 value clauses, 3-3
posstr, 3-41 week, 3-143
power, 3-67 WHERE clauses, 3-3
program_type, 3-150 year, 3-144
put_file, 3-168 schemas
quarter, 3-119 naming conventions, 2-3
radians, 3-68 security, 6-44
rand, 3-69 second function, 3-121
rdms_thread_stat function, 3-155 secondary indexes, adding (CREATE
real, 3-69 INDEX), 6-35
repeat, 3-32 security
replace, 3-33 CREATE TABLE
replicate, 3-32 MAPPER and TIP, 6-83
restrictions on usage, 3-4 specifying access control, 6-64, 6-83
reverse, 3-33 specifying the table owner, 6-64
right, 3-34 owned and unowned schemas, 6-44
round, 3-8, 3-70, 3-120 row level, views, 2-55
routines, 3-4 views, 7-16
rpad, 3-35 SELECT Multirow statement
rtrim, 3-7, 3-36 example, 9-37
rules and guidelines, 3-2 query specification processing, 2-60
run_id, 3-150 rules/guidelines for use, 9-37
second, 3-121 syntax, 9-37
select lists, 3-3 SELECT Single Row statement
sign, 3-71 examples, 9-39
sinh, 3-72 rules/guidelines for use, 9-40
smallint, 3-72 syntax, 9-38
soundex, 3-36 sequential access, DECLARE CURSOR, 7-26
space, 3-37 SET AUXINFO statement
sqrt, 3-73 examples, 9-46
str, 3-73 rules/guidelines for use, 9-45
strftime, 3-8, 3-122 syntax, 9-45
strptime, 3-125 set operations, IN operator, 2-47
stuff, 3-28 SET RESULT SET statement
substr, 3-37 examples, 4-19
substring, 3-37 syntax and examples, 9-47
system information functions, 3-146 SET SKIPGENERATED statement
tan, 3-75 example, 9-49
tanh, 3-75 rules/guidelines for use, 9-50
time, 3-128 syntax, 9-49
timestamp, 3-129 SET statement (nonstandard)
timestampadd, 3-130 example, 9-43
timestampdiff, 3-132 rules/guidelines for use, 9-43
to_char, 3-8, 3-134 syntax, 9-42
triggers, 3-4 SET statement (standard), 4-44
trunc, 3-8, 3-76, 3-142 SET STATISTICS statement
truncate, 3-76 example, 9-51
ucase, 3-40 rules/guidelines for use, 9-51
uds_slot, 3-151 syntax, 9-51

Index–18 7830 8160–027


Index

Shared File System (SFS) END DECLARE, 8-2


access to files, 6-25 END THREAD, 8-3
ASCII COBOL, D-7 EXECUTE, 8-5
SHARED RETRIEVAL lock, 9-8 EXECUTE IMMEDIATE, 8-7
SHARED UPDATE lock, 9-8 EXPLAIN, 8-8
sign function, 3-71 FETCH, 8-23
SIGNAL statement, 4-46 FETCH NEXT n, 8-30
sinh function, 3-72 FUNCTION, 8-33
SMALLINT data type GET DESCRIPTION, 8-43
introduced, 1-7 GET PARAMETERS, 8-49
smallint function, 3-72 GET RESULT SET CURSOR NAME, 8-54
snapshots (DECLARE CURSOR), 7-35 GETERROR, 8-47
SOME, universal quantifier, 2-25 GRANT, 8-56
soundex function, 3-36 INSERT, 8-61
space function, 3-37 LEVEL, 9-2
spaces (blanks), 2-44, 3-5, 3-6 LOCATE, 9-3
SQL (See Structured Query Language) LOCK, 9-6
SQLCODE variable, ESQL, C-3 naming conventions, 2-3
SQLSTATE system variable, 4-23, B-10 one-time execution, preparing for, 8-7
sqrt function, 3-73 OPEN, 9-12
standards, SQL, 5-2 PREPARE, 9-17
statements PROCEDURE, 9-20
ALLOCATE CURSOR, 6-2 READY [CURSOR], 9-12
alphabetical summary of SQL REVOKE, 9-29
statements, 5-5 ROLLBACK, 9-34
ALTER TABLE, 6-4 SELECT Multirow, 9-37
BEGIN DECLARE, 6-20 SELECT Single Row, 9-38
BEGIN THREAD, 6-21 SET, 9-42
CALL, 6-28 SET AUXINFO, 9-45
CLOSE, 6-31 SET RESULT SET, 9-47
comments in SQL statements, 5-3 SET SKIPGENERATED, 9-49
COMMIT, 6-33 SET STATISTICS, 9-51
compile-time, 2-121 single execution, preparing for, 8-7
CREATE INDEX, 6-35 statement rollbacks, B-4
CREATE ROLE, 6-41 summary, 1-20
CREATE SCHEMA, 6-42 syntax rules, 2-2
CREATE TABLE, 6-45 UNLOAD, 10-2
CREATE TRIGGER, 7-2 UNLOCK, 10-19
CREATE VIEW, 7-12 UPDATE ALL, 10-21
DEBUG, 7-18 UPDATE positioned, 10-25
DECLARE CURSOR, 7-22 UPDATE searched, 10-30
DEFINE TABLE, 6-45 UPDATE SYNCHRONIZE, 10-34
DELETE, 7-43 UPDATE VALUES, 10-40
DROP CURSOR, 7-48 USE, 10-44
DROP INDEX, 7-49 USE DEFAULT, 10-44
DROP PROCEDURE/FUNCTION, 7-51 WHENEVER, 10-47
DROP ROLE, 7-53 static ESQL, 1-16, 2-119
DROP TABLE, 7-54 step control options, ROLLBACK
DROP TRIGGER, 7-57 statement, 9-34
DROP VIEW, 7-58 storage areas
dynamic ESQL, allowed in EXECUTE calculating BLOB storage area sizes, I-8
IMMEDIATE/PREPARE designating storage areas (CREATE
statements, 2-126 TABLE), 6-79

7830 8160–027 Index–19


Index

referencing storage areas in SQL, 2-9 notation conventions, 1-2


sharing storage areas (ALTER rules for statements, 2-2
TABLE), 6-12 system information functions
stored functions (See also routines and generated_run_id, 3-146
triggers) identity_val_local function, 3-160
defined, 4-21 max_aor_updates, 3-146
defining (FUNCTION), 8-33 pages_updates function, 3-154
dropping (DROP FUNCTION), 7-51 partition _id function, 3-158
dynamic result sets (GET RESULT SET permuted_id, 3-147
CURSOR NAME), 8-54 program_type, 3-150
invoking (SET), 9-42 rdms_thread_stat function, 3-155
parameters information (GET run_id, 3-150
PARAMETERS), 8-49 uds_slot, 3-151
RETURN statement, 4-43 unique_id, 3-151
returned values, assigning, 9-42 user, 3-154
setting value of, 4-43 system variables
stored procedures (See also routines and RDMSAUXINFO, 4-22
triggers) SQLSTATE, 4-23
defined, 4-1
defining (PROCEDURE), 9-20
dropping (DROP PROCEDURE), 7-51 T
dynamic result sets (GET RESULT SET
CURSOR NAME), 8-54 tables
executing, 6-28 access-specification clause, CREATE
parameters information (GET TABLE, 6-64
PARAMETERS), 8-49 altering (ALTER TABLE), 6-4
str function, 3-73 base tables, 1-8
strftime function, 3-8, 3-122 CREATE INDEX statement
string and blob expressions, 2-37 performance, 6-39
string literals, 2-11 creating
strptime function, 3-125 CREATE TABLE statement, 6-45
Structured Query Language (SQL) examples, 6-72
introduced, 1-4 deleting rows (DELETE), 7-43
routines, 4-1 dropping indexes (DROP INDEX), 7-49
SQL standards, 5-2 dropping tables (DROP TABLE), 7-54
stuff function, 3-28 fetching rows from tables, 8-31
subqueries foreign keys, 6-81
defined, 2-71 global temporary tables
evaluation rules, 2-75 ALTER TABLE, 6-19
guidelines for use, 2-77 CREATE TABLE, 6-46, 6-84
in Boolean expressions, 2-75 described, 1-8
operands in expressions, 2-40 DROP TABLE, 7-56
scope of references, 2-74 LOCK, 9-6
substr function, 3-37 ROLLBACK, 9-36
substring function, 3-37 UNLOCK, 10-19
subtraction rounding algorithm, 2-32 inserting rows (INSERT), 8-61
SUM function locking (LOCK), 9-6
aggregate operation, 2-67 naming
example, 2-51 naming conventions, 2-3
format, 2-48 table specification clause, CREATE
synonyms, keyword, A-14 TABLE, 6-48
syntax nulls, designing for, 2-14
checking with DEBUG, 7-18

Index–20 7830 8160–027


Index

owner specification, CREATE TABLE, 6-64 hour, 3-106


public tables, 6-83 microsecond, 3-109
referencing tables in SQL statements, 2-5 midnight_seconds, 3-110
retrieving rows from cursor, 8-31 minute, 3-111
revoking privileges (REVOKE), 9-29 new_time, 3-115
rows in, determining, 9-40 round, 3-120
storage areas second, 3-121
ALTER TABLE, 6-12 strftime, 3-122
CREATE TABLE, 6-48 time, 3-128
table-constraint-specification clause, timestampadd, 3-130
CREATE TABLE, 6-59 timestampdiff, 3-132
version names, 2-5 to_char, 3-134
views, 1-9 trunc, 3-142
tan function, 3-75 TIME literal format, 2-16
tanh function, 3-75 TIMESTAMP data type
temporary tables (See global temporary casting a value to a timestamp, 3-81
tables) format, 2-87
TERMINATE recovery step option, 6-33, 8-3 introduced, 1-7
threads timestamp function, 3-129
beginning and registering (BEGIN timestamp functions
THREAD), 6-21 cast, 3-79
committing current step updates, 6-33 casting a value to a timestamp, 3-81
ending (END THREAD), 8-3 convert, 3-85
implicit CURRENT_TIMESTAMP, 2-51
BEGIN THREAD statement, datediff, 3-92
example, 6-25 datepart, 3-94
determining application group dayname, 3-97
name, 6-24 dayofmonth, 3-97
OMIT THREAD (ROLLBACK), 9-34 dayofweek, 3-98
rollback dayofyear, 3-100
errors, B-4 days, 3-101
ROLLBACK statement, 9-34 erdate_to_timestamp, 3-102
thread control, UDS Control, 1-10 erdwtime_to_timestamp, 3-102
TIME data type ertdate_to_timestamp, 3-103
format, 2-87 extract, 3-103
introduced, 1-7 getdate, 3-105
time function, 3-128 hour, 3-106
time functions last_day, 3-108
cast, 3-79 microsecond, 3-109
casting a value to an interval, 3-82 midnight_seconds, 3-110
convert, 3-85 minute, 3-111
CURRENT_TIME, 2-51 month, 3-112
CURRENT_TIMESTAMP, 2-51 monthname, 3-113
curtime, 3-88 months_between, 3-114
dateadd, 3-90 new_time, 3-115
datediff, 3-92 next_day, 3-118
datepart, 3-94 now, 3-105
dayname, 3-97 quarter, 3-119
erdate_to_timestamp, 3-102 round, 3-120
erdwtime_to_timestamp, 3-102 second, 3-121
ertdate_to_timestamp, 3-103 strftime, 3-122
ertime_to_time, 3-103 strptime, 3-125
extract, 3-103 time, 3-128

7830 8160–027 Index–21


Index

timestamp, 3-129 trunc function, 3-8, 3-76, 3-142


timestampadd, 3-130 truncate function, 3-76
timestampdiff, 3-132
to_char, 3-134
trunc, 3-142 U
week, 3-143
year, 3-144 ucase function, 3-40
TIMESTAMP literal format, 2-16 UDS Control
timestamp_format, 3-21 RDMS environment, 1-10
timestamp_format Function, 3-134 TRCCTL (trace control) program, 7-20
timestampadd function, 3-130 uds_slot function, 3-151
timestampdiff function, 3-132 UDSMSG/UDSMESSAGE(S) option, BEGIN
TIP environment THREAD statement, 6-23
determining the application group uncorrelated query, 2-74
name, 6-24 UniAccess software, 1-13
TIPMALLOC compiler keyword UNION and UNION ALL operators (DECLARE
option, H-5 CURSOR), 7-24, 7-32
TIP programs unique constraints, defining (CREATE
ASCII COBOL, D-8 TABLE), 6-59
ASCII FORTRAN, E-9 unique_id function, 3-151
VALTAB parameter, 6-33, 8-3, 9-34 Universal Compiling System (UCS)
TIPMALLOC compiler keyword option, H-5 C programs
title names, naming conventions, 2-3 embedded SQL, 1-13
to_char function, 3-8, 3-134 rsa_param, G-2
to_date, 3-22 COBOL programs
to_date Function, 3-138 embedded SQL, 1-13
to_timestamp, 3-22 encountering error, 10-47
to_timestamp Function, 3-141 ESQL statements at compile-
tokens, A-1 time, 2-121
tracing fetching into array, 8-30
ESQL compilation and execution inserting a row, 2-116
(DEBUG), 7-20 LEVEL/SQL FLAGGER, 6-20
SQL execution (TRCCTL program), 7-20 RDMCA variables, C-7
trailing blanks, 2-44, 3-5, 3-6 static ESQL, 2-119
transaction programs, VALTAB FORTRAN programs
parameter, 6-33, 8-3, 9-34 calling RDMS, 2-113
TRCCTL program, tracing SQL DECLARE CURSOR and OPEN
execution, 7-20 statements, 9-13
triggers RDMS level returned, 9-2
BEFORE and AFTER triggers, 7-6 using indicator variable, 2-116
creating (CREATE TRIGGER), 7-2 passing SQL statements as
DECLARE CURSOR, 7-38 arguments, 1-12
DELETE, 7-47 placeholder variables, 2-113
dropping, 4-12 TIPMALLOC compiler keyword
examples, 7-7 option, H-5
executing, 4-12 universal quantifiers (SOME, ANY, ALL), 2-25
introduction to, 4-3 UNLOAD statement
invoking, 4-12 column descriptions, 10-16
naming conventions, 2-3 cursors, 10-11
RDMS-TRIGGER-DROPPING, 7-52, 7-54, descriptions ignored by RDMUTL
7-58 LOAD, 10-12
statements allowed, 4-28 examples, 10-7
version names, 4-9

Index–22 7830 8160–027


Index

EXTERNAL clause, 10-13 examples, 10-35


INTERNAL format, 10-14 rules/guidelines for use, 10-37
long data images, 10-12 syntax, 10-34
no-finds, 10-13 UPDATE VALUES statement
number of rows unloaded, 10-13 example, 10-41
performance, improving, 10-12 rules/guidelines for use, 10-41
query expressions, 10-12 syntax, 10-40
query specification processing, 2-60 updates, committing (COMMIT), 6-33
syntax, 10-2 updating columns
transferring data to MAPPER, 10-15 in a subset of rows (UPDATE
WITH DESCRIPTION clause, 10-14 Searched), 10-30
UNLOCK statement in all rows (UPDATE ALL), 10-21
errors with multiple tables, 10-20 in one or more rows (UPDATE
example, 10-19 VALUES), 10-40
global temporary tables, 10-19 in the current row (UPDATE
releasing UPDATE locks, 10-19 Positioned), 10-25
restrictions, 10-19 upper function, 3-40
syntax, 10-19 UREP (See Repository for ClearPath
XTC application groups, 10-20 OS 2200)
unowned schemas, security, 6-44 USE DEFAULT statement
unqualified names, functions, 2-8 examples, 10-44
UPDATE ALL statement rules/guidelines for use, 10-45
character string too long, 10-23 syntax, 10-44
check constraints, 10-23 user function, 3-154
embedded variable specification USER function, 2-55
list, 10-24 user-ids
example, 10-22 ALTER TABLE, 6-17
foreign key constraints, 10-23 CREATE TABLE, 6-79
locking and committing, 10-22 CREATE TABLE, specifying the table
NONE recovery option, 10-22 owner, 6-64
syntax, 10-21 MAPPER and TIP (CREATE TABLE), 6-83
unique constraints, 10-23 schemas, 6-43
updating a primary key, 10-23 tables, 6-9
update counts, 9-47 USER function, 2-55
UPDATE lock, 9-8
UPDATE option, BEGIN THREAD
statement, 6-22 V
UPDATE Positioned statement
character string too long, 10-29 VALTAB parameter, TIP programs, 6-33, 8-3,
check constraints, 10-29 9-34
example, 10-26 value function, 3-56
foreign key constraints, 10-28 VARCHAR data type, 3-4
locking and committing, 10-27 varchar_format, 3-23
NONE recovery option, 10-27 varchar_format Function, 3-143
routines and triggers, 10-29 variables
syntax, 10-25 assigning values from stored
unique constraints, 10-28 function, 9-42
updating the primary key, 10-27 AUX-INFO, RDMCA, C-4
UPDATE Searched statement BLOB variables
examples, 10-31 COBOL, I-19
rules/guidelines for use, 10-32 UCS C, I-13
syntax, 10-30 creating in routines and triggers, 4-40
UPDATE SYNCHRONIZE statement

7830 8160–027 Index–23


Index

data and indicator pairs, INSERT statement, using, 7-14


format/examples, 2-115 introduced, 1-8
embedded variables, 2-109, 2-110 naming conventions, 2-3
error messages, placing into variables read-only, 7-14
(GETERROR), 8-47 referencing views in SQL statements, 2-5
ERROR-STATUS, RDMCA, C-4 row level security, 2-55
host language variables, 2-109 security, 7-16
indicator variables, 2-110, 2-114
internal level number, returning, 9-2
naming conventions, 2-3 W
OPEN statement, 9-13
parameter markers, 2-111 week function, 3-143
placeholder variables week of year
defined, 2-109 defined, 3-8
in application programs, 2-113 week function, 3-143
names in placeholder variables, 2-112 WHENEVER statement
usage and naming, 2-111 altering program flow, C-2
RDMSAUXINFO, 4-22 error processing, C-2
resolving references in SQL examples, 10-47
routines, 4-33 rules/guidelines for use, 10-48
returning internal level number, 9-2 scope, C-2
rounding on comparisons, 2-34 syntax, 10-47
RSA$PARAM subroutine, passing ASCII WHILE statement, 4-48
COBOL parameters, G-1 widths of columns, 3-5
SQLSTATE, 4-23 wildcard characters, 2-44
version names WITH CHECK OPTION clause, CREATE
DECLARE CURSOR, 7-40 VIEW, 7-15
default (USE DEFAULT), 10-44 work space, UCS programs, H-1
described, 2-5
ESQL considerations, 2-7
GRANT statement, 8-59 X
naming conventions, 2-3
referencing versions in SQL
XOR, binary operator, 2-27
statements, 2-5
routines and triggers, 4-9
views
aggregate operations, 2-67, 2-68
Y
creating (CREATE VIEW), 7-12
deleting rows (DELETE), 7-14, 7-43 year function, 3-144
described, 1-9
dropping
ALTER TABLE, 6-17
automatically (cascading), 7-59
DROP VIEW, 7-58

Index–24 7830 8160–027


.
© 2015 Unisys Corporation.

*78308160-027*
All rights reserved.

7830 8160–027

You might also like