DB2 Refresher: by Parvathavardhini Sathya
DB2 Refresher: by Parvathavardhini Sathya
DB2 Refresher: by Parvathavardhini Sathya
By Parvathavardhini Sathya
What is a Database?
Database
Page 2
What is a Database?
Data are binary computer representations of stored logical entities. Relationships represent a correspondence between the various data elements. Constraints are predicates that define correct database states The schema describes the organization of data and relationships within the database.
Page 3
Collection of interrelated data Set of programs to access the data DBMS contains information about a particular enterprise DBMS provides an environment that is both convenient and efficient to use. Database Applications: Banking: all transactions Airlines: reservations, schedules Universities: registration, grades Sales: customers, products, purchases Manufacturing: production, inventory, orders, supply chain Human resources: employee records, salaries, tax deductions Databases touch all aspects of our lives
Page 4
Page 5
Page 7
Page 8
In the early days, database applications were built on top of file systems Drawbacks of using file systems to store data: Data redundancy and inconsistency Multiple file formats, duplication of information in different files Difficulty in accessing data Need to write a new program to carry out each new task Data isolation multiple files and formats Integrity problems Integrity constraints (e.g. account balance > 0) become part of program code Hard to add new constraints or change existing ones
Page 9
Drawbacks of using file systems (cont.) Atomicity of updates Failures may leave database in an inconsistent state with partial updates carried out E.g. transfer of funds from one account to another should either complete or not happen at all Concurrent access by multiple users Concurrent accessed needed for performance Uncontrolled concurrent accesses can lead to inconsistencies E.g. two people reading a balance and updating it at the same time Security problems Database systems offer solutions to all the above problems
Page 10
Data Models
A collection of tools for describing data data relationships data semantics data constraints Hierarchical model Network model Entity-Relationship model Relational model Object-oriented model
Page 11
A Hierarchical Structure
Page 12
Basic Structure Collection of records logically organized to conform to the upside-down tree (hierarchical) structure. The top layer is perceived as the parent of the segment directly beneath it. The segments below other segments are the children of the segment above them. A tree structure is represented as a hierarchical path on the computers storage media.
Page 13
Hierarchical Database Model Advantages Conceptual simplicity Database security Data independence Database integrity Efficiency dealing with a large database
Disadvantages
Complex implementation Difficult to manage Lacks structural independence Applications programming and use complexity Implementation limitations Lack of standards
Page 14
Page 15
Basic Structure
Set -- A relationship is called a set. Each set is composed of at least two record types: an owner (parent) record and a member (child) record. A set is represents a 1:M relationship between the owner and the member.
Page 16
Page 17
Network Database Model Advantages Conceptual simplicity Handles more relationship types Data access flexibility Promotes database integrity Data independence Conformance to standards
Disadvantages
System complexity Lack of structural independence
Page 18
Database
A database consists of multiple relations Information about an enterprise is broken up into parts, with each relation storing one part of the information E.g.: account : stores information about accounts depositor : stores information about which customer owns which account customer : stores information about customers Storing all information as a single relation such as bank(account-number, balance, customer-name, ..) results in * repetition of information (e.g. two customers own an account)
Page 19
Relational Model
The relational model uses tables to organize data elements Each table corresponds to an application entity and each row represents an instance of that entity Relationships link rows from two tables by embedding row identifiers (keys) from one table as attribute values in the other table Structured Query Language (SQL) serves as a uniform interface for users providing a collection of standard expressions for storing and retrieving data.
Page 20
RDBMS Terminology
The relational model, is an abstract theory of data that is based on the mathematical theory whose principles were laid down by Dr.E.F.Codd. The following table gives a list of the relational term and their corresponding informal equivalent(s).
Formal Relational term Relation Tuple Cardinality Attribute Degree Primary key Domain Informal Equivalent(s) Table Row record Number of rows Column field Number of columns Unique identifier Set of legal values
Page 21
RDBMS
The Relational Database Management Systems, as said above, are based on the relational model. The relational model, in turn, is a way of looking at data which is, it is a prescription for how to represent and manipulate data Relational model is concerned with three aspects of data: data structure, data integrity and data manipulation.
Page 22
Page 23
Normalization Defined
In relational database design, the process of organizing data to minimize duplication. Normalization usually involves dividing a database into two or more tables and defining relationships between the tables. The objective is to isolate data so that additions, deletions, and modifications of a field can be made in just one table and then propagated through the rest of the database via the defined relationships.
Page 24
Normalization ..
2)
Lossless join decomposition: For any legal relation r, if we decompose r and then ``recompose'' r, we get what we started with - no more and no less. Dependency Preservation: Ensures that all functional dependencies are represented in some of the individual resulting relations.
Page 25
Why Normalize?
Flexibility Structure supports many ways to look at the data. Data Integrity & Consistency Deletion Insertion Update Efficiency Eliminate redundant data and save space.
Page 26
Want to keep tables simple so user can make their own queries Avoid processing multiple tables Testing shows Normalization has poorer performance on retrieval.
Page 27
DB2 Objects
Tables
All data in a DB2 database is presented in tables collections of rows all having the same columns. A table that holds persistent user data is a base table. A table that stores data temporarily is a temporary table. Table name and column names are unique for owner and table respectively. A Table can have alternate name.
Page 29
Index
Index is used to : Locate the row(s) that contain a given value. Gain efficient and faster direct access to data. Index is based on one or more columns of a table.
Page 30
Index structure
Page 31
Index contd
Multiple indexes can be defined on a table. A table having a primary key will necessarily have a primary unique index. DB2 decides whether or not to use any index to access the table data - when and how to use.
Page 32
Views
CREATE VIEW MYVIEW AS SELECT DEPTNO,DEPTNAME,MGRNO FROM DEPT; SELECT * FROM MYVIEW;
Page 33
Alternate names for a table Aliases are used by other users , synonyms can be used only by creators CREATE ALIAS A1 FOR T1
Page 34
Structured Query Language (SQL) is the standard command set used to communicate with the relational database management systems. All tasks related to relational data management creating tables, querying the database for information, modifying the data in the database, deleting them, granting access to users, and so on can be done using SQL Different database vendors use different dialects of SQL Implementation of the advanced features of SQL differs from vendor to vendor, but here also the concepts are the same
Page 36
Data Definition Language (DDL) Data Manipulation Language (DML) Data Query Language Transaction/Data control language (TCL/DCL)
Page 37
Page 38
Create command is used to create a table in the database Syntax.. Create table <table-name> (filed-name data-type, ..) ; Eg: Create table emp (eno char(4), ename varchar(10), salary number(10,2), dob date);
Page 39
Alter command is used to modify the structure of the table in the database
Modes Add, Modify Add Adds a new column to the table Modify Modifies the field defined in the table
Page 40
Syntax : Alter table <table-name> add/modify (field-name, data-type,..) Eg: Alter table emp add (Address varchar(25)); Alter table emp modify (ename varchar(25));
Page 41
Drop command is used to remove the structure and the data of a table from the database. Syntax : Drop table <table-name>; Eg: Drop table emp;
Page 42
Page 43
Page 44
BASIC DB2 DATA TYPES CHAR SMALLINT INTEGER DECIMAL DATE (YYYY-MM-DD) TIME (HH.MM.SS) TIMESTAMP yyyy-mm-ddhh.mm.ss.mmmmmm 10 10 10 10 10 10 10
COBOL DEFINITION PIC X(20) PIC S9(4) COMP PIC S9(9) COMP PIC S9(7) V99 COMP - 3 PIC X(10) PIC X(8) PIC X(26)
Page 45
These commands are used to perform changes on those data stored in the database.
Page 46
Insert command is used to insert data into a table Insert into emp values (E001, Nishi, 25000.00, 12-May1978); Insert into emp (eno, ename) values (E002, Yashwanth);
Page 47
Update command is used to perform changes on the data stored in the database Update emp set salary = 30000.00 Update emp set commission = salary+salary*10/100 Update emp set salary = salary+5000 where grade=5; WHERE clause is used to enforce logical conditions
Page 48
Delete command is used to remove unwanted data stored in the database Delete from emp; Delete emp; Delete from emp where eno=E001; WHERE clause is used to enforce logical conditions
Page 49
SELECT statement is used to query data from the table in the database. It has many different options that one can use to retrieve the data from the table.
WHERE clause is used to enforce conditions while retrieving the data. It is used to filter the unwanted data.
Page 51
Select eno, ename from emp where salary > 15000 and salary < 30000; Select eno, ename from emp where salary = 25000 or salary = 15000; Select eno, ename from emp where salary not > 5000;
Page 52
Select eno, ename where salary in {10000, 25000, 30000} Select eno, ename where salary between 20000 and 25000 Select eno, ename where ename like a%; (Wild card characters - % and _) NOT is used to inverse the output.
Page 53
Page 54
Meant for the Transaction manager Commit/Rollback of the updates Closes all the cursors (except those using WITH HOLD) All locks are released
Page 55
Grant and revoke privileges on objects to users Grants can have with GRANT option Revoking can be cascading
GRANT SELECT ON TABLE customer TO GROUP salesreps REVOKE ALL PRIVILEGES ON TABLE staff FROM USER jen
Page 56
Page 58
BIND PLAN
BIND PLAN accepts one or more DBRMs as input or one or more packages produced from previous BIND PACKAGE commands or combination of DBRMs and Packages. Output of BIND PLAN is the application plan containing the executable logic giving the access path to DB2 data. To execute the application plan, corresponding Load module should exist.
BINDPACKAGE
BIND PACKAGE accepts a DBRM as input and produces a SINGLE package. A package is not executable. Package must be bound into a plan before executing. Packages can be bound into an application plan using BINDPLAN command. BIND also performs: Syntax checking of SQL statements. Checks the DB2 table and column catalog information. Authorization Validation.
Page 59
What is a plan?
A plan is an executable module containing the access path logic produced by the DB2 optimizer. It can be composed of one or more DBRMs and packages. Before a DB2 for z/OS program (with static SQL) can be run, it must have a plan associated with it. Plans are created by the BIND command. The plan is stored in the DB2 directory and accessed when its program is run. Information about the plan is stored in the DB2 catalog.
Page 60
What is a package?
A package is a single, bound DBRM with optimized access paths. By using packages, the table access logic is "packaged" at a lower level of granularity than a plan -- at the package (or program) level. To execute a package, you first must include it in the package list of a plan. Packages are not directly executed, they are only indirectly executed when the plan in which they are contained executes -- as discussed previously, UDFs and triggers are exceptions to this rule. A plan can consist of one or more DBRMs, one or more packages or, a combination of packages and DBRMs.
Page 61
Package &Plan
PLAN
Page 62
Bind Parameters
ACQUIRE : Whether resources are acquired when first accessed, or when the plan is allocated. (USE) : Open table spaces and acquire locks only as they are used. (ALLOCATE): Open all table spaces and acquire all table and table space locks when the plan is allocated. In this case, RELEASE(DEALLOCATE) must also be added.
Page 63
Bind Parameters ISOLATION : To what extent a program bound to this package can be isolated from the effects of other programs that are running. (RR) Repeatable Read: Database values read or changed by this package cannot be changed by other programs until this application commits or terminates. (CS) Cursor Stability : Database values read by this package are protected only while being used. (UR) Uncomitted Read (RS) Read stability
Page 64
Bind Parameters
VALIDATE : How to handle "object not found" and "not authorized" errors. (RUN) : If all objects exist and all privileges are held, make no check at execution time If not, bind the plan and check for authorization And existence at Run time (BIND): If an object does not exist or a privilege is not held, produce a message
Page 65
Embedded SQL
Page 66
Host Variable
The definitions of the field that can be used to receive the data from DB2 or pass data to DB2. EXEC SQL FETCH CUSTCURS INTO : FNAME, END EXEC.
Page 67
Host structures
Table CUSTINFO : CUSTNO CHAR(6) NOT NULL, FNAME CHAR(20) NOT NULL, LNAME CHAR(30) NOT NULL, ADDR CHAR(30) NOT NULL Host structure: 01CUSTOMER ROW. 10 CUSTNO PIC X(6). 10 FNAME PIC X(20). 10 LNAME PIC X(30). 10 ADDR PIC X(30).
Page 68
Host structure
SELECT * FROM CUSTINFO INTO : CUSTOMER ROW Advisable to use individual host variables rather than Host structures
Page 69
Null Indicators
Not supplying an indicator variable for a column in the SQL statement and accessing a row with a null value in the column the SQL return code is 305 Indicator variable is required for NULL data in the host language DCLGEN does not automatically define indicator variables. 05 IND-VAR PIC S9(4) COMP SELECT NOTES INTO :NOTES :IND-VAR FROM T1 WHERE CUSTNO = :CUSTNO
Page 70
Null Indicators
After a program issues a SELECT or FETCH statement DB2 sets the value of the indicator variable to 1 if the corresponding values is NULL. DB2 does not return anything into the primary host variable for the column and the programmer should ignore its contents If the value in the column is not NULL, then the indicator variable has the value 0 The value is -2 if there are any data conversion errors If DB2 has to truncate the value it returns to fit into the host variable, it reports the original length of the value in the indicator variable with the positive value.
Page 71
SQLCA
EXEC SQL INCLUDE SQLCA END EXEC. 01SQLCA 05 SQLCAID PIC X(8). 05 SQLCABC PIC S9 (9) COMP-4. 05 SQLCODE PIC S9 (9) COMP-4. 05 SQLERRM. 49 SQLERRML PIC S9(4) COMP-4. 49 SQLERRMC PIC X (70). 05 SQLERRP PIC X (8). 05 SQLERRD OCCURS 6 TIMES PIC S9(9) COMP-4. 05 SQLWARN. 10 SQLWARN0 PIC X.
Page 72
SQLCA
SQL WARN0 Contains W if any other SQLWARN field is set to w SQLWARN1 Contains W if a character column is truncated when it is assigned to a host variable by the SQL statement SQLWARN3 Contains W when the number of columns retrieved does not match the number of fields in the host variable structure into which they are being selected.
Page 73
SQLCA
SQLWARN4 Contains W when the SQL statement was an update or delete without a where clause. SQLWARN6 Contains W when a date or timestamp conversion is performed during date arithmetic. For e.g.., If 4 months are added to 1992-01-31, this results in 1992-04-31. But April does not have 31 days, so the results would be converted to 1992-04-30.
Page 74
DCLGEN
The DB2 equivalent to a record description in a host structure. Host structure is a COBOL group item that contains host variables used to store data for the table's columns. DCLGEN output stored as a member of PDS can be included in the COBOL program . DCLGEN output also includes SQL declare table statement that names the columns the table contains. Automatically created.
Page 75
DCLGEN
EXEC SQL DECLARE MMADBV.CUST TABLE ( CUSTNO CHAR(6) NOT NULL, FNAME CHAR(20) NOT NULL, LNAME CHAR(30) NOT NULL, ADDR CHAR(30) NOT NULL )END - EXEC. COBOL DECLARATION FOR TABLE MMADBV.CUST 01 CUSTOMER ROW. 10 CUSTNO PIC X(6). 10 FNAME PIC X(20). 10 LNAME PIC X(30). 10 ADDR PIC X(30).
Page 76
Cursors
A pointer that identifies the current row in a result table STANDARD COBOL NO EQUIVALENT OPEN FILE NAME READ FILE NAME CLOSE FILE NAME
SQL STATEMENT DECLARE CURSOR OPEN CURSOR NAME FETCH COLUMN NAME CLOSE CURSOR- NAME
EXEC SQL DECLARE CUSTCURS CURSOR FOR SELECT FNAME, LNAME FROM MMADBV.CUST WHERE STATE = CA END EXEC.
Page 77
Cursor Open
EXEC SQL OPEN CUSTCURS END EXEC Does not move values in to host variables
Page 78
Cursor - Fetch
SUSAN
CURSOR
ELAINE PAT
Page 79
EXEC SQL DECLARE C1 CURSOR .. FOR UPDATE OF FNAME,LNAME END-EXEC. EXEC SQL UPDATE T1 SET FNAME=:FNAME, LNAME=:LNAME WHERE CURRENT OF C1 END-EXEC.
Page 80
Join The capability to query data from multiple tables using a single SQL statement is known as a join. Example : SELECT E.EMPNO, E.LASTNAME, D.DEPTNAME FROM EMP E, DEPT D WHERE E.WORKDEPT = D.DEPTNO; An inner join will match the data based on the values of one or more columns in each table
Page 81
An outer join causes rows in one of the tables having no match in the other to appear in the result set. The missing column positions in the result set will contain nulls. This is necessary because sometimes the results will contain a value (when there is a match) and sometimes the results will not contain a value (when there is no match).
Three types of outer joins : Left outer join, Right outer join, Full outer join.
Page 82
Left Outer join SELECT EMP.EMPNO, EMP.LASTNAME, DEPT.DEPTNAME FROM EMP LEFT OUTER JOIN DEPT ON EMP.WORKDEPT = DEPT.DEPTNO; The keywords LEFT OUTER JOIN cause DB2 to invoke an outer join returning rows that have matching values in the predicate columns but also return unmatched rows from the table on the left side of the join FULL OUTER JOIN. It, like all previous outer joins, returns matching rows from both tables, but it also returns non-matching rows from both tables; left and right. A FULL OUTER JOIN can use only the equal (=) comparison operator
Page 83
Union
SELECT E.EMPNO, E.LASTNAME, D.DEPTNAME FROM EMP E, DEPT D WHERE E.WORKDEPT = D.DEPTNO UNION SELECT E.EMPNO, E.LASTNAME, '** NO DEPT NAME **' FROM EMP E WHERE NOT EXISTS (SELECT D.DEPTNAME FROM DEPT D WHERE E.WORKDEPT = D.DEPTNO);
Page 84
Subquery
A subquery is a SELECT statement within the WHERE or HAVING clause of an INSERT, UPDATE, MERGE, or DELETE SQL statement
Page 85
Non-correlated subqueries
Non-correlated subqueries do not refer to any tables or columns that are outside of the scope of the subquery. The following example query refers only to tables are within the scope of the FROM clause. SELECT * FROM DSN8910.EMP WHERE JOB = 'DESIGNER' AND WORKDEPT IN ( SELECT DEPTNO FROM DSN8910.PROJ WHERE MAJPROJ = 'MA2100');
Page 86
Correlated subqueries
Correlated subqueries contain a reference to a table or column that is outside of the scope of the subquery. In the following query, for example, the correlation name X is a value from a table that is not listed in the FROM clause of the subquery. The inclusion of X illustrates that the subquery references the outer query block: SELECT * FROM DSN8910.EMP X WHERE JOB = 'DESIGNER' AND EXISTS (SELECT 1 FROM DSN8910.PROJ WHERE DEPTNO = X.WORKDEPT AND MAJPROJ = 'MA2100');
Page 87
A correlated subquery is a subquery that is evaluated once for each row of the outer query. select category , articletitle , articlepubdate from articles zz where articlepubdate = ( select max(articlepubdate) from articles where category = zz.category )
Page 88
Follow these general guidelines: If efficient indexes are available on the tables in the subquery, then a correlated subquery is likely to be the most efficient kind of subquery. If no efficient indexes are available on the tables in the subquery, then a non-correlated subquery would be likely to perform better. If multiple subqueries are in any parent query, make sure that the subqueries are ordered in the most efficient manner. DB2 performs non-correlated subquery predicates before correlated subquery predicates
Page 89
CASE expression
A CASE expression allows an expression to be selected based on the evaluation of one or more conditions. In general, the value of the case-expression is the value of the result-expression following the first (leftmost) whenclause that evaluates to true. If no case evaluates to true and the ELSE keyword is present, the result is the value of the result-expression or NULL. If no case evaluates to true and the ELSE keyword is not present, the result is NULL
Page 90
Examples
SELECT EMPNO, LASTNAME, CASE SUBSTR(WORKDEPT,1,1) WHEN A THEN Administration WHEN B THEN Human Resources WHEN C THEN Design WHEN D THEN Operations END FROM EMPLOYEE;
Page 91
Examples
SELECT EMPNO, WORKDEPT, SALARY+COMM FROM EMPLOYEE WHERE (CASE WHEN SALARY=0 THEN 0 ELSE COMM/(SALARY+COMM) END) > 0.25;
Page 92
You can use a CASE expression to avoid "division by zero" errors in another way. The following queries show an accumulation or summing operation. In the first query, DB2 performs the division before performing the CASE statement and an error occurs along with the results. SELECT REF_ID,PAYMT_PAST_DUE_CT, CASE WHEN PAYMT_PAST_DUE_CT=0 THEN 0 WHEN PAYMT_PAST_DUE_CT>0 THEN SUM(BAL_AMT/PAYMT_PAST_DUE_CT) END FROM PAY_TABLE GROUP BY REF_ID,PAYMT_PAST_DUE_CT;
Page 93
However, if the CASE expression is included in the SUM aggregate function, the CASE expression would prevent the errors. In the following query, the CASE expression screens out the unwanted division because the CASE operation is performed before the division. SELECT REF_ID,PAYMT_PAST_DUE_CT, SUM(CASE WHEN PAYMT_PAST_DUE_CT=0 THEN 0 WHEN PAYMT_PAST_DUE_CT>0 THEN BAL_AMT/PAYMT_PAST_DUE_CT END) FROM PAY_TABLE GROUP BY REF_ID,PAYMT_PAST_DUE_CT;
Page 94
The following example shows how to group the results of a query by a CASE expression without having to re-type the expression. Using the sample employee table, find the maximum, minimum, and average salary. Instead of finding these values for each department, assume that you want to combine some departments into the same group.
Page 95
SELECT CASE_DEPT,MAX(SALARY),MIN(SALARY),AVG(SALARY ) FROM (SELECT SALARY, CASE WHEN WORKDEPT = 'A00' OR WORKDEPT = 'E21' THEN 'A00_E21' WHEN WORKDEPT = 'D11' OR WORKDEPT = 'E11' THEN 'D11_E11' ELSE WORKDEPT END AS CASE_DEPT FROM DSN8810.EMP) X GROUP BY CASE_DEPT;
Page 96
Concurrency
Concurrency is the ability of more than one application process to access the same data at essentially the same time Concurrency must be controlled to prevent lost updates and such possibly undesirable effects as unrepeatable reads and access to uncommitted data. Lost updates. Without concurrency control, two processes, A and B, might both read the same row from the database, and both calculate new values for one of its columns, based on what they read. If A updates the row with its new value, and then B updates the same row, A's update is lost.
Page 97
Access to uncommitted data. Also without concurrency control, process A might update a value in the database, and process B might read that value before it was committed. Then, if A's value is not later committed, but backed out, B's calculations are based on uncommitted (and presumably incorrect) data. Unrepeatable reads. Some processes require the following sequence of events: A reads a row from the database and then goes on to process other SQL requests. Later, A reads the first row again and must find the same values it read the first time. Without control, process B could have changed the row between the two read operations.
Page 98
Locks
What do locks do? A lock associates a DB2 resource with an application process in a way that affects how other processes can access the same resource. The process associated with the resource is said to "hold" or "own" the lock. DB2 uses locks to ensure that no process accesses data that has been changed, but not yet committed, by another process. What do you do about locks? To preserve data integrity, your application process acquires locks implicitly, that is, under DB2 control. It is not necessary for a process to request a lock explicitly to conceal uncommitted data. Therefore, sometimes you need not do anything about DB2 locks
Page 99
Locks
Page 100
Levels
DB2 supports locking at four levels, or granularities: tablespace, table, page, and row-level locking. Locks to enable the reading of data Locks to enable the updating of data Tablespace, Table Locks all other users of the table or TS Less overhead Page & Row - More users to use the table at the same time - Results in more lock overheads
Page 101
Modes
Shared Data is being read Other users can read the same data for select requests Exclusive Data is being changed No other users allowed to Insert, UPDATE, DELETE Select Shared mode Insert, Update , delete Exclusive mode
Page 102
Lock promotion
Definition: Lock promotion is the action of exchanging one lock on a resource for a more restrictive lock on the same resource, held by the same application process. Example: An application reads data, which requires an IS lock on a table space. Based on further calculation, the application updates the same data, which requires an IX lock on the table space. The application is said to promote the table space lock from mode IS to mode IX. Effects: When promoting the lock, DB2 first waits until any incompatible locks held by other processes are released. When locks are promoted, they are promoted in the direction of increasing control over resources: from IS to IX, S, or X; from IX to SIX or X; from S to X; from U to X; and from SIX to X.
Page 103
Lock escalation
Definition: Lock escalation is the act of releasing a large number of page, row or LOB locks, held by an application process on a single table or table space, to acquire a table or table space lock, or a set of partition locks, of mode S or X instead. When it occurs, DB2 issues message DSNI031I, which identifies the table space for which lock escalation occurred, and some information to help you identify what plan or package was running when the escalation occurred. Lock counts are always kept on a table or table space level. When it occurs: Lock escalation balances concurrency with performance by using page or row locks while a process accesses relatively few pages or rows, and then changing to table space, table, or partition locks when the process accesses many.
Page 104