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

Stop Thinking and Get Coding: Property Parameters

One of the cool things about C# is the way it handles "properties". When writing set statements, there is an implicit argument named "value" that holds the value passed to the property. Hence, within your implementation of the property, to get the value passed to the property you use the "value" variable, like so:

  1. public string Name
  2. {
  3.     get { return _Name; }
  4.     set { _Name = value; }
  5. }

What's good about this? Well, you just didn't have to think of a name for the variable, like newName, or new_name, or name. Which shaved precious seconds of (wasted) thought off your coding.

Can we do this in Actionscript? Well, not exactly - there's no language support for it. But, if you think about it (and stop thinking about it), you can do it quite easily: use "value" as the name of the variable passed to every set method you write for the rest of your life.

  1. public function get Name() : String { return _Name; }
  2. public function set Name( value:String ) { _Name = value; }

This has a secondary (though equally if not more important) effect: it forces you to ensure the name of your property is sensible. You shouldn't need the parameter name of a property to clarify the intent of the property. If you do, you'll probably want to rethink your property name, which is way more important than deciding between new_name and newName. After all, when someone else is coding with or to your API, you don't want them to have to think about it, right?

Heck, take it a step further and use it in Javascript, too. Just for the fun of it.

Have a great weekend...

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

On C# And Role-based Security

I've been wrapping my head around building Role Based security into some .NET applications. I really like the way Coldfusion does this in components (roles="RoleA,RoleB"), which is cool and all. Coldfusion, of course, has a nice little security framework sitting around that enables you to do things like that really easily.

My goal is to (essentially) replicate that in .NET, while allowing for custom Authentication and Role providers, extensibility, etc. My example scenario is a set of WebServices that require authentication, or an application that has classes/methods requiring role-based access restrictions.
(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

Remoting Tip…

When using Flash Remoting with CF, the Remoting Services window in Flash incorrectly reports the required attribute of a method parameter if the 'required' attribute of the parameter is set to 'yes' in ColdFusion. It seems that while CF happily accepts yes/no in place of true/false, Flash doesn't like it.

Long story short - when intercommunicating with Flash, use true/false, not yes/no.

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

CFmail, CFQuery, and Validation Errors

We inherited a few ColdFusion websites over the past month or so. Originally written for CF 5, we upgraded to CF MX 6.1, and of course had to deal with all the migration issues there (few and far between, to be honest - and the CF Code Analyzer is a great tool if you ever need to do this). In any case, there were obviously bugs, which we fixed, and everything was running along smoothly...
Until, that is, the first time the client sent out a newsletter...
(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