In the music the moment you own it and can decode your database!

Yesterday I had the awesome opportunity to present at Big Mountain Data and SQL Saturday Salt Lake City.  I was super nervous, but I think it went well over all.  Huge thank you to the kind friends that sat in the audience to help build my confidence and for everyone that attended.  Here are the scripts that I promised to post.  If you would like the slide deck, it is posted on the Utah Geek Events website here: http://www.utahgeekevents.com/Downloads

The first script is the one that gets the row counts on each table so you can see what tables you want to look at and what tables you want to skip.

 
-- Shows all user tables and row counts for the current database
-- Remove is_ms_shipped = 0 check to include system objects
-- i.index_id < 2 indicates clustered index (1) or hash table (0)
SELECT o.name,
ddps.row_count
FROM sys.indexes AS i
INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID
AND i.index_id = ddps.index_id
WHERE i.index_id = 2
AND o.is_ms_shipped = 0
ORDER BY ddps.row_count DESC

This next part is the second demo I did about digging through the database.

 
--What columns are in the Sales Tables?
SELECT A.name, B.name
FROM sys.tables A
INNER JOIN sys.columns B ON A.object_id = B.object_id
WHERE A.name LIKE '%Sales%'

--Column called "Order" something with amount?
SELECT A.name, B.name
FROM sys.tables A
INNER JOIN sys.columns B ON A.object_id = B.object_id
WHERE B.name LIKE '%Order%'

--OrderQty is the column I am looking for...
SELECT A.name, B.name
FROM sys.tables A
INNER JOIN sys.columns B ON A.object_id = B.object_id
WHERE B.name LIKE '%OrderQty%'

--How do I know for sure it is the table I want?
SELECT 
c.name 'Column Name',
t.Name 'Data type',
c.max_length 'Max Length',
c.precision ,
--c.scale ,
--c.is_nullable,
ISNULL(i.is_primary_key, 0) 'Primary Key'
FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT OUTER JOIN sys.index_columns ic ON ic.object_id = c.object_id AND ic.column_id = c.column_id
LEFT OUTER JOIN sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id
WHERE c.object_id = OBJECT_ID('Sales.SalesOrderDetail')

This is the code from the third demo where I was looking for the foreign keys. I got this off stack overflow and it has been very helpful.

 
SELECT obj.name AS FK_NAME, sch.name AS [schema_name], tab1.name AS [table], col1.name AS [column], tab2.name AS [referenced_table], col2.name AS [referenced_column]
FROM sys.foreign_key_columns fkc
INNER JOIN sys.objects obj ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1 ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1 ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2 ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2 ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id
WHERE tab1.name = 'SalesOrderDetail'

The other demos that I did were opening Views and stored procedures and a walk through of how to use the Database Diagram feature.

Hope you all had a wonderful time at the event like I did!

Someone says “You’re in the wrong place master, you better leave”

Moving system databases. Whenever I have brought this up with a co-worker they seem to get a bit freaked out and want to avoid moving them.  I used to be the same, but happily now I am comfortable moving them around.

Let me first tell you why I want to move them.  I like to have my Data files on the D: drive, Log files on the E: drive, Backup files on the F: and my Tempdb files on the G: Drive.  These are all SAN drives.  This method keeps me consistent for all my servers and I am able to quickly know where to find everything I need.  I am also able to easily identify which drive my problem is on.  But my favorite reason is that in the past (three separate times), I have lost the OS to my SQL Server.  Because I had master, model, and msdb on the D: drive, after a quick re-install of SQL and the correct patch, I was able to re-point to master and everything came up beautifully without further recovery.  I had over 70 databases on one of these instances, and this method prevented me from having to restore each one along with log files. It was a wonderful surprise the first time it worked.

There are performance reasons for splitting out your files on to different drives, but we can get into that later because it requires its own post.

This step comes before I split out my tempdb files, so I am only moving one. You could easily add more lines of code to allow you to move more tempdb files.

So let’s get to the code and you will see how easy it is to do.  You will never fear moving the system databases again. This code is set up for SQL2008, but is easily modified for whatever version you are using.  Just set it up to match the folder structure.


--Check to see where your files are now.

SELECT *
FROM sys.master_files

--Move your files
USE master
GO

ALTER DATABASE model
MODIFY FILE (NAME = modeldev, FILENAME = 'D:\MSSQL10.MSSQLSERVER\MSSQL\DATA\model.mdf');
GO

ALTER DATABASE model
MODIFY FILE (NAME = modellog, FILENAME = 'E:\MSSQL10.MSSQLSERVER\MSSQL\DATA\modellog.ldf');
GO

ALTER DATABASE msdb
MODIFY FILE (NAME = MSDBData, FILENAME = 'D:\MSSQL10.MSSQLSERVER\MSSQL\DATA\MSDBData.mdf');
GO

ALTER DATABASE msdb
MODIFY FILE (NAME = MSDBLog, FILENAME = 'E:\MSSQL10.MSSQLSERVER\MSSQL\DATA\MSDBLog.ldf');
GO

ALTER DATABASE  tempdb
MODIFY FILE (NAME = tempdev, FILENAME = 'G:\MSSQL10.MSSQLSERVER\MSSQL\DATA\tempdb.mdf');
GO

ALTER DATABASE tempdb
MODIFY FILE (NAME = templog, FILENAME = 'G:\MSSQL10.MSSQLSERVER\MSSQL\DATA\templog.ldf');
GO

Stop the SQL Server and physically copy over the files. Restart the SQL Server and verify they moved your files moved.

SELECT *
FROM sys.master_files

Now here is the next part of the magic.  Go to the SQL Server Configuration Manager, right click on your SQL Server and go to Advanced.  There is a line for Start-up Parameters.  You will also need to modify this string to match your version, but I simply paste this in:

-dD:\MSSQL10.MSSQLSERVER\MSSQL\DATA\master.mdf;-eC:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\Log\ERRORLOG;-lE:\MSSQL10.MSSQLSERVER\MSSQL\DATA\mastlog.ldf

Then I stop my SQL Server, copy my master files to the right locations and start up SQL Server again.  It is so easy.  Test it out a few times until you are comfortable and then it will be like you are moving them around with a magic wand.