programming4us
programming4us
DATABASE

Reusing T-SQL Code - Reusing Business Logic: Stored Procedure, Trigger, Constraint or Index?

4/30/2013 7:56:23 PM

There are several ways in which we can choose to implement our business logic. For example, we could use:

  • stored procedures

  • constraints

  • triggers

  • unique filtered indexes.

Over the coming sections we'll discuss the sort of situations where each approach may, or may not be appropriate

Use constraints where possible

In many cases, constraints are the easiest and simplest to use. To demonstrate this point, consider the Teams table shown in Listing 1, with a primary key constraint on the TeamID column.

Listing 1. Creating the Teams table.

Since we wish to forbid access to the base tables, teams will be inserted into the table, one at a time, by calling a stored procedure. Our business rule is simple: team names must be unique. So, we need to decide where to implement this business rule. One choice is to enforce it in the stored procedure, as shown in Listing 2.

Listing 2. The InsertTeam stored procedure inserts a team, if the team name does not already exist in the table.

So, we have a stored procedure that enforces our rule, at least in the absence of high concurrency. However, what happens when we need another stored procedure that modifies a single row in the Teams table, or one that merges a batch of new rows into that table? We'll need to re-implement this same logic for every stored procedure that modifies this table. This is a form of copy-and-paste and is both time consuming and error prone.

Besides, unless you can guarantee that no applications can run modifications directly against the Teams table, it's likely that your business rule will be bypassed at some point, and inconsistent data will be introduced.

It is much easier and safer to just create the business rule once, in one place, as a UNIQUE constraint, as shown in Listing 3.

Listing 3. The UNQ_Teams_Name constraint enforces the uniqueness of team names.

We can now let the database engine make sure that this business rule is always enforced, regardless of the module or command that modifies the table.

Turn to triggers when constraints are not practical

As we have seen, constraints are extremely useful in many simple cases. However, our business rules are often more complex, and it is sometimes not possible or not practical to use constraints. To demonstrate this point, let's add one more table, TeamMembers, which references the Teams table through the TeamID column, as shown in Listing 4.

Listing 4. Creating the TeamMembers table.

Suppose that we need to implement the following business rule: no team can have more than two members. Implementing this business rule in a trigger is quite straightforward, as shown in Listing 5, and you only have to do it once. It is possible, but much more complex, to implement this rule via constraints.

Listing 5. The TeamMembers_TeamSizeLimitTrigger trigger ensures that the teams do not exceed the maximum size.

With our business rule implemented in only one place, we can comprehensively test just one object. In order to test this trigger, we need some test data in our parent table, as shown in Listing 6.

Listing 6. Adding some test data to the Teams table.

The script shown next, in Listing 7, verifies that we can successfully add new team members, as long as the teams' sizes do not exceed the limit imposed by our trigger.

Listing 7. Testing the _TeamSizeLimitTrigger trigger with valid INSERTs.

The script shown next, in Listing 8, verifies that we can successfully transfer team members between teams, as long as the teams' sizes do not exceed the limit.

Listing 8. Testing the _TeamSizeLimitTrigger trigger with valid UPDATEs.

So, we've proved that our trigger allows modifications that do not violate our business rules. Now we need to make sure that it does not allow modifications that do violate our business rules; there are quite a few cases, and we need to verify them all. First of all, Listing 9 verifies that we cannot add new team members if the resulting teams' sizes are too big. All the statements in the script must, and do, fail.

Listing 9. Testing the _TeamSizeLimitTrigger trigger with invalid INSERTs.

Also, we need to make sure that we cannot transfer team members if the resulting teams' sizes are too big, as shown in Listing 10. Again, all the following statements fail as expected.

Listing 10. Testing the _TeamSizeLimitTrigger trigger with invalid UPDATEs.

The amount of testing needed to ensure that a trigger works as expected can be quite substantial. However, this is the easiest alternative; if we were to re-implement this business rule in several stored procedures, then the same amount of testing required for the single trigger would be required for each of these procedures, in order to ensure that every one of them implements our business rule correctly.

Unique filtered indexes (SQL Server 2008 only)

Last, but not least, in some cases filtered indexes also allow us to implement business rules. For example, suppose that we need to make sure that each team has at most one team lead. If you are using SQL Server 2008 and upwards, then a filtered index can easily implement this business rule, as shown in Listing 11. I encourage you to try out this index and see for yourself that it works.

Listing 11. The TeamLeads filtered index ensures that each team has at most one team lead.
Other  
 
Top 10 Video Game
-   Minecraft Mods - MAD PACK #10 'NETHER DOOM!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #9 'KING SLIME!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #2 'LAVA LOBBERS!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Minecraft Mods - MAD PACK #3 'OBSIDIAN LONGSWORD!' with Vikkstar & Pete (Minecraft Mod - Mad Pack 2)
-   Total War: Warhammer [PC] Demigryph Trailer
-   Minecraft | MINIONS MOVIE MOD! (Despicable Me, Minions Movie)
-   Minecraft | Crazy Craft 3.0 - Ep 3! "TITANS ATTACK"
-   Minecraft | Crazy Craft 3.0 - Ep 2! "THIEVING FROM THE CRAZIES"
-   Minecraft | MORPH HIDE AND SEEK - Minions Despicable Me Mod
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 92 "IS JOE DEAD?!"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 93 "JEDI STRIKE BACK"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 94 "TATOOINE PLANET DESTRUCTION"
-   Minecraft | Dream Craft - Star Wars Modded Survival Ep 95 "TATOOINE CAPTIVES"
-   Hitman [PS4/XOne/PC] Alpha Gameplay Trailer
-   Satellite Reign [PC] Release Date Trailer
Video
programming4us
 
 
programming4us