Author: way0utwest

  • Why Don’t You Unit Test Code?

    First, I’ll apologize to those that do use formal, automated tests in advance. I’m not really writing for you, and I’m sure you can teach me more about testing. Perhaps you can comment about how and why you do this, or even write some articles to help others.

    For everyone else, why don’t you test in a repeatable fashion? Let me know with a comment today.

    One thing I’ve noticed as I’ve talked DevOps and testing for a number of years is that so many developers agree testing is a good idea, but claim they have no time, no support from management, or no need to repeat tests once code is written. Sometimes I hear all three excuses at the same time. The same people will also admit that they have problems with code at times, and that quality could be improved.

    Perhaps it’s me, but I’ve never had my boss sit there and watch me code. He or she doesn’t know how I might write code. I certainly write a query, run it, and look at a bunch of rows and see if I think the code is correct. Perhaps I need to run other queries to verify values in the results. However, I could also build a quick test with something like tSQLt, like the one I set up for checking COALESCE that does the same thing. With my unit test, I can run it over and over, modifying the test as I discover new edge cases to validate. Which way do you want to write code?

    Even if I have a set of data I need to assemble, it doesn’t take much longer for me to write a test, especially when I need to also solve the problem. I find that putting a test together forces me to slow down and think about the rules for my code. Since I need to come up with some result set, building that into a test of some sort is fairly easy and let’s me double check how I think data will change. I can then repeat the test over and over as I modify code. I can even grab sample data from production and use that as the basis for my unit test if I need to check a specific entity’s values.

    I know many things I write in SQL might not be worth a test. Often the simple CRUD queries and basic aggregations aren’t things I’d test, but when my query becomes complex, includes APPLY or outer joins, and logic to decide how to filter or format data, wouldn’t a unit test make sense? What about if you want to be sure you’re processing the correct rows from a large CUBE or ROLLUP operator? Certainly if I’m fixing a bug, writing tests makes sense, at least I think so.

    Let me know what you think today.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 4.0MB) podcast or subscribe to the feed at iTunes and Libsyn.

  • Compound FKs with SQL Data Generator

    This is a series on SQL Data Generator, covering some interesting scenarios I’ve run into. If you’ve never tried it, SQL Data Generator is a part of the SQL Toolbelt. Give it a try today with an evaluation today.

    A person was wondering about how data is generated with SQL Data Generator and foreign keys. In this case, the person was having an issue with a compound foreign key.

    Here’s a quick look at how this works. I’ve got two tables

    CREATE TABLE Product
    (   ProductCode VARCHAR(30) PRIMARY KEY
       , ProductDesc VARCHAR(100))
    ;
    CREATE TABLE SubProduct
    (   SubProductCode VARCHAR(30)
       , ProductCode    VARCHAR(30)
       , SubProductDesc VARCHAR(100)
       , CONSTRAINT SubProductCodePK PRIMARY KEY (ProductCode, SubProductCode)
    );
    ALTER TABLE dbo.SubProduct
    ADD
         CONSTRAINT fk_SubProduct_ProductCode FOREIGN KEY (ProductCode)
                          REFERENCES dbo.Product (ProductCode)
    ;
    GO

    These two tables are related with a FK. In this case, SubProduct relates to Product, but there is a constraint that says I can’t have duplicate product/subproduct combinations. That’s fine, and my data looks like this:

    2017-09-27 12_58_04-SQLQuery1.sql - (local)_SQL2016.sandbox (PLATO_Steve (63))_ - Microsoft SQL Serv

    Now, I have a new table, this one contains a FK back to the other tables. In fact, I have two FKs, though I could deal with one.

    ALTER TABLE dbo.SubProduct
    ADD
         CONSTRAINT fk_OrderItems_ProductCode FOREIGN KEY (ProductCode) REFERENCES dbo.Product
                                              (   ProductCode)
    ;
    ALTER TABLE OrderItems
    ADD
         CONSTRAINT fk_OrderItems_SubProductCode_within_ProductCode FOREIGN KEY
                                                                 (
                                                                     ProductCode
                                                                   , SubProductCode) REFERENCES dbo.SubProduct
                                                                 (
                                                                     ProductCode
                                                                   , SubProductCode)
    ;

    This FK is compound, consistenting of both ProductCode and SubProductCode. What does this mean? It means I can’t have an entry in OrderItems for a SubProductCode unless that SubProductCode has a matching ProductCode in the SubProduct table.

    Or, in better English, If I have a Product Code of “RXZP”, of which I have 2 above, I can’t have a SubProductCode of “BA”, which isn’t in the table. I’ve constrained my SubProductCodes to those values that are available for a particular ProductCode. In this case, my only SubProductCode choices are “TJ” and “TW”.

    A good data consistency model.

    In Data Generator, this DRI is picked up. If I look at the generation for the OrderItems table, I see that both ProductCode and SubProductCode are listed as FK values.

    2017-09-27 13_10_49-SQL Data Generator - datagen_fk.sqlgen _

    That’s good, but I have two FKs on OrderItems. Which one is important? In this case, I can click the column and see. For ProductCode, it’s using the compound FK.

    2017-09-27 13_11_41-SQL Data Generator - datagen_fk.sqlgen _

    The same thing appears for the SubProductCode

    2017-09-27 13_11_47-SQL Data Generator - datagen_fk.sqlgen _

    If I generate data, I then get something like this:

    2017-09-27 13_27_58-● SQLQuery1 — carbon

    As you can see, my product “RXZP” will all have “TJ” or “TW”. I know this because the FK will prevent anything else. This is handled and enforced by SQL Server, but Data Generator doesn’t create any errors when it generates the data since it’s using the source tables as the domain of possible values.

    The User’s Problem

    The user in this case didn’t have any DRI declared in this way. Their schema actually had the primary key in Subproduct as only the SubProductCode, not as a compound primary key. Their FK from OrderItems had the same issue, with a FK only to SubProductCode. As a result, Data Generator, and really any script, would assume that all values in SubProductCode are valid, regardless of ProductCode.

    The lesson here is that DRI matters, and if you have business rules such as these, use a FK to enforce them.

  • Teaching Quickly

    I’m a constant learner. I try to regularly experiment and try new things at work and in the rest of my life. For work, sometimes this means working outside of the other hours and commitments I have to get better at manipulating data. Sometimes I go deep and sometimes I just want the general gist of how to solve a problem I’m having. Time constraints come into play at times because there’s never enough. Even with limited time, I do want to understand the reasons why things work, or why I should make a choice for some function/method/framework/pattern/etc.

    I’ve been working with R a bit this summer, trying to learn a bit more. I’ve tried tryr.codeschool.com as a guided tour, but sometimes it doesn’t help me understand enough of the details. Even as I experiment, I’m going through the motions. I purchased R in a Nutshell, and just got Stephanie Locke’s Working with R. I’m hoping these books will give me a more thorough grounding in R.

    As I’m learning, I always want to ensure I understand the implications of how I may write scripts. What do my choices mean for quality, performance, etc. Sometimes trying to understand why slows me down, and I don’t get much done. That’s fine, and maybe that’s for the better. However, I don’t want to learn slowly by going through all the pain that someone else went through. I want to know how someone would write code today, and why they do so.

    I ran across this post on learning the hard way. It discusses the way some people try to teach others, and I’ve been through some of this as I’ve tried to learn various technologies. The teacher sometimes wants to assume I am going through their pain and can sympathize, but often I’m learning something new for the first time. I’m sure I’ve been guilty of this as well, perhaps trying to level set or show an old (or poor) practice to emphasize why it’s better to write code in a new way.

    The thing is that my time is precious, and I shouldn’t have to work through the mess of the way things used to work to build good habits today. What’s new to someone might not be new to all, and certainly at some point, all code isn’t new anymore. I’d rather teachers, and me, sometimes focus on giving us good habits today. Teach us the right way now, and spend time on error handling, testing, or other good habits. Certainly there are cases where we need to know about the changes to systems, but explain this is an upgrade section. And then tell me what’s different, don’t wax nostalgic on the way you once were forced to find innovative solutions.

    Steve Jones

    The Voice of the DBA Podcast

    Listen to the MP3 Audio ( 3.9MB) podcast or subscribe to the feed at iTunes and Libsyn.

  • Enabling Database Containment for an Instance – #SQLNewBlogger

    Another post for me that is simple and hopefully serves as an example for people trying to get blogging as #SQLNewBloggers. This is also a part of a basic series on git and how to use it.

    I wanted to test a contained database feature the other day and ran this:

    ALTER DATABASE [sandbox2] SET CONTAINMENT = PARTIAL WITH NO_WAIT
    GO

    However, this didn’t work. I ended up with an error:

    Msg 12824, Level 16, State 1, Line 3

    The sp_configure value 'contained database authentication' must be set to 1 in order to alter a contained database.  You may need to use RECONFIGURE to set the value_in_use.

    The issue is that the server instance needs to have contained authentication enabled in order to pass any authentication requests to the database

    EXEC sys.sp_configure N'contained database authentication', N'1'
    GO
    RECONFIGURE WITH OVERRIDE
    GO

    Now I can run the code again to alter the database for containment.

    SQLNewBlogger

    The issue was obvious to me since I’d dealt with it in the past, but this is something you could solve and write up in 10-15 minutes.