A typical installation of Dynamics GP adds roughly 500 tables to the DYNAMICS
database and each company can generate another 2,000 tables. In addition to the tables, there are over 400 views and 20,000 stored procedures per company. That's right, 20,000. This is a big data model to navigate! What makes it even more challenging is that there are no foreign keys defined for the tables. Without foreign keys you cannot easily discern which tables are related to which other tables. As you can see in the following screenshot, a quick scan of SQL Server Management Studio doesn't yield much more information:
It is no surprise when clients tell me they are very confused by the seemingly cryptic table names. We're so used to those legacy table names that we don't appreciate what a wonder it must be for a new user or developer.
Any effort that involves manipulating data or creating reports will sooner or later result in the question How do we know which table to use? This query spawns much gnashing of teeth and all sorts of unusual behavior. So, what do the table names mean?
There is actually a very good naming convention for Dynamics GP data tables. However, this is only a convention. While you will not be arrested by the table-naming police for not following the convention, adhering to a standard makes it easier on everybody. The published naming conventions were followed by the Dynamics GP programmers pretty diligently, but not so much by many third-party developers. Here are the basics: the first two or three characters will indicate the module name, and the remaining numbers indicate the type of table.
Some of the more popular module prefixes are listed in the following table:
Prefix |
Module |
---|---|
AA |
Analytical Accounting |
AF |
Advanced Financial Analysis |
AHR |
Advanced Human Resources |
APR |
Advanced Payroll |
ASI |
SmartList Favorites |
BM |
Bill of Materials |
CM |
Cash Management (Bank Rec) |
DD |
Direct Deposit |
DTA |
Multi-dimensional Analysis |
ECM |
Enhanced Commitment Management |
EDCML |
Multilingual Checks |
EDCVAT |
VAT Daybook |
EHW |
Employee Health and Wellness |
ENC |
Encumbrance Management |
ERB |
Excel ReportBuilder |
EXT |
Extender |
FA |
Fixed Assets |
GL |
General Ledger |
HR |
Human Resources |
IV |
Inventory |
IVC |
Invoicing (NOT Sales Order Processing) |
LK |
Linked Transactions |
MC |
Multicurrency |
ME |
EFT (Electronic Funds Transfer) |
MX |
Electronic Signatures / Audit Trails |
PA |
Project Accounting |
PM |
Payables Management (Accounts Payable) |
POP |
Purchase Order Processing |
RM |
Receivables Management (Accounts Receivable) |
RVLP |
Payables Document Management |
SLB |
SmartList Builder |
SOP |
Sales Order Processing |
SVC |
Field Service |
SY |
System or Company |
UPR |
US Payroll (Canadian payroll is CPR) |
WDC |
Field-Level Security (Advanced Security) |
After the prefix, the number indicates the table type. Knowing these numbers will help you zero in on the correct table. The following table sets out the numbering convention used to indicate the table type.
Developers often put their company's initials at the beginning of the table name. For instance, table WDC41101
is the Advanced Security Setup table, which is part of the Advanced Security module. The Advanced Security module was developed by Winthrop Dexterity Consultants (WDC).
Table number |
Description |
Abbreviation |
---|---|---|
00000 |
Master tables |
MSTR |
10000 |
Work tables |
WORK |
20000 |
Open tables |
OPEN |
30000 |
History tables |
HIST |
40000 |
Setup tables |
SETP |
50000 |
Temp tables |
TEMP |
60000 |
Relation tables |
REL |
70000 |
Report Options tables |
ROPT |
80000 |
Posting Journal Reprint tables |
REPRINT |
90000 |
A mixed bag. There is no consistency in this group |
An explanation of how data flows through the WORK, OPEN, and HIST tables deserves its own section; the remaining table types are covered next.
Master tables are mostly what you find under the "Cards" area. These are your Customers, Vendors, Inventory Items, GL Accounts, and the like. For instance, the information you see on the Customer Maintenance window is stored in the RM00101
table.
Setup tables include choices you have made to initiate a module. For instance, the information entered on the Payables Management Setup window is stored in the PM40100
table.
Temp tables are tables that are used temporarily by the system and the records in those tables can normally be deleted without issue. For instance, the Net Profit Temporary table or AF50000
table is used by the Advanced Financial Analysis module to hold the Net Profit amount that will be used on one of the financial statements. Once the statement has been printed, the number is irrelevant.
Relational tables are used to store information that spans more than one module. For instance, the SOP/POP link table (SOP60100
table) holds the information about POP documents linked to SOP documents. Another example is the Sales Customer Item Cross Reference (SOP60300
table). This table stores how customer item numbers relate to regular item numbers. There are not that many tables in the 60000 range.
Report Options tables contain all of the information you enter in any of the report options windows that defines what information you would like to appear on a particular report. The following screenshot comes from the Payables Trial Balance Report Options window; information recorded on this window would be stored in the Report Options series of tables (PM70500
).
Posting Journal Reprint tables contain all of the information you need to reprint the posting journals. So, don't feel like you MUST print all of those reports the system generates after posting a transaction. The data is waiting for you in these tables, should you ever need to reprint them.
The Miscellaneous tables group is a mixed bag of information. To give you an idea of what kind of information is included in the 90000 tables, take a look at the following table. There you can see the Display names of several 90000 tables.
Physical name |
Display name |
---|---|
CM90000 |
CM Transmission Log |
CM90001 |
Checkbook EFT Log |
CN90000 |
Collections - User Preferences |
ERB90100 |
Data Connection Products |
ERB90200 |
Data Connection Series |
ERB90300 |
Data Connections |
ERB90400 |
Data Connection Restrictions |
ERB90450 |
Data Connection Restriction Values |
PA91301 |
PA Contract Segment Override Header |
PA91304 |
PA Contract Segment Override Detail |
PA92301 |
PA Contract Template Seg Override Header |
PA92304 |
PA Contract Template Seg Override Detail |
PDK90003 |
PDK File Error Log |
PDK90100 |
PDK Security |
PP900000 |
Deferral Opened Periods |
PTO90000 |
PTO Pending Master Conversion |
SE90001 |
Account Rollups Account List Accelerator |
SE988977 |
Account Rollups Options Columns |
SLB90000 |
Third Party GoTo Types |
SY90000 |
SY_User_Object_Store (Dynamics User Object Store) |
SY90100 |
Default Chart of Accounts |
If your customization will be interacting with transactions, you need to understand how the transactions flow through the transaction tables. Generally, there are three phases to a transaction: Work, Open, and History. How transactions move through each of these phases varies by module, with no two modules working exactly the same way, but the concepts are the same.
With a broad brush we will paint the Work phase
of a transaction as an unposted transaction. In my world, the term posted means to be committed to the ledger. Once a transaction is posted, it cannot be deleted nor can it be unposted. Before it is posted, you can still work on it. Therefore, work transactions are not posted. Transactions in the Work phase are stored in the 10000 tables. For example, if you were looking for an unposted inventory adjustment, you would start by looking in the IV10000
table.
The next phase of a transaction is the Open phase. What we know about an Open transaction is that it has been posted, but it is not yet in history. Examples of Open transactions include a vendor invoice that has not been paid by the company or an amount due from a customer as an account receivable. Often, transactions that are in the Open phase are called outstanding transactions. Open transactions are stored in the 20000 tables. If you were hunting down an unpaid vendor invoice, you would look in the PM20000
table.
The final phase of a transaction is the History phase
. A transaction in history has been closed and settled. No amounts are outstanding, nothing is unapplied, and it is a fully completed transaction. How a transaction moves to history is different for each module; whether a transaction can come out of history and move back into the Open phase also varies by module. What we do know about a transaction in history is that it has been posted and is no longer considered open. History transactions are stored in the 30000 tables. A void sales order would be found in the SOP30200
table.
Victoria Yudin has some great information on the popular tables from each module at http://victoriayudin.com/gp-tables/.
You can find a more thorough explanation of how transactions flow through the Work, Open, and History tables at http://tinyurl.com/d5townx.
Whenever Dexterity is used to create a SQL table, a number of stored procedures are automatically created and are used to optimize database performance when performing table operations. The names of most of the auto-generated stored procedures that apply to normal table operations typically begin with zDP_
, followed by the table's physical name and a suffix that indicates the purpose of the stored procedure. The following table lists the purpose and numbers of these procedures:
Suffix |
Purpose |
Quantity |
---|---|---|
F |
First record |
One per key |
L |
Last record |
One per key |
N |
Next record |
One per key |
SD |
Delete a record |
One per table |
SI |
Insert a record |
One per table |
SS |
Select a record |
One per key |
UN |
Unpositioned Next |
One per non-unique key |
For example, the following table shows that the stored procedures are auto-generated for the PM Class Master file (PM00100
). This table has three keys; keys 1 and 2 are unique, key 3 is not.
Stored procedure |
Function |
---|---|
|
Get the first record using key 1 |
|
Get the first record using key 2 |
|
Get the first record using key 3 |
|
Get the last record using key 1 |
|
Get the last record using key 2 |
|
Get the last record using key 3 |
|
Get the next record using key 1 |
|
Get the next record using key 2 |
|
Get the next record using key 3 |
|
Delete a record from the table |
|
Insert a record into the table |
|
Select a record using key 1 |
|
Select a record using key 2 |
|
Select a record using key 3 |
|
Unpositioned next for key 3 which is a non-unique key. Keys 1 and 2 are unique keys |
Other automatically generated stored procedure prefixes include:
Prefix |
Purpose |
---|---|
|
System Manager stored procedures found in the DYNAMICS database |
|
General Ledger |
|
General Ledger Posting |
|
General Ledger Multicurrency Posting |
|
Microsoft Dynamics GP Utilities |
|
Microsoft FRx |
Back in the Dark Ages, we had only eight characters to work with for naming tables and fields. Who needed more than eight characters, right? By following the strict but sensible naming convention described in the previous section, thousands of integrating products have been created including tens of thousands of tables. Using the old naming convention, very few duplicate table names have cropped up.
The new table naming convention includes real words and abbreviations that we all can understand instead of the eight characters we were limited to before. Sounds good, but can you imagine working with an application containing 3,000 tables that are not named in any consistent manner? As with most things, when it comes to naming database tables, consistency is a virtue.
While there is still no table-naming-convention police that will visit your office, we think you will find the table-naming convention described next to be a best practice. This new naming convention is both easy to understand and easy to implement. Dexterity programmers will recognize this as the table's Technical Name .
Table names will comprise of a module abbreviation, followed by a term that describes the contents of the table, followed by a subtype abbreviation (if appropriate), and then by a main type abbreviation:
MODULE_Contents_SUB_MAIN
So the General Ledger chart of accounts would be translated to:
GL_Account_MSTR
The common module abbreviations are the same ones described in the Original table-naming convention section. It's from this table that you would get the GL portion of the previous table name.
The following table shows common subtable abbreviations and the type of subtable. For the Asset Financial Detail Master table of the Fixed Assets module, the new physical name would be FA_Financial_DTL_MSTR
. The DTL portion of the name would come from the following table:
SUB table abbreviation |
Subtype |
---|---|
ADDR |
Address |
BHDR |
Batch Header |
DTL |
Detail |
HDR |
Header |
HTAX |
Tax Header |
LINE |
Line Item |
LTAX |
Line Item Tax |
SERL |
Serial/Lot Number |
DIST |
Account Distributions |
The following table shows common Main table abbreviations. For the Invoicing Transaction History table, the physical name would be IVC_HDR_HIST
. The subtype of HDR comes from the previous table and the Main table type of HIST comes from the following table:
MAIN table abbreviation |
Main type |
---|---|
MSTR |
Master tables |
WORK |
Work tables |
OPEN |
Open tables |
HIST |
History tables |
SETP |
Setup tables |
TEMP |
Temp tables |
REL |
Relation tables |
ROPT |
Report Options tables |
REPRINT |
Posting Journal Reprint tables |
Although SQL allows a table name of 128 characters, the Dexterity limit is 80 characters. Adhering to the most restrictive case of 80 characters will help ensure the portability of integrating applications. As a side note, if we need more than 80 characters for a table name, perhaps we need to reconsider our approach.
The previous tables certainly do not represent the exhaustive list of all possible table abbreviations, but they will get you off to a good start. Your fellow developers will thank you for your consistency. Don't forget to add your company's initials at the beginning of the name; this will both help reduce duplicate table names, and make your module's tables easier to spot.