Writing Output from MSTest

Unit testing can sometimes throw up unexpected issues that are entirely concerned with the unit tests and not the application under test. Recently I’ve been having issues with DateTime formats affecting the results of the unit tests: the format of the DateTime was different on the build server than it was on my local machine. The stored procedure could not be altered (because reasons*). Continue reading “Writing Output from MSTest”

Import-Module SqlPs Takes Forever To Load

Hello!

I’ve been working on some pre-deployment scripts to SQL Server using PowerShell, and I chose to use Invoke-Sqlcmd as opposed to creating a sql connection*, however the first time I ran the script on my local box to test, it seemed to hang. I thought it may be my local instance not running, but that was running fine. So I created the simplest command possible and tried it:


Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery;" -ServerInstance "."

But still it was hanging. And then warning messages started to appear:

slowToImport

And at the end of the messages, my query returned. Subsequent re-runs of the Invoke-Sqlcmd ran almost instantly. But the errors pertain to Azure, and I’m not using Azure!. But I do have the Azure modules installed on my machine. A little bit of Googling led me to this Connect issue. Essentially what is happening is tha the Import-Module that is ran implicitly when using Invoke-sqlcmd “incorrectly loads files (e.g. DLLs, .ps1xml, etc) in the context of the current provider, as opposed to the context of the “file system” provider (this causes the SQL Provider to try to connect to entities that may look like SQL Server, but they are not – as stated in the description of this issue; there isn’t anything intrinsically wrong that the SQL Provider is doing here.)”

And now for the good news: it’s fixed. Hurrah! But now for the bad news: you need to install SQL Server 2016 to get the fix. I did install just the June 2016 release of SSMS as it’s far more realistic for people to upgrade this than the database engine, but unfortunately this did not resolve the issue even after a restart. It was a long shot, but one worth trying. You can also uninstall the Azure modules; it’s arguably easier to uninstall these and run them on another box than upgrade to SQL Server 2016, but I’ll admit that’s hardly a great solution.

*I have found that it’s easier to set Invoke-sqlcmd to verbose and save any print messages from SQL to a file that can then be saved as an artifact to be used for deployment than any other way.

 

Preventing Plan Regressions During Testing Slides

Hello!

Thanks to everyone who turned up at last nights SQL Supper to see me talk about preventing plan regressions during database testing. The testing framework I demoed was written by me, but the decision whether to make it open source or not is not mine. So the best I can do today is share the slides, and hopefully the framework will go online and be improved upon by the community.

Sup Dawg, I Heard You Like NULLS…

Quick note on NULLS: NULL means “Unknown Value”, not “0”. So adding a value to NULL results in NULL:

1 + NULL = NULL

Because NULL means “I Don’t Know”, adding two NULLS together does not equate to the same value; it’s still two indeterminate values.

NULL + NULL != NULL

You can work around this in T-SQL by using COALESCE.


declare @i VARCHAR(8) = NULL
declare @j VARCHAR(8) = NULL
SELECT @i

SELECT @i + 'bob'

SELECT COALESCE (@i, 'bob')

if @i = @j
select 'yes'
else
select 'no'

Forcing SQL Server To Order Operations

The subject of my last post was to do with returning DBCC CHECKDB results from a temp table, which was populated by running DBCC DBINFO against each database hosted on the SQL instance. I shared a query that returned any databases that had not had a CHECKDB run against it for over 7 days. The query is below:

 
select dbi.Value from #db dbi
WHERE field LIKE '%lastknow%'
AND (CASE WHEN isDate(dbi.value) = 1 THEN CAST (dbi.Value AS DATETIME2(3))END) < DATEADD (DAY,-7, GETDATE())

That “CASE” statement stands out quite a bit doesn’t it. Let’s explore why this query needs a CASE expression. Begin by creating a temp table that contains a sample of the data stored in the temp table. Continue reading “Forcing SQL Server To Order Operations”

Copy and Delete Data Across Tables When There is no Space

Hello!

Recently I needed to apply compression data on a particularly large table. One of the main reasons for applying compression was because the database was extremely low on space, in both the data and the log files. To make matters worse, the data and log files were nowhere near big enough to accommodate compressing the entire table in one go. If the able was partitioned then I could have done one partition at a time and all my problems would go away. No such luck.

So I had to think quite outside of the box to compressing the data. The solution I came up with was to create a new empty table, and copy 50 rows at a time (that was the largest I could move at any one time, yes I really was THAT low on space) and then delete the 50 rows copied. But instead of COPY/DELETE, which would seem the logical way, I ran the DELETE first and then run an INSERT from the output table. This way I would be certain that the same rows that were deleted were copied into the new table, and meant that I was only scanning the original table the once.

I had to run further checks into the script: the database was set to simple mode, but the log file would still grow because of ETL processes etc running on other parts of the db, and so I needed to check to make sure that I wasn’t saturating the log file with each delete. So the logic here will work for both SIMPLE, BULK and FULL recovery models. Continue reading “Copy and Delete Data Across Tables When There is no Space”

Log Shipping: It’s Better Than Bad It’s Good!

better than bad its good

This is something of an epic post, so grab a tea and get ready…I’m probably showing my age by quoting an old Ren and Stimpy cartoon here, but to be fair it probably sums up log shipping pretty well. This post is focusing on using a read-only log shipping database for reporting purposes, and the limitations of read-only log shipped databases. I also share some monitoring scripts and a few ideas on how to improve restore performance without having to upgrade the hardware/software.

Despite the development of AlwaysOn in recent releases of SQL Server, log shipping is still a great way to set up a copy of databases to be used for reporting. One of the main reasons it is great is because, unlike AlwaysOn, it is available in less expensive editions like Standard and Web from SQL Server 2008 onwards. Sure, in 2016 AlwaysOn will be available in Standard, but in a greatly deprecated form, and you cannot read from the secondary. So it will be good for DR, but not for reporting (as an aside it still might be easier to set up log shipping for DR than AlwaysOn Basic because you need to setup a failover cluster. Read through the “how to set up Standard Edition Availability Groups” here.) However you do need to be careful though when setting up log shipping across different editions of SQL Server: whilst you can log ship between Enterprise to Standard/Web, if the database uses any Enterprise features then you’ll need to log ship to an Enterprise edition of SQL Server. And because you’ll be using the database for reporting, you’ll need to get it licensed. Continue reading “Log Shipping: It’s Better Than Bad It’s Good!”

Access Denied When Initializing Subscriber (OS 5)

Today I needed to initialize a pull subscription from a server that had been in the pool of subscribers for a published database, and had been out for sometime. In that time the distribution database had moved, so it was a case of re-creating the subscriptions all over. Once the pull subscription and distribution jobs created, I ran the snapshot agent, which uses a file share. When the snapshot agent had completed, I stared up the agent job on the subscriber. I had done this many times before, and was surprised to see an error not too dissimilar from the one below in the subscriber logs on Replication Monitor:

The process could not read file ‘\\Server1\SQLShareFiles\unc\publication\2050530095003\slmnc.pre’ due to OS error 5. (Source: MSSQL_REPL, Error number: MSSQL_REPL21022)
Get help: http://help/MSSQL_REPL21022
Access is denied.
(Source: MSSQL_REPL, Error number: MSSQL_REPL5)
Get help: http://help/MSSQL_REPL5

Oh. Access is denied? Quickly Googling the error I found a useful post at DBAStackExchange. Although we do use SQL Agent Authentication, what was missing was the permissions to the file share. Browsing to the file share and giving the Agent account full control of the file share resolved the issue for me. And though using Agent accounts does not follow best practice for the Replication Agent Security Model, it got the snapshot pushing out.

 

FizzBuzz In SQL

This has been done many times before by many other people, but I set this challenge to a friend of mine who was interested in programming, and then realised that I had no solution. So I spent the train journey home writing my effort below. Like a lot of things in computer programming, there’s more than one correct way, but many more incorrect ways! I like this way because it’s quite small and readable.


DECLARE @COUNT TINYINT = 1
DECLARE @FizzBuzz VARCHAR(8)

WHILE @COUNT < 101
BEGIN
SELECT @FizzBuzz = CASE
WHEN @COUNT % 3 = 0
AND @COUNT % 5 = 0
THEN 'FizzBuzz'
WHEN @COUNT % 3 = 0
THEN 'Fizz'
WHEN @COUNT % 5 = 0
THEN 'Buzz'
ELSE CAST(@Count AS VARCHAR(3))
END

PRINT @FizzBuzz

SELECT @COUNT = @COUNT + 1
END