Andy’s Neural Works

A wise folly can lead to great things!


Designing the Database Structures for The All Roads Project

Published by

on

Introduction

With the database engine chosen, we can now start building some objects! It’s time to create the database structures. This provides a direction for the project’s data flow. Let’s keep this as simple as it can be. I do expect changes as the project goes on. We’ll follow these steps:

  1. Defined the data requirements
  2. Build out the entities and constraints in the conceptual design
  3. Identify the business level attributes and keys in the logical design.
  4. Fill out the implementation details in the physical design.

This is a pretty standard process with RDBMS design. There is no need to do anything exotic. Remember the goal is to get data in a format to be analyzed.

Data Requirements

Let’s start with reviewing the original requirements for data to be analyzed. This tends to be a fun step to do. Rather than say “data are data,” think about the components that make up the data itself. Ask yourself a series of questions:

  • What parts make up the data?
  • In this case, what is a Religious Text composed of? 
  • How are those parts organized?
  • Do some parts reference other parts?

With that in mind, time to dive in! Here is my initial set of requirements:

  • D1. A text can be a single page, book, or a library of books (ex: Bible).
  • D2. A text has a root URL, title, and description.
  • D3. A text might have organization into chapters and/or sections which groups pages.
  • D4. A page is composed of paragraphs.
  • D5. A page has an associated URL and title.
  • D6. A page might have a header.
  • D7. A page can have zero or more references.
  • D8. A paragraph can be a single sentence.
  • D9. A paragraph might be proceeded with an identifier.
  • D10. A paragraph can have citations to one or more references.
  • D11. A single reference might be a series of texts.
  • D12. Abbreviations exist that are used by references.

That seems to cover the bases. Maybe there will be more to uncover as we dive deeper. No one gets a database perfect in one try. That’s why the alter and create commands exist!

Conceptual Design

A conceptual design has the purpose of taking the broad requirements and focusing them into individual entities. Those components will further be defined later. For now, identifying them and seeing how they relate to each other is the key goal.

The following are the identified entities:

Entity NameDescription
TextsA text can be a book, letter, doctrine, and any other form of written material. A text can also be part of a grouping of texts (example: The Bible is a collection of books).
ChaptersIn the case of books, there are often chapters used to group together a series of pages under a common topic.
PagesThis is a single page of material in the religious text.
ParagraphsParagraphs are basic groupings of sentences and are stored in the page.
ReferencesCitations to other texts. Often formatted as the text name along with the specific page or related chapter.
AbbreviationsBasic list of abbreviations used by references to other texts.

Assumptions and Constraints

For each entity, we need to describe possible constraints that might be needed. If there are elements that are essential, we need to note them. We also want to put anything else that might be needed for relationships.

EntityAssumptions/Constraints
TextsMust have at least one entry when a page is found. Text title, text type, group, description, and URL are required.
ChaptersThese are optional (ex: simple letter on a teaching). When entry exists, must have a relationship to at least one page and one text.
PagesEach page must be related to a text. A page must have a title and URL. Description is an optional attribute.
ParagraphsA paragraph might have an identifier (typically, a sequence Id). It might also have one or more references. It must be related to a page.
ReferencesReferences must be related to a paragraph. It must contain reference text to relate to external source material.
AbbreviationsMust have a full description along with the abbreviation.

Reviewing the conceptual design, we have the following diagram. This shows the basic concept of how the entities work together to create a data blueprint.

Logical Design

The first step in logical design is to develop the schema for each of the entities. A schema merely organizes the attributes that are critical to describing the properties of the entity. This should not be too much of a challenge. Again, remember to keep this simple. We want to avoid a situation of over-engineering.

Schema Diagram

SchemaFields
TextsText_IdTitleDescriptionURLGroupType
ChaptersChapter_IdTitleDescriptionURLText_Id

PagesPage_IdPage_Sequence_IdTitleDescriptionURLText_IdChapter_Id
ParagraphsParagraph_IdParagraph_Sequence_IdParagraph_TextURLReference_IdsText_IdPage_Id
ReferencesReference_IDReference_Sequence_IdReference_TextURLPage_IdText_Id
AbbreviationsAbbreviation_IdAbbreviated_NameFull_NameCategoryText_Id

Entity Definition

Now it’s time to get some details into the attributes. We also want to get the keys defined. For this project, I see the ability to pull together lineage at the text and page level as being essential. When you look at the entities, you will see the Text_Id and Page_Id used to accomplish that goal. For example, if we run a query on paragraphs, we can go back to the text without touching other entities.

Here are the entity definitions with their attributes. I will define the potential keys along with the dependencies. If you are not familiar with this process, it is a method for determining unique keys used in the database definition.

Entity: Texts

Contains the highest level information about the Religious Text.

Attribute NameDescription
Text_IdSystem generated identifier.
TitleTitle of the religious text.
DescriptionSummary of the religious text.
URLURL pointing to the root of the text source.
GroupGeneral group used to describe if the text is part of a library of books (ex: Bible).
TypeRelays if the type is a book, library, doctrine, letter, etc.

Keys:

  • Text_Id

Functional Dependencies:

  • Text_Id > Title
  • Text_Id > Description
  • Text_Id > URL
  • Text_Id > Group
  • Text_Id > Type

Attribute Closures:

  • (Text_Id)+ = (Title, Description, URL, Group, Type)

Unique Keys:

  • Text_Id

Entity: Chapters

This entity relays the grouping of pages within a Religious Text. It is not required to have a set of chapters for a given text.

Attribute NameDescription
Chapter_IdSystem generated identifier.
URLURL (if available) pointing to the chapter listings.
TitleChapter title.
DescriptionDescription of what is contained in the chapter.
Text_IdReligious text identifier that this chapter is contained within.

Keys:

  • Chapter_Id

Foreign Keys:

  • Text_Id

Functional Dependencies:

  • Chapter_Id > URL
  • Chapter_Id > Title
  • Chapter_Id > Description
  • Chapter_Id > Text_Id

Attribute Closures:

  • (Chapter_Id)+ = (URL, Title, Description, Text_Id)

Unique Keys:

  • Chapter_Id

Entity: Pages

All pages related to a text are held in this entity. This can be representative of a website page as well as a page in a book. There are no limits to the size of the page.

Attribute NameDescription
Page_IdSystem generated identifier.
Page_Sequence_IdSimple identifier for page within text.
TitleTitle of the page.
DescriptionPage summary.
URLURL pointing to the page source.
Text_IdReligious text identifier that this page is held.
Chapter_IdIf part of a chapter, this field has the identifier value to foreign record.

Keys:

  • Page_Id

Foreign Keys:

  • Text_Id
  • Chapter_Id

Functional Dependencies:

  • Page_Id > Title
  • Page_Id > Description
  • Page_Id > URL
  • Page_Id > Text_Id
  • Page_Id > Chapter_Id

Attribute Closures:

  • (Page_Id)+ = (Title, Description, URL, Text_Id, Chapter_Id)

Unique Keys:

  • Page_Id

Entity: Paragraphs

Within a page, there are paragraphs. This entity contains these paragraphs.

Attribute NameDescription
Paragraph_IdSystem generated identifier.
Paragraph_Sequence_IdIf available, the paragraph’s sequence is taken from the source. If not, the value will be blank/null.
Paragraph_TextThe actual text of the paragraph.
URLURL pointing the paragraph (if available).
Reference_IdsMatched references in the paragraph text.
Text_IdReligious text identifier that this paragraph is held.
Page_IdPage that this paragraph is held.

Keys:

  • Paragraph_Id
  • Paragraph_Sequence_Id

Foreign Keys:

  • Reference_Ids
  • Text_Id
  • Page_Id

Functional Dependencies:

  • Paragraph_Id > Paragraph_Sequence_Id
  • Paragraph_Id > Paragraph_Text
  • Paragraph_Id > URL
  • Paragraph_Id > Reference_Ids
  • Paragraph_Id > Text_Id
  • Paragraph_Id > Page_Id

Attribute Closures:

  • (Paragraph_Id)+ = (Paragraph_Sequence_Id, Paragraph_Text, URL, Reference_Ids, Text_Id, Page_Id)

Unique Keys:

  • Paragraph_Id

Entity: References

This contains the external references cited throughout the texts.

Attribute NameDescription
Reference_IdSystem generated identifier.
Reference_Sequence_IdSequence that the citation is called.
Reference_TextThe list of references.
URLReference URL.
Page_IdPage reference is cited.
Text_IdText reference is cited.

Keys:

  • Reference_Id

Foreign Keys:

  • Page_Id
  • Text_Id

Functional Dependencies:

  • Reference_Id > Reference_Sequence_Id
  • Reference_Id > Reference_Text
  • Reference_Id > URL
  • Reference_Id > Page_Id
  • Reference_Id > Text_Id

Attribute Closures:

  • (Reference_Id)+ = (Reference_Sequence_Id, Reference_Text, URL, Page_Id, Text_Id)

Unique Keys:

  • Reference_Id

Entity: Abbreviations

Attribute NameDescription
Abbreviation_IdSystem generated identifier.
Abbreviated_NameAbbreviated name text.
Full_NameFull version name of text.
CategoryCategory, if any, that the abbreviation belongs.
Text_IdMatching text identifier for abbreviated name.

Keys:

  • Abbreviation_Id

Foreign Keys:

  • Text_Id

Functional Dependencies:

  • Abbreviation_Id > Abbreviated_Name
  • Abbreviation_Id > Full_Name
  • Abbreviation_Id > Category
  • Abbreviation_Id > Text_Id

Attribute Closures:

  • (Abbreviation_Id)+ = (Abbreviated_Name, Full_Name, Category, Text_Id)

Unique Keys:

  • Abbreviation_Id

Physical Design

The Physical Design Phase now brings in how the tables will be built in the server (again, PostgreSQL). The data types will be added on as well as whether NULLs are to be allowed in the column. The primary and foreign keys are noted. Also, please note that I will add audit columns to each table. These are used as housekeeping data points in case there is some traceability needed for support issues.

*Notes: 

  • I will use a postfix of “T” to designate “Table.”
  • URL is set to 2048 after doing a web search on large URL string lengths.
  • Primary Key Ids are set to auto-incrementing SERIAL type.
  • Foreign Key Ids will be INTEGER type.
  • Titles will be set to 1000 varying characters.
  • Description and text needs to handle large character streams (TEXT data type).
  • Basic strings will be set to 50 varying characters.
  • User Ids will be set to 100 varying characters.
  • Dates are to include timestamp without time zone.
  • The JSON data type will be used when fields contain variable, delimited values.

Table: Texts_T

TableTexts_T
DescriptionContains the highest level information about the Religious Text.
AttributeDescriptionTypeAllow NULL?Example of Values
Text_IdSystem generated IdSERIALNo1
TitleTitle of Religious TextVARCHAR(1000)NoCatechism of the Catholic Church
DescriptionDescription of TextTEXTYesSummary of Catholic Faith
URLURL pointing to the root of the text sourceVARCHAR(2048)Yeshttps://www.usccb.org/beliefs-and-teachings/what-we-believe/catechism/catechism-of-the-catholic-church
GroupGeneral group used to describe if the text is part of a library of books (ex: Bible)VARCHAR(50)YesSummary
TypeRelays if the type is a book, library, doctrine, letter, etcVARCHAR(50)NoBook
Audit_Create_DateAudit field for creation date and timeTIMESTAMPNo05/15/2024
Audit_Create_UserAudit field for created by userVARCHAR(100)Noandy
Audit_Update_DateAudit field for record update date and timeTIMESTAMPYesNULL
Audit_Update_UserAudit field for updated by userVARCHAR(100)YesNULL

Primary Keys:

  • Text_Id

Foreign Keys:

  • None

Table: Chapters_T

TableChapters_T
DescriptionThis relays the grouping of pages within a Religious Text. It is not required to have a set of chapters for a given text.
AttributeDescriptionTypeAllow NULLs?Example of Values
Chapter_IdSystem generated identifierSERIALNo1
URLURL (if available) pointing to the chapter listingsVARCHAR(2048)YesNULL
TitleChapter titleVARCHAR(1000)NoPART ONE: THE PROFESSION OF FAITH
DescriptionDescription of what is contained in the chapterTEXTYesNULL
Text_IdReligious text identifier that this chapter is contained withinINTEGERNo1
Audit_Create_DateAudit field for creation date and timeTIMESTAMPNo05/15/2024
Audit_Create_UserAudit field for created by userVARCHAR(100)Noandy
Audit_Update_DateAudit field for record update date and timeTIMESTAMPYesNULL
Audit_Update_UserAudit field for updated by userVARCHAR(100)YesNULL

Primary Keys:

  • Chapter_Id

Foreign Keys:

  • Text_Id to Texts_T.Text_Id

Table: Pages_T

TablePages_T
DescriptionAll pages related to a Religious Text.
AttributeDescriptionTypeAllow NULLs?Example of Values
Page_IdSystem generated identifierSERIALNo1
Page_Sequence_IdSimple identifier for page within text.INTEGERNo1
TitleTitle of the pageVARCHAR(1000)NoTHE FINAL DOXOLOGY
DescriptionPage summaryTEXTYesNULL
URLURL pointing to the page sourceVARCHAR(2048)Yeshttps://www.vatican.va/archive/ENG0015/__PAD.HTM
Text_IdReligious text identifier that this page is heldINTEGERNo1
Chapter_IdIf part of a chapter, this field has the identifier value to foreign recordINTEGERYes1
Audit_Create_DateAudit field for creation date and timeTIMESTAMPNo05/15/2024
Audit_Create_UserAudit field for created by userVARCHAR(100)Noandy
Audit_Update_DateAudit field for record update date and timeTIMESTAMPYesNULL
Audit_Update_UserAudit field for updated by userVARCHAR(100)YesNULL

Primary Keys:

  • Page_Id

Foreign Keys:

  • Text_Id to Texts_T.Text_Id
  • Chapter_Id to Chapters_T.Chapter_Id

Table: Paragraphs_T

TableParagraphs_T
DescriptionHolds the actual text data at the lowest level (paragraphs).
AttributeDescriptionTypeAllow NULLs?Example of Values
Paragraph_IdSystem generated identifierSERIALNo1
Paragraph_Sequence_IdIf available, the paragraph’s sequence is taken from the source. If not, the value will be blank/nullVARCHAR(1000)Yes2856
Paragraph_TextThe actual text of the paragraphTEXTNoThen, after the prayer is over you say ‘Amen,’ which means ‘So be it,’ thus ratifying with our ‘Amen’ what is contained in the prayer that God has taught us.”179
URLURL pointing the paragraph (if available)VARCHAR(2048)YesNULL
Reference_Sequence_IdsMatched references in the paragraph textJSONYes{Reference:“179”}
Text_IdReligious text identifier that this paragraph is heldINTEGERNo1
Page_IdPage that this paragraph is heldINTEGERNo1
Audit_Create_DateAudit field for creation date and timeTIMESTAMPNo05/15/2024
Audit_Create_UserAudit field for created by userVARCHAR(100)Noandy
Audit_Update_DateAudit field for record update date and timeTIMESTAMPYesNULL
Audit_Update_UserAudit field for updated by userVARCHAR(100)YesNULL

Primary Keys:

  • Paragraph_Id

Foreign Keys:

  • Text_Id to Texts_T.Text_Id
  • Page_Id to Pages_T.Page_Id

Table: References_T

TableReferences_T
DescriptionThis contains the external references cited throughout the texts.
AttributeDescriptionTypeAllow NULLs?Example of Values
Reference_IdSystem generated identifierSERIALNo1
Reference_Sequence_IdSequence that the citation is calledVARCHAR(1000)No179
Reference_TextThe list of referencesJSONNo{reference:”St. Cyril of Jerusalem, Catech. myst. 5,18: PG 33, 1124,”reference:”cf. Cf. Lk 1:38.”}
URLReference URLVARCHAR(2048)YesNULL
Page_IdPage reference is citedINTEGERNo1
Text_IdText reference is citedINTEGERNo1
Audit_Create_DateAudit field for creation date and timeTIMESTAMPNo05/15/2024
Audit_Create_UserAudit field for created by userVARCHAR(100)Noandy
Audit_Update_DateAudit field for record update date and timeTIMESTAMPYesNULL
Audit_Update_UserAudit field for updated by userVARCHAR(100)YesNULL

Primary Keys:

  • Reference_Id

Foreign Keys:

  • Text_Id to Texts_T.Text_Id
  • Page_Id to Pages_T.Page_Id

Table: Abbreviations_T

TableAbbreviations_T
DescriptionBasic list of abbreviations used by references to other texts.
AttributeDescriptionTypeAllow NULLs?Example of Values
Abbreviation_IdSystem generated identifierSERIALNo1
Abbreviated_NameAbbreviated name textVARCHAR(100)NoActs
Full_NameFull version name of textVARCHAR(1000)NoActs of the Apostles
CategoryCategory, if any, that the abbreviation belongs toVARCHAR(100)YesBible
Text_IdMatching text identifier for abbreviated nameINTEGERYes2
Audit_Create_DateAudit field for creation date and timeTIMESTAMPNo05/15/2024
Audit_Create_UserAudit field for created by userVARCHAR(100)Noandy
Audit_Update_DateAudit field for record update date and timeTIMESTAMPYesNULL
Audit_Update_UserAudit field for updated by userVARCHAR(100)YesNULL

Primary Keys:

  • Abbreviation_Id

Foreign Keys:

  • Text_Id to Texts_T.Text_Id

Building Staging Tables

Staging tables are used for a method of temporary storage when loading from external files. They are typically loose in their constraints. This allows flexibility when organizing data. The end goal will be to maintain data integrity. Design of these will be done in future articles to accommodate the individual sources.

Entity Relationship Diagram

Finally, we have a full ER Diagram to represent the entire structure:

Next Steps

This finishes up the basic database design. For those new to this process, you should not be afraid of the work involved. In fact, a database architect might take further steps involving more detailed data normalization techniques. Perhaps this will be revisited later on if the structure grows.

In the next step, we will start loading data! I believe in continuing with a simple approach will be important. I am considering using a 3rd party tool to assist with this but that might not be necessary. I will do some research and experimentation then publish my results.

Thank you

Appendix

SQL to Generate Database Tables

*Note: I used the pgAdmin Tool included with PostgreSQL to pull this together. The schema is set to “public” but I’ll set to a different one later.

BEGIN;


CREATE TABLE IF NOT EXISTS public."Texts_T"
(
    "Text_Id" serial NOT NULL,
    "Title" character varying(1000)[] NOT NULL,
    "Description" text,
    "URL" character varying(2048)[],
    "Group" character varying(50)[],
    "Type" character varying(50)[] NOT NULL,
    "Audit_Create_Date" timestamp without time zone NOT NULL,
    "Audit_Create_User" character varying(100)[] NOT NULL,
    "Audit_Update_Date" timestamp without time zone,
    "Audit_Update_User" character varying(100)[],
    CONSTRAINT pk_texts_t PRIMARY KEY ("Text_Id")
);

CREATE TABLE IF NOT EXISTS public."Chapters_T"
(
    "Chapter_Id" serial NOT NULL,
    "URL" character varying(2048)[],
    "Title" character varying(1000)[] NOT NULL,
    "Description" text,
    "Text_Id" integer NOT NULL,
    "Audit_Create_Date" timestamp without time zone NOT NULL,
    "Audit_Create_User" character varying(100)[] NOT NULL,
    "Audit_Update_Date" timestamp without time zone,
    "Audit_Update_User" character varying(100)[],
    CONSTRAINT pk_chapters_t PRIMARY KEY ("Chapter_Id")
);

CREATE TABLE IF NOT EXISTS public."Pages_T"
(
    "Page_Id" serial NOT NULL,
    "Page_Sequence_Id" integer NOT NULL,
    "Title" character varying(1000)[] NOT NULL,
    "Description" text,
    "URL" character varying(2048)[],
    "Text_Id" integer NOT NULL,
    "Chapter_Id" integer,
    "Audit_Create_Date" timestamp without time zone NOT NULL,
    "Audit_Create_User" character varying(100) NOT NULL,
    "Audit_Update_Date" timestamp without time zone,
    "Audit_Update_User" character varying(100)[],
    CONSTRAINT pk_pages_t PRIMARY KEY ("Page_Id")
);

CREATE TABLE IF NOT EXISTS public."Paragraphs_T"
(
    "Paragraph_Id" serial NOT NULL,
    "Paragraph_Sequence_Id" character varying(1000)[],
    "Paragraph_Text" text NOT NULL,
    "URL" character varying(2048)[],
    "Reference_Sequence_Ids" json,
    "Text_Id" integer NOT NULL,
    "Page_Id" integer NOT NULL,
    "Audit_Create_Date" timestamp without time zone NOT NULL,
    "Audit_Create_User" character varying(100)[] NOT NULL,
    "Audit_Update_Date" timestamp without time zone,
    "Audit_Update_User" character varying(100)[],
    CONSTRAINT fk_paragraphs_t PRIMARY KEY ("Paragraph_Id")
);

CREATE TABLE IF NOT EXISTS public."References_T"
(
    "Reference_Id" serial NOT NULL,
    "Reference_Sequence_Id" character varying(1000)[] NOT NULL,
    "Reference_Text" json NOT NULL,
    "URL" character varying(2048)[],
    "Page_Id" integer NOT NULL,
    "Text_Id" integer NOT NULL,
    "Audit_Create_Date" timestamp without time zone NOT NULL,
    "Audit_Create_User" character varying(100) NOT NULL,
    "Audit_Update_Date" timestamp without time zone,
    "Audit_Update_User" character varying(100)[],
    CONSTRAINT pk_references_t PRIMARY KEY ("Reference_Id")
);

CREATE TABLE IF NOT EXISTS public."Abbreviations_T"
(
    "Abbreviation_Id" serial NOT NULL,
    "Abbreviated_Name" character varying(100)[] NOT NULL,
    "Full_Name" character varying(1000)[] NOT NULL,
    "Category" character varying(100)[],
    "Text_Id" integer,
    "Audit_Create_Date" time without time zone NOT NULL,
    "Audit_Create_User" character varying(100)[] NOT NULL,
    "Audit_Update_Date" timestamp with time zone,
    "Audit_Update_User" character varying(100)[],
    CONSTRAINT pk_abbreviations_t PRIMARY KEY ("Abbreviation_Id")
);

ALTER TABLE IF EXISTS public."Chapters_T"
    ADD CONSTRAINT fk_chapters_t_to_text_t_01 FOREIGN KEY ("Text_Id")
    REFERENCES public."Texts_T" ("Text_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;


ALTER TABLE IF EXISTS public."Pages_T"
    ADD CONSTRAINT fk_pages_t_to_texts_t_01 FOREIGN KEY ("Text_Id")
    REFERENCES public."Texts_T" ("Text_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;


ALTER TABLE IF EXISTS public."Pages_T"
    ADD CONSTRAINT fk_pages_t_to_chapters_t_01 FOREIGN KEY ("Chapter_Id")
    REFERENCES public."Chapters_T" ("Chapter_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;


ALTER TABLE IF EXISTS public."Paragraphs_T"
    ADD CONSTRAINT fk_paragraphs_t_to_texts_t_01 FOREIGN KEY ("Text_Id")
    REFERENCES public."Texts_T" ("Text_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;


ALTER TABLE IF EXISTS public."Paragraphs_T"
    ADD CONSTRAINT fk_paragraphs_t_to_pages_t_01 FOREIGN KEY ("Page_Id")
    REFERENCES public."Pages_T" ("Page_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;


ALTER TABLE IF EXISTS public."References_T"
    ADD CONSTRAINT fk_references_t_to_pages_t_01 FOREIGN KEY ("Page_Id")
    REFERENCES public."Pages_T" ("Page_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;


ALTER TABLE IF EXISTS public."References_T"
    ADD CONSTRAINT fk_references_t_to_texts_t_01 FOREIGN KEY ("Text_Id")
    REFERENCES public."Texts_T" ("Text_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;


ALTER TABLE IF EXISTS public."Abbreviations_T"
    ADD CONSTRAINT fk_abbreviations_t_to_texts_t_01 FOREIGN KEY ("Text_Id")
    REFERENCES public."Texts_T" ("Text_Id") MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE NO ACTION
    NOT VALID;

END;

One response to “Designing the Database Structures for The All Roads Project”

  1. […] Up until now, the work for The All Roads Project has been more high level. The final table structures are defined in the previous article. That step does gets more detailed but staging the data will bring us even closer to the atomic parts. We will have to review and deeply understand the source files. There are many files to go through but I think we can find some sort of pattern.  […]

    Like