Too frequently, both in training and implementation, people ask me about the entity relationship. Although we added the list of available tables in SpiraDocs, I find it missing fields and has inconsistent names. Further, as we grow the functionality, we keep adding more tables and views which are not consistent with the list of queries in the Query Builder.
Addressing these observations over time, I created many requests to product to fix the SpiraDocs as well as update the backend where necessary to ensure consistent naming guidelines.
Recently, in meetings with clients and partners, I have seen requests to me asking how to get my brain dump to develop custom queries. Yes, it is a large request. While I can't train people on ESQL or XSLT, I asked myself how to accomplish this?
In response to some customers asking for the database schema, I asked a few partners to create the ER diagram. Through the Partnership training series, I also showed how to make the connections based on SpiraDocs.
But I didn't see anyone volunteer or express interest. On the contrary, I only saw hesitiation.
Frequently, people think of using the diagramatic tools (e.g.: Visio, PowerPoint) to create the ER diagram. Some with experience to SQL Management studio can create this ER diagram. But, creating the schema with the crowfoot notation for relationship is cumbersome when there are too many entities. In addition, some entities on SpiraDocs is very long because not all of them are not just stand-alone entitites. So, when representing all the available entities on SpiraDoc, the result will not be visually appealing. Nor will it be helpful. Besides, such an approach will also be difficult for ongoing maintenance when this approach is handed over to the product support team for continued updates. So, I began experimenting ideas.
Having reviwed a few known tools and explored other ideas, I decided to use the DBNL syntax to create these minimal ER model (only primary and foreign keys). If I enforce all the referential integrities, it will be too cumbersome and less usable for anyone. I also decided to refer to the SpiraDocs where additioanl attributes exist. So, after checking a few tools, I landed on dbdiagram that allowed the data definition langauge (DDL) and Data Control Lanaguage (DCL) syntax to create the ER diagrams.
I don't have a name for the model but I see this as "Spira Minimal Entity Relationship "Diagram.
NOTE: While this dbdiagram tool provided a means to embed images directly from the code created, it required an advanced premium, which I was not sure required at least for now. So, I used the free tool features to design the SMEAR model in phases and downloaded the schema to complete my experiment.
| Group Name | Summary Description |
| Essential PPM | A collection of entities representing how the workspaces are organized as products, programs, and portfolios. Products derive properties from templates. |
| Essential Traceability | A collection of entities representing how essential artifact traceability is maintained using requirements, testcases, and incidents. |
| Scenario Traceability | A collection of entities that allow scenario level traceabilities using test sets, configurations, and automation hosts. |
| Artifact Connections | A collection of entities that allow track documents, associations, and comments. |
| Team Accountability | A collection of entities that use tasks and risks. |
| Product Auditability | A collection of entitites that use baselines and history tracking. |
| Program Functions | A collection of entities for program and portfolio level information to support scaled agile functions. |
Given below is the high level visual summary of these entity groups.

Note: Please note that some entities do not fall within any of these groups. At this point, it is the "Events" table.
My next experiment is to use AI to use this model to create queries. But, one at a time!
Each section has four tabs that contain details for that section. Please click on the tabs to review the details.
This group represents a collection of entities representing how the workspaces are organized as products, programs, and portfolios. Products derive properties from templates.
| Scheme Ref | Primary Key | SpiraDocs Reference for Additional Fiels |
|---|---|---|
| Portfolios | Portfolio_Id | SpiraTestEntities.R_Portfolios |
| ProjectGroups | Project_Group_Id | SpiraTestEntities.R_ProjectGroups |
| ProductTemplate | Product_Template_Id | SpiraTestEntities.R_ProductTemplate |
| Projects | Project_Id | SpiraTestEntities.R_Projects |
| Components | Component_Id | SpiraTestEntities.R_Components |
| Releases | Release_Id | SpiraTestEntities.R_Releases |
| ProjectTags | Project_ID | SpiraTestEntities.R_ProjectTags |
Please click here for the DBNL reference file.
| Query | Result |
|
select pf.portfolio_id, pf.name as portfolio_name, pg.project_group_id, pg.name as program_name from SpiraTestEntities.R_Portfolios as pf join SpiraTestEntities.R_ProjectGroups as pg on pf.portfolio_id = pg.portfolio_id | ![]() |
| Query | Result |
|
select pt.project_template_id, pt.name as template_name, p.project_id, p.name as project_name from SpiraTestEntities.R_ProjectTemplates as pt join SpiraTestEntities.R_Projects as p on pt.project_template_id = p.project_template_id | ![]() |
| Query | Result |
|
select p.project_id, p.name as project_name, c.component_id, c.name as component_name from SpiraTestEntities.R_Projects as p join SpiraTestEntities.R_Components as c on p.project_id = c.project_id | ![]() |
This group represents a collection of entities representing how essential artifact traceability is maintained. The traceability is mainly around Requirements, Test Cases, and Incidents and the associated tables that faciliate running queries.
| Scheme Ref | Primary Key | SpiraDocs Reference for Additional Fiels |
|---|---|---|
| RequirementSteps | Position | SpiraTestEntities.R_RequirementSteps |
| Requirements | Requirement_ID | SpiraTestEntities.R_Requirements |
| RequirementTypes | Requirement_Type_ID | SpiraTestEntities.R_RequirementTypes |
| RequirementTestCases | Requirement_ID, Test_Case_ID | SpiraTestEntities.R_RequirementTestCases |
| RequirementIncidents | Requirement_ID, Incident_ID | SpiraTestEntities.R_RequirementIncidents |
| TestCases | Test_Case_ID | SpiraTestEntities.R_TestCases |
| TestSteps | Test_Step_ID | SpiraTestEntities.R_TestSteps |
| TestCaseIncidents | Test_Case_ID, Incident_ID | SpiraTestEntities.R_TestCaseIncidents |
| TestCaseFolders | Test_Case_Folder_ID | SpiraTestEntities.R_TestCaseFolders |
| TestCaseTypes | Test_Case_Type_ID | SpiraTestEntities.R_TestCaseTypes |
| TestRuns | Test_Run_ID | SpiraTestEntities.R_TestRuns |
| TestRunSteps | Test_Run_Step_ID | SpiraTestEntities.R_TestRunSteps |
| TestRunIncidents | Test_Run_ID, Incident_ID | SpiraTestEntities.R_TestRunIncidents |
| Incidents | Incident_ID | SpiraTestEntities.R_Incidents |
| IncidentPriorities | Priority_ID | SpiraTestEntities.R_IncidentPriorities |
| IncidentSeverities | Severity_ID | SpiraTestEntities.R_IncidentSeverities |
| IncidentStatuses | Incident_Status_ID | SpiraTestEntities.R_IncidentStatuses |
| IncidentTypes | Incident_Type_ID | SpiraTestEntities.R_IncidentTypes |
| Query | Result |
|
select r.requirement_id, r.name as requirement_name, t.test_case_id, t.name as test_case_name from SpiraTestEntities.R_Requirements as r left join SpiraTestEntities.R_RequirementTestCases as rt on r.requirement_id = rt.requirement_id and r.project_id = rt.project_id join SpiraTestEntities.R_TestCases as t on t.test_case_id = rt.test_case_id and t.project_id = rt.project_id where r.is_summary = False and r.is_deleted = False | ![]() |
| Query | Result |
|
select i.incident_id, i.name as incident_name, t.test_case_id, t.name as test_case_name from SpiraTestEntities.R_Incidents as i join SpiraTestEntities.R_TestCaseIncidents as ti on i.incident_id = ti.incident_id join SpiraTestEntities.R_TestCases as t on t.test_case_id = ti.test_case_id where i.project_id = ${ProjectId} and i.is_deleted = False | ![]() |
| Query | Result |
|
select tr.release_id, t.test_case_id, t.name as test_case_name, tr.execution_status_name from SpiraTestEntities.R_TestCases as t join SpiraTestEntities.R_TestRuns as tr on tr.test_case_id = t.test_case_id and t.project_id = tr.Project_ID where tr.release_id is not null and tr.release_id = ${ReleaseId} order by tr.release_id | ![]() |
This group represents a collection of entities that allow scenario level traceabilities. This collection includes Test Sets, Test Configuration, Automation Host, and information about Test Case and Test Incident collections for a test set.
| Entity Name | Primary Key | SpiraDocs Reference for Additional Fiels |
|---|---|---|
| TestSets | Test_Set_Id | SpiraTestEntities.R_TestSets |
| TestConfigurationEntries | Test_Configuration_Id | SpiraTestEntities.R_TestConfigurationEntries |
| TestConfigurationSets | Test_Configuration_Set_Id | SpiraTestEntities.R_TestConfigurationSets |
| TestSetTestCases | Test_Set_Test_Case_Id | SpiraTestEntities.R_TestSetsTestCases |
| TestSetIncidents | Test_Set_Id, Incident_ID | SpiraTestEntities.R_TestSetIncidents |
| TestSetFolders | Test_Set_Folder_Id | SpiraTestEntities.R_TestSetFolders |
| AutomationHosts | Automation_Host_Id | SpiraTestEntities.R_AutomationHosts |
| Query | Result |
|
select tsc.test_set_id, tsc.test_set_name, tsc.test_case_id, tsc.test_case_name from SpiraTestEntities.R_TestSetTestCases as tsc join SpiraTestEntities.R_TestSets as ts on ts.test_set_id = tsc.test_set_id where ts.project_id = ${ProjectId} and ts.release_id = ${ReleaseId} | ![]() |
| Query | Result |
|
select i.project_id, t.release_id, i.incident_id, i.name as incident_name, t.test_set_id, t.name as test_set_name from SpiraTestEntities.R_Incidents as i join SpiraTestEntities.R_TestSetIncidents as ti on i.incident_id = ti.incident_id join SpiraTestEntities.R_TestSets as t on t.test_set_id = ti.test_set_id where i.incident_id = ${ProjectId} and t.release_id = ${ReleaseId} | ![]() |
| Query | Result |
|
select ts.project_id, ts.release_id, ts.test_set_id, ts.name, ts.test_configuration_set_id as config_id, tcs.name as Test_Config_Name, tc.test_case_parameter_value from SpiraTestEntities.R_TestSets as ts join SpiraTestEntities.R_TestConfigurationSets as tcs on ts.test_configuration_set_id = tcs.test_configuration_set_id and tcs.project_id = ts.project_id join SpiraTestEntities.R_TestConfigurationEntries as tc on tcs.test_configuration_set_id = tc.test_configuration_set_id where tcs.is_deleted = False and tcs.is_active = True and ts.project_id = ${ProjectId} and ts.release_id = ${ReleaseId} | ![]() |
This group represents a collection of entities that allow track documents, associations and comments that can be added to artifacts.
Many organizations can upload documents to many artifacts and also establish associations. As part of the ways of working to support traceability and auditability, comments can be added as well to the artifacts. This section addresses entities related to these features.
Furthermore, Spira also allows visibility into the source code associations to specific artifacts increasing the transparency of the development process and traceabilty to artifacts.
| Scheme Ref | Primary Key | SpiraDocs Reference for Additional Fiels |
|---|---|---|
| ArtifactAssociations | Artifact_Link_Type_Id | SpiraTestEntities.R_ArtifactAssociations |
| ArtifactTags | Artifact_Id | SpiraTestEntities.R_ArtifactTags |
| AttachmentFolders | Project_Attachment_Folder_Id | SpiraTestEntities.R_AttachmentFolders |
| Attachments | Attachment_Id | SpiraTestEntities.R_ArtifactAttachments |
| ArtifactTypes | Artifact_Type_Id | SpiraTestEntities.R_ArtifactTypes |
| Comments | Artifact_Type_Id, Artifact_Id | SpiraTestEntities.R_Comments |
| Attachments | Attachment_Id | SpiraTestEntities.R_Attachments |
| AttachmentVersions | Attachment_Version_Id | SpiraTestEntities.R_AttachmentVersions |
| SourceCodeAssociations | Artifact_Source_Code_Revision_Id | SpiraTestEntities.R_R_SourceCodeAssociations |
| SourceCodeCommits | Version_Control_System_Id | SpiraTestEntities.R_SourceCodeCommits |
| DocumentStatuses | Document_Status_Id | SpiraTestEntities.R_DocumentStatuses |
| DocumentTypes | Document_Type_Id | SpiraTestEntities.R_DocumentTypes |
| Query | Result |
|
select a.filename, a.document_type_name, a.project_attachment_folder_name, a.project_id from SpiraTestEntities.R_Attachments as a where a.project_id = ${ProjectId} | ![]() |
| Query | Result |
|
select c.artifact_id, r.name, c.comment_text, c.creation_date, c.creator_name from SpiraTestEntities.R_Comments as c join SpiraTestEntities.R_ArtifactTypes as at on c.artifact_type_id = at.artifact_type_id and at.name = "Requirement" join SpiraTestEntities.R_Requirements as r on c.artifact_id = r.requirement_id and r.is_deleted = false and r.is_summary = false where R.project_id = ${ProjectId} | ![]() |
| Query | Result |
|
select at.artifact_id, at.artifact_type_id, at.tags, at.artifact_Type_name from SpiraTestEntities.R_ArtifactTags as at where at.project_id = ${ProjectId} and at.tags is not null | ![]() |
This group represents a collection of entities that allow track tasks and risks that are associated with a project delivery team to monitor their progress towards completion while addressing any impediment, blocker, or obstacles.
Project delivery teams, regardless of their chosen delivery methodology, uses tasks monitor the progress of their work within their release cadence. In plan driven approaches, the project managers use tasks to monitor the progress. In change driven approaches, the delivery team uses the tasks to monitor their definition of done. At the same time, every team uses risks to identify, evaluate, and treat risks that challenge their delivery. This section addresses entities related to these features.
| Scheme Ref | Primary Key | SpiraDocs Reference for Additional Fiels |
|---|---|---|
| Tasks | Task_Id | SpiraTestEntities.R_Tasks |
| TaskPriorities | Task_Priority_Id | SpiraTestEntities.R_TaskPriorities |
| TaskTypes | Task_Type_Id | SpiraTestEntities.R_TaskTypes |
| Risks | Risk_Id | SpiraTestEntities.R_Risks |
| RiskProbabilities | Risk_Probability_Id | SpiraTestEntities.R_RiskProbabilities |
| RiskImpacts | Risk_Impact_Id | SpiraTestEntities.R_RiskImpacts |
| RiskStatuses | Risk_Status_Id | SpiraTestEntities.R_RiskStatuses |
| RiskTypes | Risk_Type_Id | SpiraTestEntities.R_RiskTypes |
| RiskMitigations | Risk_Mitigation_Id | SpiraTestEntities.R_RiskMitigations |
| Query | Result |
|
select r.risk_id, r.name as Risk_Name, R.risk_probability_name as probability, r.risk_impact_name as impact, r.risk_exposure as exposure, p.name as Project_Name, rl.name as release from SpiraTestEntities.R_Risks as r join SpiraTestEntities.R_Projects as p on r.project_id = p.project_id and r.is_deleted = false join SpiraTestEntities.R_Releases as rl on r.release_id = rl.release_id | ![]() |
| Query | Result |
|
select t.task_Id, t.name, t.task_type_name, t.task_status_name from SpiraTestEntities.R_Tasks as t where t.project_id = ${ProjectId} and t.task_type_name = "Development" and t.is_delted = false | ![]() |
| Query | Result |
|
select r.risk_id, r.name as risk_name, r.risk_exposure as exposure, r.component_name as component, rm.risk_mitigation_Id, rm.description, rm.review_date from SpiraTestEntities.R_Risks as r join SpiraTestEntities.R_RiskMitigations as rm on rm.risk_id = r.risk_id and rm.is_deleted = false where r.project_id = ${ProjectId} and r.is_deleted = false and r.component_name is null" | ![]() |
This group represents a collection of entities that allow track baselines and history that are required for tracking changes for every artifacts as well as within every baseline. Since custom lists and custom properties further add definitions to the artifacts themselves, these definitions are also tracked in this section.
Auditability involves tracking changes made. This involves changes made within an artifact as well as changes made to all the artifacts within a release. Hisotry details tracks changes to an artifact but baselines tracks changes to all artifacts within specific snapshots identified by the change sets.
Spira provides 99 custom properties that can be added to most artifacts. This custom property can be one of the many standard properties (number, text, date, user, release, etc.) or a user defined custom list values. This section also brings this information.
| Scheme Ref | Primary Key | SpiraDocs Reference for Additional Fiels |
|---|---|---|
| Baselines | Baseline_Id | SpiraTestEntities.R_Baselines |
| HistoryChangeSets | ChangeSet_Id | SpiraTestEntities.R_HistoryChangeSets |
| HistoryDetails | SpiraTestEntities.R_HistoryDetails | |
| CustomLists | Custom_Property_List_Id | SpiraTestEntities.R_CustomLists |
| CustomListValues | Custom_Property_Value_Id | SpiraTestEntities.R_CustomListValues |
| CustomPropertyDefinitions | SpiraTestEntities.R_CustomPropertyDefinitions | |
| Global_HistoryDetails | Artifact_History_Id | SpiraTestEntities.R_Global_HistoryDetails |
| GlobalHistoryChangeSets | ChangeSet_Id | SpiraTestEntities.R_HistoryChangeSets |
| GlobalCustomPropertyDefinitions | Custom_Property_Id | SpiraTestEntities.R_GlobalCustomPropertyDefinitions |
| GlobalCustomListValues | Custom_Property_Value_Id | SpiraTestEntities.R_GlobalCustomListValues |
| GlobalCustomLists | Custom_Property_List_Id | SpiraTestEntities.R_GlobalCustomLists |
| Query | Result |
|
select h.artifact_id, h.field_Name, h.old_value, h.new_value, h.changeset_id, h.changer_name, h.change_date from SpiraTestEntities.R_HistoryDetails as h join SpiraTestEntities.R_ArtifactTypes as at on at.artifact_type_id = h.artifact_type_id and at.name = "Test Case" join SpiraTestEntities.R_HistoryChangeSets as hc on hc.changeset_id = h.changeset_id where hc.project_id = ${ProjectId} | ![]() |
| Query | Result |
|
select b.baseline_id, b.name as baseline_name, b.changeset_id, b.release_id, b.last_update_date, b.artifact_type_name, b.changeset_type_name, h.artifact_id from SpiraTestEntities.R_Baselines as b join SpiraTestEntities.R_HistoryDetails as h on b.changeset_id = h.changeset_id where b.project_id = ${ProjectId} and b.changeset_creator_login = "administrator" and b.release_id = ${ReleaseId} | ![]() |
| Query | Result |
|
select i.Incident_id, i.name, clv.custom_property_list_name as ListName, clv.name as ListValue from SpiraTestEntities.R_Incidents as i INNER JOIN SpiraTestEntities.R_CustomListValues as clv on Contains(i.cust_01, Concat(Concat('0', cast(clv.custom_property_value_id as Edm.String)), ',')) or EndsWith(i.cust_01, Concat('0', cast(clv.custom_property_value_id as Edm.String))) or StartsWith(i.cust_01, cast(clv.custom_property_value_id as Edm.String)) where i.project_id = clv.project_id clv.custom_property_list_id = 1 i.project_id = ${ProjectId} i.incident_status_name = "Open" clv.is_deleted = false i.is_deleted = false order by i.name, clv.custom_property_list_name | ![]() |
This group represents a collection of program level entities relating to Capabilities and Milestones that are mapped to individual product level requirements and releases.
The Program Management support builds on functionalities bigger than the product level needs. At the program level, the higher level capabilities (i.e., benefits) are strategically alinged with one or more product level requirements. Similarly, the strategic milestones at the program levels are connected with one or more product level release cadence.
This section also brings this information. The entities related to Projects, ProjectGroups, and Releases were described in Essential PPM section.
| Scheme Ref | Primary Key | SpiraDocs Reference for Additional Fiels |
|---|---|---|
| ProjectGroupCapabilities | Capability_Id | SpiraTestEntities.R_Capabilities |
| ProjectGroupCapabilityProjectRequirements | Capability_Id, Requirement_Id | SpiraTestEntities.R_ProjectGroup_Capability_Project_Requirements |
| ProjectGroupCapabilityPriorities | Priority_Id | SpiraTestEntities.R_ProjectGroup_Capability_Priorities |
| ProjectGroupCapabilityStauses | Status_Id | SpiraTestEntities.R_ProjectGroup_Capability_Statuses |
| ProjectGroupCapabilityTypes | Type_Id | SpiraTestEntities.R_ProjectGroup_Capability_Types |
| ProjectGroupMilestones | Project_Group_Milestone_Id | SpiraTestEntities.R_R_ProjectGroup_Milestones |
| ProjectGroupMilestoneTypes | Type_Id | SpiraTestEntities.R_R_ProjectGroup_Milestone_Types |
| ProjectGroupMilestoneStatuses | Status_Id | SpiraTestEntities.R_ProjectGroup_Milestone_Statuses |
| ProjectGroupMilestoneProjectReleases | Project_Group_Milestone_Id | SpiraTestEntities.R_ProjectGroup_Milestone_Project_Releases |
| Query | Result |
|
select pgc.project_group_id as program_id, pgc.project_group_name as program_name, c.capability_id, c.capability_name, r.project_name, c.requirement_name from SpiraTestEntities.R_ProjectGroup_Capability_Project_Requirements as c join SpiraTestEntities.R_Requirements as r on r.requirement_id = c.requirement_id join SpiraTestEntities.R_ProjectGroup_Capabilities as pgc on pgc.capability_id = c.capability_id and pgc.project_group_id = r.project_group_id where pgc.project_group_id = ${ProjectGroupId} and pgc.is_deleted = false and r.is_deleted = false | ![]() |
| Query | Result |
|
select c.project_group_id as program_id, c.project_group_name as program_name, c.project_group_milestone_id, c.name as milestone_name, c.status_name as status, r.project_name, r.name as release, r.release_status_name as rel_status from SpiraTestEntities.R_ProjectGroup_Milestones as c join SpiraTestEntities.R_ProjectGroup_Milestone_Project_Releases as m on m.project_group_milestone_id = c.project_group_milestone_id join SpiraTestEntities.R_Releases as r on r.release_id = m.release_id where c.project_group_id = ${ProjectGroupId} and c.is_deleted = false and r.is_deleted = false | ![]() |
| Query | Result |
|
select c.capability_id, c.name, c.status_id, c.status_name, c.type_id, c.type_name, c.priority_id, c.priority_name from SpiraTestEntities.R_ProjectGroup_Capabilities as c where c.PROJECT_GROUP_ID = ${ProjectGroupId} | ![]() |