Words: 853
Time to read: ~ 4.5 minutes
Continue reading “[PowerShell] Name Parameters When Using ForEach-Object…or else!”
…or else you script may not work properly. That’s all, I’m not that scary.
Words: 853
Time to read: ~ 4.5 minutes
Continue reading “[PowerShell] Name Parameters When Using ForEach-Object…or else!”
Before I learned the joys of dbatools, I had to always run the depreciated [System.Reflection.Assembly]::LoadWithPartialName()
method to make sure that I could access the SMO objects of SQL Server Instances and Databases.
…well once, pre-SqlServer Module stage, I wanted to connect to my SQL Server Instance using SMO. However, when I ran New-Object -TypeName Microsoft.SqlServer.Management.Smo.Server -ArguementList "server name"
I got an error message complaining that the assembly wasn’t loaded.
New-Object : Cannot find type [Microsoft.SqlServer.Management.Smo.Server]: verify that the assembly containing this type is loaded.
…here because a lot of my custom function rely on Microsoft.SqlServer.Smo
and if that assembly isn’t loaded then I’m going to have a bad time!
But how do we check if an assembly is loaded already?
AppDomain to the rescue!
[appdomain]::CurrentDomain.GetAssemblies() | Sort-Object -Property FullName | Select-Object -Property FullName;
Now that I know what assemblies I have loaded, I can see that Smo isn’t loaded. So I would probably load it using LoadWithPartialName()
.
You may have noticed that I mentioned “pre-SqlServer module” and “before […] dbatools“. This is because with these two modules, I don’t need to worry about assemblies anymore.
We’re going to use the SqlServer module to load the required assemblies for us.
First of all, let’s use a throw away cmdlet so that PowerShell can auto-load the module for us. Normally people would chose Get-SqlDatabase
but it doesn’t matter. As long as it’s a cmdlet in the SqlServer module, then this is going to work.
In this case, I’m going to use Get-SqlAgent
and throw the results away.
$null = Get-SqlAgent -ServerInstance 'localhost\SQLServer2K16';
Now, if we check if our Smo assembly is loaded…
[AppDomain]::CurrentDomain.GetAssemblies() | Where-Object FullName -like '*SMO*';
2 result sets? How much assemblies does it load for us? Running our original assembly query check again, it seems to be a lot bigger than just 2 assemblies.
Opening a new PowerShell window, and throwing the results of our assemblies check into $PreLoad, we then call a SqlServer Module cmdlet. We then throw the results of our assemblies check into $PostLoad.
$PreLoad = [AppDomain]::CurrentDomain.GetAssemblies() | Sort-Object -Property FullName | Select-Object -Property FullName; $null = Get-SqlAgent -ServerInstance 'localhost\SQLSERVER2K16'; $PostLoad = [AppDomain]::CurrentDomain.GetAssemblies() | Sort-Object -Property FullName | Select-Object -Property FullName;
Then we can use our good old Compare-Object
, that we’ve used before, to see what else gets loaded for us
Compare-Object -ReferenceObject $PreLoad.FullName -DifferenceObject $PostLoad.FullName;
I probably wouldn’t have even known about them, and they get loaded for me! I have to check them out.
It is nice to know that you don’t have to manually load assemblies.
LoadWithPartialName()
is deprecated and I don’t think anybody wants to memorize the FullName of the assembly to do it the Add-Type
way.
Don’t worry though, you don’t have to anymore.
PowerShell got you covered 🙂
I realised I hadn’t done a blog post this week and didn’t think I had anything planned, so here is a random PowerShell/SQL Server encounter on Twitter. Hope you enjoy
Recently a question came up on the #sqlhelp hashtag on Twitter asking about a problem that a user was having with using .Contains with an array.
Normally when I see a question regarding PowerShell, Arrays, and Contains I keep an eye on them, not to answer them but to read the responses and learn from them.
However, this one caught my eye for two reasons; it had an image with Invoke-Sqlcmd
in it , and it was on the #sqlhelp hashtag. So I said let’s see if I can help out here.
… was if you have a table like below…
and you are running the following PowerShell command to check if the results contain a value…
$String = "abc" $Array = @(Invoke-Sqlcmd -ServerInstance "SQLServer" -Database "Database" -Query "SELECT code FROM dbo.users") $Array.Contains($string)
It will return FALSE
.
Now we know that the FALSE
is false because we know that the string is in there!
This code is proven to work with arrays as stated here by the “Hey, Scripting Guy!”s so this was getting filed under “WTF PowerShell”
… and I’ve done the same so I can’t blame them, was they failed to use Get-Member
; they made assumptions (bad idea)
If they had run $array | gm
, they would have seen that the $array is not an array but a System.Data.DataRow
, and we’ve seen them before.
…was running $array | gm
and seeing that there was no method called .Contains
.
So I was going down the route of using a mix of foreach
and -eq
.
This wouldn’t have been great though as we would have to iterate over every single row and seeing if the value existed. I assumed that the reason the questioner wanted to use .Contains
was to get around iterating over every single row, so this wasn’t going to work either.
…was use Get-Member
.
The Questioner should have used $Array | gm
and I, knowing the next step, should have used $Array.code | gm
It’s nice to see the way that NULLs are treated differently in PowerShell. 🙂
If we drop down from the DataRow into the property of the DataRow, it becomes a string! Perfect because the string contains the method .Contain
.
$Array.code.Contains($String);
…and we have our True
.
PowerShell…beautiful!
In my ongoing attempt to learn Powershell to help automate my workloads, I’ve come across the need to use the Transact-SQL SUBSTRING() function but, in using it, I got the following error:
Now if you are like me, that is very hard to read but the error is saying
StartIndex cannot be larger than length of string
The main difference that I can see when using SUBSTRING()
in SQL Server versus in PowerShell is that SQL Server is very forgiving.
If you have a string that is 20 characters longs and you ask for everything from the 5th character to the 100th character, SQL Server is going to look at this, see that the string does not go to the 100th character, and just give you everything that it can.
PowerShell on the other hand, while being amazingly forgiving with some things….
Examples:
"a" + 2
= a2"a" * 2
= aa2 + 2
= 4"2" + 2
= 22…is surprisingly less forgiving than SQL Server here.
If we checked the length of the results we can see the length of each individual row:
foreach ($row in ($dbResults.name)) { [PSCustomObject]@{ RowName = $row RowLength = $row.Length } }
So PowerShell goes to find the 5th to the 100th character, sees that the 100th character is outside the length of the string, and freaks out!
…can also be a PowerShell Scalpel as well. You can get as precise as you need to and in this case, with the error complaining about the length, we should probably be more specific about the length we want.
So let’s get more specific about the length! Now we could go and input all the different values for substring function but let’s get a bit more dynamic about it.
It is PowerShell after all…
#...now check the substring function... #...with proper values... foreach ($row in ($dbResults.name)) { [PSCustomObject]@{ RowName = $row RowSubString = $row.Substring(5, ($row.Length) - 5) } }
So there we go, SQL Server substring and PowerShell substring are basically the same. We just have to be concise about it!
Thanks to Michael Villegas ( blog | twitter ) for pointing out in the comments that PowerShell has a simpler syntax to deal with this.
While SQL Server requires 3 arguments for the substring function (expression, start, length)
; PowerShell has the same thing but it also has a simpler syntax for getting the characters from a starting point all the way to the end.
#...simpler syntax... foreach ($row in ($dbResults.name)) { [PSCustomObject]@{ RowName = $row RowSubString = $row.Substring(5) }; };
The more you know… 🙂
TSQL Tuesday, the brain-child of Adam Machanic ( blog | twitter ), has come around once more and this time it is being hosted by Kendra Little ( blog | twitter ). The topic? Interviewing Patterns & Anti-Patterns.
… I have not had that many interviews. A combination of not being that long in the working community since college and staying at the same company for quite a while means that it’s just not something at which I’ve had a lot of practice.
I suppose that I should do one or two, if not to look for a new place to work, then to practice them, see how I measure up, and test my skill.
Mainly though to answer some questions that I have.
Questions about interviewing for DBAs.
I hope you don’t find them too boring or basic.
This question is one that I couldn’t really wrap my head around. How do you interview a DBA? If the purpose of an interview is to evaluate a candidate for a position then how do you measure them?
Technical wise, what do you do? Most of the interviews that I’ve been to have involved some aspect of testing, but the thing is there are different types of DBAs, all to do with what they focus on.
Do you judge a DBA, who is focused on Virtualisation, on the intrinsics of SQL Internals?
Or a DBA, focused on Azure, on their knowledge of SQL Server 2005 and when certain T-SQL functions came in?
A company who is looking for a database design expert is going to focus on that and may not care about a DBA’s expertise in HA/DR options.
How do you ensure that you are adequately testing the competency of a DBA?
Interviews go two ways though, and companies can be more wrong that right (it happens).
The question here is when you run into a company with the wrong beliefs, what do you do?
If the company interviews you and says that you’re wrong in saying that TRUNCATE TABLE
can be rolled back, what do you do?
If they say that index rebuilds doesn’t update index statistics on the columns in the index, again what do you do?
What do you do if they won’t listen, if they won’t look at any examples, if they won’t see reason when given proof to the contrary?
How do you deal with a company that is incorrect in their basic assumptions and unwilling to learn?
…and that we, as DBAs, have to learn to change with it otherwise we’ll get left behind.
A concern for me is that maybe the way that we interview DBAs isn’t right, and that it needs to change or it, too, will get left behind.
Unfortunately, like most things, I don’t have the answer yet…
I’m learning though…
I recently ran into a problem with the QUOTED_IDENTIFIERS
option in SQL Server, and it got me to thinking about these SET
options.
I mean the fact that, on tables where there are filtered indexes or computed columns with indexes, QUOTED_IDENTIFIER
is required to be on to create any other indexes is just not intuitive. But if you can’t create indexes because of it then I’d argue that it’s pretty damn important! I also found out that this problem is not just limited to QUOTED_IDENTIFIER
but to ARITHABORT
and ANSI_WARNINGS
as well.
Just check out the Microsoft Docs and what it has to say about it:
SET ARITHABORT must be ON when you are creating or changing indexes on computed columns or indexed views. If SET ARITHABORT is OFF, CREATE, UPDATE, INSERT, and DELETE statements on tables with indexes on computed columns or indexed views will fail.
And for ANSI_WARNINGS
it says:
SET ANSI_WARNINGS must be ON when you are creating or manipulating indexes on computed columns or indexed views. If SET ANSI_WARNINGS is OFF, CREATE, UPDATE, INSERT, and DELETE statements on tables with indexes on computed columns or indexed views will fail.
So, like a dog when it sees a squirrel, when I found out about the problems with ARITHABORT
and ANSI_WARNINGS
I got distracted and started checking out what else I could break with it. Reading through the docs, because I found that it does help even if I have to force myself to do it sometimes, I found a little gem that I wanted to try and replicate. So here’s a reason why you should care about setting ARITHABORT
and ANSI_WARNINGS
on.
At one stage or another if you’re working with SQL Server, you’ve probably encountered the dreaded “Divide By 0” error:
Msg 8134, Level 16, State 1, Line 4 Divide by zero error encountered.
If you want to check this out, then here’s the code below for our table:
USE Pantheon; -- Create our test table... CREATE TABLE dbo.ArithAborting ( id tinyint NULL ); GO
And our attempt at inserting that value into the table:
SET ARITHABORT ON; GO SET ANSI_WARNINGS ON; GO -- Check can we insert a "divide by 0"... BEGIN TRY INSERT INTO dbo.ArithAborting (id) SELECT 1/0; END TRY BEGIN CATCH PRINT 'NOPE!'; THROW; END CATCH;
And we get our good, old, dreaded friend:
We check our ArithAborting table and nothing is there, like we expected!
SELECT * FROM dbo.ArithAborting;
What about if we were to turn our ARITHABORT
and ANSI_WARNINGS
off though, what happens then? Well that’s a simple thing to test, we just turn them off and run the script again:
--Turn ARITHABORT off; SET ARITHABORT OFF; GO SET ANSI_WARNINGS OFF; GO -- ...insert into our table... BEGIN TRY INSERT INTO dbo.ArithAborting (id) SELECT 1/0; END TRY BEGIN CATCH PRINT 'NOPE!'; THROW; END CATCH;
Now before I freak out and start thinking that I’ve finally divided by zero, let’s check the table:
What’s going on here? Checking the docs…
During expression evaluation when SET ARITHABORT is OFF, if an INSERT, DELETE or UPDATE statement encounters an arithmetic error, overflow, divide-by-zero, or a domain error, SQL Server inserts or updates a NULL value. If the target column is not nullable, the insert or update action fails and the user receives an error.
Nope!
If I have a terminating error in my script, I quite like the fact that SQL Server is looking out for me and won’t let me put in bad data, but if you have these options turned off, even if you wrap your code in an TRY...CATCH
block, it’s going to bypass it.
Plus if you are trying to divide by 0, please stop trying to break the universe. Thank you.
DBA Fundamentals VG has 3 different sessions ready for you all this August, with 2 sessions from our American Group and 1 from our down-under group.
If any of these sessions catch your eye, sign up here: DBA Fundamentals
Damien would like to show you the most interested features you can find in SQL Server 2017. He will briefly talk about SQL Server on Linux (Security), how to use Python scripts, Adaptive query processing and many more.
Very demo heavy.
The power of cloud storage and compute power has made data warehousing possible for businesses of all sizes. What was once a large capital expenditure and multi-year implementation can now be deployed and ready to use within minutes and allow any organization to collect, query and discover insights from their structured data sources. With a full T-SQL interface and compatibility with the rest of the Microsoft data stack, Azure Data Warehouse can fit transparently into your business data strategy and leverage already existing and familiar development and management skills. In this session we will look at the main concepts of the Azure SQL Data Warehouse service, how it’s different than SQL Server and the advantages it provides to an on-premises solution.
I bet never in your career you thought SQL Server would run on anything other than Windows. Times are changing, and are you ready? SQL Server on Linux is right around the corner! What is Linux – really? Why run your mission-critical databases on an unfamiliar operating system? This introductory session will help seasoned SQL Server DBA understand the basics of Linux and how it is different from Windows, all the way from basic management to performance monitoring. By the end of this session, you will be able to launch your own Linux-based SQL Server instance and get hands-on with this paradigm shift to see if this new platform is right for your organization.
We’re continuing work on getting a list of past presenters up on our website. It’s a slow, deliberate progress but it’s ongoing.
You can check it out here: Past Presenters
Apart from that, anything you want to get in touch about, hit us up on Slack or Twitter!