views:

70

answers:

3

pretty simple query for u guys, im just new to this. here's the scenario - one table with 10 fields. On first aspx page, i do insert first 5 fields (programid is one of them). On the second aspx page, i update the same record entered in previous screen (same programid) for the next 5 fields. but the programid is not unique. one programid can have multiple records. I have an ID field which is unique and identity increment.

I need the query which can take the latest ID and the programid and then update only that record and not all records

e.g

update table a 
set field 6='abc',... 
where programid = @programid AND 
      ID = (select id from tablea where programid = @programid order by id desc)

I hope you get the idea

thanks in advance

A: 
UPDATE table SET
    X = x, .......
WHERE programId = @programId
AND id = (
    SELECT MAX(id)
    FROM table
    WHERE programId = @programId
)
Gabriel McAdams
MAX(id) can create some ugly race conditions. I've seen it happen before.
ristonj
What else does the poster have to go on in this case?
Gabriel McAdams
Ok, I see what you're saying, however I think you've misunderstood what the poster is asking for (not your fault, the question could have been more clear). S/he wants to insert items on one page, then update them on the next one, not a global "get me the last five things anyone inserted" query.
ristonj
+2  A: 

You can have your first query return the ID of each insert.
I usually do this by putting an output parameter called @ID (or similar) in the stored procedure. this is the basic outline:

ALTER PROCEDURE [dbo].[usp_YourInsertProcedure]
(
    @ProgramID INT, other params... ...        
    @ID INT = NULL OUTPUT
) AS BEGIN
    SET NOCOUNT ON;

    begin try
       INSERT INTO .....
    end try
    begin catch  end catch --nothing to do in catch block..
    set @id = coalesce(scope_identity(), -1) --gets the id of the inserted row
END

In your application code, grab the @id after calling the insert procedure. Then you can then pass that to the second aspx page to use in your update statement. If you get a -1 for the ID, that indicates the insert failed.

Instead of using an output parameter, you could use a return value, though return values are usually used to report success or a failure code, and using them that way may be seen as 'hacky'.

See Scope_Identity, it's a very useful t-sql function.

dan
The poster is not inserting the record in the same procedure. By the post, I would guess that any number of processes could write records to the table. This will not work unless the last insert was JUST inserted by the same process.
Gabriel McAdams
he says it's a two-step process: step 1, he does an insert. step 2 is an update. scope_identity doesn't get preempted by other threads so there's no problem.
dan
@@identity would cause issues though because it's a global variable..
dan
A: 
UPDATE tablea
SET field6 = @valueForField6, ...
WHERE programId = @programId
AND id = 
(
  SELECT TOP 1 id
  FROM tablea
  WHERE programId = @programId
  ORDER BY id DESC
)

This will accomplish what you say you are trying to do - but I think you might have a bit of a problem if you are trying to update the entry added by the previous page, and not just the last added record.

What if more than one user attempts to add entries into this table using the same programId?

I might not be on the correct track here, but you could do something like this:

INSERT INTO tablea (programId, field1, field2, field3, field4, field5)
OUTPUT INSERTED.Id
VALUES(@programId, @valueForField1, @valueForField2, @valueForField3, @valueForField4, @valueForField5)

You can then pass that returned ID to the next page (e.g. if you are using asp.net you could change the action on a button, or you could pass it around in the Session variable).

Then when you go to update, you can just update using the direct Id, e.g.

UPDATE tablea
SET field6 = @valueForField6
WHERE id = @valuePassedThroughToNextPage
Khanzor