views:

39

answers:

1

I'm using a stored procedure to update\insert data into a table using MERGE. One of the items being inserted is a VarBinary file. Now if I wish to add a new file it's just a case of using ReadAllBytes as below, to remove the file I pass DBNull.

Now what if other fields are being updated but the file is not being changed? I want the field to remain untouched unless I'm replacing the file or deleting it as above...

I cannot add the file via the parameter again as it may only exist in the database, unless I read it first and write it back which seems pointless.

Executing the Stored Procedure:

sqlCommand.CommandText = "EXEC sp_UPSERT_MYFILETABLE @Customer_ID,  @MyFile"

To store a binary file:

sqlCommand.Parameters.Add(New SqlParameter("@MyFile", SqlDbType.VarBinary)).Value = File.ReadAllBytes(MyFileLocation)

To remove the file:

sqlCommand.Parameters.Add(New SqlParameter("@MyFile", SqlDbType.VarBinary)).Value = DBNull.Value

Stored Procedure:

CREATE PROCEDURE [sp_UPSERT_MYFILEPRO]

@id int,
@MyFile varbinary(MAX),
@Customer_ID int,
@Username varchar(30),
@Password varchar(30),
@AnotherValue varchar(30)

AS
BEGIN
MERGE INTO dbo.Remote_Access_Details AS target 
USING (
       VALUES (@id
                ,@Customer_ID
                ,@Username
                ,@Password
                ,@AnotherValue)

      )  AS source (id
                ,Customer_ID
                ,Username
                ,Password
                ,AnotherValue)

   ON target.Customer_ID = source.Customer_ID
WHEN MATCHED 
   THEN UPDATE 
                SET id= source.id
                ,Username= source.Username
                ,Password = source.Password
                ,AnotherValue = source.AnotherValue

WHEN NOT MATCHED 
   THEN INSERT (Id
                ,Username
                ,Password
                ,AnotherValue) 
           VALUES (Id
                ,Username
                ,Password
                ,AnotherValue);

END
RETURN

This is VB.net (VS2008) on SQL 2008

A: 

You can add a bit flag as a parameter and then use it in a CASE statement to determine whether the procedure should do a self-update or use the new value.

CREATE PROCEDURE [sp_UPSERT_MYFILEPROC] 

@MyFile varbinary(MAX), 
@Customer_ID int,
@UpdateFile bit = 0

AS 
BEGIN 

MERGE INTO dbo.Remote_Access_Details AS target  
USING ( 
       SELECT @MyFile,
              @Customer_ID,
              @UpdateFile
      )  AS source (MyFile, Customer_ID, UpdateFile) 
   ON target.Customer_ID = source.Customer_ID 
WHEN MATCHED
   THEN UPDATE  
      SET MyFile = CASE WHEN @UpdateFile = 1 
                        THEN source.MyFile 
                        ELSE target.MyFile END
WHEN NOT MATCHED  
   THEN INSERT (MyFile)  
           VALUES (MyFile) 
;

RETURN
END 
8kb