SQL Server 2008 R2 Update for Developers Training Kit Released
06 February 10 09:37 PM | MartinBell | 1 comment(s)

I noticed that the SQL Server 2008 Developers Training Kit has been re-released last week with a R2 Update. It looks like a great resource for SQL 2008 information and the additional features in SQL 2008 R2. It includes links to 8 videos (mainly R2 features), 8 presentations (mainly RTM features) and 13 demos (mainly RTM features) and 8 Hands-on-labs (both releases).

Anyone looking for learning resources on SQL 2008 and SQL 2008 R2 should check it out, it could save you some searching. It can be downloaded from here.

ROWCOUNT when setting variables
03 February 10 12:02 PM | MartinBell | 3 comment(s)

At work last week the question was raised about what @@ROWCOUNT value was returned when you set variables in a SELECT statement. One of the most common problems you come across reviewing code as a DBA is the setting (or not) of a variable to something that the developer wasn’t expecting!

Using the following table:

USE tempdb
GO

CREATE TABLE nums ( num int, val char(10) ) ;
INSERT INTO nums ( num, val ) VALUES ( 1 , 'one') ;
GO

The two simplest ways you can set a single variable from data in a table are:

First Method 

DECLARE @num int
SET @num = ( SELECT num FROM nums ) ;
SELECT @num , @@ROWCOUNT -- 1, 1
GO

Second Method 

DECLARE @num int
SELECT @num = num
FROM nums ;
SELECT @num, @@ROWCOUNT -- 1, 1
GO

The first method may be considered by some to be safer because using that syntax then if the table contains more than one row you will get an error e.g.

INSERT INTO nums ( num, val ) VALUES ( 2 , 'two') ;
GO

DECLARE @num int
SET @num = ( SELECT num FROM nums ) ;
SELECT @@ROWCOUNT
GO

Will give you the error:

Msg 512, Level 16, State 1, Line 3
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Therefore if your table contains more than one row, you will need to use a restriction so that only one row is returned e.g.

DECLARE @num int
SET @num = ( SELECT num FROM nums WHERE val = 'one') ;
SELECT @num, @@ROWCOUNT -- 1, 1
GO

or you can specify TOP 1 to limit what is returned, and if you want a specific row you will also need an ORDER BY clause.

DECLARE @num int
SET @num = ( SELECT TOP 1 num FROM nums ORDER BY num ) ;
SELECT @num, @@ROWCOUNT -- 1, 1
GO

DECLARE @num int
SET @num = ( SELECT TOP 1 num FROM nums ORDER BY num DESC ) ;
SELECT @num, @@ROWCOUNT -- 2, 1
GO

or if you are wanting to be really safe a restriction a TOP clause and an ORDER BY:

DECLARE @num int
SET @num = ( SELECT TOP 1 num FROM nums WHERE val = 'one' ORDER BY num DESC ) ;
SELECT @num, @@ROWCOUNT -- 1, 1
GO

Using the second method to set the variable will not give you an error, and this is often the cause of many of the problems e.g.


DECLARE @num int
SELECT @num = num
FROM nums ;
SELECT @num, @@ROWCOUNT -- 2, 2
GO

@@ROWCOUNT in this case returns 2 and not one as you may expect. The value returned is not always guaranteed for instance if I add a clustered descending index:

 

CREATE CLUSTERED INDEX CLX on nums (NUM DESC);
GO

The same query will return a different value;

 

DECLARE @num int
SELECT @num = num
FROM nums ;
SELECT @num, @@ROWCOUNT -- 1, 2
GO

If you are relying on this being a given value within your application, then it may suddenly start to behave differently even though the code has not changed. Like the first method you can use an order by or restriction to make sure that you are getting the row you expect:


DECLARE @num int
SELECT @num = num
FROM nums
ORDER BY num DESC;
SELECT @num, @@ROWCOUNT -- 1, 2
GO

or better:

DECLARE @num int
SELECT @num = num
FROM nums
WHERE val = 'one'
ORDER BY num DESC;
SELECT @num, @@ROWCOUNT -- 1, 1
GO

or even better:

 

DECLARE @num int
SELECT TOP 1 @num = num
FROM nums
WHERE val = 'one'
ORDER BY num DESC;
SELECT @num, @@ROWCOUNT -- 1, 1
GO

If you are setting more than one variable, then you can't use a single set statement and you would have to write:

 

DECLARE @num int, @val char(10) ;
SET @num = ( SELECT TOP 1 num FROM nums ORDER BY num DESC ) ;
SET @val = ( SELECT TOP 1 val FROM nums ORDER BY num DESC ) ;
SELECT @num, @val  -- 2, two
GO

 

but this method is starting to get a bit messy and inefficient. You can use multiple sub-queries with a SELECT statement:

DECLARE @num int, @val char(10) ;
SELECT @num = ( SELECT TOP 1 num FROM nums ORDER BY num DESC ),
            @val = ( SELECT TOP 1 val FROM nums ORDER BY num DESC ) ;
SELECT @num, @val, @@ROWCOUNT -- 2, two, 1
GO

Looking at the query plan for this:


and comparing it to when you don't use sub-queries, such as the following statement:

DECLARE @num int, @val char(10) ;
SELECT TOP 1 @num = num,
            @val = val
FROM nums
ORDER BY num DESC ;
SELECT @num, @val, @@ROWCOUNT -- 2, two, 1
GO

and look at the query plan:



If there is a where clause that utilises the clustered index, you would get an index seek:

DECLARE
@num int, @val char(10) ;
SELECT TOP 1 @num = num,
            @val = val
FROM nums
WHERE num = 2
ORDER BY num DESC ;
SELECT @num, @val, @@ROWCOUNT -- 2, two, 1
GO



Therefore I can conclude that checking @@ROWCOUNT may have some use when setting variables, although on it's own it will not guarantee that you are returning the value you are expecting.

Filed under:
SQLBits goes West the video(s)
01 February 10 07:19 AM | MartinBell | with no comments

We have loaded up the videos from the SQLBits V conference at Celtic Manor.

They can be viewed/downloaded from the agenda items on
http://www.sqlbits.com/information/newagenda.aspx.

All the slide decks that have been made available to us have also been uploaded.

Filed under:
SQLBits sponsors DDD 8 coaches
13 January 10 07:17 AM | MartinBell | with no comments

We are proud to announce that once again SQLBits will be sponsoring the coaches at DDD to take delegates from Reading Station to TVP.

We have two coaches leaving Reading Station for Thames Valley Park between 08:00 and 08:45  The coaches will leave earlier if they are full. Similarly there will be two coaches to take delegates back to the station after the event.

Until 15 Jan 2010 00:00 you can vote for session to be included in DDD at http://developerdeveloperdeveloper.com/ddd8/Users/VoteForSessions.aspx

Filed under: ,
Powershell and SQL Authentication
01 January 10 03:25 PM | MartinBell | 2 comment(s)

In my last posting I mentioned that not everyone could use the SQL Server Provider when using Powershell. Why should this be so? To use the SQL Server Provider requires Window Authentication and uses the account running the Powershell session (see the topic “Using the SQL Server PowerShell Provider” in books online). Unfortunately Windows Authentication will not always possible, in these circumstances how useful is Powershell?

Although the SQL Server provider makes it easy to navigate around a SQL Server instance, if you have already written SMO applications using another language you will have done so without the SQL Server Provider. For instance, I gave the example of scripting views in my post Powershell and SMO scripting – Part 1:

cd SQLSERVER:\SQL\localhost\DEFAULT\Databases\AdventureWorks\Views foreach ($Item in Get-ChildItem) {
$out = "C:\PowerShell\" + $Item.Name + ".sql"
$Item.Script() | Out-File -Filepath $out
}

This could have been written without the SQL Server provider as:

# ===================================
# Windows Authentication
# ===================================
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-Null
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') "LOCALHOST" 
$s.ConnectionContext.LoginSecure=$true
$dbs=$s.Databases
foreach ($Item in $dbs["Adventureworks"].Views)
{
    $out = "C:\Powershell\" + $Item.name + ".sql"
    $Item.Script() | out-File $out
}


This still uses Windows Authentication, but you can set the username and password by changing the servercontext so that SQL Authentication is used:

# ===================================
# Hard Coded SQL Authentication
# ===================================
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-Null
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') "LOCALHOST" 
$s.ConnectionContext.LoginSecure = $false
$s.ConnectionContext.Login="sa"
$s.ConnectionContext.Password="saPassword"
$dbs=$s.Databases
foreach ($Item in $dbs["Adventureworks"].Views)
{
    $out = "C:\Powershell\" + $Item.name + ".sql"
    $Item.Script() | out-File $out
}


If you wish to prompt for the login and password you can use the Powershell Get-Credentials cmdlet to provide a dialog to input the username and password.

# ==================================
# SQL Authentication Dialog
# ===================================
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-Null
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') "LOCALHOST" 
$s.ConnectionContext.LoginSecure = $false
$credential = get-Credential
$userName = $credential.UserName.Remove(0,1)
$s.ConnectionContext.Login=$userName
$s.ConnectionContext.set_SecurePassword($credential.Password)
$dbs=$s.Databases
foreach ($Item in $dbs["Adventureworks"].Views)
{
    $out = "C:\Powershell\" + $Item.name + ".sql"
    $Item.Script() | out-File $out
}


The Get-Credentials cmdlet returns the username with a leading backslash (see http://technet.microsoft.com/en-us/library/dd315327.aspx
), therefore this should be removed before it can be used. The password is returned as a SecureString. If the Snapin SqlServerCmdletSnapin100 has been added you can still use the Invoke-SqlCmd cmdlet. The cmdlet has parameters that will allow you to specify an SQL Server Instance (-ServerInstance), Database (-Database), Username (-Username) and Password (-Password) which can be shortened to –Ser, –Da, –U and –P e.g.

Add-PSSnapin SqlServerCmdletSnapin100
invoke-sqlcmd "SELECT * FROM sys.databases" -ServerInstance "LOCALHOST" -Database Master -Username sa -Password saPassword
invoke-sqlcmd "SELECT * FROM sys.databases" -Ser "LOCALHOST" -Da Master -U sa -P saPassword

In the post Starting/Stopping SQL Server using Powershell I showed that using the SQL Server Provider is not always necessarily when using WMI in Powershell, and in this post I have shown that it is not mandatory when using SMO or with the Invoke-Sqlcmd cmdlet, but if you need to use your scripts in an environment where Windows Authentication is not available you should design your scripts so they don’t use the SQL Server Provider.


 

Filed under: , ,
Starting/Stopping SQL Server using Powershell
31 December 09 07:58 PM | MartinBell | 1 comment(s)

One thing I would like to see is more examples of using Powershell in Books Online! For instance the topic Managing Services and Network Settings by Using WMI Provider doesn’t have an example using WMI. So here is one!

# Get an instance of the ManagedComputer object that represents the WMI Provider services.
CD SQLSERVER:\SQL\LOCALHOST
$mc = (get-item .).ManagedComputer
# Reference the Microsoft SQL Server service.
$svc = $mc.Services['MSSQLSERVER']
# Display the state of the service.
'Service status is:' + $svc.ServiceState
# Stop the service if it is running and report on the status
$svc.Stop();
# Wait until the service has time to stop. Then refresh the status
wait-Event -Timeout 10
$svc.Refresh();
# Display the state of the service.
'Service status is:' + $svc.ServiceState
# Start the service again.
$svc.Start();
# Wait until the service has time to start, refresh and display the state of the service.
wait-event -Timeout 10
$svc.Refresh();
'Service status is:' + $svc.ServiceState


The wait-event the service status is incorrectly reported. This is achieved in the books online example by looping until the status changes:

Do Until String.Format("{0}", svc.ServiceState) = "Stopped"
          Console.WriteLine(String.Format("{0}", svc.ServiceState))
          svc.Refresh()
Loop


This uses the SQL Server Provider to get the Managed Computer object, although this is not absolutely necessary, the following script does not use the SQL Server Provider:

# Reference the Microsoft SQL Server service.
$svc=(get-wmiobject win32_service -filter "name='MSSQLSERVER'");
# Display the state of the service.
'Service status is: ' + $svc.State;
# Stop the service if it is running and report on the status
$svc.StopService();
# Wait until the service has time to stop. Then refresh the status
wait-Event -Timeout 10
$svc=(get-wmiobject win32_service -filter "name='MSSQLSERVER'");
# Display the state of the service.
'Service status is: ' + $svc.State;
# Start the service again.
$svc.StartService();
# Wait until the service has time to start, refresh and display the state of the service.
wait-Event -Timeout 10
$svc=(get-wmiobject win32_service -filter "name='MSSQLSERVER'");
'Service status is: ' + $svc.State;

Although the SQL Server Provider makes it very easy to navigate around a SQL Server instance, it may not be available to everyone; therefore for portable scripts you may wish to write without using it. In my next post I will explain why.

Filed under: ,
Developer Day Eight
16 December 09 06:57 PM | MartinBell | with no comments

The DDD organisers have announced the the next community Developer Day Event at Microsoft’s UK Campus in Reading on Saturday 30th January 2010!  

The call for speakers has opened so anyone wishing to submit a session, can do so at http://developerdeveloperdeveloper.com/ddd8/

DDD is always a great event and I hope to see you there.

Filed under:
Powershell 2.0 has slipped out!
12 December 09 01:31 PM | MartinBell | with no comments

Thanks to Anthony for point this out at Thursday’s User Group meeting. Windows Powershell 2.0 was released as part of the the Windows Management Framework release at the end of October. If you are not a Windows admin you may have missed it! See here for more details.

Filed under:
A nugget!
08 December 09 08:56 PM | MartinBell | with no comments
Here is something I thought was very nugget worthy!

Q: If you have a delimited string how can you easily find the number of elements without splitting the string?

A: This is one way!

Example:

A comma separated string with 4 elements -

DECLARE @str varchar(max) = 'F7C52CB0,980CADCC,1C4195F2,7881934F'

SELECT LEN(@str), LEN(REPLACE(@str,',','')), LEN(@str) - LEN(REPLACE(@str,',',''))+1

 

Filed under:
A ray of light?
28 November 09 12:57 PM | MartinBell | 2 comment(s)

 

I was interested to read Richard Barden’s appraisal of the SQL Server market this week on SQL-Server-Performance.com. This confirmed by own findings from talking to people at SQLBits, in that the market is noticeably better than this time last year. This will come as a welcome relief to anyone who has had a hard year finding employment. Hopefully his predictions will turn out to be correct.

Unfortunately I have also heard that some unpalatable practices being employed by some agencies; such as using the recession as an excuse to increase their margins and in some cases over 30% going to the agency.

Agencies may have their part to play in the contractor market, but it seems to me that there is a lack of accountability and accreditation for someone who is a position of trust by both contractor and client.

The standard of service an agency provides to a client can vary considerably. Good agencies will only submit candidates that actually fit the given criteria and have been pre-vetted to make sure that they do, bad agencies will just keyword search and throw as many CVs as they can at the client. As a contractor you want your CV to be the one that sticks out, not just one of a pile that goes straight in the bin.

When so much seems to be governed by cost and duration, I always wonder how many contractors have not been submitted for a position because the agent thinks they would not be chosen because of cost, even they would provide the best service? What happens if someone on a higher rate could do the same job in half the time, thus saving on the overall cost? When is an agent a barrier rather than a facilitator?

Trust is the key for any relationship between contractor and agent. Unfortunately trust can not be gained instantly, and the short timescale between being submitted for interview and accepting a contract is not long enough for this trust to be validated. If this trust breaks down the client and the contractor will be the ones that suffer the most.

It seems that agencies have some way to go to clean up their act and become more transparent. Organisation such as The Recruitment & Employment Confederation have their code of practice, where standard 2 calls for honesty and transparency. Unfortunately membership is not compulsory but it could be a useful indicator.

The future may be looking brighter but it seems that agencies may have already missed their chance to clean up their act.

Scottish Area SQL Server User Group Meeting, Edinburgh - Thursday 26th November
23 November 09 08:40 AM | MartinBell | 1 comment(s)

I thought I would try something slightly different at the user group on Thursday, so here is the itinary: 

SQL Nuggets Competition

A look into the Newgroups – Martin Bell

In this session I'll look at using the newsgroup as source of information, inspiration and perspiration. How you can learn for the postings in newsgroup and forums, if you want to ask a question, the how, why and what to post and I'll look at some of the posts and how to set about answering the questions.

Agenda

18:30 - 19:00 - Introduction, Networking and Food

19:00 - 19:50 – SQL Nuggets competition

19:50 - 20:00 - Break

20:00 - 20:50 – A look into the newsgroup – Martin Bell 

20:50 - 21:00 - Close

Location:

Microsoft Office at Waverley Gate

http://www.microsoft.com/uk/about/map-edinburgh.mspx

Registration will be necessary as I have to submit registrations to Microsoft on Thursday morning.

You can register here

Filed under:
Another SQLBits Conference is over!
23 November 09 08:28 AM | MartinBell | with no comments

Another SQLBits is over, but as an organizer there is still plenty to do! After each conference we go through a post-mortem and try to identify what worked well, what could be done better!

We have had lots of people complementing us, either directly or by email on how much they enjoyed it and how well it. Celtic Manor was a great venue and I know that some people regretted not taking more advantage of the facilities there. I think it was far superior to anywhere we have been before and even the food was a class above what we have come to expect. I’m sure that people will talk about this event for a long time to come and it raises the bar yet again if we are going to surpass what we have already achieved.

We will be posting on the website the presenters slide decks and the videos of the session when they have been processed. We will be sending out emails to let you know when they are available.

Everyone who registered for the event should already have in your inbox a link to your personalised survey. If you could take a few minutes of your time to complete this and give us useful feedback, it will help us when making our decisions about the next event.

Finally thank you to all our sponsors, without their support the event would not be possible.

SQLBits V is over, long live SQLBits VI :)

Filed under:
Confused.bol?
22 November 09 08:10 AM | MartinBell | 1 comment(s)

The October update of Books online was released on the 17th November as the July 2009 update. Confused?

image

Filed under:
SQLBits Car Sharing
15 November 09 08:56 PM | MartinBell | with no comments

Only a few more days before we kick of SQLBits V at Celtic Manor. After what seems like a very long time, we are now at the stage where there are just a few last minute things to do before travelling down to Newport.

We have put together a car sharing page at http://sqlbits.com/CarSharing.aspx for those people who wish to share the costs of travelling to the event. To use the page you will need Silverlight 3.

Anyone who hasn’t seen the agenda can find the it at http://sqlbits.com/information/newagenda.aspx

Please remember that if you can no longer make the event to cancel your registration using the link sent in your registration confirmation email.

Filed under:
New CTP release of SQL Server 2008 R2 available
14 November 09 07:17 AM | MartinBell | with no comments


Thursday saw the release of the November CTP of SQL Server 2008 R2.

It can be downloaded from
here and a CTP of the feature pack which can also be downloaded here, this includes a new version of Books Online for this release.

Filed under: ,
More Posts Next page »