Enough with the talking, so let’s consider the below table in which a unique constrain is defined on ProductNumber attribute:
CREATE TABLE Production.Products( ProductID int IDENTITY(1,1) NOT NULL, Name nvarchar(250) NOT NULL, ProductNumber nvarchar(25) NOT NULL, MakeFlag bit NOT NULL, FinishedGoodsFlag bit NOT NULL, Color nvarchar(15) NULL, SafetyStockLevel int NULL, ListPrice decimal(13,2) NOT NULL, StandardCost decimal(13,2) NOT NULL, CreationDate smalldatetime NOT NULL, CreatedBy int NOT NULL, ModifiedDate smalldatetime NOT NULL, ModifiedBy int NOT NULL)
The table is based on Production.Product table from AdventureWorks database, however I reduced the number of attributes and simplified table’s definition. I introduced also the Creation/Modified Dates used as timestamps for the creation/modification of a record, and the Created/Modified By as a reference to the User that performed the respective actions. From all these 4 attributes is enough to send only the User ID, the actual timestamp being obtained using the GetDate function in the background, so we’ll have in the end 13-3= 10 parameters. Here is the stored procedure:
CREATE PROCEDURE dbo.pUpdateProducts( @ProductID int , @Name nvarchar(250) , @ProductNumber nvarchar(25) , @MakeFlag bit , @FinishedGoodsFlag bit , @Color nvarchar(15) , @SafetyStockLevel int , @ListPrice decimal(13,2) , @StandardCost decimal(13,2) , @StartDate smalldatetime , @EndDate smalldatetime , @UserID int) AS BEGIN BEGIN TRY IF ISNULL(@ProductID, 0) = 0 BEGIN -- insert statement INSERT INTO Production.Products (Name, ProductNumber, MakeFlag, FinishedGoodsFlag, Color , SafetyStockLevel , ListPrice, StandardCost, StartDate, EndDate, CreationDate, CreatedBy, ModifiedDate, ModifiedBy) VALUES ( @Name, @ProductNumber, IsNull(@MakeFlag, 0), IsNull(@FinishedGoodsFlag, 0), @Color , @SafetyStockLevel , @ListPrice, @StandardCost, @StartDate, @EndDate, GETDATE(), @UserID, GETDATE(), @UserID) SET @ProductID = @@IDENTITY END ELSE BEGIN -- update statement UPDATE Production.Products SET Name = @Name , ProductNumber = @ProductNumber , MakeFlag = IsNull(@MakeFlag, 0) , FinishedGoodsFlag = IsNull(@FinishedGoodsFlag, 0) , Color = @Color , SafetyStockLevel = @SafetyStockLevel , ListPrice = @ListPrice , StandardCost = @StandardCost , StartDate = @StartDate , EndDate = @EndDate , ModifiedDate = GETDATE() , ModifiedBy = @UserID WHERE ProductID = @ProductID END SELECT @ProductID END TRY BEGIN CATCH SELECT Cast(ERROR_NUMBER() as varchar(10)) + ':' + ERROR_MESSAGE() END CATCH END
The TRY… CATCH… block introduced with SQL Server 2005 allows trapping the errors and thus returns error details to the calling application. In case the DML statement succeeded is returned the Primary Key of the just updated, respectively inserted record. Let’s see the stored procedure in action:
--inserting new records EXEC dbo.pUpdateProducts 0, 'Product 1', 'Product1', 1, 1, 'Blue', 100, 50.32 , 44.06, '2010-01-01', NULL, 1 -- Example 1 EXEC dbo.pUpdateProducts 0, 'Product 2', 'Product2', 0, 1, 'Red', 100, 51.32 , 44.45, '2010-01-01', NULL, 1 -- Example 2 EXEC dbo.pUpdateProducts 0, 'Product 3', 'Product3', 1, 0, 'Gren', 100, 59.32 , 44.87, '2010-01-01', NULL, 1 -- Example 3 EXEC dbo.pUpdateProducts 0, 'Product 4', 'Product4', 0, 0, 'Red', 100, 57.32 , 44.78, '2010-01-01', NULL, 1 -- Example 4
After running the above EXEC statements try to run them again, each of them will error out with the following error details: 2601:Cannot insert duplicate key row in object 'Production.Products' with unique index 'IX_Products_UniqueProductNumber'. It will be in developer’s attribution to translate the error to a more appealing error message.
In order to update a record all is needed to do is to transmit the ID of the record to be updated and the new values. For example in a new created table the record created by first example will more likely correspond to ProductID = 1, thus the following statement is used to change its values:
-- updating a record EXEC dbo.pUpdateProducts 1, 'Product 1', 'Product1', 1, 1, 'White', 100, 50.32 , 44.06, '2010-01-01', NULL, 1 -- Example 1
Note:
This technique has the inconvenience that it doesn’t consider the cases in which two different Users update the same record, though that’s a topic for another post.
No comments:
Post a Comment