0% found this document useful (0 votes)
7 views71 pages

106935320

The document provides information about various eBooks available for download, including titles focused on PostgreSQL programming and other subjects. It lists specific eBooks, their authors, ISBNs, and links for access. Additionally, it includes details about the authors of the featured book on PL/pgSQL and its contents, covering topics such as variables, data types, and control statements.

Uploaded by

fochszapotkq
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views71 pages

106935320

The document provides information about various eBooks available for download, including titles focused on PostgreSQL programming and other subjects. It lists specific eBooks, their authors, ISBNs, and links for access. Additionally, it includes details about the authors of the featured book on PL/pgSQL and its contents, covering topics such as variables, data types, and control statements.

Uploaded by

fochszapotkq
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 71

Download the Full Ebook and Access More Features - ebooknice.

com

(Ebook) Procedural Programming with PostgreSQL


PL/pgSQL: Design Complex Database-Centric
Applications with PL/pgSQL by Baji Shaik, Dinesh
Kumar Chemuduru ISBN 9781484298398, 148429839X,
B0CHLBQ323
https://ebooknice.com/product/procedural-programming-with-
postgresql-pl-pgsql-design-complex-database-centric-
applications-with-pl-pgsql-53467660

OR CLICK HERE

DOWLOAD EBOOK

Download more ebook instantly today at https://ebooknice.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Start reading on any device today!

(Ebook) Procedural Programming with PostgreSQL PL/pgSQL:


Design Complex Database-Centric Applications with PL/pgSQL
by Baji Shaik & Dinesh Kumar Chemuduru ISBN 9781484298404,
1484298403
https://ebooknice.com/product/procedural-programming-with-postgresql-
pl-pgsql-design-complex-database-centric-applications-with-pl-
pgsql-55758230
ebooknice.com

(Ebook) Biota Grow 2C gather 2C cook by Loucas, Jason;


Viles, James ISBN 9781459699816, 9781743365571,
9781925268492, 1459699815, 1743365578, 1925268497
https://ebooknice.com/product/biota-grow-2c-gather-2c-cook-6661374

ebooknice.com

(Ebook) Matematik 5000+ Kurs 2c Lärobok by Lena


Alfredsson, Hans Heikne, Sanna Bodemyr ISBN 9789127456600,
9127456609
https://ebooknice.com/product/matematik-5000-kurs-2c-larobok-23848312

ebooknice.com

(Ebook) PostgreSQL Development Essentials by Kaur,


Manpreet, Shaik, Baji ISBN 9781783989003, 1783989009

https://ebooknice.com/product/postgresql-development-
essentials-11861554

ebooknice.com
(Ebook) Beginning PostgreSQL on the Cloud: Simplifying
Database as a Service on Cloud Platforms by Baji Shaik,
Avinash Vallarapu ISBN 9781484234464, 1484234464
https://ebooknice.com/product/beginning-postgresql-on-the-cloud-
simplifying-database-as-a-service-on-cloud-platforms-6988088

ebooknice.com

(Ebook) SAT II Success MATH 1C and 2C 2002 (Peterson's SAT


II Success) by Peterson's ISBN 9780768906677, 0768906679

https://ebooknice.com/product/sat-ii-success-
math-1c-and-2c-2002-peterson-s-sat-ii-success-1722018

ebooknice.com

(Ebook) PostgreSQL Configuration: Best Practices for


Performance and Security by Baji Shaik ISBN 9781484256633,
1484256638
https://ebooknice.com/product/postgresql-configuration-best-practices-
for-performance-and-security-46148980

ebooknice.com

(Ebook) PostgreSQL Configuration: Best Practices for


Performance and Security by Baji Shaik ISBN 9781484256626,
148425662X
https://ebooknice.com/product/postgresql-configuration-best-practices-
for-performance-and-security-46659076

ebooknice.com

(Ebook) Master SAT II Math 1c and 2c 4th ed (Arco Master


the SAT Subject Test: Math Levels 1 & 2) by Arco ISBN
9780768923049, 0768923042
https://ebooknice.com/product/master-sat-ii-math-1c-and-2c-4th-ed-
arco-master-the-sat-subject-test-math-levels-1-2-2326094

ebooknice.com
Q L
S
E
AG
NGU
Y LA
ER
D QU
RE
TU
RUC
ST

B
TA

Procedural Programming DA

with PostgreSQL DA
TAB
A SE

DA
T

PL/pgSQL
Design Complex Database-Centric
Applications with PL/pgSQL

Baji Shaik
Dinesh Kumar Chemuduru
Procedural Programming
with PostgreSQL
PL/pgSQL
Design Complex Database-Centric
Applications with PL/pgSQL

Baji Shaik
Dinesh Kumar Chemuduru
Procedural Programming with PostgreSQL PL/pgSQL: Design Complex
Database-­Centric Applications with PL/pgSQL
Baji Shaik Dinesh Kumar Chemuduru
Texas, TX, USA Andhra Pradesh, India

ISBN-13 (pbk): 978-1-4842-9839-8 ISBN-13 (electronic): 978-1-4842-9840-4


https://doi.org/10.1007/978-1-4842-9840-4

Copyright © 2023 by Baji Shaik and Dinesh Kumar Chemuduru


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Divya Modi
Development Editor: James Markham
Cover designed by eStudioCalamar
Cover image designed by Freepik (www.freepik.com)
Distributed to the book trade worldwide by Apress Media, LLC, 1 New York Plaza, New York, NY 10004,
U.S.A. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail [email protected], or visit
www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is Springer
Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation.
For information on translations, please e-mail [email protected]; for reprint,
paperback, or audio rights, please e-mail [email protected].
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available
to readers on GitHub (https://github.com/Apress). For more detailed information, please visit
https://www.apress.com/gp/services/source-code.
Paper in this product is recyclable
I extend this dedication to Afrah Razzak, my exceptional wife.
Her enduring support and remarkable patience during the extended
writing sessions have been invaluable to me.
—Baji Shaik

I lovingly extend this dedication to my dear friend, Baji Shaik.


Your unwavering support and encouragement have been my guiding
light, especially in the most challenging moments. Your belief in me has
been a constant source of inspiration, and I am grateful for your
presence in my journey. This book is as much a tribute to our
friendship as it is a testament to the power of steadfast camaraderie.
Thank you for always being there.
—Dinesh Kumar Chemuduru
Table of Contents
About the Authors�������������������������������������������������������������������������������������������������� xiii

About the Technical Reviewer���������������������������������������������������������������������������������xv

Acknowledgments�������������������������������������������������������������������������������������������������xvii
Introduction������������������������������������������������������������������������������������������������������������xix

Chapter 1: Introduction to PL/pgSQL������������������������������������������������������������������������ 1


A Closer Look at PL/pgSQL����������������������������������������������������������������������������������������������������������� 1
PL/pgSQL Installation�������������������������������������������������������������������������������������������������������������������� 2
PL/pgSQL Execution Flow������������������������������������������������������������������������������������������������������������� 4
PL/pgSQL Blocks��������������������������������������������������������������������������������������������������������������������������� 6
Anonymous or Unnamed Blocks���������������������������������������������������������������������������������������������� 6
Named Blocks����������������������������������������������������������������������������������������������������������������������������� 10
Summary������������������������������������������������������������������������������������������������������������������������������������ 12
What’s Next��������������������������������������������������������������������������������������������������������������������������������� 12

Chapter 2: PL/pgSQL Variables������������������������������������������������������������������������������� 13


What Are Variables in PL/pgSQL?������������������������������������������������������������������������������������������������ 13
Declaring Variables��������������������������������������������������������������������������������������������������������������������� 13
Variable Scope���������������������������������������������������������������������������������������������������������������������������� 15
Constant Variables���������������������������������������������������������������������������������������������������������������������� 17
Variable Alias������������������������������������������������������������������������������������������������������������������������������ 18
Scalar Variables��������������������������������������������������������������������������������������������������������������������� 19
Array Variables���������������������������������������������������������������������������������������������������������������������� 21
Record Variables�������������������������������������������������������������������������������������������������������������������� 22
Cursor Variables�������������������������������������������������������������������������������������������������������������������� 23

v
Table of Contents

Summary������������������������������������������������������������������������������������������������������������������������������������ 25
What’s Next��������������������������������������������������������������������������������������������������������������������������������� 25

Chapter 3: PL/pgSQL Data Types���������������������������������������������������������������������������� 27


Data Types����������������������������������������������������������������������������������������������������������������������������������� 27
Declaring Variables with Data Types������������������������������������������������������������������������������������������� 28
Supported Types������������������������������������������������������������������������������������������������������������������������� 30
Base Type������������������������������������������������������������������������������������������������������������������������������������ 32
Composite Type��������������������������������������������������������������������������������������������������������������������������� 33
Domain Type�������������������������������������������������������������������������������������������������������������������������������� 35
Pseudo-Type������������������������������������������������������������������������������������������������������������������������������� 37
Range Type���������������������������������������������������������������������������������������������������������������������������������� 38
Multirange Types������������������������������������������������������������������������������������������������������������������������� 40
Summary������������������������������������������������������������������������������������������������������������������������������������ 41
What’s Next��������������������������������������������������������������������������������������������������������������������������������� 41

Chapter 4: Dealing with Strings, Numbers, and Arrays������������������������������������������ 43


Strings����������������������������������������������������������������������������������������������������������������������������������������� 43
Function Format�������������������������������������������������������������������������������������������������������������������� 45
Dealing with Null String��������������������������������������������������������������������������������������������������������� 47
Numbers������������������������������������������������������������������������������������������������������������������������������������� 50
Arrays������������������������������������������������������������������������������������������������������������������������������������������ 53
Example Use Cases��������������������������������������������������������������������������������������������������������������������� 54
Strings����������������������������������������������������������������������������������������������������������������������������������������� 54
Numbers�������������������������������������������������������������������������������������������������������������������������������� 55
Arrays������������������������������������������������������������������������������������������������������������������������������������ 57
Summary������������������������������������������������������������������������������������������������������������������������������������ 58
What’s Next��������������������������������������������������������������������������������������������������������������������������������� 59

Chapter 5: Control Statements������������������������������������������������������������������������������� 61


IF/ELSE Statement���������������������������������������������������������������������������������������������������������������������� 62
Cascading IF Statements������������������������������������������������������������������������������������������������������� 65
CASE Statement�������������������������������������������������������������������������������������������������������������������������� 66
vi
Table of Contents

Iterative Statement��������������������������������������������������������������������������������������������������������������������� 68
LOOP Statement�������������������������������������������������������������������������������������������������������������������� 69
WHILE Statement������������������������������������������������������������������������������������������������������������������������ 72
FOR Statement���������������������������������������������������������������������������������������������������������������������������� 74
Example Use Cases��������������������������������������������������������������������������������������������������������������������� 78
Example 1������������������������������������������������������������������������������������������������������������������������������ 78
Example 2������������������������������������������������������������������������������������������������������������������������������ 81
Best Practices of Using Control Statements in PL/pgSQL����������������������������������������������������� 84
Summary������������������������������������������������������������������������������������������������������������������������������������ 85
What’s Next��������������������������������������������������������������������������������������������������������������������������������� 85

Chapter 6: Handling Arrays������������������������������������������������������������������������������������ 87


Array Index���������������������������������������������������������������������������������������������������������������������������������� 88
Array Length������������������������������������������������������������������������������������������������������������������������������� 89
Iterate Array�������������������������������������������������������������������������������������������������������������������������������� 91
Find Duplicate Elements in Array������������������������������������������������������������������������������������������������ 92
Append Elements to Array����������������������������������������������������������������������������������������������������������� 93
Array Merge�������������������������������������������������������������������������������������������������������������������������������� 94
Multidimensional Arrays������������������������������������������������������������������������������������������������������������� 94
Summary������������������������������������������������������������������������������������������������������������������������������������ 96
What’s Next��������������������������������������������������������������������������������������������������������������������������������� 96

Chapter 7: Handling JSON�������������������������������������������������������������������������������������� 97


What Is JSON?���������������������������������������������������������������������������������������������������������������������������� 97
Use Cases��������������������������������������������������������������������������������������������������������������������������������� 100
Advantages and Disadvantages������������������������������������������������������������������������������������������������ 104
Build PL/pgSQL Functions for JSON������������������������������������������������������������������������������������������ 105
Indexing JSON Data������������������������������������������������������������������������������������������������������������������ 109
Other Useful JSON Functions���������������������������������������������������������������������������������������������������� 111
Summary���������������������������������������������������������������������������������������������������������������������������������� 111
What’s Next������������������������������������������������������������������������������������������������������������������������������� 112

vii
Table of Contents

Chapter 8: Cursors������������������������������������������������������������������������������������������������ 113


What Are Cursors?�������������������������������������������������������������������������������������������������������������������� 113
CURSOR Attributes��������������������������������������������������������������������������������������������������������������� 115
ISOPEN Attribute������������������������������������������������������������������������������������������������������������������ 115
FOUND Attribute������������������������������������������������������������������������������������������������������������������� 117
NOTFOUND Attribute������������������������������������������������������������������������������������������������������������ 119
ROWCOUNT Attribute����������������������������������������������������������������������������������������������������������� 120
Monitor Cursors������������������������������������������������������������������������������������������������������������������� 122
SCROLL Cursor�������������������������������������������������������������������������������������������������������������������� 123
NO SCROLL Cursor��������������������������������������������������������������������������������������������������������������� 125
WITH HOLD Cursors������������������������������������������������������������������������������������������������������������� 127
Refcursors��������������������������������������������������������������������������������������������������������������������������� 128
Summary���������������������������������������������������������������������������������������������������������������������������������� 130
What’s Next������������������������������������������������������������������������������������������������������������������������������� 130

Chapter 9: Custom Operators������������������������������������������������������������������������������� 131


Built-In Operators���������������������������������������������������������������������������������������������������������������������� 131
Creating a Custom Operator������������������������������������������������������������������������������������������������������ 135
Simple Example������������������������������������������������������������������������������������������������������������������� 136
SCENARIO 1: Case-Insensitive Comparison������������������������������������������������������������������������� 140
SCENARIO 2: Custom Data Type Math��������������������������������������������������������������������������������� 142
SCENARIO 3: Date Differentiate Operator���������������������������������������������������������������������������� 144
SCENARIO 4: Custom Operator for Data Classification�������������������������������������������������������� 146
Advantages������������������������������������������������������������������������������������������������������������������������������� 148
Disadvantages�������������������������������������������������������������������������������������������������������������������������� 149
Summary���������������������������������������������������������������������������������������������������������������������������������� 149
What’s Next������������������������������������������������������������������������������������������������������������������������������� 149

Chapter 10: Custom Casting��������������������������������������������������������������������������������� 151


Built-In Casts���������������������������������������������������������������������������������������������������������������������������� 151
Custom Casts���������������������������������������������������������������������������������������������������������������������������� 160

viii
Table of Contents

Creating a Custom Cast������������������������������������������������������������������������������������������������������� 160


Simple Example������������������������������������������������������������������������������������������������������������������� 161
SCENARIO 1: Converting Custom Data Types����������������������������������������������������������������������� 163
SCENARIO 2: Custom Data Type to JSONB��������������������������������������������������������������������������� 165
Summary���������������������������������������������������������������������������������������������������������������������������������� 168
What’s Next������������������������������������������������������������������������������������������������������������������������������� 168

Chapter 11: Dynamic SQL������������������������������������������������������������������������������������� 169


What Is Dynamic SQL?�������������������������������������������������������������������������������������������������������������� 169
Syntax of Dynamic SQL in PL/pgSQL����������������������������������������������������������������������������������� 169
Simple Example������������������������������������������������������������������������������������������������������������������� 170
Use Cases of Dynamic SQL�������������������������������������������������������������������������������������������������� 171
Best Practices and Considerations for Dynamic SQL���������������������������������������������������������������� 178
1. Preventing SQL Injection������������������������������������������������������������������������������������������������� 179
2. Sanitizing and Validating Inputs�������������������������������������������������������������������������������������� 179
3. Security Concerns����������������������������������������������������������������������������������������������������������� 180
4. Performance Optimization����������������������������������������������������������������������������������������������� 180
Summary���������������������������������������������������������������������������������������������������������������������������������� 181
What’s Next������������������������������������������������������������������������������������������������������������������������������� 181

Chapter 12: Building Functions and Procedures�������������������������������������������������� 183


Functions���������������������������������������������������������������������������������������������������������������������������������� 183
Defining Functions��������������������������������������������������������������������������������������������������������������� 184
Calling Functions����������������������������������������������������������������������������������������������������������������� 184
Categories��������������������������������������������������������������������������������������������������������������������������������� 185
Immutable Functions���������������������������������������������������������������������������������������������������������������� 186
STABLE Functions��������������������������������������������������������������������������������������������������������������������� 188
VOLATILE Functions������������������������������������������������������������������������������������������������������������������� 191
Procedures�������������������������������������������������������������������������������������������������������������������������������� 194
Temporary Functions/Procedures��������������������������������������������������������������������������������������������� 195
VARIADIC Functions/Procedures����������������������������������������������������������������������������������������������� 196
Best Practices���������������������������������������������������������������������������������������������������������������������� 198

ix
Table of Contents

Summary���������������������������������������������������������������������������������������������������������������������������������� 199
What’s Next������������������������������������������������������������������������������������������������������������������������������� 199

Chapter 13: Return Values and Parameters���������������������������������������������������������� 201


Return Values���������������������������������������������������������������������������������������������������������������������������� 201
Simple Example������������������������������������������������������������������������������������������������������������������� 202
Different Ways to Return Values������������������������������������������������������������������������������������������������ 203
RETURNS����������������������������������������������������������������������������������������������������������������������������� 203
RETURNS SETOF������������������������������������������������������������������������������������������������������������������ 204
RETURNS TABLE������������������������������������������������������������������������������������������������������������������ 204
OUT�������������������������������������������������������������������������������������������������������������������������������������� 205
Simple Difference Matrix����������������������������������������������������������������������������������������������������� 206
Different Examples for Each RETURN Type�������������������������������������������������������������������������� 206
Using SELECT Statements��������������������������������������������������������������������������������������������������� 207
Using RETURNS TABLE�������������������������������������������������������������������������������������������������������� 208
Using RETURN NEXT������������������������������������������������������������������������������������������������������������ 209
Using RETURNS SETOF TABLE��������������������������������������������������������������������������������������������� 210
Using RETURNS SETOF Data Type���������������������������������������������������������������������������������������� 210
Using RETURNS RECORD����������������������������������������������������������������������������������������������������� 211
Using RETURNS SETOF RECORD������������������������������������������������������������������������������������������ 212
Using OUT Parameters��������������������������������������������������������������������������������������������������������� 214
Using INOUT Parameter������������������������������������������������������������������������������������������������������� 216
Summary���������������������������������������������������������������������������������������������������������������������������������� 216
What’s Next������������������������������������������������������������������������������������������������������������������������������� 217

Chapter 14: Handling Exceptions�������������������������������������������������������������������������� 219


Exceptions��������������������������������������������������������������������������������������������������������������������������������� 219
GET DIAGNOSTICS���������������������������������������������������������������������������������������������������������������� 219
FOUND��������������������������������������������������������������������������������������������������������������������������������� 223
Exceptions in PL/pgSQL������������������������������������������������������������������������������������������������������������ 225
Different Ways to Handle Exceptions in PL/pgSQL�������������������������������������������������������������� 226
Using the BEGIN and END Statements��������������������������������������������������������������������������������� 226

x
Table of Contents

Using the RAISE Statement������������������������������������������������������������������������������������������������� 231


Custom Exceptions�������������������������������������������������������������������������������������������������������������� 232
Rethrow Exceptions������������������������������������������������������������������������������������������������������������� 233
ASSERT�������������������������������������������������������������������������������������������������������������������������������� 234
Get Call Stack���������������������������������������������������������������������������������������������������������������������� 235
Using the GET STACKED DIAGNOSTICS Statement�������������������������������������������������������������� 237
Advantages of Using Exceptions����������������������������������������������������������������������������������������� 238
Disadvantages of Using Exceptions������������������������������������������������������������������������������������� 239
Summary���������������������������������������������������������������������������������������������������������������������������������� 239
What’s Next������������������������������������������������������������������������������������������������������������������������������� 240

Chapter 15: Triggers��������������������������������������������������������������������������������������������� 241


What Are Triggers?�������������������������������������������������������������������������������������������������������������������� 241
Syntax���������������������������������������������������������������������������������������������������������������������������������� 242
Simple Example������������������������������������������������������������������������������������������������������������������� 243
Types of Triggers in PostgreSQL������������������������������������������������������������������������������������������������ 245
Row-Level Triggers�������������������������������������������������������������������������������������������������������������� 246
INSTEAD OF Triggers������������������������������������������������������������������������������������������������������������ 253
Statement-Level Triggers���������������������������������������������������������������������������������������������������� 254
Event Triggers���������������������������������������������������������������������������������������������������������������������� 258
Advantages of Triggers�������������������������������������������������������������������������������������������������������� 260
Disadvantages of Triggers��������������������������������������������������������������������������������������������������� 261
DROP Triggers��������������������������������������������������������������������������������������������������������������������������� 261
Summary���������������������������������������������������������������������������������������������������������������������������������� 262
What’s Next������������������������������������������������������������������������������������������������������������������������������� 262

Chapter 16: Transaction Management������������������������������������������������������������������ 263


Nested Transactions������������������������������������������������������������������������������������������������������������������ 263
Exception Handling������������������������������������������������������������������������������������������������������������������� 266
Summary���������������������������������������������������������������������������������������������������������������������������������� 270
What’s Next������������������������������������������������������������������������������������������������������������������������������� 270

xi
Table of Contents

Chapter 17: Aggregates���������������������������������������������������������������������������������������� 271


Custom Aggregate��������������������������������������������������������������������������������������������������������������������� 271
Simple Example������������������������������������������������������������������������������������������������������������������� 272
State Transition Function����������������������������������������������������������������������������������������������������� 273
Final Function���������������������������������������������������������������������������������������������������������������������� 275
Creating Custom Aggregate������������������������������������������������������������������������������������������������� 276
Create Type�������������������������������������������������������������������������������������������������������������������������� 277
Create State Transition Function����������������������������������������������������������������������������������������� 277
Create Aggregate����������������������������������������������������������������������������������������������������������������� 278
Final Function���������������������������������������������������������������������������������������������������������������������� 279
Summary���������������������������������������������������������������������������������������������������������������������������������� 281
What’s Next������������������������������������������������������������������������������������������������������������������������������� 281

Chapter 18: Listen and Notify������������������������������������������������������������������������������� 283


Simple Example������������������������������������������������������������������������������������������������������������������������ 283
Build Polling in psql������������������������������������������������������������������������������������������������������������������ 285
TCN Extension��������������������������������������������������������������������������������������������������������������������������� 290
Summary���������������������������������������������������������������������������������������������������������������������������������� 292
What’s Next������������������������������������������������������������������������������������������������������������������������������� 292

Chapter 19: PL/pgSQL Essential Extensions��������������������������������������������������������� 293


plprofiler Extension������������������������������������������������������������������������������������������������������������������� 293
Installation��������������������������������������������������������������������������������������������������������������������������� 295
Usage����������������������������������������������������������������������������������������������������������������������������������� 296
plpgsql_check Extension���������������������������������������������������������������������������������������������������������� 305
Installation��������������������������������������������������������������������������������������������������������������������������� 305
Usage����������������������������������������������������������������������������������������������������������������������������������� 306
Summary���������������������������������������������������������������������������������������������������������������������������������� 309

Index��������������������������������������������������������������������������������������������������������������������� 311

xii
About the Authors
Baji Shaik, currently serving as a Senior Database
Consultant at AWS Professional Services, embarked on
his journey into the world of databases in 2011. Since
then, his expertise has encompassed an array of database
technologies, including Oracle, PostgreSQL, EDB Postgres,
Amazon RDS, Amazon Aurora, Amazon Redshift, and
Greenplum. Baji’s extensive background spans both depth
and breadth, showcasing his mastery in SQL/NoSQL
database technologies.
Baji stands out as a Database Migration Expert, having
successfully developed numerous database solutions that
tackle complex business challenges, particularly in migrating databases from on-
premises environments to Amazon RDS and Aurora PostgreSQL/MySQL. His prowess
also extends to performance optimization, having fine-tuned RDS/Aurora PostgreSQL/
MySQL databases to achieve remarkable performance benchmarks.
With a passion for knowledge sharing, Baji has authored several notable books on
PostgreSQL, such as PostgreSQL Configuration, Beginning PostgreSQL on the Cloud, and
PostgreSQL Development Essentials. His commitment to education and information
dissemination is further evident through his contributions to conferences, workshops,
and a multitude of insightful blogs within the AWS blog community.

Dinesh Kumar Chemuduru, an accomplished Principal


Architect (OSS), brings a wealth of experience to the realm
of technology and open source solutions. With a notable
background at AWS as a proficient database consultant,
Dinesh excelled in orchestrating numerous successful
database migrations. His expertise extends to the open
source arena, where he has both crafted and augmented
solutions around PostgreSQL, showcasing his commitment
to collaborative innovation.

xiii
About the Authors

A coding enthusiast at heart, Dinesh finds joy in crafting applications using Flutter,
Golang, and C++, platforms where his creativity knows no bounds. His proficiency
extends to the deployment phase, as he deftly navigates Kubernetes to bring his coding
creations to life. In the literary domain, Dinesh stands as a coauthor of the esteemed
PostgreSQL High Performance Cookbook, a testament to his mastery of the subject
matter. Beyond his own works, he actively engages in the appraisal of fellow authors’
PostgreSQL books, cementing his status as a valued participant in the exchange of
knowledge.
Dinesh’s impact reverberates through his open source contributions, which include
the inception and enrichment of projects such as PTOR – an ingenious RPO/RTO/SLA
calculator tailored for PostgreSQL. Another tool, “hammerpost,” sets a benchmark for
synthetic parameter evaluation in PostgreSQL, seamlessly integrated with HammerDB.

xiv
About the Technical Reviewer
Deepak Ramnandan Mahto works as a PostgreSQL
Database Engineer at Google Cloud. He has been working
with PostgreSQL since 2018, and he also worked as a
database migration consultant at AWS. He is also a keen
blogger and loves to publish articles on migration, best
practices, and on cloud with PostgreSQL. He loves to
code and build database-related utilities using PL/pgSQL
and SQL.

xv
Acknowledgments
I would like to express my gratitude to several individuals who have played a crucial
role in making this book a reality. A heartfelt thank-you to Apress Media for providing
me with this valuable opportunity. I am especially grateful to my coauthor and mentor,
Dinesh Kumar Chemuduru, for his exceptional collaboration. I want to express my
gratitude to Divya Modi and Nirmal Selvaraj for being understanding of our hectic
schedules and providing us with continuous support throughout the entire process.
Special thanks to Deepak Mahto for his thorough review of the book. Lastly, I am
profoundly thankful to my parents, Lalu Saheb Shaik and Nasar Bee, whose unwavering
support has shaped me into the person I am today.

—Baji Shaik

I would like to extend my heartfelt gratitude to a remarkable group of individuals who


have been instrumental in making this endeavor a reality. My heartfelt thank-you
to Apress Media for providing me with this valuable opportunity. A special note of
appreciation to my esteemed coauthor, Baji Shaik. Sincere thanks to Deepak Mahto,
whose meticulous review and insightful feedback significantly enhanced the quality and
depth of this manuscript. To Divya Modi and Nirmal Selvaraj, our project coordinators,
your organizational skills and dedication ensured that every aspect of this project fell
seamlessly into place. To my parents Vanamma, Sreenivasulu and my dearest children,
Yashvi and Isha, and to the future luminaries, Hema Siri K and Rahul Sonu K – your
unwavering love and understanding throughout the demanding phases of this project
have served as my steadfast anchor. Your continuous support is my driving force.
Finally, a heartfelt thank-you to my exceptional team at Tessell. Your commitment
to excellence and innovation is awe-inspiring. Together, we are shaping the future of
DBaaS, and I am privileged to work alongside such talented individuals.

—Dinesh Kumar Chemuduru

xvii
Introduction
The PostgreSQL engine comes with its own dedicated procedural language, similar
to procedural languages found in other commercial database engines. This language,
known as PL/pgSQL, offers a range of powerful features that developers have long
desired. For instance, PL/pgSQL includes certain object-oriented programming
capabilities like the ability to define custom operators and types, as well as custom
aggregates.
In contrast to other programming languages supported by PostgreSQL, PL/pgSQL is
intricately linked with the PostgreSQL database engine interface. This tight integration
ensures optimal performance and a seamless fit for constructing business logic on
the database side. In this book, we not only introduce the fundamentals of PL/pgSQL,
but we also dive deep into specific use cases that we’ve implemented for particular
scenarios. Our aim is to comprehensively cover the various features, functionalities, and
application scenarios of PL/pgSQL, offering assistance in crafting effective server-side
objects with ease.
Through the content of this book, you will gain an understanding of PL/pgSQL’s
design and dive deep into its transaction model, including how commit and rollback
operations function. You’ll discover strategies for optimizing PL/pgSQL functions and
procedures and explore the mechanics of inline or anonymous server-side code, along
with its limitations. Furthermore, you’ll acquire insights into debugging and profiling
PL/pgSQL code and learn techniques for conducting statistical analyses on the PL/
pgSQL code you create.

xix
CHAPTER 1

Introduction to PL/pgSQL
In this chapter, we will start with an introduction of PL/pgSQL, on what is PL/pgSQL
and what are the key features of it. We will talk about some common use cases where
PL/pgSQL is used. PL/pgSQL comes by default when you install the PostgreSQL server.
However, we will provide the steps to install PL/pgSQL. We will explain how PL/pgSQL
works with a simple flow diagram. We will show some basic examples of PL/pgSQL code
blocks which are called anonymous and named code blocks.

A Closer Look at PL/pgSQL


PostgreSQL uses SQL (Structured Query Language) as a default query language.
SQL is a common domain-specific language for relational databases. PostgreSQL uses
some extensions and features to implement the standards of SQL. In addition to SQL,
PostgreSQL supports many procedural languages like PL/pgSQL, PL/Java, PLV8,
PL/Python, PL/Perl, etc. Using these languages, you can create functions, stored
procedures, and triggers which will improve the performance by reducing the multiple
iterations to the databases.
PL/pgSQL is the most commonly used procedural language in PostgreSQL. It is
an extension of SQL. It is similar to Oracle's PL/SQL and supports features like control
structures, exception handling, variables, loops, and conditional statements. These
features help us to develop complex database applications in an efficient way.
When working on designing a complex business logic inside the database, you would
need to develop multiple SQLs which are sometimes interdependent. Results of one SQL
will be used by other SQLs. In this case, running multiple SQLs increases the data flow
between the database and the client application and will cause performance bottlenecks
due to high data transfer through the network. To overcome this, you can use stored
procedures or functions.

1
© Baji Shaik and Dinesh Kumar Chemuduru 2023
B. Shaik and D. K. Chemuduru, Procedural Programming with PostgreSQL PL/pgSQL,
https://doi.org/10.1007/978-1-4842-9840-4_1
Chapter 1 Introduction to PL/pgSQL

PL/pgSQL supports stored procedures, functions, and triggers. A stored procedure


is a set of precompiled SQL statements which can be executed repeatedly. Stored
procedures can help to reduce network traffic and improve performance by reducing the
amount of data that needs to be sent between the database and the client application.
The common use cases to use stored procedures or functions using PL/pgSQL are
1. Improve data processing speed by using precompiled code
through stored procedures which will be faster than raw SQL
queries.
2. Write more complex code using features like control structures,
exception handling, variables, loops, conditional statements, etc.

3. Using stored procedures or functions, you can create a reusable


code to call from the applications to save time and effort.

4. PL/pgSQL is portable across different operating systems and


platforms. This makes it easier to migrate code between different
environments.
5. Prevent unauthorized access and data breaches by controlling the
user authentication on stored procedures or functions.

6. Use triggers to implement constraints of business processes that


cannot be expressed as foreign keys or check constraints.

PL/pgSQL Installation
PL/pgSQL is already included in PostgreSQL, so if you have PostgreSQL installed, you
should have PL/pgSQL as well. However, you may need to enable it if it is not already
enabled. Here are the steps to enable PL/pgSQL in PostgreSQL:
1. Install PostgreSQL psql client to connect to the database, or you
can use the pgAdmin client tool.

For Ubuntu, the following are the simple steps to install the client:

# Create the file repository configuration:

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt


$(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'

2
Chapter 1 Introduction to PL/pgSQL

# Import the repository signing key:

wget --quiet -O - https://www.postgresql.org/media/keys/


ACCC4CF8.asc | sudo apt-key add -

# Update the package lists:

sudo apt-get update

# Install the latest version of PostgreSQL. If you want a specific


version, use 'postgresql-12' or similar instead of 'postgresql':

sudo apt-get -y install postgresql-client-15

For Linux (RHEL), you can follow the steps here:


www.postgresql.org/download/linux/redhat/

2. Connect to the database and check if PL/pgSQL is already


installed:
postgres=# \dx
List of installed extensions
Name | Version | Schema | Description
-----+---------+--------+-------------
(0 rows)
postgres=# select * from pg_extension where extname='plpgsql';
oid | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition
----+---------+----------+--------------+----------------+------------+-----------+--------------
(0 rows)

3. Execute the following command to enable PL/pgSQL:

postgres=# CREATE EXTENSION plpgsql;


CREATE EXTENSION

3
Chapter 1 Introduction to PL/pgSQL

4. Verify that PL/pgSQL is enabled by executing the following


command:
postgres=# \dx
List of installed extensions
Name    | Version |   Schema   |         Description
------ -+---------+------------+------------------------------
plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
(1 row)
JavaScript
postgres=# select * from pg_extension where extname='plpgsql';
oid   | extname | extowner | extnamespace | extrelocatable | extversion | extconfig | extcondition
------+---------+----------+--------------+----------------+------------+-----------+-------------
16388 | plpgsql |       10 |        11 | f              | 1.0        |        |
(1 row)

PL/pgSQL Execution Flow


PL/pgSQL is like every other “loadable, procedural language.” PL/pgSQL gets loaded
through a function manager called fmgr. The fmgr loads the language handler when
a procedural language function or procedure is executed and calls it. The execution
flow of PL/pgSQL code is similar to that of other procedural programming languages,
with parsing, compilation, execution, and cleanup stages. However, PL/pgSQL code is
executed on the server side, which means that it has direct access to the database and
can perform database operations more efficiently than client-side code.
On the first call of a PL/pgSQL function or procedure in a session, the server first
parses the code to check for syntax errors. The call handler will “compile” a function
statement tree once the code is parsed. When the code is compiled, it turns into an
internal form that the server can execute more efficiently. SQL queries in the function
are just kept as a string at this point, and the expressions like the following are actually
SQL queries:

my_var := some_param * 10

4
Chapter 1 Introduction to PL/pgSQL

The SQL queries are actually parsed at this point, and parser hooks are used to replace
variables/parameters with PARAM nodes in the parse tree. The PL/pgSQL statement tree
is very similar to a PostgreSQL execution tree. After the parse and compile, the call handler
then executes that statement tree. On the first execution of a statement node that has an
SQL query in it, that query is prepared via the Server Programming Interface (SPI). The SPI
provides a simple and efficient way to execute SQL commands, retrieve query results, and
manipulate the database. The compiled code is then executed by the server. Based on any
variable and control structure declaration, the server creates a new execution environment
for the PL/pgSQL code. If the PL/pgSQL code is a function or stored procedure that returns
a result set, the server will send the result set back to the client. Once the execution of the
code is complete, the server will clean up any resources that were used by the PL/pgSQL
code, including variables and any temporary tables that were created.
Figure 1-1 represents the flow of execution.

Figure 1-1. PL/pgSQL execution flow

5
Chapter 1 Introduction to PL/pgSQL

This diagram illustrates the high-level steps of the PL/pgSQL execution flow.
However, it's important to note that PL/pgSQL code can be quite complex and may
include multiple control structures, error handling blocks, and nested and even
recursive PL/pgSQL function calls and trigger invocations and database operations. The
actual execution flow of a specific PL/pgSQL function or stored procedure will depend
on the specific code and logic used. This call hierarchy is not limited to PL/pgSQL. All
procedural languages share the common entry point of the fmgr, so they can be mixed
and matched in trigger and function call stacks.

PL/pgSQL Blocks
PL/pgSQL is a block-structured language. The basic unit in any PL/pgSQL code is a
block. All PL/pgSQL code is composed of a single block or blocks that occur either
sequentially or nested within another block. There are two kinds of blocks:
• Anonymous or unnamed blocks (DO)

• Named blocks (functions)

Anonymous or Unnamed Blocks


Anonymous or unnamed blocks are generally constructed dynamically and executed
only once by the user. It is sort of a complex SQL statement.
The following is the structure of an anonymous block, for example:

DO $$
[ <<label>> ]
[ DECLARE
-- Variable declaration here
]
BEGIN
-- Execute statements here
END [ label ];
$$;

6
Chapter 1 Introduction to PL/pgSQL

Now, let us start with a simple hello world code block, which does not have any
name associated with it:

postgres=# DO
$$
BEGIN
        RAISE NOTICE 'Hello World';
END;
$$;

NOTICE:  Hello World
DO

In the preceding example, the RAISE NOTICE command will help us to print the
given message on the client console. As you can see here, the block is declared without
a name, and if you want to print Hello World, then you have to repeat the same set of
instructions again.
Now, let us print the Hello World line by line rather than in a single line:

postgres=# DO
$o$
BEGIN
        RAISE NOTICE $i$
        Hello
        World
        $i$;
END;
$o$;

NOTICE:
        Hello
        World
DO

In the preceding example, we used different multiline specifiers. The whole block got
enclosed by $o$, and the inner Hello World got enclosed by $i$. From this example, we
can learn that in PL/pgSQL, we can have the nested multiliners, where each multiline
should follow its own enclosure.

7
Chapter 1 Introduction to PL/pgSQL

Now, let us write a nested BEGIN ... END inside a main BEGIN ... END block. Here
is an example:

postgres=# DO
$$
BEGIN

        BEGIN
                RAISE NOTICE 'Hello World';
        END;
END;
$$;
NOTICE:  Hello World
DO

In the preceding example, we print the Hello World message from the nested BEGIN
... END block. It is possible to have multiple nested statements inside a single BEGIN...
END block. We will see more of these in the coming chapters, where we discuss exception
handling.
Now, let us go a little deeper and print the Hello World message from the nested
unnamed code block:

postgres=# DO
$o$
BEGIN
        DO
        $i$
                BEGIN
                        RAISE NOTICE 'Hello World';
                END;
        $i$;
END;
$o$;
NOTICE:  Hello World
DO

As you can see in the preceding example, we are able to define an unnamed block
inside an unnamed block. By defining the nested code blocks, we can segregate a large
unnamed block into multiple stand-alone work units. We don’t need to write a nested
8
Chapter 1 Introduction to PL/pgSQL

unnamed block; in most of the cases, the nested BEGIN...END block would be sufficient.
But in general, we don’t keep large unnamed blocks in the database; rather, we store
them inside with a name (function/procedure), and we call that object name, whenever
it is required.
Here is another example where we can have a nested block inside an exception:

postgres=# DO $inline$
BEGIN
        PERFORM 1/0;
        RAISE NOTICE 'Hello World!';

EXCEPTION
        WHEN OTHERS THEN
        DO $$
        BEGIN
                RAISE NOTICE 'Got error';
        END;
        $$;
END;
$inline$;
NOTICE:  Got error
DO

PL/pgSQL does not restrict the anonymous blocks as stand-alone objects; we can
also embed these inline definitions inside the function or procedure object. We haven’t
discussed about procedures and functions yet, but showing you an example where
you can declare the inline anonymous block inside a function:

postgres=# CREATE OR REPLACE FUNCTION test_func()


RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
        DO $$ BEGIN RAISE NOTICE 'Hello World!'; END;$$;
END;
$function$;
CREATE FUNCTION

9
Chapter 1 Introduction to PL/pgSQL

postgres=# SELECT test_func();


NOTICE:  Hello World!
test_func
-----------

(1 row)

How it works is, unlike other procedural languages, PL/pgSQL gives an inline
statement handler plpgsql_inline_handler. By using this handler, PL/pgSQL executes
the unnamed or inline PL/pgSQL blocks. If there are any nested code blocks, then those
will be evaluated recursively by the plpgsql_inline_handler.

Note that it is not possible to return any value from the unnamed code blocks.
Always use anonymous code blocks to define the business logic, which involves
making a set of function or procedure calls. If you want to return any value from
anonymous blocks, then we might need to use any session-level variables, which
need to be set inside the anonymous block, and access them from the outside of
the blocks.

Named Blocks
Named blocks have a name associated with them, are stored in the database, can be
executed repeatedly, and can take in parameters.
A named block in PL/pgSQL is defined using the following syntax:

<<label>>
DECLARE
-- declare variables here
BEGIN
-- Named block's code here
END;

Here, label is the name of the block and is enclosed within << >> brackets.It is not
just cosmetic, but that nested code blocks can refer to outer variables by using that label
instead of finding the innermost match for the variable name.

10
Chapter 1 Introduction to PL/pgSQL

The DECLARE section is used to declare variables that are used within the block,
while the BEGIN and END sections contain the actual code for the block.
Once a named block has been defined, it can be called from within the same
function or procedure using the PERFORM statement:

PERFORM block_name;

This will execute the code within the named block. Named blocks can be called
multiple times within the same function or procedure, allowing for reusable and
modular code.
Here's an example of a PL/pgSQL function that uses named blocks to calculate the
factorial of a number:

CREATE OR REPLACE FUNCTION factorial(num INTEGER)


RETURNS INTEGER AS $$
DECLARE
   result INTEGER := 1;
BEGIN
   <<factorial_loop>>
   FOR i IN 1..num LOOP
      result := result * i;
   END LOOP factorial_loop;

   RETURN result;
END;
$$ LANGUAGE plpgsql;

In this example, the named block factorial_loop is used within a FOR loop to
calculate the factorial of the input number. The DECLARE section declares a variable
result to store the final result, while the BEGIN and END sections contain the code for
the named block.
The named block is called within the FOR loop using the LOOP statement. This
allows the loop to continue until it reaches the specified number of iterations.
Once the FOR loop is complete, the final result is returned by the function.
To call the function and calculate the factorial of a number, you would execute the
following SQL statement:

SELECT factorial(5);

This would return the value 120, which is the factorial of 5.


11
Chapter 1 Introduction to PL/pgSQL

Summary
In this chapter, we talked about PL/pgSQL use cases, installation, and how it works with
a flow diagram. We have also shown how simple PL/pgSQL code blocks look like and
how to execute them. These examples will help you to understand and start with PL/
pgSQL code. In the next chapter, we will talk about the variables that are used inside
PL/pgSQL code blocks. We will start with how to declare those variables and dive deep
into different types of methods to use based on the use cases. These will help you to
decide which type of variables you should use when building the PL/pgSQL code for the
functions or procedures.

What’s Next
In the next chapter, we will be covering some key features of PL/pgSQL variables like the
following:
• Variable Types: Explore the different types of variables and learn
how to choose the appropriate variable type for your needs.
• Variable Scoping Mastery: Gain a better grasp of variable scoping
rules and how to manage variables effectively within different blocks.
• Variable Naming Conventions: Learn about naming conventions
that can help you write more maintainable and readable code.
• Advanced Variable Usage: Extend your knowledge by using
variables in more complex scenarios.

12
CHAPTER 2

PL/pgSQL Variables
In the previous chapter, we talked about what PL/pgSQL is and some use cases where
you need it. We also explained the steps to install and the execution flow of PL/pgSQL
with a simple diagram. We have discussed some PL/pgSQL anonymous and named
code block examples which will help in understanding the basics. In this chapter, we will
introduce variables that are used in the PL/pgSQL code. We will provide different types
of variables and use cases on when to use them. We will show the declaration and scope
of variables and different types of variables with some examples.

What Are Variables in PL/pgSQL?


Similar to other programming languages, PL/pgSQL has variables which are used to
store values for later use in the program. These variables can hold different types of data
such as integers, floating-point numbers, strings, and boolean values.

Declaring Variables
PL/pgSQL offers to declare variables in its declaration section of the block. Here is an
example:

postgres=# DO
$$
DECLARE
        v_var1 INT;
        v_var2 INT:=10;
BEGIN
        RAISE NOTICE 'v_var1 %', v_var1;
        RAISE NOTICE 'v_var2 %', v_var2;

13
© Baji Shaik and Dinesh Kumar Chemuduru 2023
B. Shaik and D. K. Chemuduru, Procedural Programming with PostgreSQL PL/pgSQL,
https://doi.org/10.1007/978-1-4842-9840-4_2
Chapter 2 PL/pgSQL Variables

END;
$$;
NOTICE:  v_var1 <NULL>
NOTICE:  v_var2 10
DO

In the preceding example, we have declared two variables. The v_var1 variable is
declared but not defined with any value to it. The second variable v_var2 is declared but
has a value 10 to it. If we try to access a variable which is declared and not defined, then
expect that we would get NULL from it. In the preceding output, we can also see that the
v_var1 is set to NULL.
From the previous chapter, we learned that we can have nested blocks inside the
main PL/pgSQL block. By using that nested block feature, we have multiple declarations
and multiple variables in the single PL/pgSQL block. Here is an example:

postgres=# DO
$o$
DECLARE
        v_var1 INT:=10;
BEGIN

        RAISE NOTICE 'v_var1 %', v_var1;

        DO
        $i$
        DECLARE
                v_var1 INT:=100;
        BEGIN
                RAISE NOTICE 'v_var1 %', v_var1;
        END;
        $i$;

END;
$o$;
NOTICE:  v_var1 10
NOTICE:  v_var1 100
DO

14
Chapter 2 PL/pgSQL Variables

In the preceding example, we have nested unnamed blocks, where we have two
variable declarations. The variable v_var1 in the main block is declared with the value
10, and also v_var1 in the inside block is declared with the value 100. Also, the scope of
the variable is always local.

Note In PL/pgSQL, we can’t declare variables on the fly. We should always


declare them in the DECLARE section, and we have to use them in the block. But,
while defining the FOR LOOP, we can have the variables declared on the fly. We
will discuss more about this in the coming chapters.

Variable Scope
The scope of the declared variables in PL/pgSQL is always local to its current block. That
is, once we declare the variable in a block, we can’t access them outside of that block.
Here is an example:

postgres=# DO
$$
DECLARE
BEGIN
        DECLARE
                v_var1 INT:=10;
        BEGIN
                RAISE NOTICE 'v_var1 %', v_var1;
        END;

        RAISE NOTICE 'v_var1 %', v_var1;


END;
$$;
NOTICE:  v_var1 10
ERROR:  column "v_var1" does not exist
LINE 1: v_var1
        ^
QUERY:  v_var1
CONTEXT:  PL/pgSQL function inline_code_block line 10 at RAISE

15
Chapter 2 PL/pgSQL Variables

From the preceding example, as you can see we got an error, column "v_var1"
does not exist, when we try to access the variable v_var1 from the outer BEGIN...
END block. That is, the scope of variable v_var1 is local to that inner BEGIN...END block,
and we can’t access them from the outside. If we declare the variable v_var1 in the
parent BEGIN...END block, then we can access that variable inside the nested BEGIN...
END blocks too. Because the v_var1 is declared at the parent block level, its scope is
at the whole block level. Now, you might have questions like what if we declare the
same variable v_var1 in parent and nested BEGIN...END blocks and how to access the
parent block’s v_var1 along with the local declared variable. Here is an example for this
use case:

postgres=# DO
$$
DECLARE
        v_var1 INT:=1;
BEGIN
        DECLARE
                v_var1 INT:=10;
        BEGIN
                RAISE NOTICE 'v_var1 %', v_var1;
        END;
END;
$$;
NOTICE:  v_var1 10
DO

From the preceding example, we were only able to access the variable v_var1, which
was declared in the nested BEGIN...END block. To access the parent v_var1 variable,
then we should access that variable with the block’s label. That is, we have to give a label
name to the parent block, and then we should access the v_var1 along with its label
name. Here is an example:

postgres=# DO
$$
<<parent>>
DECLARE
        v_var1 INT := 1;

16
Chapter 2 PL/pgSQL Variables

BEGIN
        DECLARE
                v_var1 INT := 10;
        BEGIN
                RAISE NOTICE 'Parent v_var1 %', parent.v_var1;
                RAISE NOTICE 'Local  v_var1 %', v_var1;
        END;
END;
$$;
NOTICE:  Parent v_var1 1
NOTICE:  Local  v_var1 10
DO

Constant Variables
We can declare constant variables inside PL/pgSQL, which shouldn’t get updated by
further instructions. Here is an example:

postgres=# DO
$$
DECLARE
    v_c_pi CONSTANT REAL DEFAULT 3.14;
BEGIN
    v_c_pi = 3.15;
END;
$$;
ERROR:  variable "v_c_pi" is declared CONSTANT
LINE 6:     v_c_pi = 3.15;

In the preceding example, we declared the variable v_c_pi as CONSTANT and set its
DEFAULT value as 3.14. But, in further instructions, when we tried to update its value as
3.15, we got the exception as the variable is declared as CONSTANT, which should not get
updated by any of the instructions.

17
Chapter 2 PL/pgSQL Variables

Variable Alias
In PL/pgSQL, we can also create a reference variable which points to another variable or
system variables. For example, if we want to create a reference variable or a short-length
variable name to another variable, then we can create those short-length variables using
ALIAS. Here is an example:

DO
$$
DECLARE
    var_earth_sun_distance REAL DEFAULT 149.6;
    v_e_s_d ALIAS FOR var_earth_sun_distance;
BEGIN
    RAISE NOTICE 'Reference      #1 %', v_e_s_d;
    v_e_s_d = 149.5;
    RAISE NOTICE 'Actual Variable   %', var_earth_sun_distance;
END;
$$;
NOTICE:  Reference      #1 149.6
NOTICE:  Actual Variable   149.5
DO

In the preceding example, we created a reference variable v_e_s_d to the actual


variable var_earth_sun_distance. Also, if we perform any update on the reference
variable, then we can see those changes from the actual variable. ALIAS is not limited to
creating a reference variable to the actual variable, it will allow creating a reference to
another reference. Here is an example:

DO
$$
DECLARE
    var_earth_sun_distance REAL DEFAULT 149.6;
    v_e_s_d ALIAS FOR var_earth_sun_distance;
    vd ALIAS FOR v_e_s_d;
BEGIN
    RAISE NOTICE 'Reference       #1 %', v_e_s_d;
    RAISE NOTICE 'Reference       #2 %', vd;

18
Chapter 2 PL/pgSQL Variables

    RAISE NOTICE 'Update Ref #1';


    v_e_s_d = 149.5;
    RAISE NOTICE 'Actual Variable    %', var_earth_sun_distance;
    RAISE NOTICE 'Update Ref #2';
    vd = 149.4;
    RAISE NOTICE 'Actual Variable    %', var_earth_sun_distance;
END;
$$;
NOTICE:  Reference       #1 149.6
NOTICE:  Reference       #2 149.6
NOTICE:  Update Ref #1
NOTICE:  Actual Variable    149.5
NOTICE:  Update Ref #2
NOTICE:  Actual Variable    149.4
DO

In the preceding example, we created an ALIAS variable from another ALIAS variable.
That is, we created a new reference variable, which points to another reference variable.
Also, if we update the second reference variable, it will reflect those changes on the
actual variable via the first reference.
PL/pgSQL supports the following types of variables:
• Scalar Variables

• Array Variables

• Record Variables

• Cursor Variables

Scalar Variables
In all the previous examples, we demonstrated scalar variables. Scalar variables hold a
single value of a specific data type, such as an integer or a string. They can be declared
and initialized using the DECLARE keyword and can be assigned values using the :=
assignment operator.

19
Chapter 2 PL/pgSQL Variables

For example, the following code declares each type of scalar variable:

postgres=# DO $$
DECLARE
   my_int integer := 1;
   my_text text := 'Hello, world!';
   my_bool boolean := true;
BEGIN
   -- perform operations on the scalar variables
   my_int := my_int + 10;
   my_text := my_text || ' How are you?';
   my_bool := not my_bool;

   -- print the scalar variables


   RAISE NOTICE 'my_int = %', my_int;
   RAISE NOTICE 'my_text = %', my_text;
   RAISE NOTICE 'my_bool = %', my_bool;
END;
$$;
NOTICE:  my_int = 11
NOTICE:  my_text = Hello, world! How are you?
NOTICE:  my_bool = f
DO

In the preceding example, we declare three scalar variables: my_int with a value
of 1 and a data type of integer, my_text with a value of 'Hello, world!' and a data
type of text, and my_bool with a value of true and a data type of boolean. We then
perform some operations on these variables using arithmetic, concatenation, and logical
negation. Finally, we print the values of the variables using the RAISE NOTICE statement.
Scalar variables are useful for storing temporary values or performing calculations
within a stored procedure or function. They can be used in a variety of ways, such as
tracking state, performing conditional logic, or holding input or output parameters.

20
Chapter 2 PL/pgSQL Variables

Array Variables
Array variables are variables that can hold multiple values of the same data type. They
are declared using a data type followed by the [] syntax, such as integer[] or text[].
For example, the following code declares an array variable:

postgres=# DO $$
DECLARE
   my_array integer[] := '{1, 2, 3, 4, 5}';
BEGIN
   -- print the entire array
   RAISE NOTICE 'my_array = %', my_array;

   -- access individual elements of the array


   RAISE NOTICE 'my_array[2] = %', my_array[2];

   -- modify individual elements of the array


   my_array[3] := 10;

   -- print the modified array


   RAISE NOTICE 'my_array = %', my_array;
END;
$$;
NOTICE:  my_array = {1,2,3,4,5}
NOTICE:  my_array[2] = 2
NOTICE:  my_array = {1,2,10,4,5}
DO

In the preceding example, we declare an array variable my_array with a data type of
integer[] and initialize it with the values {1, 2, 3, 4, 5}. We then print the entire
array using the RAISE NOTICE statement, access and print the value of the second
element of the array, modify the value of the third element of the array, and print the
entire array again.
Array variables are useful for storing and manipulating sets of related data, such
as lists of numbers, strings, or boolean values. They can be used in a variety of ways,
such as for performing calculations on multiple values at once, storing input or output
parameters, or passing data between functions or procedures.

21
Chapter 2 PL/pgSQL Variables

Record Variables
Record variables are used to store a row of data from a table or a query result. They are
declared using the %ROWTYPE attribute and can be assigned values using the SELECT INTO
statement.
For example, the following code declares a record variable:

postgres=# CREATE TABLE emp (emp_id INT, emp_name VARCHAR, emp_salary


NUMERIC);
CREATE TABLE

postgres=# INSERT INTO emp VALUES (100, 'SCOTT', '10000.00');


INSERT 0 1

postgres=# DO $$
DECLARE
   my_record emp%ROWTYPE;
BEGIN
   -- select a row of data into the record variable
   SELECT * INTO my_record FROM emp WHERE emp_id = 100;

   -- print the values of the record variable


   RAISE NOTICE 'emp_id = %', my_record.emp_id;
   RAISE NOTICE 'emp_name = %', my_record.emp_name;
   RAISE NOTICE 'emp_salary = %', my_record.emp_salary;

   -- update the values of the record variable


   my_record.emp_name := 'Smith';
   my_record.emp_salary := 50000;

   -- update the row of data in the table


   UPDATE emp SET emp_name = my_record.emp_name, emp_salary = my_record.
emp_salary WHERE emp_id = 1001;
END;
$$;
NOTICE:  emp_id = 100
NOTICE:  emp_name = SCOTT
NOTICE:  emp_salary = 10000.00
DO

22
Chapter 2 PL/pgSQL Variables

In the preceding example, we declare a record variable my_record that holds a row
of data from the emp table. We then select a row of data into the record variable using
a SELECT statement, print the values of the record variable using the RAISE NOTICE
statement, update the values of the record variable, and update the row of data in the
table using an UPDATE statement.
Record variables are useful for storing and manipulating rows of data from tables
or query results within a stored procedure or function. They can be used in a variety of
ways, such as for passing data between functions or procedures, performing calculations
on data, or storing input or output parameters.

Cursor Variables
Cursor variables are variables that hold a reference to a cursor, which is a named SQL
statement that can be executed repeatedly. They are declared using the CURSOR
keyword.
For example, the following code declares a record variable named “my_row” that
corresponds to the columns of a table named “my_table”:

postgres=# CREATE TABLE emp (emp_id INT, emp_name VARCHAR, emp_salary


NUMERIC);
CREATE TABLE

postgres=# INSERT INTO emp VALUES (100, 'SCOTT', '10000.00');


INSERT 0 1

postgres=# INSERT INTO emp VALUES (100, 'ROBERT', '50000.00');


INSERT 0 1

postgres=# DO $$
DECLARE
   my_cursor refcursor;
   my_record emp%ROWTYPE;
BEGIN
   -- open the cursor and fetch the first row of data
   OPEN my_cursor FOR SELECT * FROM emp;
   FETCH my_cursor INTO my_record;

   -- print the values of the first row of data

23
Chapter 2 PL/pgSQL Variables

   RAISE NOTICE 'emp_id = %', my_record.emp_id;


   RAISE NOTICE 'emp_name = %', my_record.emp_name;
   RAISE NOTICE 'emp_salary = %', my_record.emp_salary;

   -- fetch the next row of data


   FETCH my_cursor INTO my_record;

   -- print the values of the second row of data


   RAISE NOTICE 'emp_id = %', my_record.emp_id;
   RAISE NOTICE 'emp_name = %', my_record.emp_name;
   RAISE NOTICE 'emp_salary = %', my_record.emp_salary;

   -- close the cursor


   CLOSE my_cursor;
END;
$$;
NOTICE:  emp_id = 100
NOTICE:  emp_name = SCOTT
NOTICE:  emp_salary = 10000.00
NOTICE:  emp_id = 100
NOTICE:  emp_name = ROBERT
NOTICE:  emp_salary = 50000.00
DO

In the preceding example, we declare a cursor variable my_cursor and a record


variable my_record that holds a row of data from the emp table. We then open the cursor
using a SELECT statement, fetch the first row of data into the record variable using
a FETCH statement, print the values of the first row of data using the RAISE NOTICE
statement, fetch the second row of data into the record variable, print the values of the
second row of data, and then close the cursor using the CLOSE statement.
Cursor variables are useful for manipulating and iterating through result sets
returned by queries. They can be used in a variety of ways, such as for processing large
datasets, performing calculations on data, or storing input or output parameters.
Variables can be very useful in PL/pgSQL programs as they allow you to store and
manipulate data in a flexible way.

24
Chapter 2 PL/pgSQL Variables

Summary
In this chapter, we learned about the types of variables with nice examples and
explanations of how they work. We went through the declaration of variables in the
DECLARE section of the code as well as in an independent code block on the fly. The
scope of variables is different for each block of PL/pgSQL code. We explained how the
scope of variables varies with some examples. Also, we looked at constant variables and
how to use aliases for the variables.

What’s Next
In the next chapter, we will be covering some key features of PL/pgSQL data types like
the following:
• Advanced Data Type Exploration: Delve into complex data types
like composite and range types to efficiently manage intricate data
structures.
• Custom Domain Types: Create user-defined domain types with
specific constraints to ensure data integrity and validation in your
applications.
• Optimal Type Selection: Understand how to choose the right
data type based on application needs, considering performance,
maintainability, and space efficiency.
• Dynamic Application Building: Harness PL/pgSQL data types to
create adaptable applications that handle diverse data inputs and
outputs.

25
CHAPTER 3

PL/pgSQL Data Types


In the previous chapter, we introduced variables that are used in the PL/pgSQL code.
We talked about different types of variables and use cases on when to use them. We have
shown the declaration and scope of the variables and different types of variables with
some examples. In this chapter, we will introduce the supported data types to use in PL/
pgSQL code. We will walk through each data type and use cases with some examples.

Data Types
Choosing the right data type for the data being used is a best practice that developers
should follow. Choosing the correct data type can help us avoid many data validation
checks and prevent exceptions when incorrect data is entered. The PostgreSQL database
engine supports multiple data types for each data kind. By using these data types, we
build tables and insert proper data into them. We can use most of the PostgreSQL data
types inside PL/pgSQL blocks, besides pseudo-types like any, anyenum, and record. It is
not just limited to using existing data types; we can also construct new composite types
by using these existing data types.
Understanding data types is crucial for developing efficient and effective database
applications. We will cover data types such as integers, floating-point numbers,
booleans, and strings, as well as more advanced data types like arrays and composite
types. By the end of this chapter, you will have a good understanding of the different data
types available in PL/pgSQL and how to use them effectively in your business logic. We
will also cover how to declare variables and constants using these data types and how to
convert between different data types using type casting. This knowledge is essential for
writing robust and error-free PL/pgSQL code that can handle a variety of data inputs and
outputs.

27
© Baji Shaik and Dinesh Kumar Chemuduru 2023
B. Shaik and D. K. Chemuduru, Procedural Programming with PostgreSQL PL/pgSQL,
https://doi.org/10.1007/978-1-4842-9840-4_3
Chapter 3 PL/pgSQL Data Types

Note You can find the list of supported data types here: www.postgresql.
org/docs/current/datatype.html.

Declaring Variables with Data Types


In the previous chapter, we saw several examples where we declared variables along
with their data types. Now, let us begin with a simple example where we demonstrate the
primitive data types like int, boolean, and text:

postgres=# DO
$$
declare
v_int int:=10;
v_text text:='text';
v_boolean boolean:=false;
begin
raise notice 'v_int      %',v_int;
raise notice 'v_text     %',v_text;
raise notice 'v_boolean  %',v_boolean;
end;
$$;

NOTICE:  v_int      10
NOTICE:  v_text     text
NOTICE:  v_boolean  f
DO

In the preceding example, we declared three variables along with their data types
and printed the results. Let us rewrite the previous example as follows and see the
results:

postgres=# DO
$$
declare
int int:=10;
text text:='text';

28
Chapter 3 PL/pgSQL Data Types

boolean boolean:=false;
begin
raise notice 'int  %',int;
raise notice 'text %',text;
raise notice 'boolean %', boolean;
end;
$$;
NOTICE:  int  10
NOTICE:  text text
NOTICE:  boolean f
DO

As you can see in the preceding example, variable names can be declared with the
corresponding data type names. As data type names are not reserved keywords, we can
also use them as variable names. Here, we are demonstrating the possibility of declaring
variable names as data types. However, this kind of variable declaration is not typically
used in production.
In the previous example, as well as in the previous chapter, we discussed only the
base scalar data types in PostgreSQL. These data types accept only a single value into
their declared variable type. To obtain a list of available base scalar types in the current
database, we can query the PostgreSQL catalog table pg_type. The following query
returns base data types in the database limited to three only:

postgres=# SELECT typname FROM pg_type WHERE typtype='b' LIMIT 3;


typname
---------
bool
bytea
char
(3 rows)

29
Other documents randomly have
different content
se haltia, joka suoltaa öisin hevostallissa varsoilta häntäjouhet
hämmennyksiin. Ei niin sydänmaalainen eikä niin mieltäkiehtova,
mutta yhtä pikkusukkelana kujehtijana hän piirteli musteviiksiä
sisareni nukeille. Vuoteissamme kuuntelimme häntä ennen unen
tuloa: hän itki katoilla kissojen kanssa, haukkui kilpaa koirien kera,
voihkaeli savutorvissa ja matki kaduilla juopuneiden yökulkijain
loilotuksia.

Se mikä teki Putois'n meille eläväksi ja tutuksi, mikä meistä oli


jännittävää hänessä, oli että hänen muistonsa yhtyi kaikkiin
ympärillämme oleviin esineihin. Zoén nuket, omat kouluvihkoni,
joitten sivut hän niin monet kerrat oli tuhrinut ja tahrinut, puutarhan
muuri, jonka takaa me olimme nähneet hänen punaisten silmiensä
kiiluvan iltapimeästä, sininen porsliini-uurna, jonka hän eräänä
talviyönä oli halaissut — ellei se ehkä ollut pakkasen työtä —, puut,
kadut, penkit, kaikki ne muistuttivat meitä Putois'sta, meidän
Putois'stamme, lasten Putois'sta, paikkakunnan myytillisestä
olennosta. Sulossa ja runollisuudessa hän ei vetänyt vertoja
kömpelöimmällekään satyyrille, typerimmällekään faunille Sisilian tai
Tessalian mailta. Mutta puolijumala hän oli kuitenkin kaikitenkin.

Isällemme hänellä oli aivan toinen luonne: hän oli tunnuskuvallinen


ja filosofinen. Isämme tunsi suurta surkua ihmisiä kohtaan. Hän ei
pitänyt heitä erittäin järkivoittoisina; mutta heidän erehdyksensä,
milloin ne eivät olleet julmia, huvittivat häntä ja saivat hänet
myhäilemään. Usko Putois'han kiinnitti häntä lyhykäisenä
yhteenvetona kaikista inhimillisistä uskoista. Ollen luonteeltaan
ivallinen ja kujeilevainen hän puhui Putois'sta ikäänkuin todellisesta
olennosta. Häh jutteli hänestä toisinaan sellaisella vakavuudella ja
esitti kaikki seikat niin tarkalla asiallisuudella, että äitini aivan
hämmästyi ja sanoi hänelle sydämensä vilpittömyydessä:
"Luulisi sinun puhuvan ihan tosissasi, ystäväiseni… Ja kuitenkin
sinä tiedät hyvin…"

Hän vastasi vakavasti:

"Koko Saint-Omer uskoo Putois'n olemassaoloon. Olisinko kunnon


kansalainen, jos sen kieltäisin? Saa ajatella kahdesti ympäri päänsä,
ennenkuin menee kumoamaan yleistä uskonkappaletta."

Ainoastaan läpeensä rehellinen mieli tuntee moisia arveluja.


Pohjaltaan isäni oli Gassendin kannattaja. Hän sovitti siis yksityisen
mielipiteensä yleiseen, hän uskoi kuten muutkin Audomarilaiset
Putois'n olemassaoloon, mutta hän ei myöntänyt hänen suoranaista
kajoamistaan meloonivarkauteen ja kyökkipiikojen viettelyyn. Sanalla
sanoen, hyvänä Audomarin kansalaisena hän tunnusti uskovansa,
että on olemassa Putois, mutta hän ei turvannut Putois'han
selittääksensä kaupungissa sattuneita tapahtumia. Niin että hän
tässä kohden, kuten kaikissa muissakin, osoitti olevansa sekä kelpo-
että järkimies.

Mitä äitiimme tulee, niin hän hieman syytti itseään Putois'n


synnystä, eikä ilman aihetta. Sillä olihan näet Putois syntynyt äitini
valheesta, kuten Caliban runoilijan valheesta. Tosin eivät virheet
olleet verrattavissa toisiinsa, ja äitini oli viattomampi kuin
Shakespeare. Mutta kuitenkin hän oli hämillään ja kauhuissaan
nähdessänsä tuon pikkuruisen valheensa kasvavan yli kaikkien
mittojen ja viattoman petoksensa saavuttavan niin suurensuuntaisen
menestyksen, joka ei pysähtynyt enää, vaan valloitti kokonaisen
kaupungin ja uhkasi valloittaa koko maailman. Ja eräänä päivänä
hän kalpeni, luullen saavansa nähdä oman valheensa astuvan elävin
silmin eteensä.
Kävi näet niin, että palvelustyttö, joka oli vasta otettu ja outo
paikkakunnalla, astui sisään ja ilmoitti, että eräs mies tahtoi puhutella
rouvaa.

"Mikä mies hän on?"

"Työmiehen puvussa. Näyttää maalaiselta."

"Onko hän sanonut nimensä?"

"On, rouva."

"No, mikä hän sitten on nimeltään?"

"Putois."

"Kuinka sanoit nimen olevan?…"

"Putois, niin rouva, Putois."

"Onko hän täällä?…"

"On, rouva. Hän odottaa kyökissä."

"Oletko nähnyt hänet?"

"Olen rouva."

"Mitä hänellä on asiaa?"

"Sitä hän ei sanonut. Hän tahtoi puhutella itse rouvaa."

"Mene kysymään mitä hän tahtoo."


Kun palvelija palasi kyökkiin, ei Putois'ta enää ollut siellä. Tämä
muukalaisen palvelustytön ja Putois'n kohtaus jäi ainiaaksi selitystä
vaille. Mutta luuloni on, että siitä päivästä lähtien äitini alkoi uskoa
että Putois hyvinkin saattoi olla olemassa, ja että hän kenties ei ollut
valehdellutkaan.
RIQUET

Muuttopäivän tultua jätti herra Bergeret sisarensa ja tyttärensä


keralla vanhan rapistuneen talon Seine-kadun varrella asettuakseen
uudenaikaiseen huoneistoon Vaugirard-kadun varrelle. Niin olivat
Zoé ja kohtalo päättäneet.

Muuttotouhun pitkinä hetkinä Riquet harhaili haikein mielin


hävityksenalaisissa huoneissa. Hänen rakkaimmille tottumuksilleen
oli tullut pysty eteen. Tuntemattomat, huonosti puetut, äreät ja
äkäiset miehet häiritsivät hänen lepoaan ja tulivat kyökkiin saakka
polkien jaloissaan hänen ruokalautaistaan ja vesikuppiaan. Juuri kun
hän oli vain mille tuolille paneutunut maata, otettiin se häneltä pois,
ja matot temmaistiin kursailematta hänen poloisen takalistonsa alta,
joka omassa kodissaan ei enää tiennyt mihin asettua.

Sanokaamme hänen kunniakseen, että hän alussa oli koettanut


tehdä vastarintaa. Heti kun oli kajottu siirtämään vesisäiliötä, oli hän
alkanut vimmatun haukunnan vihollista vastaan. Mutta kukaan ei
ollut piitannut kuulla hänen kutsuaan. Hän ei tuntenut saavansa
mitään rohkaisua, päinvastoin häntä aivan ilmeisesti painostettiin
alas. Zoé neiti oli hänelle sanonut hyvin epäsuopeasti:
— Ole nyt hiljaa!

Ja neiti Pauline oli lisännyt:

— Riquet, sinä olet hassu!

Silloin hän luopui antamasta hyödyttömiä merkkejä ja


taistelemasta yksinään yhteisen hyvän puolesta. Hän suri
hiljaisuudessa talon hävitystä ja muutti turhaan huoneesta
huoneeseen saadakseen rahtusen rauhaa. Kun muuttomiehet tulla
tömistivät siihen huoneeseen, mihin hän oli paennut, kätkeytyi hän
vikkelästi jonkun pöydän tai pesukaapin alle, joka vielä oli
paikoillaan. Mutta tämä varovaisuus oli hänelle pikemmin vahingoksi
kuin hyödyksi, sillä heti kohta alkoi huonekalu huojua hänen
päällään, nousi kohoksi, jysähti taas permantoon ja uhkasi musertaa
hänet alleen. Hän pakeni pyöräpäisenä ja karvat pystyssä ja pääsi
toiseen suojapaikkaan, joka ei ollut edellistä turvallisempi.

Mutta nämä kiusat, jopa suorastaan vaaratkin olivat vähäpätöisiä


hänen sisäisiin tuskiinsa verraten. Sielullisesti näet, kuten sanotaan,
hänen kärsimyksensä olivat suurimmat.

Talon huonekalut eivät olleet hänen silmissään elottomia esineitä,


vaan eläviä, hyvänsuopia olentoja, lempeitä haltiahenkiä, joiden
poislähtö ennusti hirmuisia onnettomuuksia. Lautaset, sokerirasiat,
paistinpannut ja kastrullit, kaikki kyökin jumaluudet; nojatuolit, matot,
tyynyt, kaikki kotilieden suojelushaltiat, sen huone- ja kotijumalat —
kaikki olivat tiessään. Hän ei saattanut uskoa, että niin suuri häviö
koskaan voisi tulla korvatuksi. Ja hän tunsi siitä niin suurta surua,
kuin hänen sielu-pahaansa vain mahtui. Onneksi se samoinkuin
ihmissielukin helposti takertui muuhun ja unohti pian huolet.
Sillävälin kuin janoiset muuttomiehet pitivät pitkiä väliaikojaan,
pölähytti Anqueliquen luuta lentoon permannosta ammoisen tomun,
ja Riquet vainusi hiiren hajua tai seurasi silmillään pakenevaa
hämähäkkiä, ja hänen häilähtelevä ajatuksensa ilahtui siitä tuokioksi.
Mutta pian hän taas vaipui takaisin mielihaikeaansa.

Lähtöpäivänä, nähdessään asiaintilan pahenevan hetki hetkeltä,


hän tyrmistyi epätoivoon. Vielä kolkommalta kuin muu tuntui
hänestä, kun ladottiin liinavaatteita suuriin, pimeihin
tavaralaatikoihin. Iloisella kiireellä sulloi Pauline pukujaan
matkavasuun. Riquet kääntyi pois hänestä, ikäänkuin olisi nähnyt
hänet missä pahanteossa. Ja hykistyen seinäviereen hän ajatteli:
"Tuo oli pahinta! Nyt on kaikki lopussa!" Ja joko hän luuli lakkaavan
olemasta sen mitä hän ei enää nähnyt tai tahtoi vain karttaa
tuskallista näkyä, niin hän laittoihe siten, ettei hänen tarvinnut katsoa
Paulineen päin.

Mutta liikkuessaan edes takaisin Pauline osui huomaamaan


Riquet'n allapäisen asennon. Se näytti hänestä kovin
hassunkuriselta ja hän purskahti nauramaan. Ja naurunsa seasta
hän huusi:

— Tule tänne, Riquet!

Mutta Riquet ei hievahtanut nurkastaan eikä kääntänyt päätään.


Hänellä ei ollut tällä hetkellä halua hyväillä nuorta emäntäänsä, ja
jokin salainen vaisto, jokin aavistus mielessään hän pelkäsi lähestyä
avoimena ammottavaa vaatevasua.

Pauline toisti kutsunsa moneen kertaan. Ja kun Riquet ei totellut,


meni hän ja otti hänet syliinsä.
— Voi toki pikku poloista! sanoi hän. Kuinka sitä käy sääliksi!

Hänen äänensä oli ivallinen. Riquet ei ymmärtänyt ivaa. Hän pysyi


liikkumattomana ja apeana Paulinen sylissä eikä ollut mitään
näkevinään eikä kuulevinaan.

— Riquet, katso minuun!

Kolmesti hän komensi sitä ja kolmesti turhaan. Silloin hän oli kovin
suuttuvinaan ja heitti hänet vaatevasuun:

— Ole siellä, tuhma elukka!

Ja hän kimmahutti kannen kiinni. Samassa tuokiossa hän kuuli


tätinsä kutsuvan ja poistui huoneesta jättäen Riquet'n vasuun.

Siellä vanki tunsi mielensä kovin levottomaksi. Hänen ei


pälähtänyt päähänsäkään, että hänet oli paiskattu arkkuun vain
leikillä ja kujetta tehden. Otaksuen asemansa jo ilmankin kyllin
arveluttavaksi hän koetti olla pahentamatta sitä millään
varomattomuudella. Ja hän oli hetkisen liikkumattomana, henkeä
vetämättä.

Sitten hän arveli hyödylliseksi tutkia pimeän vankilansa laatua.


Hän tunnusteli käpälillään hameita ja paitoja, joiden sekaan hänet oli
niin surkeasti paiskattu ja hän etsi, eikö olisi mitään pääsyaukkoa
tästä kamalasta paikasta. Hän oli puhkunut tässä toimessa pari
kolme minuuttia, kun herra Bergeret kutsui häntä lähdössä ulos:

— Tänne, Riquet, tänne! Mennään kävelemään rantakaduille.


Siellä on todellakin ihanaa. Sinne on rakennettu asemakartano,
suurenmoisen muodoton ja perikuvallisen ruma. Rakennustaide on
ollutta ja mennyttä. Revitään talo, joka muodosti Bac-kadun kulman
ja joka oli kaunis. Ja sijalle kohoo tietysti joku kamala
rakennuspelätin. Kunpa toki arkkitehtimme eivät toisi Quai
d'Orsay'lle tuota raakalaistyyliä, josta Washington-kadun kulma ja
Avenue des Champs Elysées jo antavat kammottavan esimerkin!…
Tule, Riquet!… Mennään kävelemään rantakaduille. Siellä on todella
ihanaa. Rakennustaide on tosiaankin rappeutunut Gabrielin ja Luis'n
ajoista… Mutta missä on koira?… Riquet! Riquet!…

Herra Bergeret'n ääni vahvisti Riquet'n mieltä suuresti. Hän


vastasi käpäläinsä rapinalla, jotka vimmatusti raapivat vaatevasun
pajukudosta.

— Missä koira on? kysyi herra Bergeret Paulinelta, joka tuli


takaisin latomus liinavaatteita käsivarrellaan.

— Vaatevasussa, isä.

— Kuinka se on sinne tullut? Ja mitä varten se on siellä? kysyi


herra
Bergeret.

— Siksi että se oli tuhma, vastasi Pauline.

Herra Bergeret vapautti ystävänsä. Riquet seurasi häntä etehiseen


asti liehien hännällään. Silloin välähti eräs ajatus hänen aivoihinsa.
Hän palasi huoneistoon, juoksi Paulinea kohti ja kurottui pystyyn
nuoren tytön hameen nojaan. Ja vasta sittenkuin hän oli hillittömästi
sitä syleillyt jumaloimisensa merkiksi, hän tavoitti taas isäntänsä
portaissa. Hän olisi luullut lyöneensä laimin sekä viisauden että
uskonnon vaatimukset, ellei hän olisi täten osoittanut rakkauttaan
henkilölle, jonka mahti oli syössyt hänet syvään juurivasuun.
Kadulla herra Bergeret ja hänen koiransa näkivät murheellisen
näyn: omat huonekalunsa rivissä katukäytävällä.

Sill'aikaa kuin muuttomiehet olivat poikenneet kastamaan kaulaa


pieneen kadunkulma-kapakkaan, kuvasteli Zoé neidin pukupeili
ohikulkijoita, työmiehiä, taideakatemian oppilaita, nuoria tyttösiä,
kauppiaita, ajurinrattaita, vaunuja ja tavaravankkureita ja
apteekkipuotia lasisäiliöineen ja eskulaapinkäärmeineen.
Katupylvääseen nojaten hymyili herra Bergeret vanhempi
kehyksissään leppeä sävy hienon kalpeilla kasvoilla ja hiukset
taaksekammattuina. Herra Bergeret katseli isäänsä kunnioittavalla
hellyydellä ja veti hänet syrjemmäksi pylväästä. Samoin hän asetti
suojempaan Zoén pienen jalustapöydän, joka näytti häpeävän sitä
että oli joutunut kadulle.

Mutta Riquet hieroi käpäliään isäntänsä jalkoihin ja loi häneen


kauniit, surulliset silmänsä. Ja se katse sanoi:

Oi isäntäni, sinä, joka olit vast'ikään niin rikas ja niin mahtava,


olisitko sinä tullut köyhäksi? Olisitko sinä tullut heikoksi? Sinä annat
ilkeihin ryysyihin puettujen miesten tunkeutua vierashuoneeseesi,
makuukammioosi, ruokasaliisi, kolahutella vammoja huonekaluihisi
ja raahata ne pois, raahata alas portaita sinun syvän nojatuolisi,
sinun ja minun, nojatuolin, jossa me lepäsimme joka ilta ja hyvin
usein aamupäivällä, sinä ja minä vieretysten. Minä olen kuullut sen
voihkivan huonopukuisten miesten käsissä, tuon nojatuolin, joka on
suuri haltia ja ystävällinen suojelushenki. Sinä et vastustanut noita
anastajia. Jos sinulla ei ole enää ainoatakaan noista kotijumalista,
jotka täyttivät sinun asuntosi, jos olet kadottanut yksin nuokin pikku
jumalolennot, jotka aamusin vuoteesta noustessasi puit jalkaasi, nuo
tohvelit, joita minä monesti leikillä olen pureskellut, jos sinä olet
joutunut puutteeseen ja kurjuuteen, rakas isäntäni, niin kuinka käy
silloin minun?
RIQUETN AJATUKSIA

Ihmiset, eläimet ja kivet kasvavat, mitä likemmäksi tulevat, ja käyvät


suunnattoman suuriksi, kun ovat aivan edessäni. Niin en tee minä.
Minä pysyn aina yhtä suurena, missä olenkin.

II

Kun isäntä ojentaa minulle pöydän alle ruokapalan, jonka hän aikoo
pistää suuhunsa, tekee hän sen kiusatakseen minua ja
rangaistakseen, jos lankean kiusaukseen. Sillä en saata uskoa, että
hän luopuisi omastaan minun tähteni.

III

Koirien haju on suloinen.

IV
Minun isäntäni pitää minut lämpöisenä, kun makaan hänen selkänsä
takana nojatuolissa. Se johtuu siitä että hän on jumala. Myöskin
uunin edessä on lämmin kivilaatta. Se laatta on jumalallinen.

Minä puhun milloin tahdon. Isäntäni suusta lähtee myös ääniä, jotka
muodostavat lauseita. Mutta ne eivät ole läheskään yhtä selviä kuin
ne, mitä minä ilmaisen puheeni äänillä. Minun suussani on kaikella
järjellinen ajatuksensa. Isännän suussa on paljon vain tyhjää ääntä.
On vaikeaa, mutta välttämätöntä arvata isännän ajatukset.

VI

Syöminen on hyvää. Olla syönyt on vielä parempi. Sillä vihollinen,


joka väijyy siepatakseen ruokasi, on nopea ja kavala.

VII

Kaikki katoo ja seuraa toinen toistaan. Minä yksin olen pysyväinen.

VIII

Minä olen aina kaiken keskustassa, ja ihmiset, eläimet ja esineet,


olivatpa ne vihamielisiä tai suosiollisia, ovat piirissä ympärilläni.

IX
Unessa näkee ihmisiä, koiria, taloja, puita, mieluisia olentoja ja
kammottavia olentoja. Mutta kun herää, ovat nämä olennot
kadonneet.

Mietelmä. Minä rakastan isäntääni Bergeret'ä, sillä hän on väkevä ja


peljättävä.

XI

Teko, josta on piesty, on paha teko. Teko, josta on saatu hyväilyjä tai
ruokaa, on hyvä teko.

XII

Yön tullessa liikkuu pahoja voimia talon ympärillä. Minä haukun, jotta
isäntä olisi varuillaan ja karkoittaisi ne.

XIII

Rukous. Oi isäntäni Bergeret, verisen lihan jumala, minä kumarran


sinua. Sinä peljättävä, ollos ylistetty! Ollos ylistetty, sinä laupias!
Minä ryömin jaloissasi; minä nuolen käsiäsi. Sinä olet suuri ja
sangen ihana, koska sinä katetun pöydän ääressä ahmit runsaita
liharuokia. Sinä olet suuri ja sangen ihana, koska sinä pikkuruisella
puutikulla saat valkean leimahtamaan ja muutat yön päiväksi. Pidä
minut huoneessasi ja sulje kaikki muut koirat sieltä pois. Ja sinä,
Angelique keittäjätär, sinä hyvä ja suuri jumalatar, minä pelkään ja
rakastan sinua, ettäs antaisit minulle paljon syödä.
XIV

Koira, jolla ei ole kunnioitusta ihmisiä kohtaan ja joka ylenkatsoo


isäntänsä huoneessa olevia kotijumalia, viettää harhailevaa ja kurjaa
elämää.

XV

Eräänä päivänä kulki rikkinäinen vesikannu, salin läpi kastellen


kiilloitetun permannon. Luulen, että epäsiisti kannu sai siitä vitsaa.

XVI

Ihmisillä on jumalallinen voima avata kaikki ovet. Minä voin avata


ainoastaan, muutamia. Ovet ovat mahtavia jumaluuksia, jotka eivät
mielellään tottele koiria.

XVII

Koiran elämä on täynnä vaaroja, ja kärsimyksen välttämiseksi täytyy


alati valvoa, syödessään, jopa nukkuessaankin.

XVIII

Ei koskaan tiedä, onko käyttäytynyt oikein ihmisiä kohtaan. Heitä


tulee kunnioittaa koettamatta ymmärtää heitä. Heidän viisautensa on
salaperäinen.

XIX
Avuksihuuto. Oi Pelko, suurivaltainen ja äidillinen Pelko, pyhä ja
terveellinen Pelko, astu minun sieluuni, täytä minut vaarassa, jotta
välttäisin sen, joka minua vahingoittaa taitaisi, ja jotta en, karatessani
vihollisen kimppuun, joutuisi kärsimään uhkamielisyydestäni.

XX

On olemassa vaunuja, joita hevoset vetävät kaduilla. Ne ovat


kammottavia. On myös vaunuja, jotka kulkevat itsestään kovasti
puuskuttaen. Nekin ovat kovin vihamielisiä. Repaleisia ihmisiä ei tule
sietää eikä niitä, jotka kantavat tavaravasuja päälaellaan tai
työntävät tynnyreitä. Minä en pidä lapsista, jotka tavoitellen ja paeten
toisiaan juoksentelevat kaduilla ja kirkuvat täyttä kurkkua. Maailma
on täynnä vihamielisiä ja peljättäviä seikkoja.
VANHURSKAAT TUOMARIT

Näin kerran, sanoi Jean Marteau, vanhurskaita tuomareita. Näin ne


eräässä taulussa. Olin matkustanut Belgiaan päästäkseni
muutamasta uteliaasta virkamiehestä, joka oli pannut päähänsä että
minä olin sekaantunut anarkistien vehkeisiin.

En tuntenut rikostovereitani eivätkä rikostoverini tunteneet minua.


Se ei tuottanut mitään pulmaa tuolle viranomaiselle. Ei mikään
saattanut häntä hämminkiin. Hän tutki yhtä myötään eikä tullut hullua
hurskaammaksi. Hänen virkavimmansa tuntui minusta kamalalta.
Matkustin siis Belgiaan ja asetuin Antwerpeniin, missä sain paikan
maustekaupan apulaisena. Eräänä sunnuntaina minä näin kaksi
vanhurskasta tuomaria muutamassa Mabusen taulussa,
taulumuseossa. Ne kuuluvat rotuun, joka on kuollut sukupuuttoon.
Tahtoisin sanoa, että ne ovat kiertäviä tuomareita, jotka taivaltavat
virkuillaan hiljaisessa hölkässä. Asemiehiä, keihäät ja pertuskat
olalla, astuu heidän saattonaan. Näillä molemmilla pitkätukkaisilla ja
-partaisilla tuomareilla on, kuten vanhojen flamilaisten raamattujen
kuninkailla, merkillinen ja muhkean näköinen päähine, puoleksi
yömyssyyn, puoleksi diadeemiin vivahtava. Heidän kirjosilkkiset
viittansa ovat kudotut kukkia täyteen. Vanha mestari on osannut
antaa heille vakavan, tyynen ja lempeän ilmeen. Hevoset ovat
säveät ja tasaiset kuten itse isännätkin.

Kuitenkaan ei heillä, näillä tuomareilla, ole sama luonne eikä sama


katsantokanta. Sen huomaa heti. Toinen pitää kädessään paperia ja
viittaa sormellaan tekstiin. Toinen taas, vasen käsi satulanastan
varassa, kohottaa oikeaa enemmän hyväntahtoisesti kuin arvoansa
ajatellen. On kuin hänellä olisi peukalon ja etusormen välissä
hyppysellinen hyvin hienoa pölyä. Ja tämä huolekkaan käden liike
osoittaa viisautta ja terävä-älyisyyttä. He ovat vanhurskaita
molemmat, mutta ilmeisesti toinen pitää kiinni kirjaimesta, toinen
hengestä.

Nojaten kaiteeseen, joka erottaa heidät yleisöstä, minä kuuntelin


heidän puhettaan. Ensimäinen tuomari sanoi:

— Minä pysyn siinä, mikä on kirjoitettu. Ensimäinen laki kirjoitettiin


kiveen, merkiksi että se oli kestävä yhtä kauan kuin maailma.

Toinen tuomari vastasi:

— Jokainen kirjoitettu laki on jo vanhettunut. Sillä kirjoittajan käsi


on hidas, mutta ihmisten mieli on liikkuva ja heidän kohtalonsa
muuttuvainen.

Ja molemmat kunnon vanhukset jatkoivat miettehikästä


keskusteluaan:

Ensimäinen tuomari: Laki on pysyväinen.

Toinen tuomari: Laki ei ole hetkeäkään vakiutunut.

Ensimäinen tuomari: Jumalasta lähteneenä se on järkkymätön.


Toinen tuomari: Yhteiskunnallisen elämän luonnollisena tuloksena
se on riippuvainen tämän elämän vaihtelevista ehdoista.

Ensimäinen tuomari: Se on Jumalan tahto, joka ei koskaan muutu.

Toinen tuomari: Se on ihmisten tahto, joka muuttuu lakkaamatta.

Ensimäinen tuomari: Se oli olemassa ennen ihmistä ja on häntä


ylempi.

Toinen tuomari: Se on alkuisin ihmisestä, on vajavainen kuten


hänkin, mutta saattaa myös täydellistyä kuten hän.

Ensimäinen tuomari: Tuomari, avaa kirjasi ja lue mitä on kirjoitettu!


Sillä Jumala itse on julistanut lain niille, jotka uskoivat häneen: Sic
locutus est patribus nostris, Abraham et semini eius in sæcula.

Toinen tuomari: Sen mitä kuolleet ovat kirjoittaneet, pyyhkivät


elävät pois, sillä muutoin niiden tahto, joita ei enää ole olemassa,
kahlehtisi niitä, jotka vielä elävät. Ja silloinhan kuolleet olisivatkin
eläviä ja elävät kuolleita.

Ensimäinen tuomari: Elävien tulee totella kuolleitten säätämiä


lakeja. Jumalan edessä ovat elävät ja kuolleet samanaikaisia. Moses
ja Cyrus, Caesar, Justinianus ja Saksan keisari hallitsevat meitä yhä
vielä. Sillä me kaikki olemme heidän aikalaisiaan Iankaikkisen
edessä.

Toinen tuomari: Elävien tulee saada lakinsa eläviltä. Opastamaan


meille mikä on sallittua mikä kiellettyä eivät Zoroaster ja Numa
Pompilius vedä vertoja rajasuutarille Sainte-Gudule kirkon vieressä.
Ensimäinen tuomari: Ensimäiset lait ilmoitti meille Kaikkiviisaus.
Mitä lähempänä tätä alkulähdettä, sitä parempi laki.

Toinen tuomari: Etkö näe, että joka päivä tehdään uusia ja että
asetukset ja lakikirjat ovat erilaisia eri aikoina ja eri maissa?

Ensimäinen tuomari: Uudet lait lähtevät vanhoista. Ne ovat nuoria


vesoja samasta rungosta, joita sama mahla ravitsee.

Toinen tuomari: Lakien vanhasta puusta tihkuu karvas mehu.


Lakkaamatta käydään siihen käsiksi kirveen terin.

Ensimäinen tuomari: Tuomarin ei ole tutkiminen ovatko lait oikeat,


koska ne välttämättömästi ovat oikeat. Hänen on vain käyttäminen
niitä oikein.

Toinen tuomari: Meidän on tutkiminen, onko laki, jota


sovellutamme käytäntöön, oikea vaiko ei, sillä jos olemme
havainneet sen epäoikeaksi, voimme saattaa jotakin lievennystä
siihen käytäntöön, mihin meidän on pakko sitä sovelluttaa.

Ensimäinen tuomari: Lakien arvosteleminen ei sovi siihen


kunnioitukseen, mitä meidän on niille osoittaminen.

Toinen tuomari: Ellemme käsitä niiden kovuutta, kuinka voimme


silloin niitä lieventää?

Ensimäinen tuomari: Me olemme tuomareita, emmekä lainsäätäjiä


ja filosofeja.

Toinen tuomari: Me olemme ihmisiä.


Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebooknice.com

You might also like