Using Rules to Enforce Data Integrity - Some ExamplesFebruary 28, 2001 There are many aspects involved in creating a well-designed database that insure the integrity of the data that it contains. The proper use of data types, identity columns, nullability, defaults, primary keys, and foreign keys all go a long way in making sure that the business rules for the database are maintained. As part of this concept of data integrity is the idea of a domain. A domain is a set of all the valid values that a column might have. One of the ways to enforce a domain is by creating a look up table to support a column in a primary table and assigning a foreign key to that column which references the look up table. This insures that the data for that column can only be selected from the target table or remain null if Null is allowed. Sometimes creating a lookup table is not practical. For instance, if I wanted to insure that the user entered a valid zip code number, I would not create a lookup table of every zip code value that was valid because the valid range for a zip code is 00601 through 99950. Obviously, a more practical plan must be devised. Let's look at two possible scenarios to solve this problem by creating user defined fields and rules. Then we will discuss one more example of how to validate an employee social security number. Example #1 - the zip code Scenario # 1:
Try It Out: insert into tblzip1 ( zip1 ) values ( 600 ) Results: Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblzip1', column 'zip1'. The statement has been terminated. insert into tblzip1 ( zip1 ) values ( 601 ) Results : (1 row(s) affected) insert into tblzip1 (zip1) values( 00799 ) Results : (1 row(s) affected insert into tblzip1 ( zip1 ) values ( 60077 ) Results : (1 row(s) affected) insert into tblzip1 (zip1) values ( 99951 ) Results: Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblzip1', column 'zip1'. The statement has been terminated. select * from tblzip1 Results: zip1 ----------- 601 799 60077 (3 row(s) affected) While the first scenario meets some of the criteria of limiting the values of the zip code, it is not very appealing because we would like every zip code to contain 5 digits. By using an integer, we lose the ability to have leading zeros as part of the data as can be seen when we insert 00799 into the table. Scenario # 2 :
Try It Out: insert into tblzip2 ( zip2 ) values ( '600' ) Results: Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblzip2', column 'zip2'. The statement has been terminated. insert into tblzip2 ( zip2 ) values ( '601' ) Results : Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblzip2', column 'zip2'. The statement has been terminated. Note: This time the insert failed because of the length of the string. insert into tblzip2 ( zip2 ) values ( '00601' ) Results : (1 row(s) affected) insert into tblzip2 (zip2) values( '00799' ) Results : (1 row(s) affected insert into tblzip2 ( zip2 ) values ( '60077' ) Results : (1 row(s) affected) insert into tblzip2 values ( 'a1234' ) Results: Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblzip2', column 'zip2'. The statement has been terminated. insert into tblzip2 ( zip2 ) values ( 99951 ) Results: Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblzip2', column 'zip2'. The statement has been terminated. select * from tblzip2 Results: zip2 ----- 00601 00799 60077 (3 row(s) affected) Note: We maintain our leading zeroes and always have 5 numeric characters by using this scenario. Example #2 - Social Security number Let's try one more example. In this case we need to validate an employee's social security number to insure that it has 9 digits and they are all numeric.
Try It Out: insert into tblemp values( '123' ) Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblemp', column 'emp_num'. The statement has been terminated. insert into tblemp values( '123456789' ) Results: (1 row(s) affected) insert into tblemp values( 'a12345678' ) Results: Server: Msg 513, Level 16, State 1, Line 1 A column insert or update conflicts with a rule imposed by a previous CREATE RULE statement. The statement was terminated. The conflict occurred in database 'rules_demo', table 'tblemp', column 'emp_num'. The statement has been terminated. In this article , we have shown how by using user-defined fields and assigning rules to them, we can extend our ability to insure data integrity by using domains. |