SCOPE_IDENTITY vs. @@IDENTITY

I stumbled across some extremely handy information today, looking for something completely different.

The deal is such:

When writing your CRUD operations, often-times you'll find yourself writing SQL that looks something like this:

  1. CREATE PROCEDURE dbo.app_CreateSomeDataPlease
  2. (
  3.         @someData nvarchar( 1024 ),
  4.         @moreData nvarchar( 2048 ),
  5.         @irrelevantNumber int = 42
  6. )
  7. AS
  8. BEGIN
  9.         INSERT INTO
  10.                 MyTable
  11.                 (
  12.                         SomeData,
  13.                         SomeMoreData,
  14.                         IrrelevantNumberForNoGoodReason
  15.                 )
  16.                 VALUES
  17.                 (
  18.                         @someData,
  19.                         @moreData,
  20.                         @irrelevantNumber
  21.                 );
  22.                
  23.         SELECT @@IDENTITY AS NewDataId;
  24. END
  25. GO

Which is all good and well (obviously a contrived and simple example). You expect to get back the new ID for the item you just created, right?

Maybe not.

Y'see, there are these things called "Triggers". You've heard of them, maybe played with them, whatever. Basically, a Trigger is SQL that gets "triggered" when something happens, like, perhaps, an INSERT, UPDATE or DELETE.

Now, I'm not going to debate whether Triggers are good, bad, or Satan in disguise (they're not). The point here is that, uh-oh - if you have an INSERT trigger on the table you're creating your data in, and that Trigger creates a row (or rows) in another table (or tables), your @@IDENTITY is not going to do what you think it's going to do.

Why not? Hang on, we'll get there.

There's another method of retrieving the last identity value, and that is the SCOPE_IDENTITY function. And the very, very subtle difference between SCOPE_IDENTITY() and @@IDENTITY is enough to trip you up for hours on end (if you hadn't read this post, of course - bear with me, we'll get there).

So what is the difference between SCOPE_IDENTITY() and @@IDENTITY?

Scope.

And I don't mean the mouthwash.

To quote the MSDN documentation:

SCOPE_IDENTITY and @@IDENTITY return the last identity values that are generated in any table in the current session. However, SCOPE_IDENTITY returns values inserted only within the current scope; @@IDENTITY is not limited to a specific scope.

A scope is a module: a stored procedure, trigger, function, or batch. Therefore, two statements are in the same scope if they are in the same stored procedure, function, or batch.

What that means is that if have a trigger that fires on INSERT (into Table1) and INSERTs into another table (let's call that Table2), returning @@IDENTITY will return the new identity value from Table2, not Table1.

Maybe that's what you want, but probably not.

To make a long story short, to be safe, you're probably better off using SCOPE_IDENTITY to protect yourself in the event that a Trigger you don't know about* is firing and inserting somewhere else. And if you know about the Trigger and you want the ID from that, use @@IDENTITY.

Read a bit more about SCOPE_IDENTITY at the MSDN.

* - In all unfairness, you should know which triggers (if any) are firing, but...hey...someone else on your team may add one later on and suddenly your app breaks...now you'll know why and how to fix it...

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Intellisense for SQL

Intellisense (code-completion, for those of you who don't work with MS products) is one of those features that really make an IDE useful. We all no that we can't remember much (if anything), and having that little drop-box show up when we need it is a huge time saver.

One place I've always found it lacking is with Sql Queries.

Well, no more. Red Gate has released a product called Sql Prompt that adds Intellisense support for Sql.

SQL Prompt provides Intellisense® style auto-completion for Microsoft SQL Server editors. It will tell you the exact formatting you should use for your SQL commands, while you are writing them and will therefore help you write fast, perfectly formatted SQL statements. SQL Prompt improves the productivity of all SQL script creation. SQL Prompt can be downloaded free until 1st September 2006 and we are providing forum support on the SQL Prompt support forum. A web help file is also available.

SQL Prompt simply sits behind the scenes and provides unobtrusive help when you press Ctrl-Space or when you type "." after a table/view/alias name.

SQL Prompt works with Microsoft Query Analyzer, SQL Server 2005 Management Studio, Visual Studio 2005, Visual Studio .NET 2003, SQL Server 2000 Enterprise Manager, UltraEdit32.

How. Cool. Is. That.

Btw, that's free as in beer (until Sept 2006). Works forever.

So go download your copy @ reg-gate.com/products/SQL_Prompt/

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Dynamically Sorting Stored Procedure Results

(was It's A Dynamic Sort Of... ... which is, admittedly, a pretty lame title. So I changed it. Not that the new one's really catchier, but it's at least more to the point.)

Sql's my friend. Transact Sql (T-Sql) in particular. We get along well. Every once in a while, though, there's something little that I want to do in a more, how do you say...elegant manner, and my buddy, my pal, my devoted declarative language just doesn't want to make it easy.

Here's what's been bugging me (to be fair, it's been bugging me for a while, but I've never really been bugged enough to go looking for solutions...one of those little things that crops up relatively infrequently, and there's already an inelegant way to get around it). How do you choose, dynamically, the column (or columns) on which to sort a Stored Procedure's result?

My first try (way back when, I can't even remember when) didn't work out. Obviously. Or I wouldn't be writing this. This first shot was the simplest thing I could think of.
(more...)

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Sexy Sql Tip

Monsieur Keebler has a quick little post on avoiding divide by zero errors in Sql.

Coupled with some fairly... warm and fuzzy ... imagery of the foxy Megan Fox.

Have a read (and look) over @ keebler.net

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Sql Connection Tester Utility

I found myself needing to test for the ability to connect to a given Sql Server from a workstation today, without access to Enterprise Manager. Instead of simply installing it (or, come to think of it, simply attempting to connect through Visual Studio - ha! that would be too smart), I whipped up this handy .NET command line utility that will test for connectivity to a Sql Server. It's written in C# and targets the .NET 1.1 runtime.

It's quite simple to use - fire it up, and follow the instructions. Granted, in an environment where you have all the usual tools it's completely useless, but you may occasionally find yourself with nothing but Notepad and an internet connection...and then you'll thank me.

Download the bits:

TODO:

  • Allow the user to choose the type of connection (Sql Server, ODBC, etc)
  • Build a GUI (If more than 2 people use it. That means you.)
Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati

Sql…Where…In…

Along the vein of posting things having to with finding things, here's a handy Sql tip for making a selection (or update or deletion), with multiple possible values for a column.

The hack way of doing it would be something a la:

  1. SELECT
  2.         columnA, columnB
  3.     FROM
  4.         tableA
  5.     WHERE
  6.         columnA = 'this' OR columnA = 'that';

Obviously, that could get pretty hairy, pretty quickly. Imagine having 19 different values that are valid (and non sequential, so you can't use 'columnA > 4 AND columnA < 10 or the like.

Enter the 'IN' clause:

  1. SELECT
  2.         columnA, columnB
  3.     FROM
  4.         tableA
  5.     WHERE
  6.         columnA IN ( 'this', 'that' );

The only caveat being that if the column you're querying off is a numeric field, you don't enclose the values in quotes:

  1. SELECT
  2.         numericColumnA, columnB
  3.     FROM
  4.         tableA
  5.     WHERE
  6.         columnA IN ( 12, 15, 24 );

Sql can be so much darned fun!

Share me: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati