Showing posts with label primary key. Show all posts
Showing posts with label primary key. Show all posts

Saturday, 17 August 2013

Db2 Relational Database Anatomy: Tables, Rows, Columns, Keys, and Views

Relational database anatomy diagram showing a customer table, rows, columns, primary key, view, and SQL result
Tables give SQL a structure to query.

A COBOL program does not read a Db2 table by track number or page location. It issues SQL against a logical structure: tables, rows, columns, keys, relationships, and views. That separation is one reason a Db2 application can keep working even when storage, indexes, or access paths change underneath it.

This refresh explains the anatomy of a relational database from a Db2 application developer's point of view. The focus is not catalog administration. The focus is the structure a COBOL or SQL developer needs to understand before writing SELECT, INSERT, UPDATE, DELETE, and cursor logic.

What Relational Database Anatomy Means

A relational database stores data in tables. A table has rows and columns. Keys identify rows, foreign keys connect tables, and views present selected data from one or more base tables.

Db2 uses that logical model while the engine handles physical storage, access paths, locking, logging, and recovery. A developer usually works with the logical model first.

Tables Represent One Subject

A table should represent one subject, such as a customer, account, policy, claim, employee, transaction, or order. Mixing subjects in one table makes SQL harder to read and makes update rules harder to control.

CREATE TABLE CUSTOMER
 (CUST_NO     CHAR(10)     NOT NULL,
  CUST_NAME   VARCHAR(60)  NOT NULL,
  STATUS      CHAR(1)      NOT NULL,
  OPEN_DATE   DATE,
  PRIMARY KEY (CUST_NO));

In this example, the subject is one customer. Account balances, claim lines, and policy coverage rows belong in separate tables unless the business rule says otherwise.

Columns Store Named Values

A column stores one named value about the table subject. The column name should tell the reader what the value means, and the data type should match how Db2 and COBOL will use it.

ColumnMeaningDb2 type exampleCOBOL concern
CUST_NOCustomer identifierCHAR(10)Match host variable length exactly.
CUST_NAMECustomer display nameVARCHAR(60)Use a varying-length host structure when needed.
STATUSBusiness stateCHAR(1)Validate expected values such as A or I.
OPEN_DATEDate the customer was openedDATEUse the date format expected by the program and Db2.

Rows Represent Individual Facts

A row is one instance of the table subject. In a CUSTOMER table, one row represents one customer. In an ACCOUNT_TXN table, one row represents one transaction.

Rows have no guaranteed physical order from a SQL point of view. If a COBOL report needs account transactions by date, the SQL must say so:

SELECT TXN_DATE,
       TXN_AMT
  FROM ACCOUNT_TXN
 WHERE ACCT_NO = :WS-ACCT-NO
 ORDER BY TXN_DATE

Without ORDER BY, a program should not depend on row order.

Primary Keys Identify Rows

A primary key identifies one row in a table. It can be one column or a set of columns. A good primary key is stable, unique, and not nullable.

CREATE TABLE ACCOUNT
 (ACCT_NO     CHAR(12) NOT NULL,
  CUST_NO     CHAR(10) NOT NULL,
  BALANCE     DECIMAL(13,2),
  PRIMARY KEY (ACCT_NO));

In application work, primary keys show up in WHERE clauses, cursor predicates, update statements, delete statements, and joins. A weak key design usually becomes a maintenance problem later.

Composite Keys Use More Than One Column

A composite key uses two or more columns to identify a row. Linking tables often use composite keys because a row is unique only when two parent keys are combined.

CREATE TABLE ENROLLMENT
 (STUD_ID     CHAR(8) NOT NULL,
  COURSE_ID   CHAR(8) NOT NULL,
  ENROLL_DATE DATE,
  PRIMARY KEY (STUD_ID, COURSE_ID));

A COBOL program must provide all key columns when it reads or updates a row identified by a composite key.

Foreign Keys Connect Tables

A foreign key stores a value that points to a parent table key. This is how relational databases avoid disconnected business facts, such as an order without a customer.

ALTER TABLE ACCOUNT
  ADD CONSTRAINT FK_ACCOUNT_CUSTOMER
  FOREIGN KEY (CUST_NO)
  REFERENCES CUSTOMER (CUST_NO);

The related Db2 Relationships article explains one-to-one, one-to-many, and many-to-many patterns in more detail.

Views Present a Useful Shape of Data

A view is a named SQL definition that presents data from one or more base tables. A view can hide columns, join tables, simplify a query, or expose a controlled read-only shape to programs.

CREATE VIEW ACTIVE_CUSTOMER_V AS
SELECT CUST_NO,
       CUST_NAME,
       OPEN_DATE
  FROM CUSTOMER
 WHERE STATUS = 'A';

A program can then read the view as if it were a table:

SELECT CUST_NAME
  INTO :WS-CUST-NAME
  FROM ACTIVE_CUSTOMER_V
 WHERE CUST_NO = :WS-CUST-NO

For view types and update considerations, see Db2 View Classification.

Logical Design Is Separate from Physical Storage

The relational model lets the application work with tables and columns while Db2 manages physical storage. A table can have indexes, table spaces, buffer pools, partitions, and statistics that affect performance without changing the SELECT list a program uses.

That separation is useful, but it is not a reason to ignore physical design. A COBOL cursor can be logically correct and still slow if the access path is poor. Use Db2 Indexing and Db2 SQL Optimization Tips for COBOL Programs when performance matters.

How COBOL Uses the Anatomy

A COBOL program usually sees the relational anatomy through host variables and embedded SQL:

EXEC SQL
    SELECT CUST_NAME,
           STATUS,
           OPEN_DATE
      INTO :WS-CUST-NAME,
           :WS-STATUS,
           :WS-OPEN-DATE
      FROM CUSTOMER
     WHERE CUST_NO = :WS-CUST-NO
END-EXEC.

The SELECT list maps to columns. The WHERE clause uses a key. The host variables must match the Db2 column types closely enough to avoid conversion problems or unexpected truncation.

Common Beginner Mistakes

  • Treating row order as fixed without using ORDER BY.
  • Using SELECT * in production cursors when the program needs only a few columns.
  • Putting multiple values in one column instead of using child rows.
  • Choosing a primary key that can change during normal business processing.
  • Confusing a view with stored data when the view only stores a query definition.

Anatomy Checklist Before Writing SQL

QuestionWhy it matters
What table owns the data?Prevents joining to a table that only looks similar.
What row should qualify?Drives the WHERE clause and host variables.
What columns are actually needed?Keeps SELECT lists and COBOL target variables clean.
What key identifies the row?Reduces accidental duplicate reads or updates.
Is a view hiding any filter or join?Prevents surprise predicates or read-only behavior.

How This Fits with Db2 Objects

This article covers logical relational anatomy: tables, rows, columns, keys, relationships, and views. The later Db2 Objects article is the better place for a wider object list such as databases, table spaces, indexes, aliases, and packages.

For current product context, see IBM's Db2 for z/OS page and the ISO SQL framework.

FAQ

What are the basic parts of a relational database?

The basic parts are tables, rows, columns, keys, relationships, and views. Db2 also has physical and administrative objects, but those are separate from the basic logical model.

What is the difference between a row and a column?

A row is one instance of the table subject, such as one customer. A column is one named value about that subject, such as customer number or status.

Is a Db2 view the same as a table?

No. A view presents data through a stored query definition. The data comes from one or more base tables unless a specific Db2 feature stores results separately.

When the table subject, columns, keys, and relationships are clear, the embedded SQL in a COBOL program becomes easier to write, test, bind, and maintain.

Db2 Relationships: One-to-One, One-to-Many, and Many-to-Many

Db2 table relationships diagram showing one-to-one, one-to-many, and many-to-many relationships with primary and foreign keys
Relationships decide how Db2 tables join.

A COBOL cursor that joins CUSTOMER to ACCOUNT is only as good as the table relationship behind it. If ACCOUNT.CUST_NO does not point back to a real customer key, the program can return missing rows, duplicate rows, or orphan account records that no business user can explain.

This refresh explains the three relationship patterns used in relational database design: one-to-one, one-to-many, and many-to-many. The examples use Db2 table names, primary keys, foreign keys, and embedded SQL patterns that a mainframe developer is likely to review in batch or CICS programs.

What a Db2 Relationship Means

A relationship exists when rows in one table are associated with rows in another table. In Db2, that association is usually expressed through key columns: a primary key or unique key on the parent table, and a foreign key on the child table.

CREATE TABLE CUSTOMER
 (CUST_NO     CHAR(10) NOT NULL,
  CUST_NAME   VARCHAR(60),
  PRIMARY KEY (CUST_NO));

CREATE TABLE ACCOUNT
 (ACCT_NO     CHAR(12) NOT NULL,
  CUST_NO     CHAR(10) NOT NULL,
  BALANCE     DECIMAL(13,2),
  PRIMARY KEY (ACCT_NO),
  FOREIGN KEY (CUST_NO)
    REFERENCES CUSTOMER (CUST_NO));

In this example, CUSTOMER is the parent table and ACCOUNT is the child table. The relationship says that an account row must reference an existing customer row.

Primary Key, Foreign Key, and Parent Table

TermMeaning in Db2 designExample
Primary keyColumn or columns that uniquely identify a row in a table.CUSTOMER.CUST_NO
Foreign keyColumn or columns in one table that reference a parent key.ACCOUNT.CUST_NO
Parent tableTable that owns the referenced key.CUSTOMER
Child tableTable that stores the foreign key.ACCOUNT
Referential integrityRule that keeps child rows from pointing to missing parent rows.Account cannot reference an unknown customer.

One-to-One Relationship

A one-to-one relationship means one row in the first table matches at most one row in the second table, and one row in the second table matches at most one row in the first table.

A common design is a base table plus a detail table:

CUSTOMER
  CUST_NO       primary key
  CUST_NAME

CUSTOMER_PROFILE
  CUST_NO       primary key and foreign key
  TAX_STATUS
  CONTACT_PREF

The detail table uses the same key as the parent. This pattern is useful when optional or sensitive columns should be stored separately, but the row still belongs to exactly one parent row.

One-to-Many Relationship

A one-to-many relationship means one parent row can have many child rows, while each child row points to one parent row. This is the most common relationship in business applications.

CUSTOMER
  CUST_NO       primary key

ACCOUNT
  ACCT_NO       primary key
  CUST_NO       foreign key to CUSTOMER

A COBOL program might fetch all accounts for one customer like this:

EXEC SQL
    DECLARE C-ACCT CURSOR FOR
    SELECT A.ACCT_NO,
           A.BALANCE
      FROM ACCOUNT A
     WHERE A.CUST_NO = :WS-CUST-NO
END-EXEC.

If CUST_NO is indexed on ACCOUNT, this kind of cursor is easier for Db2 to access efficiently.

Many-to-Many Relationship

A many-to-many relationship means rows on both sides can match many rows on the other side. Do not store repeating columns such as COURSE_1, COURSE_2, and COURSE_3. Use a linking table, also called an associative or junction table.

STUDENT
  STUD_ID       primary key

COURSE
  COURSE_ID     primary key

ENROLLMENT
  STUD_ID       foreign key to STUDENT
  COURSE_ID     foreign key to COURSE
  ENROLL_DATE
  PRIMARY KEY (STUD_ID, COURSE_ID)

The linking table turns one many-to-many relationship into two one-to-many relationships. That keeps inserts, deletes, and joins easier to control.

Join Pattern for a Linking Table

A COBOL report that lists courses for one student can join through the linking table:

EXEC SQL
    DECLARE C-COURSE CURSOR FOR
    SELECT C.COURSE_ID,
           C.COURSE_TITLE,
           E.ENROLL_DATE
      FROM ENROLLMENT E
      JOIN COURSE C
        ON C.COURSE_ID = E.COURSE_ID
     WHERE E.STUD_ID = :WS-STUD-ID
     ORDER BY E.ENROLL_DATE
END-EXEC.

The cursor does not need repeating host variables for course slots. Each enrollment row is one fact.

Relationship Cardinality at a Glance

RelationshipParent and child patternDb2 design note
One-to-oneOne parent row maps to one detail row.The child key often acts as both primary key and foreign key.
One-to-manyOne parent row maps to many child rows.The foreign key belongs on the many side.
Many-to-manyMany rows on each side can match.Use a linking table with foreign keys to both parent tables.

Delete Rules Need Care

Relationships affect delete and update behavior. If a customer row has account rows, Db2 must know what should happen when someone tries to delete the customer.

Referential actionTypical meaningProduction caution
RESTRICT or NO ACTIONPrevent parent delete when child rows exist.Common for master data that must not be removed while dependent rows remain.
CASCADEDelete child rows when the parent is deleted.Use only when the business rule is explicit and tested.
SET NULLSet the child foreign key to null when the parent is deleted.Only works when a missing parent is valid for the application.

Batch purge programs need special care here. A delete that looks small in the parent table can affect many child rows.

Common Design Mistakes

  • Putting the foreign key on the wrong side of a one-to-many relationship.
  • Modeling many-to-many relationships with repeating columns instead of a linking table.
  • Using nullable foreign keys when the business rule requires a parent row.
  • Skipping indexes on foreign key columns that are frequently joined or searched.
  • Writing joins from column names alone without checking the real relationship.

How Relationships Affect Db2 Performance

Relationships are logical design, but they also affect access paths. A cursor that joins parent and child tables usually needs useful indexes on join columns and current statistics.

SELECT C.CUST_NAME,
       A.ACCT_NO,
       A.BALANCE
  FROM CUSTOMER C
  JOIN ACCOUNT A
    ON A.CUST_NO = C.CUST_NO
 WHERE C.CUST_NO = :WS-CUST-NO

After the relationship is correct, use EXPLAIN and statistics to review the access path. The Db2 SQL Optimization Tips for COBOL Programs post covers that check.

How This Fits with Other Db2 Topics

Relationships are part of relational design. They sit close to Db2 Anatomy of a Relational Database, Db2 Objects, and Db2 Indexing. For current product context, see IBM's Db2 for z/OS page and the ISO SQL framework.

FAQ

What is a one-to-many relationship in Db2?

A one-to-many relationship means one parent row can match many child rows. The child table stores a foreign key that points to the parent key.

How do I model a many-to-many relationship?

Use a linking table. The linking table stores foreign keys to both parent tables and often uses those columns as a composite primary key.

Do foreign keys improve query performance?

Foreign keys define the relationship and protect data consistency. Performance usually depends on indexes, statistics, predicates, and the access path Db2 chooses.

Good relationship design gives COBOL SQL a clean target: one parent key, clear child rows, and joins that match the business rule.

New In-feed ads