SELECT
s.NAME AS SchemaName,
t.NAME AS TableName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables t
INNER JOIN sys.Schemas s ON t.schema_id = s.schema_id
INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE
t.NAME NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
AND i.OBJECT_ID > 255
GROUP BY
s.Name,
t.Name,
p.[Rows]
ORDER BY
s.Name,
t.Name
Thursday, 24 May 2012
SQL Server - Query to get table sizes
Once again I am posting SQL that I have found on the internet (mainly so that I have can find this scriopt easily in the future). This one is thanks to marc_s and can be found in this Stackoverflow post.
The script will give you a breakdown of the table size for each table in your database. This includes a row count, disk space used and disk space available. I have modified the original script slightly as a number of databases I work with have multiple schemas and the original script doesn't show the schema name.
Wednesday, 16 May 2012
T-SQL script for finding object dependencies
This morning I wanted to find out where a specific stored procedure was being used. I wasn't sure how to do this using T-SQL so did a bit of googling and found this article. I have made a slight enhancement to the scripts shown in the article.
I am sure I will get a lot of milage out of this in the future.
DECLARE @ObjectName VARCHAR(500) SET @ObjectName = 'dbo.sp_test_Proc' -- shows objects that the named object depends on SELECT DISTINCT OBJECT_NAME(DEPID) DEPENDENT_ON_OBJECT, OBJECT_NAME (ID) OBJECTNAME FROM SYS.SYSDEPENDS WHERE ID = OBJECT_ID(@ObjectName) -- shows objects that use the named object SELECT DISTINCT OBJECT_NAME(DEPID) OBJECT_NAME, OBJECT_NAME (ID) USED_IN_OBJECT FROM SYS.SYSDEPENDS WHERE DEPID = OBJECT_ID(@ObjectName)
I am sure I will get a lot of milage out of this in the future.
Monday, 30 April 2012
tSQLt - Assertions
In this post my aim is to introduce the basic tSQLt assertions. The examples should be enough to get you going with assertions. My assumption is that you have at least some experience writing unit tests with any unit testing framework.
tSQLt.Fail
tSQLt.AssertEquals
tSQLt.AssertEquals with System Under Test (SUT)
tSQLt.AssertEqualsString
tSQLt.AssertEqualsTable
For this test we once again need some setup (i.e. we need to create an object to test if it exists)
tSQLt.AssertResultSetsHaveSameMetaData
That's it for now. I hope to get some time to look at how to isolate dependencies in the near future.
tSQLt.Fail
CREATE PROCEDURE [UnitTest_FirstGo].[test Fail] AS BEGIN EXEC tSQLt.Fail 'This test should fail and display this message'; END
CREATE PROCEDURE [UnitTest_FirstGo].[test AssertEquals] AS BEGIN --Assemble DECLARE @expected int DECLARE @actual int SET @expected = 1; SET @actual = 0; --Act --Assert EXEC tSQLt.AssertEquals @expected, @actual, 'The is a TEST FAILURE MESSAGE!' END
First we need to create something to represent the SUT
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fn_SUM]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) DROP FUNCTION [dbo].[fn_SUM] GO CREATE FUNCTION fn_SUM ( @a int, @b int ) RETURNS int BEGIN RETURN @a+@b; END
and now the test
CREATE PROCEDURE [UnitTest_FirstGo].[test AssertEquals with SUT] AS BEGIN --Assemble DECLARE @expected int DECLARE @actual int SET @expected = 3; --Act SELECT @actual = dbo.fn_SUM(1,2); --Assert EXEC tSQLt.AssertEquals @expected, @actual END
CREATE PROCEDURE [UnitTest_FirstGo].[test AssertEqualsString] AS BEGIN --Assemble DECLARE @expected varchar(20) DECLARE @actual varchar(20) SET @expected = 'hello world'; SET @actual = 'goodbye world'; --Act --Assert EXEC tSQLt.AssertEqualsString @expected, @actual, 'The is a TEST FAILURE MESSAGE!' END
tSQLt.AssertEqualsTable
This one takes a bit of time to get your head around, but once you get going and when used in conjunction with Fake tables it's really awesome.
CREATE PROCEDURE [UnitTest_FirstGo].[test AssertEqualsTable] AS BEGIN --Assemble if exists(select * from information_schema.tables where table_schema='dbo' and table_name='tablea') begin drop table dbo.TableA; create table dbo.TableA (id int not null); end if exists(select * from information_schema.tables where table_schema='dbo' and table_name='tableb') begin drop table dbo.TableB; create table dbo.TableB (id int not null); end insert tablea (id) values (1); insert tablea (id) values (2); insert tablea (id) values (3); insert tableb (id) values (1); --insert tableb (id) values (2); insert tableb (id) values (3); --Act -- nothing to do here --Assert exec tSQLt.AssertEqualsTable 'TableA', 'TableB' END
Uncomment the commented out insert to make the test pass.
The failure message attempts to point you to what failed showing which rows matched and which failed to match.
tSQLt.AssertObjectEqualsFor this test we once again need some setup (i.e. we need to create an object to test if it exists)
SELECT OBJECT_ID (N'dbo.fn_SUM', N'F') IF OBJECT_ID (N'dbo.fn_SUM', N'F') IS NOT NULL DROP FUNCTION dbo.fn_sum GO CREATE FUNCTION fn_SUM ( @a int, @b int ) RETURNS int BEGIN RETURN @a+@b; END
And now the test
CREATE PROCEDURE [UnitTest_FirstGo].[test AssertObjectExists] AS BEGIN --Assert EXEC tSQLt.AssertObjectExists 'fn_SUM' END
CREATE PROCEDURE [UnitTest_FirstGo].[test AssertObjectExists] AS BEGIN --Assemble if exists(select * from information_schema.tables where table_schema='dbo' and table_name='tablea') begin drop table dbo.TableA; create table dbo.TableA (id int not null); end if exists(select * from information_schema.tables where table_schema='dbo' and table_name='tablec') begin drop table dbo.TableC; create table dbo.TableC (id int not null, name varchar(50) not null); end insert tablea (id) values (1); insert tablea (id) values (2); insert tablea (id) values (3); insert tablec (id, name) values (5, 'andrew') --Act -- nothing to do here --Assert exec tSQLt.AssertResultSetsHaveSameMetaData 'select * from tablea', 'select * from tablec' END
That's it for now. I hope to get some time to look at how to isolate dependencies in the near future.
Wednesday, 4 April 2012
MSDTC Troubleshooting
Yesterday afternoon I was caught out by this error for a few hours.
The MSDTC and linked server were setup on the test machine as I had described in my test document.
It took me a fair bit of googling to find the solution. Most of the obvious setup problems were covered in my test document. The problem in the end turned out to be the firewall on the test machine, something I should have checked much sooner.
Links for future reference:
http://stackoverflow.com/questions/673806/msdtc-how-many-ports-are-needed
http://support.microsoft.com/kb/306843
http://www.lewisroberts.com/2009/08/16/msdtc-through-a-firewall-to-an-sql-cluster-with-rpc/
A severe error occurred on the current command. The results, if any, should be discarded. OLE DB provider "SQLNCLI10" for linked server "LinkedServerName" returned message "No transaction is active.".I had release the appliaction I am currently working on to testing. The applcation has been runnin g perfectly on my development machine, but no such luck on our testers machine. A new feature for this release is the use of distributed transactions to complete some of the business functionality. This obviously requires that MSDTC is setup and a linked server is created on the local SQL Server.
The MSDTC and linked server were setup on the test machine as I had described in my test document.
It took me a fair bit of googling to find the solution. Most of the obvious setup problems were covered in my test document. The problem in the end turned out to be the firewall on the test machine, something I should have checked much sooner.
Links for future reference:
http://stackoverflow.com/questions/673806/msdtc-how-many-ports-are-needed
http://support.microsoft.com/kb/306843
http://www.lewisroberts.com/2009/08/16/msdtc-through-a-firewall-to-an-sql-cluster-with-rpc/
Comparing Byte Arrays with Linq
This morning I ran into a small issue. I needed to extract a series of images from a database table. The problem I had was there were duplicate images in the database table and I needed a unique set of images written to disk. To filter the duplicates I have used the Enumerable.SequenceEqual linq operator. So here is how I did it.
using (var sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
foreach (var deliveryNumber in deliveryNumbers)
{
var images = new List<byte[]>();
// get all ewtphotos for this sapdeliverynumber
using (var sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandText = "select imagedata " +
"from delivery d " +
"inner join image i on d.imageid=i.imageid " +
"where d.deliverynumber='" + sapDeliveryNumber + "'";
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
var imageData = (byte[])sqlDataReader["ImageData"];
var imageExists = images.Any(image => image.SequenceEqual(imageData));
if (!imageExists) images.Add(imageData);
}
}
}
WriteImagesToDisk(sapDeliveryNumber, images);
}
}
private static void WriteImagesToDisk(string deliveryNumber, List<byte[]> images)
{
var counter = 1;
foreach (var image in images)
{
var fileFullName = @"images\DeliveryNumber_" + deliveryNumber + "_" + counter + ".jpg";
File.WriteAllBytes(fileFullName, image);
counter++;
}
}
Friday, 23 March 2012
tSQLt - Writing tests
I am not going to go into detail on how to download and install tSQLt here as it is pretty straight forward and all the instructions are on the tSQLt website.
It's worth creating a test database in order to try out the examples in the code below. Once you have created the test database follow the instructions on the tSQLt website to install tSQLt on this database.
Once tSQLt is installed the obvious starting point would be to write and run a test.
tSQLt introduces a concept of a TestClass. This is a class that is used to group a set of unit tests. tSQLt uses schema's to accomplish this. I am currently using the following naming convention UnitTests_<schemaName> where the schemaName is the name of the schema that contains the code that is being tested.
Creating a TestClass:
Use this query to view your TestClasses:
And to delete a TestClass
Writing a test is as simple as creating a stored procedure within a test schema (TestClass). All test stored procedures need to start with the word "test". Test names can include spaces.
It's worth creating a test database in order to try out the examples in the code below. Once you have created the test database follow the instructions on the tSQLt website to install tSQLt on this database.
Once tSQLt is installed the obvious starting point would be to write and run a test.
tSQLt introduces a concept of a TestClass. This is a class that is used to group a set of unit tests. tSQLt uses schema's to accomplish this. I am currently using the following naming convention UnitTests_<schemaName> where the schemaName is the name of the schema that contains the code that is being tested.
Creating a TestClass:
EXEC tSQLt.NewTestClass 'UnitTests_Processing'
Use this query to view your TestClasses:
SELECT * FROM tSQLt.TestClasses
And to delete a TestClass
EXEC tSQLt.DropClass 'UnitTests_Processing'
You actually don't need to create a TestClass as shown above. You can just create a normal schema and start writing tests against that schema. The downside of doing this is that the schema won't be correctly registered with tSQLt and commands like
won't run these tests.
EXEC tSQLt.RunAll
Writing a test is as simple as creating a stored procedure within a test schema (TestClass). All test stored procedures need to start with the word "test". Test names can include spaces.
CREATE PROCEDURE [UnitTests_Processing].[test 1 should equal 1]
AS
BEGIN
-- this is the simplest example of an assert
EXEC tSQLt.AssertEquals 1, 1, '1 should equal 1'
END
That is it for now.
Friday, 16 March 2012
Database unit testing with tSQLt
I am currently working on a project that has a fair amount of backend database processing happening. I have got a fair amount of TDD experience in a C# environment and have found that once you get into TDD it becomes a way of life. As such, I wanted to apply the same approach to my database development.
After a bit of researching I stumbled across an Open Source unit testing framework for SQL Server called tSQLt. I have been using it for a few weeks now and yesteday I past the 100 test mark in the project I am working on. It took me a little while to get up and running with some of the concepts and idea's around tSQLt unit testing, but I am already feeling very comfortable writing database unit tests using tSQLt.
There is a very good series of blog posts on tSQLt already at http://datacentricity.net/tag/tsqlt/
Over the next few days (I hope). I will try to put together a series of post's showing the basics working of each test type without any extra logic to get in the way of what is going on.
After a bit of researching I stumbled across an Open Source unit testing framework for SQL Server called tSQLt. I have been using it for a few weeks now and yesteday I past the 100 test mark in the project I am working on. It took me a little while to get up and running with some of the concepts and idea's around tSQLt unit testing, but I am already feeling very comfortable writing database unit tests using tSQLt.
There is a very good series of blog posts on tSQLt already at http://datacentricity.net/tag/tsqlt/
Over the next few days (I hope). I will try to put together a series of post's showing the basics working of each test type without any extra logic to get in the way of what is going on.
Subscribe to:
Posts (Atom)