Tag: sql server

  • (Mis)Using DBCC Page

    In one of my presentations recently I was recommending DBCC CHECKDB on every database every day. I realize that isn’t always possible or practical, so I noted that if you don’t have resources on your production server, or enough spare hardware, you should at least run it on every database once a month. At least on the database you care about.

    Someone in the audience asked if they could just script DBCC PAGE on every page in the database instead. I wasn’t sure if that was accurate, but I didn’t think it was. So I asked THE MAN, and he confirmed this doesn’t equate to a DBCC CHECKDB.

    I won’t attempt to give a complete explanation, mostly because I’m sure I’d miss something or be incorrect, but I will tell you how I feel about this, based on what I know.

    CHECKDB performs an extensive evaluation of not only all objects (and hence their pages), but also their linkages. It performs a more complete check by default, but you can add the PHYSICAL_ONLY flag to speed things up and limit the checks to just the physical structures and allocations. PHYSICAL_ONLY also skips Filestream checks.

    The DBCC PAGE command, undocumented, works, but it doesn’t really examine if the links and relationships between pages are correct.

    I can’t say that DBCC PAGE couldn’t be use to detect corruption or find issues, but I wouldn’t depend on it. YMMV, but I wouldn’t use this as a substitute for CHECKDB.

  • Database Maintenance Essentials – Resources

    I told people in New York at SQL in the City that I’d post some resources on the blog from my talk. My apologies for not getting it done over the weekend, but during a little downtime in Austin I’m getting it done.

    Checklist

    From the last slide, a checklist of things for you to look at on your instances.

      • Backups scheduled on all database (full and log)
      • DBCC CHECKDB running regularly on all databases
      • Test restores scheduled
      • Manage mdf/ndf/ldf file sizes
      • Proactively monitor and maintain indexes and statistics
      • Monitor jobs and set up alerts

    Challenge

    At work, someday soon, but in the next 30 days, go through the checklist on your important servers, or all your production servers, and assess your maintenance.

    Resources

    From the slide deck, which will come soon in email. These are a list of links and resources from the talk.

     

  • Transferring Table Types

    An interesting idea. I saw this question asked after I was playing with table types a bit. “Can you move a table type between schemas?”

    Suppose I had two schemas:

    CREATE SCHEMA OldSchema
    ;
    GO
    CREATE SCHEMA NewSchema
    ;
    GO

    In one of them, I create a table type and a procedure:

    CREATE TYPE OldSchema.MyTable AS TABLE
    ( IDCode INT
    , Location VARCHAR(200)
    )
    ;
    
    CREATE PROCEDURE OldSchema.MyProc 
    AS
     SELECT * FROM dbo.MyLogger
    ;
    

    There’s nothing fancy here. Just two objects created in one schema. I now have the need to move these to the other schema. Perhaps it’s a mistake. Perhaps I have developers working in one schema and I do integration testing in the other schema. In any case, it’s easy to move the proc with the ALTER SCHEMA syntax:

    ALTER SCHEMA NewSchema TRANSFER OldSchema.MyProc
    ;

    I can easily script something to move multiple procs, but if I do this:

    ALTER SCHEMA NewSchema TRANSFER OldSchema.MyTable
    ;

    I get this:

    Msg 15151, Level 16, State 1, Line 1

    Cannot find the object ‘MyTable’, because it does not exist or you do not have permission.

    I know it’s there; I just created it. What’s wrong?

    The problem is that this isn’t an object per se, but a type. As a result, to move a type, I need to use a different syntax:

    ALTER SCHEMA NewSchema TRANSFER type::OldSchema.MyTable
    ;
    GO

    That works fine and the type has moved. The class attribute of the notation is

    CLASS::Schema.Object

    I haven’t found good documentation of this, but there are numerous examples in BOL that show this is how you address various “types” in SQL Server.

  • Creating a User Defined Table Type

    I saw a post about a user defined table type in SQL Server and I was sure it was a typo. I kept thinking the poster meant table variable, but when I searched the term in Books Online, I was surprised to find User-Defined Table Types as an entry.

    These types are essentially templates that you can build for easier code reuse. They work in procedures and functions, or even as table variables. The CREATE TABLE syntax includes allowances for using these types.

    I can see this as being valuable when you have a structure that you want to pass into a module of some sort in multiple places and don’t want to have to include the code each time. I’m not sure it’s a great benefit, but it does prevent subtle mismatches like one module using varchar(50) for a column and another using varchar(200).

    A simple create for this type would be:

    CREATE TYPE StateTbl AS TABLE
    ( StateID INT
    , StateCode VARCHAR(2)
    , StateName VARCHAR(200)
    )
    ;
    

    This gives me a template I can use. Note that I can’t add rows to this table:

    INSERT StateTbl SELECT 1, 'CO', 'Colorado';
    

    I get this error:

    Msg 208, Level 16, State 1, Line 1

    Invalid object name ‘StateTbl’.

    It’s not an object yet. I need to instantiate an object based on this template. I can do that in a procedure:

    CREATE PROCEDURE SortStates
      @S StateTbl READONLY
     as
    
    SELECT StateName
     FROM @s
     ORDER BY StateName
    RETURN 0
    ;
    GO
    
    

    Fairly simple stuff. I can easily call this procedure, but I need a set of parameters first.

    DECLARE @p TABLE (id INT, scode VARCHAR(3), sname VARCHAR(20))
    
    INSERT @p
     VALUES (1, 'NC', 'North Carolina')
          , (2, 'VA', 'Virginia')
          , (3, 'CO', 'Colorado')
    ; 
    EXEC SortStates @p

    However this doesn’t work. The table isn’t compatible (I did that on purpose). Let’s clean it up.

    DECLARE @p TABLE StateTbl
       (StateID INT
       , StateCode VARCHAR(2)
       , StateName VARCHAR(200))
    
    INSERT @p
     VALUES (1, 'NC', 'North Carolina')
          , (2, 'VA', 'Virginia')
          , (3, 'CO', 'Colorado')
    ; 
    EXEC SortStates @p

    It still doesn’t work. There’s a binding here. I need to use the (cleaner) AS syntax for declaration.

    DECLARE @p as StateTbl
    
    INSERT @p
     VALUES (1, 'NC', 'North Carolina')
          , (2, 'VA', 'Virginia')
          , (3, 'CO', 'Colorado')
    ; 
    EXEC SortStates @p

    This returns results:

    udtt_1

    This means that you can use these types to create cleaner code, and enforce some standards (preventing things like people declaring columns with different lengths. However it also means that you have another “type” to manage and ensure everyone is using.

    I’m not sure how useful this is, but it is a neat little construct.