Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Feed back on proc, please

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)
as
set nocount on
set xact_abort on
set arithabort on
declare @ErrorNum int

begin transaction

--Process a new race
if (@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 race
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

--Process a race removal
if (@UpdateType = 'Delete')
begin
delete dbo.Races where ID = @RaceID;
select @ErrorNum = @@ERROR;
end

if (@ErrorNum = 0)
begin
exec @ErrorNum = dbo.spUpdateCount @UpdateCountVar;
end

if (@ErrorNum = 0)
begin
commit
end
else
begin
rollback
end

return @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 = null
so 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 null

3. you've declared
@UpdateCountVar as varchar(50)
and doing this
set @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 MVP
http://visakhm.blogspot.com/

Go to Top of Page

Eagle_f90
Constraint Violating Yak Guru

424 Posts

Posted - 2011-12-25 : 08:19:10
Thanks few follow ups thought
1. 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
Go to Top of Page

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 thought
1. 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 MVP
http://visakhm.blogspot.com/

Go to Top of Page

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

Go to Top of Page

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 MVP
http://visakhm.blogspot.com/

Go to Top of Page

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 @@ROWCOUNT

Personally 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
...
end
ELSE
if (@UpdateType = 'Update')
begin
--Process an updated race
...
end
ELSE
if (@UpdateType = 'Delete')
begin
--Process a race removal
...
end
ELSE
begin
...
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).
Go to Top of Page

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 MVP
http://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
Go to Top of Page

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 MVP
http://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 operations
And 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 MVP
http://visakhm.blogspot.com/

Go to Top of Page

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?
Go to Top of Page

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)
Go to Top of Page

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.
Go to Top of Page

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 much
We also usually have single combined insert/update proc

------------------------------------------------------------------------------------------------------
SQL Server MVP
http://visakhm.blogspot.com/

Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2012-01-04 : 05:45:59
quote:
Originally posted by Lamprey
I'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.
Go to Top of Page

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 Shaw
SQL Server MVP
Go to Top of Page
   

- Advertisement -