Tag: T-SQL

  • Common SQL Server Mistakes – Equals NULL

    One thing that I don’t see a lot, but it still happens with people new to SQL Server is the comparisons they’ll make with NULL values. Often those people new to T-SQL will write this:

    select CustomerID, CustomerName
    from Customers
    where SalesRepID = NULL

    The thought here is they are looking for those customers that don’t have a salesrep assigned. Or they might enclose the NULL in quotes, but this won’t work.

    The correct way to do this is:

    select CustomerID, CustomerName
    from Customers
    where SalesRepID Is NULL

    Note the “Is NULL” that will correctly return those customers who have a NULL value stored in that column.

    Why?

    NULL is an unknown value. We just don’t know what value it is, so it’s not a variable in algebra like “x”. In algebra, x=x, but NULL != NULL. Since we don’t know what the value is, and since each row could potentially have a different value (remember every NULL’s value is unknown) we can’t expect any NULL to equal any other NULL.

    NULL isn’t a placeholder like a blank or space, or even zero. It’s an unknown value, so equals (and not equals) does not apply. Instead you need to use “Is NULL” or “Is Not NULL” for your comparisons.

  • T-SQL Tuesday #12 – Misconceptions

    TSQL2sDay150x150 It’s time for T-SQL Tuesday again, and I’m happy to participate again. This is a monthly blog party started by Adam Machanic (Blog|Twitter )that asks people to write on a particular topic all on the same day.

    This month’s theme is misconceptions in SQL Server, hosted by Sankar Reddy. You can read the rules for the party and get information from his blog.

    The Most Common Misconception

    I read a lot of forum posts, literally hundreds a week on all topics in SQL Server. One thing that I consistently see asked is the dreaded:

    “My transaction log has grown so large it filled the disk”

    That’s a common occurrence, too common in my opinion, and while there are people that forget to setup any backups, I also find in the majority of cases people just don’t understand one thing:

    A full backup does not clear the transaction log.

    Too many people assume that the log will get managed by a full backup. It doesn’t. While some log record get included in a full backup, they do not get marked as “backed up” and the space re-used.

    If there is one thing that I wish everyone managing a SQL Server knew, it would be that they need to make full and log backups to properly manage the disk space usage by their logs.

  • Are There That Many GUIDs?

    Do a lot of people actually use GUIDs as Primary Keys? I haven’t used them much, and I would have thought that more people chose identity keys. It seems that most of the demos and examples I see from bloggers and speakers are constantly using identities.

    However an informal survey from Peter Bromberg showed that four times as many people actually had GUIDs as their primary keys. The blog actually says that GUIDs are not a good choice, but I’m not sure I agree with that. You can use sequential GUIDs, and you can avoid making them the clustered key, so I think they can work as well as anything.

    There’s nothing inherently wrong with GUIDs, and they should be unique across all of your rows. There have been some reported cases of duplicates, but for most practical purposes, especially in database work, you ought to be able to count on a GUID as unique. They even have the nice capability of being generated by clients, removing the need for an extra round trip when a client needs to insert multiple rows.

    I typically don’t use them because they’re long, hard to remember and type, and hard to view on the screen. I can’t easily compare rows in multiple tables, and it’s easier for me to work with integers.  I don’t recommend them, but if you are going to use them, be sure you understand the pros and cons, and use them appropriately.

    Steve Jones

  • Return Values from XP_CMDSHELL

    Let’s be clear: I don’t recommend the use of xp_cmdshell as a general tool. It ought to be used when you have no alternatives, and you should carefully control access and what this can do. Opening a shell from SQL Server can be dangerous for your server.

    That being said, I do think there are places that xp_cmdshell works great and if you need to use it, how do you tell if the commands you executed were successful?

    For those of you that have worked in command lines, or remember DOS, there is a thing called an Errorlevel, that is returned by programs when they exit. For many of us that used to program in DOS, we always checked ERRORLEVEL when exiting a program, and we made sure that our program always returned a 0 if it exited without an error. That’s a standard that has been in place as long as I can remember working with computers.

    How can we use this? If I execute this in a command window:

    errorlevel

    I get an instance of Notepad on my screen. When the CD.exe application completes, it sets the errorlevel to 0. Technically it returns a 0 to cmd.exe, which sets the errorlevel to that value.

    What about this:

    errorlevel2

    In this case, nothing happens. However if I switch the command to:

    errorlevel3

    Then I get notepad again.

    How can we use this in SQL Server? When xp_cmdshell exits, it returns the errorlevel from it’s shell. Let’s test it. First, enable xp_cmdshell

    -- To allow advanced options to be changed.
    EXEC sp_configure 'show advanced options', 1
    GO
    -- To update the currently configured value for advanced options.
    RECONFIGURE
    GO
    -- To enable the feature.
    EXEC sp_configure 'xp_cmdshell', 1
    GO
    -- To update the currently configured value for this feature.
    RECONFIGURE
    GO

    Now execute

    DECLARE @i INT
    EXEC
    @i = xp_cmdshell 'dir'
    SELECT @i

    This returns the current directory (\Windows\System32 in this case) and a 0.

    errorlevel4

    Now if we change to our other example:

    DECLARE @i INT
    EXEC
    @i = xp_cmdshell 'cd tim'
    SELECT @i

    We get these results

    errorlevel5

    Since that’s not a valid path on my system, the DOS error is returned as a result, and the errorlevel is returned in the variable assignment.

    You can use this to test and see if your commands execute before you do something, like try to parse a directory listing that isn’t there.