| Author |
Topic |
|
Eagle_f90
Constraint Violating Yak Guru
424 Posts |
Posted - 2011-12-24 : 21:18:04
|
I created a proc to handel 3 different siturations that would be called from the same asp.net page. It will handel Inserts, Updates, and Deletes. Not really sure if this is the best way to do it so i thought I would get some feed back before I start creating more like this to handel other stuff in the same fasion. Thanks for the help!create proc dbo.spRaces @UpdateType as char(7), @RaceID as int = null, @SectionID as smallint = null, @SectionName as varchar(50) = null, @Race as varchar(50) = null, @RaceDescription as varchar(MAX) = null, @UpdateCountVar as varchar(50)asset nocount onset xact_abort onset arithabort ondeclare @ErrorNum intbegin transaction--Process a new raceif (@UpdateType = 'Insert')begin insert into dbo.Races (SectionID, Race, RaceDescription) values (@SectionID, @Race, @RaceDescription) set @UpdateCountVar = 'Add New ' + @SectionName + ' Race'; select @ErrorNum = @@ERROR;end--Process an updated raceif (@UpdateType = 'Update')begin update dbo.Races set SectionID = coalesce(@SectionID, Position), Race = coalesce(@Race, Race), RaceDescription = coalesce(@RaceDescription, RaceDescription) where Race = @RaceID; set @UpdateCountVar = 'Update ' + @SectionName + ' Race'; select @ErrorNum = @@ERROR;end--Process a race removalif (@UpdateType = 'Delete')begin delete dbo.Races where ID = @RaceID; select @ErrorNum = @@ERROR;endif (@ErrorNum = 0)beginexec @ErrorNum = dbo.spUpdateCount @UpdateCountVar;endif (@ErrorNum = 0)begin commitendelsebegin rollbackendreturn @ErrorNum; -- If I get used to envying others...Those things about my self I pride will slowly fade away.-Stellvia |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2011-12-24 : 21:27:35
|
| 1.make @UpdateType as type varchar(7) or char(6)@UpdateType as char(6)2.You've declared @RaceID as int = nullso when its null it wont do anything in current way its written. I think if thats the case you need to have a step inside to assign it a default value when null3. you've declared @UpdateCountVar as varchar(50)and doing thisset @UpdateCountVar = 'Update ' + @SectionName + ' Race'here @SectionName itself is having varchar(50) so if it has content which is 50 character length it will overflow size of @UpdateCountVar and causes silent truncation. so increase size of @UpdateCountVar to accomodate that too (it should be varchar(63) atleast)other than that the proc looks fine as long as you want only one row processed at a time.------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
Eagle_f90
Constraint Violating Yak Guru
424 Posts |
Posted - 2011-12-25 : 08:19:10
|
| Thanks few follow ups thought1. Why set it to varchar? It should only ever contain Insert, Update or Delete. So why take up the extra memory of doing a varchar vs a char?2. @RaceID will be assigned a variable from the ASP.Net script calling it when an update or delete is ran. If an insert is ran RaceID is not needed so I am not sure why I would have to assign it a varable in the proc.-- If I get used to envying others...Those things about my self I pride will slowly fade away.-Stellvia |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2011-12-25 : 23:31:27
|
quote: Originally posted by Eagle_f90 Thanks few follow ups thought1. Why set it to varchar? It should only ever contain Insert, Update or Delete. So why take up the extra memory of doing a varchar vs a char? setting it to varchar is not mandatory. But current way you've char(7) you're passing options (insert,update,delete) which are only 6 characters long. so if you're sure options will be only above make it char(6).2. @RaceID will be assigned a variable from the ASP.Net script calling it when an update or delete is ran. If an insert is ran RaceID is not needed so I am not sure why I would have to assign it a varable in the proc.are you sure that proc will get called only from application? if somebody calls it directly from sql without passing RaceID it wont give any results-- If I get used to envying others...Those things about my self I pride will slowly fade away.-Stellvia
------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
Sachin.Nand
2937 Posts |
Posted - 2011-12-25 : 23:44:17
|
| Cant you just use a MERGE statement and get rid of all those checks ?PBUH |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2011-12-26 : 01:36:56
|
quote: Originally posted by Sachin.Nand Cant you just use a MERGE statement and get rid of all those checks ?PBUH
I think from what I understood OP wants to control DML operations individually from application. Thats why all if conditions I guess.------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2011-12-26 : 05:19:37
|
Add an OUTPUT parameter to return @ErrorNum (and also, preferably, @ErrorMessage containing an "English" or Debugging indication of why the Sproc returned error). We, now, have these in all our Sprocs and I wish I had added them from Day One. (We actually log any error return value in a Logging Table, so we can review any errors in a live running application) insert into dbo.Races (SectionID, Race, RaceDescription) values (@SectionID, @Race, @RaceDescription) set @UpdateCountVar = 'Add New ' + @SectionName + ' Race'; select @ErrorNum = @@ERROR; The Setting of @ErrorNum needs to be IMMEDIATELY after the INSERT (this applies to the UPDATE etc too). You could use TRY/CATCH instead. Personally I would also capture @@ROWCOUNT (*AND* check that it was = 1 - you might change the logic in future, e.g. to use a SELECT instead of VALUES statement, and the check for " = 1 " might catch a programming logic error, and in the case of UPDATE / DELETE would also catch that a row did not exist). Me = Belt & Braces Note that there is a "window of opportunity" for another process to INSERT the record - so you might get a "DUPLICATE PRIMARY KEY" type error. So you might prefer: insert into dbo.Races (SectionID, Race, RaceDescription) SELECT @SectionID, @Race, @RaceDescription WHERE NOT EXISTS (SELECT * FROM dbo.Races WHERE ... duplicate unique-key test(s) ...) select @ErrorNum = @@ERROR, @RowCount = @@ROWCOUNT IF @ErrorNum <> 0 OR @RowCount <> 1 BEGIN ... handle error here ... END ELSE BEGIN set @UpdateCountVar = 'Add New ' + @SectionName + ' Race'; END the same applies to the UPDATE / DELETE - someone else may have deleted the row - check @@ROWCOUNTPersonally I would put an ELSE between each test of @UpdateType - it can only be one value, and having SQL test it for all three values just wastes some CPU. Its very small, but it all adds up; it also gives you an opportunity to add an Error Condition; we put the "comment" INSIDE the IF block (particularly when ELSE is used)if (@UpdateType = 'Insert')begin --Process a new race ...endELSEif (@UpdateType = 'Update')begin --Process an updated race ...endELSEif (@UpdateType = 'Delete')begin --Process a race removal ...endELSEbegin ... process error condition - "command not recognised" ...end Note that if you do a ROLLBACK you will probably cause the outer process (i.e. another SProc, or your asp.net application) to "error" as the outer transaction will be rolled back too. We use a SAVEPOINT within the Sproc, and ROLLBACK to that, instead as this does not cause the Transaction Count to be reset to zero (which a straight ROLLBACK does), and thus any outer process can continue to run and/or handle the error (note that if the outer process FAILS to handle the @ErrorNum it is returned then it will be "submarining" an error - which will be hard to find). |
 |
|
|
Eagle_f90
Constraint Violating Yak Guru
424 Posts |
Posted - 2011-12-31 : 17:22:33
|
First thanks for all the imput I have made some suggested changes (like learning to count to 6 instead of 7).quote: Originally posted by visakh16
quote: Originally posted by Sachin.Nand Cant you just use a MERGE statement and get rid of all those checks ?PBUH
I think from what I understood OP wants to control DML operations individually from application. Thats why all if conditions I guess.------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/
I am not sure what a DML operation is or what the merge command is. The thought behind this proc is that it will be called by a single ASP.NET page that allows a loged in user to Add new race information, edit existing, or delete a mistake. Each action can only happen one at a time by each user. I decided to put everything into a single proc so keep all the data manipulation in a single area. I am open to any suggestions that will inprove performance as this site does not have many resorces to it so anything to improve performance and keep resorce usage down it a good thing.-- If I get used to envying others...Those things about my self I pride will slowly fade away.-Stellvia |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-01-01 : 02:22:56
|
quote: Originally posted by Eagle_f90 First thanks for all the imput I have made some suggested changes (like learning to count to 6 instead of 7).quote: Originally posted by visakh16
quote: Originally posted by Sachin.Nand Cant you just use a MERGE statement and get rid of all those checks ?PBUH
I think from what I understood OP wants to control DML operations individually from application. Thats why all if conditions I guess.------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/
I am not sure what a DML operation is or what the merge command is. The thought behind this proc is that it will be called by a single ASP.NET page that allows a loged in user to Add new race information, edit existing, or delete a mistake. Each action can only happen one at a time by each user. I decided to put everything into a single proc so keep all the data manipulation in a single area. I am open to any suggestions that will inprove performance as this site does not have many resorces to it so anything to improve performance and keep resorce usage down it a good thing.-- If I get used to envying others...Those things about my self I pride will slowly fade away.-Stellvia
DML means Data Manipulation Language ie insert,update and delete operationsAnd as you told your code is for handling each operation separately.and so far as its not doing major bulk operations you're good to go with it------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-01-03 : 12:43:58
|
| Any reason to use a single "generic" stored procedure instead of three specific ones? |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2012-01-03 : 12:49:36
|
| We use a single SProc for Insert/Update because it then encapsulates any validation logic in one place, and we do have cases where an update is "INSERT if not found, otherwise UPDATE" or based on a provided parameter is forced INSERT or UPDATE (i.e. record must NOT exist, or MUST pre-exist) |
 |
|
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-01-03 : 12:55:00
|
| Having a single upsert Upsert sproc makes sense. But, I'm more curious about putting the delete in there as well. |
 |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2012-01-03 : 13:11:18
|
quote: Originally posted by Lamprey Having a single upsert Upsert sproc makes sense. But, I'm more curious about putting the delete in there as well.
Thats something I've also not come across muchWe also usually have single combined insert/update proc------------------------------------------------------------------------------------------------------SQL Server MVPhttp://visakhm.blogspot.com/ |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2012-01-04 : 05:45:59
|
quote: Originally posted by LampreyI'm more curious about putting the delete in there as well.
Yeah, we have separate Sproc for DELETE(All our tables have an EditNumber column (ROWVERSION datatype would do too), and our DELETE Sproc requires that that value is provided (in case someone else changed the Row in the interval between User viewing the record and deciding to Delete it) - although the Delete Sprocs have a "don't care" parameter too. |
 |
|
|
GilaMonster
Master Smack Fu Yak Hacker
4507 Posts |
Posted - 2012-01-04 : 06:07:45
|
One point.if (@UpdateType = 'Update')begin update dbo.Races set SectionID = coalesce(@SectionID, Position), Race = coalesce(@Race, Race), RaceDescription = coalesce(@RaceDescription, RaceDescription) where Race = @RaceID; set @UpdateCountVar = 'Update ' + @SectionName + ' Race'; select @ErrorNum = @@ERROR;end If the update fails, there will be no record of it failing. The @@Error checks only the error status of the SET statement, and that's quite unlikely to fail. The insert has exactly the same problem.Why @@Error (the SQL 2000 way of handling errors) not TRY ... CATCH?--Gail ShawSQL Server MVP |
 |
|
|
|