Database Customization

SQL Naming Standards is a highly charged topic. The debate on the use of a 2 or 3 character prefix denoting the type of database object continues to this day. To make matters worse there are many so called SQL Naming Standards out there and not one of them has been adopted by Microsoft.
The objective of adopting a good SQL Naming Standard for database objects is to limit ambiguity and to aid in the ability of developers including yourself to intuit the nature of an object. There is one key point, however, that both sides can agree upon: regardless of the decisions made, be consistent with the selected convention.

EngageIP SQL Naming Standard

First some don'ts

The following are some things to avoid when naming objects in the database:

  • Avoid using object names that require quotes.

  • Avoid names with white spaces or special characters (especially dashes).  For example, naming a table "Order Detail" or "Order-Detail", instead of "OrderDetail" or "order_detail" can lead to hours of aggravated debugging.

  • Avoid reserved keywords for object names. Naming a table or field "User" can also lead to aggravated hours of debugging.

  • Avoid using data types as object names. Naming a field "Date" can also lead to aggravated hours of debugging.

  • Avoid abbreviations since SQL Server allows 128 Characters for a database object name.

Some of the Object types and their acronym prefixes used in this page are:

  • AK = Alternate Key UNIQUE Constraint

  • CK = CHECK Constraint

  • DF = DEFAULT (constraint or stand-alone)

  • FK = FOREIGN KEY Constraint

  • IX = Non Unique Index

  • IXU = Unique Index

  • PK = PRIMARY KEY Constraint

  • PKC = Clustered PRIMARY KEY

  • TR = DML Trigger

  • UDF = User Defined Function

  • USP = User Stored Procedure

  • VIEW = View

  • XP = Extended Stored Procedure

Other acronym prefixes will be discussed in their related sections.

All object names should use Pascal Case: The first letter of each concatenated word is capitalized. For example: StatementDetails and InvoiceRender.

SQL Objects

Tables

Tables are the basic storage object and do not require any prefix to identify them as such. Table names should be singular not plural. EngageIP uses both in some cases for historical reasons. The majority of the EngageIP tables use singular name notation as in:

  • AuditLog

  • ContactPoint

  • InventoryItemStatusType

Table names should normally be nouns and should not normally have verbs in the name.

Any non core tables should begin with an underscore ("_").

Any custom table needs to be identified by a leading underscore and the customer name. For example, _CustomerName_TableName.

Views

Naming standards for database views is by far the most contentious of all the SQL naming standards. A view can be used to perform so many different tasks

  • Security

    • to filter out rows from another department that the user should not see with a where clause.

    • to filter out columns like salary that the user should not see by not including those fields in the definition.

  • Join two or more tables or even join additional views.

  • Report query definition.

EngageIP uses a prefix of "View" with no trailing underscore followed by a unique name. The general naming convention is: View<UniqueName>.

Some concrete examples are:

  • ViewPaymentGroupByUser

  • ViewSearchUserAttributeProfileAnswer

Do not differentiate between View & Materialized View with a prefix as view names will be in code. Changing a view to a materialized view and changing the name will break the code.

There are two points of view on naming database views:

  • Logical naming - uses a descriptive name for the function of the view.

  • Physical naming - list the table names separated by underscores in the name.

As a view acts similarly to a table, it should be named accordingly with nouns.  It should not normally have verbs in the name. The only real difference, besides the storage of the data, between a table and a view is that a view may not be update-able. By prefixing the view name with the word "View" it can help developers to immediately know they are working with a view and not a regular database table.

If physical naming is used and the view combines entities with a join condition or where clause, be sure to combine the names of the entities separated by underscores ("_") that are joined in the name of the view. There are many views in EngageIP where this is impractical as the number of joins is in the dozens.

Any views created specifically for an EnagageIP report should use the report name and end with the suffix "Report". For example:

  • ViewAgedInvoiceDetailReport

  • ViewBatchPaymentReport

Any views that are added in addition to the standard EngageIP deployment schema should begin with an underscore ("_") prefix. For example:

  • _ViewPricePlanTotal

  • _ViewTierSyncDuplicateServices

Any custom view needs to be identified by a leading underscore and customer name as in  "_<CustomerName>_View<UniqueName>"

An indexed view should begin with an additional prefix of "ivw_" at the beginning of the name. For example, "ivw_ViewAccountPayableReportPerUser".

Scripts

EngageIP includes several scripts as part of the core product deployment. These script names use the prefix "us_" to denote that they are a user script. The name format is  us_<ScriptName>  where <ScriptName> is a self documenting name of the script. As a script performs some task or function on some object or objects the script name should have both a verb and a noun in the name. For example:

  • us_LS_Adjust_ConnectorIndexes

  • us_LS_Rename_PK_ClusteredIndexes

Any scripts that are created for a customer deployment of EngageIP should have a leading underscore, "_", and the customer name in the script name. For example, "_CustomerName_us_ScriptName".

Stored Procedures

EngageIP includes several stored procedures as part of the core product deployment. These script names use the prefix "usp_" to denote that they are user stored procedures. The name format is  "usp_<StoredProcedureName>"  where <StoredProcedureName> is a self documenting name of the stored procedure. A stored procedure performs some task and thus the procedure name should be descriptive of that task. Stored procedure names should have both a verb and a noun in the name.  For example:

  • usp_GetInvoice

  • usp_LS_ReGenStatistics.

Stored procedures should have at least one consistent prefix like "usp_". For historical reasons EngageIP has a mix of naming conventions for some older stored procedures.

For example:

  • GetOwnerTree - has no prefix

  • sp_UDRRatePlanCompare - "sp" is a poor prefix choice as it should only be used by Microsoft

  • Support_ExportDateAnalysis - "Support" prefix denotes a stored procedure used during support activities but is not prefixed correctly

  • usp_LS_RebuildIndexes - "usp_" is using the recommended prefix naming convention

Any non core EngageIP stored procedures should begin with an underscore ("_").

Any custom stored procedures should have a leading underscore, "_", and the customer name in the name. For example,  "_CustomerName_usp_StoredProcedureName"

Functions

EngageIP includes several functions as part of the core product deployment. These function names use the prefix "udf_" to denote that they are user defined functions. The name format is  "udf_<FunctionName>"  where <FunctionName> is a self documenting name of the function. A function performs some task and the name of the function should be descriptive of that task. Function names will normally have both a verb and a noun in the name. For example, udf_GetUsersBalance.

It is important that function names should also differentiate between scalar, inline and table level functions. Forethought should be used as function names will be in code and changing a scalar or inline function to a table level function and changing the name will break the code as well as requiring a different calling method.

The following is a list of different function types and their recommended prefixes:

  • Scalar - "udfs_"

  • Table - "udft_"

  • Prefix - "udfa_"

  • Other - "udf_"

Due to historical reasons EngageIP has a mix of naming conventions for some older functions.

For example:

  • Extract - is missing the recommended prefix

  • fnExtractSubstring - has a prefix but not the recommended prefix

  • func_GetDateOnly - has a prefix but not the recommended prefix

  • udf_GetUserInitials - has the recommended prefix

Any non core EngageIP functions should begin with an underscore ("_").

Any custom functions should have a leading underscore, "_", and the customer name in the name. For example, "_CustomerName_udf_FunctionName"

Foreign Key Constraints

Foreign keys used in table definitions should use the prefix "fk_" followed by underscore seperated table names between the two tables invovled in the foreign key relationship. Specifically, the format is "fk_<CurrentTableName>_<ReferencedTableName>.

For example:

  • FK_Contact_ContactType

  • FK_StatementDetails_Statement

SQL Agent Jobs

EngageIP includes SQL Agent Jobs as part of the core product deployment. These SQL Agent Job names use the prefix "LS_" to denote that they are created by LogiSense. The name format is  "LS_<SQL Agent Job name>"  where <SQL Agent Job name> is a self documenting name of the SQL Agent Job. SQL Agent Jobs perform some task and the name should be descriptive of that task.

For example:

  • LS_EngageIP_ArchiveUDR

  • LS_EngageIP_RegenStatistics_MediumSize

There are no naming conventions for non core or custom SQL Agent Jobs as their storage location unambiguously identifies them as being SQL Agent Jobs.

Non Queryable objects

Non queryable objects can normally be easily renamed with little or no issues. An Index name however can be used in a query hint and constraint names can be searched for in error messages. Renaming the index or constraint names could break something so caution should be used.

Examples of non queryable objects:

  • Indexes

  • Constraints

  • Triggers

Indexes do have a recommended naming convention in EngageIP outlined in a section below while contstraints and triggers do not.

Queryable objects

Care has to be used with queryable objects as different functionality can be added to perform some modified function. The name may no longer be accurate and changing the name may break the code that depends on it.

Examples of queryable objects:

  • Table names

  • User stored procedures

  • User defined functions

  • View names

Core vs. non-Core Objects

EngageIP includes numerous objects as part of the core product deployment.  These naming conventions are detailed in this page.  It is necessary to differentiate between the following non core object types with regards to additional naming conventions that should be applied:

  • Logisense provided custom objects - Starts with the prefix "_LS_".  For example, "_LS_IX_StatementDetails_PackageIDExtra"

  • Customer supplied custom objects - Starts with the prefix "_XY_" where "XY" is a two character abreviation for the customer name. For example, "_AC_IX_UDR_UserServiceID_UDRBillerID" for Acme Corp.

  • Temporary objects - Starts with two underscore characters followed by a two character abbreviation for the author followed by an underscore. For example, if John Smith creates an object the prefix would be "__JS_".  A optional "_<date>" suffix for temporary objects can also be used to help identify the history of the temporary object.

  • EngageIP Support team tables use the following convention: "sup_bak_TS<ticket number>_<tablename>_<date>". For example, "sup_bak_TS1234_StatementDetails_20170125" for backing up the StatementDetails table, for ticket TS-1234 on Jan 25th, 2017.

The date format to be used is "yyyymmdd" where "yyyy" is a 4 digit year, "mm" is a two digit month, and "dd" is a two digit day.

Indexes

Indexes are non queryable objects and should be relatively easy to convert to any naming standard.

There are many different types of indexes in SQL Server and many different naming standards. The recommended naming convention is as follows:

  • PK_ Primary Key Constraint Non Clustered as in: PK_TableName_ColumnName/s

  • PKC_ Clustered Primary Key Constraint as in: PKC_TableName_ColumnName/s

  • IXUC_ Clustered Unique Index as in: IXUC_TableName_ColumnName/s

  • IXC_ Clustered non Unique Index as in: IXC_TableName_ColumnName/s

  • IXU_ Unique non Clustered Index as in: IXU_TableName_ColumnName/s

  • IX_ Non Unique non Clustered  as in: IX_TableName_ColumnName/s

  • AK_ Alternate Key Unique Constraint  as in: AK_TableName_ColumnName/s

  • IXF_ Filtered Index as in: IXF_TableName_ColumnName/s

  • IXUF_ Unique Filtered Index as in: IXF_TableName_ColumnName/s

  • IX***_inc Index with Include Fields  as in: IX_TableName_ColumnName/s_inc

Field name conventions

EngageIP core tables place the Clustered Primary Key on the ID field of the table. There are a few exceptions to that rule with respect to date fields. Date fields are named with "Date" as a suffix". For example, InvoiceDate instead of InvoicedOn or DateInvoiced. Another example is CreationDate instead of CreatedOn or DateCreated.

Storage naming standards

The Microsoft standard for storage naming conventions expects this format:

<drive letter>:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER2016\MSSQL\DATA

The problem with the Microsoft recommendation is that it includes a database version in the path.  As the database is upgraded path names either have to change to be accurate or old path names will incorrectly identify the database version being used.  To avoid that problem Logisense uses the convention

  • <drive letter>:\Logisense\Client\data where <drive letter> is the drive partition letter used for this path.   For example, "E:\Logisense\Client\data".

This will be consistent on shared servers as well.

EngageIP uses the following filegroups names for standard deployments:

  • EIPDATAFG - main data file group

  • EIPNDXFG - main data indexes file group

  • LOGDATAFG - log data file group

  • UDRDATAFG - UDR Data file group

  • UDRNDXFG - UDR Data indexes file group

Datafiles should have the naming convention "<DatabaseName>_<FileGroupName>_F<FileNumber>".  In the case of a standard EngageIP deployment the files would look like this:

  • EngageIP_EIPDATAFG_F1

  • EngageIP_EIPNDXFG_F1

  • EngageIP_LOGDATAFG_F1

  • EngageIP_UDRDATAFG_F1

  • EngageIP_UDRDATAFG_F2

  • EngageIP_UDRNDXFG_F1

  • EngageIP_UDRNDXFG_F2

The EngageIP storage naming standard has a mix of naming conventions due to historical reasons.