|
|
SQL Saturdays and Twitter go together like peas and carrots. I’ve found the networking page of any SQL Saturday site is very valuable to not only get in contact with people about the event, but also to stay in contact and build long term relationships. Helping plan, organize and speak at SQLSaturday #99, I didn’t want to loose the conncections I had made, so I decided to check out all the twitter accounts of the people who had registered for for it.
What’s the easiest way to do this? POWERSHELL!!!
I stumbled a few times (one time I opened 83 tabs in Chrome and had to stop using twitter for an hour), but here is the script I came up with.
Notes on the script:
- This script will open a chrome tab for each twitter account from any (at least all I’ve tested so far) SQL Saturday Networking page.
- If Chome isn’t running, the script will open it for you, but it may open multiple instances of it.
- You can change the $url for a different SQL Saturday Networking Page
- You can set the number of tabs to open at a time – note it’s 0 relative, so 4 is actually 5
- This script creates 4 txt files in the “c:\temp” directory, but it doesn’t check for it’s existence.
- This script stores a count locally, so you will need to run it multiple times to get all the twitter users
- i.e. if there are 83 users, the script is set to open 5 tabs, you will need to run this 17 times.
- To restart or to change the SQLSaturday URL delete the file SQLSatCounter.txt file
- Powershell Programming Examples:
#--------------------------------------------------------------------------------------
#Open a tab in Chrome for each twitter account on a SQLSaturday Networking Page
#Created by Andy Lohn - http://www.sqlfeatherandquill.com/
#--------------------------------------------------------------------------------------
$url = "http://www.sqlsaturday.com/99/networking.aspx" #Change this for any SQLSaturday Networking Page
[int]$StartCount = 0
[int]$PageCount = 4 #note this is 0 relative, so this plus 1 for number of tabs to be opened
$chrome = (gi ~\AppData\Local\Google\Chrome\Application\chrome.exe ).FullName
#This didn’t work on one of my machines, so I just set it to the full path of chrome and it worked.
$webclient = New-Object system.net.webclient
$file1="c:\temp\SQLSatDownload.txt"
$file2="c:\temp\SQLSatList.txt"
$file3="c:\temp\SQLSatListwithAddress.txt"
$TURL = "www.twitter.com/"
$file4="c:\temp\SQLSatCounter.txt"
#Create the files if they don't exist
If (!(Test-Path $file1) )
{New-Item $file1 -Type file}
If (!(Test-Path $file2) )
{New-Item $file2 -Type file}
If (!(Test-Path $file3) )
{New-Item $file3 -Type file}
#Set the counter to keep track for multiple runs - 0 if new
If (Test-Path $file4)
{$SCWork = (get-content $file4)
[int]$StartCount = $SCWork.ToString()}
Else
{New-Item $file4 -Type file
add-content $file4 1
[int]$StartCount = 0}
If ($StartCount -eq 0) #Populate the local file.
{Clear-Content $file1
$webclient.DownloadFile($url,$file1)
$test = get-content $file1
Clear-Content $file2
Clear-Content $file3
$Tester = $test | Select-String -pattern "<a href=""<a href="http://www.twitter.com/"">http://www.twitter.com/"</a> |
% {$_ -replace "<span id=""ContentPlaceHolder1.*<a href="http://www.twitter.com/"">http://www.twitter.com/"</a>, ""} |
% {$_ -replace """ class=""noarrrow"">.*</span>", ""} |
% {$_ -replace "<a href="http://twitter.com/#!/"">http://twitter.com/#!/"</a>, ""} |
% {$_ -replace " ", ""} |
where {$_ -ne ""}
foreach ($T in $Tester)
{Add-content $file3 ($TURL + $T)}
}
$TestMethod = (Get-Content $file3)[$StartCount .. ($StartCount + $PageCount)] $TestMethod | % { & $chrome $_ }
Clear-Content $file4
Add-Content $file4 ($StartCount + $PageCount + 1)
#To restart or change url, run this:
#remove-item $file4
This has to be real easy to change for linkedin – I’m more a twitter guy at this point. If you do alter it, to work for linkedin, let me know!

I’ve been a stickler for default names since reading Jason Strate’s (blog/twitter) post on cleaning up auto-generated names. Today I had to create a non-nullable column with a default – can I do it in one step? Yep – here’s an example:
ALTER TABLE <<TABLENAME>> ADD <<COLUMNNAME>> <<TYPE>> NOT NULL CONSTRAINT <<DEFAULTNAME>> DEFAULT (<<Value>>)
Here’s the example in action:
Create table Testtable
(id int)
Insert Testtable Values (1),(2),(3),(4),(5)
ALTER TABLE Testtable ADD DefaultTest BIT NOT NULL CONSTRAINT DF_Testtable_DefaultTest DEFAULT (0)
Select * from Testtable
--/*Now to drop this column, do it in this order */
Alter table Testtable alter column DefaultTest bit null
Alter table Testtable Drop constraint DF_Testtable_DefaultTest
Alter table Testtable DROP column DefaultTest
Today I realized I made a fairly significant mistake. I had misspelled a column name in a bunch of procedures and views that I had updated. Not a big deal, except each procedure and view was a file and I had about 75 files. Only a few of them contained this change, I don’t know which ones, but most of them had other changes. What to do…
- I could manually check all files with a few routine of Keystrokes – that might take an couple of hours.
- I could check sysdepends for dependancies – nope none of the procedures have been executed.
- I could check syscomments for the column name – that would kind of work, but I would still need to manually update it.
- Powershell!! I could find and replace in the files and execute them as well!
I used the following sites as they have good examples.
Here’s what I came up with:
##Finds all the occurrences in the Views folder##
foreach ($f in Get-ChildItem -path "C:\Temp\Views\" -Filter *.sql | sort-object)
{$Location = $f.fullname
Select-String -path $Location -pattern "Andee"| out-file -filePath "C:\Temp\ListoObjects.txt" -append}
##Replaces all the occurrences in the Views folder##
foreach ($f in Get-ChildItem -path "C:\Temp\Views\" -Filter *.sql | sort-object)
{(Get-Content $f.fullname) |
Foreach-Object {$_ -replace "Andee", "Andy"} |
Set-Content $f.fullname}
Today I was asked which procedure (of two with similar names) is used in production. Looking at the naming convention, I had a guess, but I needed proof as we are looking to clean up old unused procedures. So I found this article Monitoring Stored Procedure Usage at Database Journal. I modified the script to this:
Select DB_NAME(st.dbid) DBName
,OBJECT_SCHEMA_NAME(st.objectid,dbid) SchemaName
,OBJECT_NAME(st.objectid,dbid) StoredProcedure
,max(cp.usecounts) Execution_count
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
where DB_NAME(st.dbid) = '<<SET DBNAME HERE>>'
and cp.objtype = 'proc'
and OBJECT_NAME(st.objectid,dbid) in ('<<LIST PROCS HERE>>')
Group by cp.plan_handle, DB_NAME(st.dbid),
OBJECT_SCHEMA_NAME(objectid,st.dbid),
OBJECT_NAME(objectid,st.dbid)
order by max(cp.usecounts) desc
I’ve got a lot of changed altered procedures for a project I’m working on. I’ve been altering a lot of data in my test database, so I needed to restore my database and apply the changes I’ve made. The easy way to do would be a powershell script. Here’s what I found.
From Martin Bell for the post, “Executing all .SQL files in a directory with Powershell” Thank you Martin!
I also used twitter and asked #SQLHELP and SQLSoldier responded with this in about 3 minutes. Very impressive!
Get-ChildItem -Path "C:\SQLScripts" -Filter "*.sql" | % {invoke-sqlcmd -InputFile $_.FullName}
Here’s what I altered Martin’s script to:
foreach ($f in Get-ChildItem -path "C:\SQLScripts\" -Filter *.sql | sort-object)
{
$out = "C:\SQLScripts\OUTPUT\" + $f.name.split(".")[0] + ".txt" ;
invoke-sqlcmd –ServerInstance <<ServerName>> -Database <<DBName>> -InputFile $f.fullname | format-table | out-file -filePath $out
}
Here’s all the info on the Invoke-SQLCMD from MSDN.
I’ve got a new step in a job that I’m concerned about the duration. Here’s a script to get the duration of a specific step of a job. Note I found that whole conversion of the Run_DateTime column from Ramblings of a DBA – Tara Kizer – kudos, Tara.
Declare @JobName varchar(255),
@StepName varchar(255)
Set @JobName = '<<Enter Job Name Here>>'
Set @StepName = '<<Enter Job Step Name Here>>'
Select top 1000 run_datetime = CONVERT(DATETIME, RTRIM(run_date)) +
(run_time * 9 + run_time % 10000 * 6 + run_time % 100 * 10) / 216e4,
run_duration = Left(RIGHT('000000' + CONVERT(varchar(6), run_duration), 6), 2)+':'
+ Substring(RIGHT('000000' + CONVERT(varchar(6), run_duration), 6), 3, 2)+':'
+ Right('00' + CONVERT(varchar(6), run_duration), 2),
SJ.name,
SJH.step_name
from msdb.dbo.sysjobs SJ
Join msdb.dbo.sysjobhistory SJH on SJH.job_id = SJ.job_id
where SJ.name = @JobName
and SJH.step_name = @StepName
Order by run_datetime desc --Use this to find the most recent
--Order by run_duration desc --Use this to find the slowest
I had to change my password today and the easiest way, at my work, is to RDP to a server in each of the domains. I couldn’t remember how to send the CTRL + ALT + Delete to a RDP/Terminal Server session.
It is:
CTRL + ALT + End
Here’s a page from mydigitallife that has a few other keyboard short cuts.
I just spent 10 minutes looking for this, it’s very simple and fairly obvious. I’m posting it so I don’t forget it and hopefully it may help others.
I’ve got to script out all tables, indexes, primary keys, foreign keys, defaults and the collation of all tables in all of our databases. They all have to be the same style and the options I have to choose are slightly different than the defaults. To make fast work of this, I’ll change the defaults to be exactly what I want then from my Central Management Server, I script each and every database I need.
Here’s how to set the defaults:
In SQL Server Management Studio, go to Tools –> Options. Expand the SQL Server Object Explorer list and select Scripting. Change what you want, close this window and Ta-Da the next time you generate scripts, the defaults are set.

Here’s a script I came up with to move my central management server’s Groups and Server from one server to another. I know it doesn’t make a ton of sense to do this, but I started testing the CMS setup on a test server and it’s worked so well, we wanted to put it on a production server. There are two scripts that are run on the source server that create scripts to run on the destination server.
/*
--Verify you've got the correct groups.
Select * from dbo.sysmanagement_shared_server_groups_internal
where is_system_object = 0 --ignore the builtin groups.
*/
Select '
Declare @server_group_id int
EXEC msdb.dbo.sp_sysmanagement_add_shared_server_group @parent_id=1, @name=N''' + name
+ ''', @description=N''' + description + ''', @server_type=0, @server_group_id=@server_group_id OUTPUT'
+ CHAR(13) + CHAR(10)
+ 'Go'
from dbo.sysmanagement_shared_server_groups_internal
where is_system_object = 0 --ignore the builtin groups.
Again, run the output of this on the destination server.
Here’s the script to move the servers with their groups – note the group id is dynamic, so even if the destination server has more groups, it will figure out the correct one.
Select
'Declare @SGID int, @SGName nvarchar(255)
Set @SGName = ''' + SGI.name + '''
Select @SGID = server_group_id from dbo.sysmanagement_shared_server_groups_internal
where name = @SGName
Declare @server_id int
EXEC msdb.dbo.sp_sysmanagement_add_shared_registered_server @server_group_id=@SGID, @name=N''' +
RSI.name + ''', @server_name=N''' + RSI.server_name + ''', @description=N''' + RSI.description + ''', @server_type=0, @server_id=@server_id OUTPUT'
+ CHAR(13) + CHAR(10)
+ 'Go'
from dbo.sysmanagement_shared_registered_servers_internal RSI
Join dbo.sysmanagement_shared_server_groups_internal SGI on RSI.server_group_id = SGI.server_group_id
Finally, run the output of this on the destination server.
Here’s a couple of resources I used to figure this stuff out:
There’s been many times I’ve tried to find the backup history of a database. Questions like when was the last backup taken? Where was it backed up to? etc. I googled a script for this and I used MSSQLTips as a baseline – found here – then altered it to this:
Declare @DBName varchar(255)
Set @DBName = '<<Database Name Here>>'
SELECT top 10
@@ServerName AS Server,
BUS.database_name,
BUS.backup_finish_date,
CASE BUS.type
WHEN 'D' THEN 'Database'
WHEN 'L' THEN 'Log'
END AS backup_type,
BUS.backup_size,
BUMF.physical_device_name
FROM msdb.dbo.backupmediafamily BUMF
INNER JOIN msdb.dbo.backupset BUS ON BUMF.media_set_id = BUS.media_set_id
WHERE BUS.database_name = @DBName
And BUS.type = 'D'
ORDER BY BUS.backup_finish_date desc
|
|