dbatools 1.0. The tools to break down barriers.

Words: 780

Time to read: ~ 4 minutes

Version 1.0 is coming…

20th June 2019 and dbatools will release version 1.0

Now, I don’t remember how I started with dbatools.
I know that I was a Junior DBA at that stage and I was experimenting with PowerShell.

After being initially introduced to PowerShell when it was only Version 2, and dismissing it for something that wouldn’t catch on in a Windows environment (I never said that I was prophetic!), I was ready to attone for my actions and dive deep into this wonderful scripting language.

They say that the way to improve is to do and I was looking for a project that interweaved PowerShell with SQL Server.
I can only assume that was when dbatools found me.

Now some time has moved on and things have moved on as well.
PowerShell has released verison 7 on pre-release, I’ve taken a position as a Production DBA, and dbatools are about to release version 1.0!

In that time, I’ve learned that dbatools, more than just a PowerShell module, helps break down barriers that exist in organisations.

Barrier to learning…

This may come across as a bit banal, something that has been thrown around a lot, and something that you have all heard been said before but there are so many new things out there for data professionals.

How are we supposed to keep up-to-date with developments, how are we supposed to keep abreast of the latest technologies, how are we supposed to drink from the water hose of learning if we are not taking advantage of the automation that dbatools brings?

I cannot imagine a data professional taking advantage of containers, spinning up a few, and then saying

Hold on, I have to connect SSMS to the container to restore a database on it now. Oh wait, I have to copy and paste the backup file over first. Then I have to make sure permissions are there and correct and…yeah you need to wait.

Not me

Imagine it! Imagine the speed and progress taking place.

  • Find an image: docker search and its done!
  • Download it: docker pull and its done!
  • Create the container: docker create and its done!
  • Deploy the database: “ah hold on guys, this is going to take at least an hour...”

The flow is cut.
Its speed-bumped; road blocked by a data professionals lack of automation.

dbatools can help you, it has the commands. Restore-DbaDatabase, Copy-DbaLogin, and the work is done!

It is not that there is no time to learn the new technologies, it is not using automation to give yourself time to learn.

Use dbatools, push the speed-bump down the pipeline, and leverage that new found time to learn to become more valuable!

Barriers in roles…

DevOps is the union of people, process, and products to enable continuous delivery of value to our end users

Donovan Brown

Now imagine trying to implement DevOps in a organisation where the people are siloed?

There is no collaboration, no communication because people don’t have the knowledge or the tools to provide support to anyone else.

Developers have to wait for the DBA each time they want to restore a database on a dev environment.

Operations can’t troubleshoot an issue on the database because they don’t have the permissions or the know-how to connect to an instance.

Middle management have to go to every single instance to run the same query for information about their SQL Server estates.
RDP, SSMS, New Query, Paste, Run over and over and over again.

dbatools empowers these people.

Tools can be written using dbatools that restores a masked database for developers. This can be logged and as open or as restrictive as you want.

Operations can use Install-DbaWhoIsActive and Invoke-DbaQuery to check out issues on an instance without having the bother the DBA first.

Middle management can be given a script to query all the servers from Get-DbaRegServer and Invoke-DbaQuery to run what they want. What was once a multitude of mouse clicks can be reduced to the running of a single file.

Everything logged, everything known, and everyone empowered.

dbatools breaks down these barriers…

dbatools is about to publish version 1.0 but this does not mean that the work stops.

There are knowledge seekers to help, Issues to troubleshoot, Feature Requests to pour over, Documentation to create and update, Tests to write and verify.

Do not be put off; version 1.0 is something to celebrate, not something to be intimidated by.

Join in!
Learn, laugh, and lend a hand.
Version 1.0 is released but, thankfully, numbers don’t stop at 1.

Now this is not the end. It is not even the beginning of the end. But it is, perhaps, the end of the beginning.

Winston Churchill

T-SQL Tuesday 114 – Puzzle Party

Words: 1,858

Time to read: ~ 5 minutes

It’s T-SQL Tuesday time and this time we have Matthew McGiffen ( blog | twitter ) who is asking us about a Puzzle Party!

Let’s see what exactly he is asking us though.

• Present a puzzle to be solved in SQL and challenge your readers to solve it.

• Or give us a puzzle or quiz about SQL or databases.

• Show the SQL solution to a classic puzzle or game.

• Provide a method for solving a classic sort of querying puzzle people face.

• Show how newer features in SQL can be used to solve old puzzles in new ways.

• Tell us about a time you solved a problem or overcame a technical challenge that was a real puzzle.

• Or just make your own interpretation of “puzzle” and go for it!

Matthew McGiffen

I didn’t have much in the idea department for most of them so I’m thankful that Matthew left us with the last own interpretation option. So here is my attempt at a puzzle.

Invoke-LollerCoaster!

Should I Cheat?

It’s a slightly strange story but I had already done a slight “puzzle” or “trick” in PowerShell where I created a Loller Coaster Don’t ask me why, blame Andy Mallon ( blog | twitter ).

Now, that implementation used PowerShell but I thought to myself…

You know what…it uses System.Data.DataTable…that’s nearly the same thing as querying from a database. Could I get away with posting that?

Me

In the end, I decided against using the PowerShell version and said is there anyway that I could port it over to SQL Server?

PowerShell

First, you can find the PowerShell version of this in my Github account here:
https://github.com/shaneis/RandomScripts/blob/master/Invoke-Lollercoaster.ps1

I’m more proud of that than this attempt…

Look at it go!!!

SQL Server

Now for the SQL Server version.

Let’s create our table in tempdb and populate it. Could this have been made more compact? Perhaps with some fancy string manipulation and some such?

Oh yeah! But this was a quick job done during my lunch break and I wanted it done more than I wanted it perfect.

Plus, if you don’t like the below, you’re really not going to like what I use in the actual script…


USE tempdb;
GO
IF OBJECT_ID(N'dbo.LollerCoaster', N'U') IS NOT NULL BEGIN
	DROP TABLE dbo.LollerCoaster;
END;
GO
CREATE TABLE dbo.LollerCoaster (
	loller_coaster_id tinyint IDENTITY(1, 1) NOT NULL,
	loller_coaster_stage varchar(4000) NOT NULL
);
GO
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
        __)
        LOL
           O
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
         __)
        LOL
           O
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          __)
        LOL
           O
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL\
           O\)
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O\
            L\)      LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L\        LOL   LOL
             O\)    O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L         LOL   LOL
             O\      O   O O   O
              L\)   L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L         LOL   LOL
             O       O   O O   O
              L\    L     L     L
               O\) O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O\_)O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O__)O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L         LOL   LOL
             O       O   O O   O
              L    )L     L     L
               O _/O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L         LOL   LOL
             O      )O   O O   O
              L    /L     L     L
               O  /O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O
            L        )LOL   LOL
             O      /O   O O   O
              L    /L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O          ) 
            L        /LOL   LOL
             O      /O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL            )
           O          / 
            L        /LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O          __)
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O           __)
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O            __)
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O          
            L         LOL\  LOL
             O       O   O\)   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O          
            L         LOL   LOL
             O       O   O\O   O
              L     L     L\)   L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L\    L
               O   O       O\) O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O__)O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L    )L
               O   O       O _/O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O  \O
              L     L     L    )L
               O   O       O  /O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O  \O
              L     L     L    )L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O( \O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O/  O
              L     L     L()   L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L(    L
               O   O       O\) O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O__)O
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O __)
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O  __)
                LOL         LOL
                               O
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL\
                               O\)
                                L     LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O\
                                L\)   LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L\    LOL
                                 O\) O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O\_)O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L     LOL
                                 O__)O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O
                                L    )LOL
                                 O _/O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL        )
                               O      /
                                L    /LOL
                                 O   O
                                  LOL')
INSERT INTO dbo.LollerCoaster (loller_coaster_stage) VALUES ('
          
        LOL
           O         
            L         LOL   LOL
             O       O   O O   O
              L     L     L     L
               O   O       O   O
                LOL         LOL
                               O      __)
                                L     LOL
                                 O   O
                                  LOL')
GO

Next we’ll need to set up some things and create a few variables

SET NOCOUNT ON;
-- Set Ctrl + T to send results to text!

DECLARE @Counter tinyint;
DECLARE @End tinyint;
DECLARE @Stage varchar(4000); -- Horribly oversized, I know and apologise.
DECLARE @Pause varchar(12);
DECLARE @Clear varchar(4000); -- again, apologies...

Then we can set the variables that we have

SET @Counter = 1;
-- I could move this after the insert and use @@ROWCOUNT
-- but I created/inserted into the table in a different session.
SET @End = (SELECT COUNT(*) FROM dbo.LollerCoaster);
-- Just 15 line feeds
SET @Clear = REPLICATE(CHAR(13), 15);

Then… the rest is a WHILE loop. 😦

RAISERROR(@Clear, 0, 1) WITH NOWAIT;

WHILE @Counter <= @End BEGIN

	SET @Stage = (SELECT loller_coaster_stage FROM dbo.LollerCoaster WHERE loller_coaster_id = @Counter);
	
	RAISERROR(@Stage, 0, 1) WITH NOWAIT;

	IF @Counter &gt;= 21 AND @Counter <= 29 BEGIN
	    SET @Pause = '00:00:00.100';
	END; ELSE BEGIN
		SET @Pause = '00:00:00.200';
	END;

	WAITFOR DELAY @Pause;
	RAISERROR(@Clear, 0, 1) WITH NOWAIT;
	SET @Counter += 1;
END;

There’s only a few things to mention here.

  • I’m clearing the screen at the start just for cleanliness.
  • There’s a tight loop between counters 21 and 29 where we want to simulate it speeding up.
  • We’re setting a pause between each one since we want the users to actually see the differences.
  • It can be improved so much!
USE [tempdb];
GO
SET NOCOUNT ON;


DECLARE @Counter tinyint;
DECLARE @End tinyint;
DECLARE @Stage varchar(4000);
DECLARE @Pause varchar(12);
DECLARE @Clear varchar(4000);

SET @Counter = 1;
SET @End = (SELECT COUNT(*) FROM dbo.LollerCoaster);
SET @Clear = REPLICATE(CHAR(10), 15);

RAISERROR(@Clear, 0, 1) WITH NOWAIT;

WHILE @Counter <= @End BEGIN

	SET @Stage = (SELECT loller_coaster_stage FROM dbo.LollerCoaster WHERE loller_coaster_id = @Counter);
	
	RAISERROR(@Stage, 0, 1) WITH NOWAIT;

	IF @Counter &gt;= 21 AND @Counter <= 29 BEGIN
	    SET @Pause = '00:00:00.100';
	END; ELSE BEGIN
		SET @Pause = '00:00:00.200';
	END;

	WAITFOR DELAY @Pause;
	RAISERROR(@Clear, 0, 1) WITH NOWAIT;
	SET @Counter += 1;
END;
It's a sled riding down a rollercoaster made of the word LOL repeating.
No, I don’t know why the sizes change half-way through.

Reflections: 2018

What a Difference a Year Makes

Words: 665

Time to read: ~ 3 minutes

2018 has been a busy year.

Blog

Let’s talk blog numbers for a moment… They say a picture paints a thousand words so I’m going to keep the word count down.

That’s 42,680 views across 34,920 visitors. Now seeing as last year it was 11,079 views across 9,061 visitors and that’s a 285% increase…yeah I’m pretty damn happy with that!

2018 was the year that I started to get more and more into the PowerShell community so I’m happy that 3 out of the top 4 posts were about topics that merges both the SQL Server and PowerShell communities.

I’m not going to read into the fact that my post with the highest views of 2018 was about me being a fan-boy of the work of somebody else. Mainly because it’s awesome and I’m a fan-boy of the work of a lot of people.

As for the Passive voice post, well it annoyed me and I was so happy to find the answer that I had to blog about it. Thank you to a certain German Fashion magazine forum for continuously sending traffic my way because of it!

Travel

SQLBits, SQL Saturday Oslo, SQL Saturday Reading, PSDay UK, etc.

It’s probably been my busiest year with regard to travel. Combine this with my moving back to Ireland from London in June this year and I’ve now reached the age stage where I can’t fully remember where I’ve been.

To combat this, I’ve enabled Google Timelines to help keep track of where I’ve been. Here is what it’s shown me since July 2018.

The amount of information that I’ve been taught, the people that I’ve finally met face to face, the beauty of the places I’ve been definitely makes me want to keep the travel going into 2019!

Shout out to Drew Furgiuele ( blog | twitter ) who I didn’t manage to meet when we were both in SQL Saturday Oslo. We’ll have our coffee/alcohol/workout/handshake eventually!

Learnings

While it has been a busy year for blogging, travelling, and meeting people it has come at a cost. One that I’ve only felt lately when I sat down and tried to a brief forward plan of the upcoming year.

I’ve been receiving an enormous amount of PowerShell help from the PowerShell community. They are extremely welcoming, open, and willing to aid knowledge seekers (so much so that I’m having a fun little argument with them about which community is more welcoming: PowerShell or SQL 🙂 ).

Catching up with some SQL webinars and reading some of the SQL blogging community’s posts has shown me that I haven’t been keeping up to date with the SQL Server announcements and new technologies.

This is something that I am going to have to actively aim to rectify in 2019.

Ideas

2018 was amazing for seeing a small subset of what someone can achieve with the technology out there in the world. To say that I’m bursting with ideas wouldn’t be far from the truth, thanks to a combination of procrastination and under-used time-management skills.

I’m going to be aiming to see if I can turn 2018, the year of ideas, into 2019, the year of actions.

Reflections

Hard to believe that I’ve been blogging for 3 years but this will be the first reflection that I have done.

Overall I’m pleased with what I’ve accomplished, learned, and realised with 2018. Yes, even the realisation that I need to increase my effort on SQL Server learning.

What get’s measured gets done!

Looking forward, I’m not quite sure what’s next. I’ve a couple of SQL Server and PowerShell days/conferences that I’m looking forward to. I suppose it’s time to stop reflecting and start planning.

To everyone who I’ve encountered in 2018, thank you.

To everyone who has encountered me in 2018, I’m sorry. I need more caffeine at the time.

To everyone I’m going to meet in 2019, looking forward to it!