February 2008 - Posts

Adios SQLJunkies

Thanks for getting me started but it's time to close the door.

 Allen
 




Cross-posted from SQLBlog! - http://www.sqlblog.com


Change Tracking and Change Data Capture

Tonight's meeting of the Ohio North SQL Server Users Group will include the Detroit SQL Server Users Group as well. Here's the agenda:

5:30 - 6:00 PM - Early Arrival/PASS Intro and Presentation Tips and Techniques - Allen White
6:00 - 6:10 PM - Get Pizza and Settle/Coordinate Live Meeting with Detroit
6:15 - 7:15 PM - Bill Wolohan - SQL Server 2008 Change Tracking and Change Data Capture
7:15 - 7:30 PM - Q/A & Wrap Up

Go to http://www.bennettadelson.com/sql and click on the link "reserve your seat".

Allen




Cross-posted from SQLBlog! - http://www.sqlblog.com


Start PowerShell in Management Studio

In the February CTP of SQL Server 2008 a new feature has appeared in SQL Server Management Studio. You now have the ability to right-click on an object in the Object Explorer window and open up a PowerShell window. In this window you can navigate the database structures much like you can a disk file subsystem, or like you can navigate the registry in PowerShell.

So, let's say you right-click on your server name and open up a PowerShell window. You can then issue the command:

cd Databases/AdventureWorks

Now you're pointing to the AdventureWorks database. Using PowerShell in this way allows you to browse the Server Management Objects (SMO) tree structures. (By the way, you'll have to remember to use proper case when browsing the SMO objects. They are case-sensitive in this environment.) Now, you can type this:

dir Tables

What returns is a list of the tables in AdventureWorks. It's kind of neat idea, and definitely fun to play with. I haven't found a productive use for it yet, but it's too new for me to make a judgement yet. I like it, but I don't yet know why.

Let me know what you think.

Allen




Cross-posted from SQLBlog! - http://www.sqlblog.com


Ohio North SQL Server Users Group February Meeting - Moved to February 21

Normally our meetings are on the second Thursday of the month, but this year that falls on Valentine's Day, so we've moved the meeting to Thursday, February 21.

Here's the agenda for the February meeting of the Ohio North SQL Server Users Group:

5:00 - 5:45 PM - PASS Chapter Acceptance/SQL 2008 Heroes Happen Here: Presentation Tips and Tricks - Allen White

The Ohio North SQL Server Users Group is now officially a PASS chapter. We'll present the PASS Welcome presentation, followed by a "Heroes Happen Here" presentation on how to deliver quality presentations, because you have something interesting to share with the rest of us, and this presentation will show you some of the ways the top presenters get their message across effectively.

5:45 - 6:00 PM - Dinner

6:00 - 7:00 PM - Change Tracking and Change Data Capture in SQL Server 2008 - Bill Wolohan, Bennett-Adelson

SQL Server 2008 has 2 new features that can notify you when your data changes. Both are easy to set up and do not require you to create triggers on each table. Change Tracking requires less overhead, but Change Data Capture gives you more detail. This presentation will explain how each of these features works and when you might use one or the other.

Registration: Go to http://www.bennettadelson.com/sql and click on the link "reserve your seat".

I look forward to seeing you there!

Allen




Cross-posted from SQLBlog! - http://www.sqlblog.com


PowerShell, SQL Server and Large Resultsets

Last week I posted about using PowerShell and SQL Server together, and I used a SQLDataAdapter and populated a DataTable with the results. This approach is fine if what you're doing returns a reasonably small resultset, but what if you're returning millions of rows. In this case a DataTable isn't too practical, and a forward-only DataReader is the best way to go.

In my company we have some legacy applications which need data from a large relational database. The preferred format is a comma-separated data file with the columns quoted (to handle whatever imbedded data might be found). I needed to supply separate text files, with subscriber lists, with the list name as the file name of the text file, and the first row a list of the column names of the data.

The first thing I need to do is open a connection to the database.

#extract_subs.ps1
#This script will extract information for subscribers
#and write the results into text files named with the list name.

$cn = new-object System.Data.SqlClient.SqlConnection("Data Source=MyServer/MyInstance;Integrated Security=SSPI;Initial Catalog=Subscribers");
$cn.Open()

Once the connection is open I build a SqlCommand object with the query to be processed. (To prevent collisions with the application using the database, and because dirty reads are acceptable to this process, I use the NOLOCK hint.) The results are ordered by list name and email address - the list name order is important because I'm creating separate files based on that list name. I also need to set the CommandTimeout property of the SqlCommand object to 0 to prevent PowerShell from timing out waiting for results - as I mentioned, there are millions of rows coming back.

$q = "SELECT	List,"
$q = $q + "	EmailAddr,"
$q = $q + "	FullName,"
$q = $q + "	UserID,"
$q = $q + "	CompanyName,"
$q = $q + "	Address1,"
$q = $q + "	CityName,"
$q = $q + "	StateProvince,"
$q = $q + "	PostalCode,"
$q = $q + "	Country,"
$q = $q + "	Telephone,"
$q = $q + "  FROM .[dbo].[SubList] WITH (NOLOCK)"
$q = $q + "  ORDER BY [List], [EmailAddr]"
$cmd = new-object "System.Data.SqlClient.SqlCommand" ($q, $cn)
$cmd.CommandTimeout = 0

Now I can use the ExecuteReader method of the SqlCommand object to return a SqlDataReader object. I'll also initialize a variable I'll use to know when the List name changes, so I can write a header row to the output file. I then use a while loop to iterate through the results. The DataReader Read() method returns true if it has data and false if it is done, so using that method in the while condition returns a row and tests for the end of the data.

$dr = $cmd.ExecuteReader()
$l = ""

while ($dr.Read()) { 

There are a number of methods to return column data from a DataReader, but GetValue returns a datatype appropriate to the data returned, so I use that method pretty consistently. I return that data to variables for clarity.

	$List = $dr.GetValue(0)
	$EmailAddr = $dr.GetValue(1)
	$FullName = $dr.GetValue(2)
	$UserID = $dr.GetValue(3)
	$CompanyName = $dr.GetValue(4)
	$Address1 = $dr.GetValue(5)
	$CityName = $dr.GetValue(6)
	$StateProvince = $dr.GetValue(7)
	$PostalCode = $dr.GetValue(8)
	$Country = $dr.GetValue(9)
	$Telephone = $dr.GetValue(10)

Now that I have the row data in variables I test to see if the List name changed. If it did I build a header row. I then use the new List name and concatenate the ".txt" extension onto it for the output file name, then pipe the header row to the out-file cmdlet. I specify -append in case the file from the previous run still exists (it shouldn't), and I specify -encoding ASCII because by default PowerShell will create a Unicode format file. I also set my list change variable to the name of the list.

	if ($List -ne $l) {
		$r = """List"",""EmailAddr"",""FullName"",""UserID"
		$r = $r + """,""CompanyName"",""Address1"
		$r = $r + """,""CityName"",""StateProvince"",""PostalCode"
		$r = $r + """,""Country"",""Telephone"""
		
		$f = $List + ".txt"
		$r | out-file $f -append -encoding ASCII
		
		$l = $List
		}

Now I build the row data into its comma-separated string and write out the data using the out-file cmdlet.

	$r = """" + $List + """,""" + $EmailAddr + ""","""
	$r = $r + $FullName + """,""" + $UserID + ""","""
	$r = $r + $CompanyName + """,""" + $Address1 + ""","""
	$r = $r + $CityName + """,""" + $StateProvince + """,""" + $PostalCode + ""","""
	$r = $r + $Country + """,""" + $Telephone + """"
	
	$f = $List + ".txt"
	$r | out-file $f -append -encoding ASCII
	
	}

The last thing we need to do is to close the DataReader and the Connection.

$dr.Close()
$cn.Close()

There are many different ways to accomplish a task like this. PowerShell gives us one more tool in the toolbox to get tasks done.

Allen




Cross-posted from SQLBlog! - http://www.sqlblog.com