|
|
|
|
-
Wow, it's been a crazy month! Two weeks of Tech Ed in Orlando, where I spent time helping people with questions on SQL Server in the Database Platform area and presented two sessions on SMO and PowerShell (one with my friend Peter Ward from Australia). Then, my last week as a DBA at Advanstar, followed by my first week as a Trainer for Scalability Experts! Wow.
So I wanted to get the word out about our upcoming SQL Saturday event in Berea, Ohio, on the campus of Baldwin-Wallace College. If you're going to be in the area, or if this will provide motivation to come to Cleveland, it should be a great event. I'm hoping to have about 30 sessions on SQL Server, both how to do things now, and how you'll be able to do things much easier with SQL Server 2008.
The Call for Abstracts is open, so if you're interested in presenting, please submit your session idea here.
If speaking isn't your strong suit but you'd like to attend we'll be happy to have you. The link to register is here.
The morning sessions will each be an hour long, in the Math and Computer Science building, and the afternoon sessions will be 75 minutes each, and be held in larger rooms in Strosacker Union. We'll have a box lunch on the picnic tables behind the Union (weather permitting) and a nice wrapup after the sessions with some great giveaways, including a full MSDN Team Suite subscription!
I look forward to seeing you at SQL Saturday, and perhaps meeting some of you in my teaching assignments with Scalability Experts!
Allen
|
-
When SQL Server Agent runs its tasks it normally does so using the context of the service account you assigned to the Agent service. This may or may not be the best context for your application, so you can set up a Proxy. This allows you to run the task under the context of the account you set up in the proxy, and it's pretty easy to do.
First, set up a Credential. This defines the ADS login credentials the proxy will use. You can do this under the Security tree in Object Explorer, or you can set it up in Transact-SQL like this:
CREATE CREDENTIAL [cred_MyCredential] WITH IDENTITY = N'MyDomain\MyLogin', SECRET = N'S0meComp1exP@ssw0rd' GO
Once the credential exists then you define the proxy. Expand the tree under SQL Server Agent/Proxies, select the job task type you plan to use the proxy for, then right-click and select New Proxy, or use this Transact-SQL:
USE [msdb] GO EXEC msdb.dbo.sp_add_proxy @proxy_name=N'proxy_MyProxy',@credential_name=N'cred_MyCredential', @enabled=1 GO EXEC msdb.dbo.sp_grant_proxy_to_subsystem @proxy_name=N'proxy_MyProxy', @subsystem_id=3 GO
EXEC msdb.dbo.sp_grant_login_to_proxy @proxy_name=N'proxy_MyProxy', @msdb_role=N'SQLAgentUserRole' GO
In the sp_grant_proxy_to_subsystem stored procedure, @subsystem_id=3 indicates this proxy will be used to run Operating System commands.
Once the proxy exists it can be selected in setting up a job task by specifying the new proxy in the Run As dropdown in the task dialog. If setting up the job through Transact-SQL you specify the proxy in the sp_add_jobstep stored procedure with the @proxy_name parameter:
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Step 01', @step_id=1, @cmdexec_success_code=0, @on_success_action=1, @on_success_step_id=0, @on_fail_action=2, @on_fail_step_id=0, @retry_attempts=0, @retry_interval=0, @os_run_priority=0, @subsystem=N'CmdExec', @command=N'"d:\ApplicationDirectory\MyJobStep.bat"', @flags=0, @proxy_name=N'proxy_MyProxy'
This may seem like a lot, but really it's not, and it ensures that the automation you're implementing is being done using the right context.
Allen
|
-
Here's the agenda for the May 8th 2008 meeting of the Ohio North SQL Server Users Group. The meetings are held on the 2nd Thursday of every month at 5:15 in the Cleveland Microsoft office. The address of the office is below: Microsoft Corporation 6050 Oak Tree Blvd. Suite 300 Cleveland, OH 44131 Agenda: 5:15 - 5:45 PM - Excel 2007 Data Mining Add-In by Bruce SzaboThe Excel Data Mining Add-In allows one to Use Excel 2007 and Analysis Server 2005 to do some great data mining. This is a quick overview of getting this functionality up and running on a computer. 5:45 - 6:00 PM - Dinner6:00 - 7:00 PM - Dynamic Package Loading with SSIS Presented by Dave Gabele Dave will discuss leveraging the properties of SSIS to create a scheduler and dynamic package loader. The concepts Dave presents provide the ground work for building enterprise ETL processes with (SSIS). The focus will be on the Control Flow aspects of SSIS and should allow others to learn from Dave’s experiences. Having used DTS extensively Dave will delve into the gotchas he found in making his transition to SSIS. 7:00 - 7:30 PM - Wrap up / Ongoing discussionsRegistration: To register, go to www.bennettadelson.com/sql and click on the link "reserve your seat".
|
-
Last night I picked up my tickets for Commencement Exercises on May 11, and found out that I'll be graduating Summa Cum Laude from Baldwin-Wallace College with a Bachelors of Science Degree in Computer Information Systems.
Needless to say, I'm really pleased.
Allen
|
-
Matthias Berndt, Principal Group Program Manager at Microsoft, has just blogged about the new approach for Service Packs and Cumulative Updates. He shared this with us at the MVP Summit and it's nice to have it public now.
A Changed Approach to Service Packs
Thanks, Matthias
Allen
|
-
Last week I presented a session on Using SMO to Manage SQL Server at SQL Connections in Orlando, Florida. This was the third major conference I've presented this session, and each time I do this session I change more demos from VB.Net to PowerShell. This time it was the demo to create a new database.
The big thing about my demos is that I want to reflect what I actually do in my job as a DBA, and I now use this script whenever I want to create a new database. The demo files I included with my presentation contained the VB.Net code I used to use so I wanted to make the code available here.
The first thing we need to do is load the SMO object library and connect to the server.
#createdb.ps1
#Creates a new database using our specifications
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') 'MyServer/MyInstance'
The next thing we'll do is set a string variable to the name of the database. This value can also be supplied as an argument to the script if you want. Then we'll instantiate the database object and add filegroups for PRIMARY (required for SQL Server), and another filegroup I call AppFG for the application data. I've found that I improve performance and recoverability by putting only the database metadata in the PRIMARY filegroup, setting its size to 5MB without expansion, then setting the AppFG (application filegroup) to be the default filegroup.
$dbname = 'SMO_DB'
# Instantiate the database object and add the filegroups
$db = new-object ('Microsoft.SqlServer.Management.Smo.Database') ($s, $dbname)
$sysfg = new-object ('Microsoft.SqlServer.Management.Smo.FileGroup') ($db, 'PRIMARY')
$db.FileGroups.Add($sysfg)
$appfg = new-object ('Microsoft.SqlServer.Management.Smo.FileGroup') ($db, 'AppFG')
$db.FileGroups.Add($appfg)
Once the filegroups have been created, we can create the files for the database. First we create the file for the database metadata. I've set the size to be 5MB with no growth. To create the database the PRIMARY filegroup has to be set to be the default, so we'll set that here as well.
# Create the file for the system tables
$syslogname = $dbname + '_SysData'
$dbdsysfile = new-object ('Microsoft.SqlServer.Management.Smo.DataFile') ($sysfg, $syslogname)
$sysfg.Files.Add($dbdsysfile)
$dbdsysfile.FileName = $s.Information.MasterDBPath + '\' + $syslogname + '.mdf'
$dbdsysfile.Size = [double](5.0 * 1024.0)
$dbdsysfile.GrowthType = 'None'
$dbdsysfile.IsPrimaryFile = 'True'
Next we'll create the file to hold the application tables. Normally 25MB works for my databases, so I've set that in the Size parameter, and I use a growth parameter of 25%, because 10% is too small an increment when growth is required, in my opinion. I've also set a maximum size for this file of 100MB. I have to watch this to make sure we don't run out of space, but this is rarely a problem in my environment, and this max helps prevent me from running out of physical disk. (Note that sizes are specified in KB units, so I "do the math" in the script so it's easier to read.)
# Create the file for the Application tables
$applogname = $dbname + '_AppData'
$dbdappfile = new-object ('Microsoft.SqlServer.Management.Smo.DataFile') ($appfg, $applogname)
$appfg.Files.Add($dbdappfile)
$dbdappfile.FileName = $s.Information.MasterDBPath + '\' + $applogname + '.ndf'
$dbdappfile.Size = [double](25.0 * 1024.0)
$dbdappfile.GrowthType = 'Percent'
$dbdappfile.Growth = 25.0
$dbdappfile.MaxSize = [double](100.0 * 1024.0)
Now I can create the file for the transaction log. I set this to an initial size of 10MB with 25% growth.
# Create the file for the log
$loglogname = $dbname + '_Log'
$dblfile = new-object ('Microsoft.SqlServer.Management.Smo.LogFile') ($db, $loglogname)
$db.LogFiles.Add($dblfile)
$dblfile.FileName = $s.Information.MasterDBLogPath + '\' + $loglogname + '.ldf'
$dblfile.Size = [double](10.0 * 1024.0)
$dblfile.GrowthType = 'Percent'
$dblfile.Growth = 25.0
We can create the database now, and once it's been created we can grab the AppFG filegroup, set it's default property to True, alter the filegroup and alter the database. Now it's ready for loading the tables and other objects necessary for the application to work properly.
# Create the database
$db.Create()
# Set the default filegroup to AppFG
$appfg = $db.FileGroups['AppFG']
$appfg.IsDefault = $true
$appfg.Alter()
$db.Alter()
This script allows me to quickly create a new application database without the tedium of clicking through the GUI dialogs, but I can run this script against any of my servers without changing it to reference the specific database file locations, because I pull that from the server's Information collection, so it's cleaner than using Transact-SQL scripts as well. (Note, in this case I'm using the MasterDBPath and MasterDBLogPath properties from the Information collection.)
Allen
|
-
Thursday's meeting of the Ohio North SQL Server Users Group will be a good one. Here's the agenda:
5:00 - 5:45 PM - Early Arrival/Discussions/SQL 2008 Launch Update
We will discuss the status of SQL 2008, including the recent launch event, the latest timetable for release, and touch on some of the more interesting features. We'll also provide online resources to get you started with SQL 2008.
5:45 - 6:00 PM - Dinner
6:00 - 7:00 PM -"Database Mirroring - Lessons from the Field," Presented by Craig Purnell & Michele Adams, Baker & Hostetler
Baker Hostetler uses the database mirroring in SQL Server 2005 to maintain data protection and high availability. They will present their real world techniques, and also demonstrate how to set up mirroring between 2 servers.
7:00 - 7:30 PM - Wrap up / Ongoing discussions
Registration:
To register, go to www.bennettadelson.com/sql and click on the link "reserve your seat".
Allen
|
-
The most important lesson I learned in flight training was in managing priorities:
1. Aviate
2. Navigate
3. Communicate
First, keep the plane flying straight and level. Second, keep it going on the intended flight path (and avoid any other objects in the area). Third, communicate your intentions, needs, etc. with the proper services, be they Air Traffic Control, Flight Services, the local airport Unicom, or simply another pilot in the same airspace.
These rules apply in managing database systems, if you think about it. First, aviate - make sure the database is running, or fix the problem preventing it from running. Second, figure out where the problem has taken you and how you need to get back to your normal production mode. Third, document what happened, why it happened, what you did to correct the problem and what you will do to ensure continued quality service.
This set of priorities can help you keep a cool head when problems come up and everyone's screaming at you.
Allen
|
-
There are some really great books available on SQL Server and I had an opportunity to really put them to work.
Last week I traveled to sunny Los Angeles to our office in Woodland Hills, California to train some of our employees on SQL Server technology. They hold Data Analyst positions with my company and are responsible for producing reports from our show data for the marketing managers, and it was determined that they could be more effective if they could write their own Transact-SQL queries.
First, I wanted to give them an understanding of the relational model - something I didn't have when I started working as a DBA. Louis Davidson's book Pro SQL Server 2005 Database Design and Optimization served as the perfect guide to build this understanding. The way Louis explains the relational model is clear and easy to grasp, and the reader comes away understanding both how and why database design should be done this way.
After giving them a basic background in SQL, the language, we then dove into Itzik's book Inside Microsoft SQL Server 2005: T-SQL Querying, which allowed us to dive into how SQL Server processes the queries as well as how to build queries to solve an incredible array of problems.
Finally, we finished up with Itzik's other great Transact-SQL book Inside Microsoft SQL Server 2005: T-SQL Programming, which allowed us to get into the details of how to write the stored procedures and views (as well as many other topics) to allow them to produce the more complicated reports their managers request.
The week was quite intense, but one of the great rewards one gets in teaching is to see that "ah ha!" moment when a student "gets" it. Last week had quite a number of those moments, and I give the credit to the great material that Itzik (and his co-authors Lubor Kollar, Dejan Sarka and Roger Wolter) and Louis provided.
I highly recommend these books to anyone getting started in Transact-SQL or anyone wanting to take their skills to the next level.
Thanks, guys.
Allen
|
-
The Windows/Visual Studio/SQL Server 2008 Launch Event is working its way around the country, and Tuesday, March 18, it hits Detroit. I'll be there to help out with the SQL Server portion of the event and answer people's questions on the new version. (It came to Cleveland last Thursday, but I was out of town.)
If you still haven't registered, here's the website: http://www.microsoft.com/heroeshappenhere/events/Detroit/default.mspx.
I hope to see you there!
Allen
|
-
Thanks for getting me started but it's time to close the door. Allen
|
-
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
|
-
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
|
-
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
|
-
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
|
|
|
|
|
|