How to allow users to only update certain fields - sql-server

I have this store procedure and I lets assume the user want to update some fields not all of it, what should I add on the update section
CREATE PROCEDURE [dbo].[helpChainAllCRUD]
#action char(1),
#lineId char(2),
#lineShift smallint = NULL,
#sequence smallint = NULL,
#Role VARCHAR(32) = NULL,
#radioChannel VARCHAR(16)= NULL,
#officePhone VARCHAR(16)= NULL,
#cellPhone VARCHAR(16)= NULL
as
IF(#action = 'I')
BEGIN TRY
BEGIN TRAN
INSERT INTO [dbo].[tbl_helpChain] (lineId,lineShift,sequence,Role,radioChannel,officePhone,cellPhone)
VALUES (#lineId ,#lineShift,#sequence,#Role,#radioChannel,#officePhone,#cellPhone)
COMMIT
END TRY
BEGIN CATCH
IF ##TRANCOUNT >0
ROLLBACK
END CATCH
IF(#action = 'U')
BEGIN TRY
BEGIN TRAN
UPDATE [dbo].[tbl_helpChain] SET lineShift=#lineShift,sequence=#sequence,Role=#Role,radioChannel=#radioChannel,officePhone=#officePhone,cellPhone=#cellPhone WHERE lineId=#lineId
COMMIT
END TRY
BEGIN CATCH
IF ##TRANCOUNT >0
ROLLBACK
END CATCH
IF(#action = 'D')
BEGIN TRY
BEGIN TRAN
Delete from [dbo].[tbl_helpChain] WHERE lineId=#lineId
COMMIT
END TRY
BEGIN CATCH
IF ##TRANCOUNT >0
ROLLBACK
END CATCH
IF(#action = 'S')
Begin
select lineId,lineShift,sequence,Role,radioChannel,officePhone,cellPhone from [dbo].[tbl_helpChain]
end
GO

I'm sure there are much better solutions, but a quick and easy solution might be to use very ugly dynamic SQL
DECLARE #QueryText nvarchar(max) = 'UPDATE [dbo].[tbl_helpChain] SET '
IF #radioChannel<> NULL
#QueryText = #QueryText + 'RadioChannel=#radioChannel'
EXECUTE SP_EXECUTESQL #QueryText

If i.e. null means don't update you could simply write
SET lineShift = COALESCE(#lineShift,lineShift), ...
or you take another special value and a case-expression
SET lineShift = CASE WHEN #lineShift = -1 then lineShift else #lineShift end,
or you give extra boolean parameters for each column for use in the case-expression

UPDATE helpChain
SET
fullName = ISNULL(#fullName,fullName),
lineShift = ISNULL(#lineShift,lineShift),
sequence = ISNULL(#sequence,sequence),
Role = ISNULL(#Role,Role),
radioChannel = ISNULL(#radioChannel,radioChannel),
officePhone = ISNULL(#officePhone,officePhone),
cellPhone = ISNULL(#cellPhone,cellPhone)
WHERE lineId = #lineId

Related

Transactions in while loop in SQL Server

An error occurs while rollback:
Msg 6401, Level 16, State 1, Procedure our_trigger, Line 76
Cannot roll back t1. No transaction or savepoint of that name was found.
And here is the SQL code in the trigger
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [DOCSADM].[our_trigger]
ON [DOCSADM].[PROFILE]
FOR UPDATE, INSERT
AS
DECLARE #DocSystemId AS INTEGER
DECLARE #docNumber AS INTEGER
DECLARE #lastUsedSystemId AS INTEGER
DECLARE #itemType AS VARCHAR(1) --dm10
DECLARE #manualBarcode AS VARCHAR (50)
DECLARE #oldBarcodeFK AS INTEGER
--user typed barcode, it must be inserted/UPDATED into pd_barcode table
DECLARE #COUNTEXISTINGBARCODE AS INTEGER
SET nocount ON;
BEGIN
DECLARE activity_cursor CURSOR local FOR
SELECT
system_id, docnumber,
a_doc_barcode, pd_doc_barcode, item_type
FROM
inserted
--find the last used systemid
SELECT #lastUsedSystemId = lastkey
FROM docsadm.seq_systemkey
OPEN activity_cursor
FETCH next FROM activity_cursor INTO #DocSystemId, #docNumber, #manualBarcode, #oldBarcodeFK, #itemtype
WHILE (##fetch_status <> -1)
BEGIN
IF (( #itemType = 'M' OR #itemType = 'P' ))
--FIND IF IT EXISTS ALREADY A BARCODE
SELECT #COUNTEXISTINGBARCODE = COUNT(*)
FROM docsadm.pd_barcode
WHERE pd_barcode = #manualBarcode
IF (#COUNTEXISTINGBARCODE = 0)-- THERE IS NO EXISTING BARCODE
DECLARE #barcodeSystemId AS INTEGER = 0
BEGIN TRANSACTION t1
BEGIN TRY
-- get next sys id
EXECUTE [DOCSADM].[Sp_nextkey] 'SYSTEMKEY'
SELECT #barcodeSystemId = lastkey
FROM docsadm.seq_systemkey
INSERT INTO docsadm.pd_barcode
VALUES (#manualBarcode, #barcodeSystemId, 'D', NULL, NULL, 'Y', NULL, NULL)
UPDATE docsadm.profile
SET pd_doc_barcode = #barcodeSystemId
WHERE docnumber = #docNumber
COMMIT TRANSACTION t1
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION t1
END CATCH
END
IF (#COUNTEXISTINGBARCODE <> 0)
--YES THERE IS AT LEAST ONE BARCODE
BEGIN
SELECT TOP 1 #barcodeSystemId = system_id
FROM docsadm.pd_barcode
WHERE pd_barcode = #manualBarcode
BEGIN TRANSACTION t1
BEGIN TRY
--update profile's new barcode reference
UPDATE docsadm.profile
SET pd_doc_barcode = #barcodeSystemId
WHERE docnumber = #docNumber
UPDATE docsadm.pd_barcode
SET pd_doc_bcode_used = 'Y'
WHERE system_id = #barcodeSystemId
IF (#oldBarcodeFK <> 0)
BEGIN
--update old barcode as not used!
UPDATE docsadm.pd_barcode
SET pd_doc_bcode_used = 'N'
WHERE system_id = #oldBarcodeFK
END
COMMIT TRANSACTION t1
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION t1
END CATCH
END
FETCH next FROM activity_cursor INTO #DocSystemId, #docNumber, #manualBarcode, #oldBarcodeFK, #itemtype
END
CLOSE activity_cursor
DEALLOCATE activity_cursor
END
The error comes from here
BEGIN CATCH
ROLLBACK TRANSACTION t1
END CATCH
I tried to save trans but i got the same error. I also begin a trans before the loop but the message occured.
This error says you tried to Commit or Rollback a transaction which does not exist. So, Before ROLLBACK check whether there exists an uncommitted transaction. Like this
IF ##TRANCOUNT>0
ROLLBACK TRANSACTION

SQL Server : Deadlocks during token issuing stored procedure in multi-process scenario

We have a set of items in a table , and the worker children invokes a StoredProc(get_next_item) to get the next item to be worked upon.
The stored procedure attaches a token to an Item at each invocation, and returns back the item in the below order
First Items marked as 'P1'
And then rest of them
Sample data:
item priority token
--------------------------
item1 P1 NULL
item2 NULL NULL
item3 P1 NULL
item4 NULL NULL
item5 P1 NULL
item6 NULL NULL
item7 NULL NULL
Stored procedure "get_next_item":
Declare #token int,
#item varchar(50),
#prty varchar(50)
EXEC get_token 'token_key',#token out
BEGIN TRAN
BEGIN TRY
SET ROWCOUNT 1
-- FIRST TRY P1 ITEMS (U1)
UPDATE Item_audit
SET token = #token
WHERE priority = 'P1' AND token IS NULL
SELECT #rows = ##ROWCOUNT
-- IF no more P1 then rest of the items (U2)
IF 0 = #rows
BEGIN
UPDATE Item_audit
SET token = #token
WHERE token IS NULL
SELECT #rows = ##ROWCOUNT
END
IF #rows <> 0
BEGIN
SELECT #item = item , #prty = priority
FROM Item_audit
WHERE token = #token
END
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK
SET #err_msg = 'Exception '
GOTO ERROR
END CATCH
IF ##TRANCOUNT > 0
COMMIT
Issues:
Deadlocks are seen at update statements (U1 & U2) when multiple unix processes invoke the StoredProc(get_next_item), why?
I would replace all of these update and selecting from table multiple times with a single update along with output clause query.
Also move your BEGIN TRAN and COMMIT TRAN inside the TRY BLOCK why leave the transaction hanging for so long only to be rolled back if something went wrong in the try block? doesn't make sense.
Anyway I would rewrite the whole thing something like....
Declare #token int
,#item varchar(50)
,#prty varchar(50)
EXEC get_token 'token_key',#token out
BEGIN TRY
BEGIN TRANSACTION;
Declare #L TABLE (item VARCHAR(50), [priority] VARCHAR(50), token INT);
WITH X AS (
Select TOP 1 *
from Item_audit
WHERE ([priority] = 'P1' AND token IS NULL)
OR (token IS NULL)
ORDER BY [priority] desc
)
UPDATE X
SET token = #token
OUTPUT inserted.token , inserted.[priority] , inserted.item
INTO #L (token , [priority], item)
Select #item = item
, #prty = [priority]
, #token = token
FROM #L
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION;
SET #err_msg = 'Exception '
END CATCH

Error Handle in sql server

DECLARE #id bigint=0,
#id int=0,
#name varchar(50) = '36',
#marks int = 'SDFGS'
#Op varchar(50) = 'UPSERT'
IF(#Op='UPSERT')
BEGIN
INSERT INTO tbl_student
(name, marks)
VALUES
(#name, #marks)
SELECT SCOPE_IDENTITY()
END
ELSE
BEGIN
UPDATE tbl_student SET
name = #name,
marks = #marks
WHERE id = #id
SELECT 'Success'
END
It throw error 'Conversion failed when converting the varchar value 'SDFGS' to data type int.'
I want to handle this error.
If error then it will be return 'Error' string.
You can handle this error using TRY... CATCH Block
Begin
declare #msg varchar(100)
Begin try
DECLARE #id bigint=0,#name varchar(50) = '36',#marks int = 'SDFGS',#Op varchar(50) = 'UPSERT'
IF(#Op='UPSERT')
BEGIN
INSERT INTO tbl_student
(name, marks)
VALUES
(#name, #marks)
SELECT SCOPE_IDENTITY()
END
ELSE
BEGIN
UPDATE tbl_student SET
name = #name,
marks = #marks
WHERE id = #id
SELECT 'Success'
Set #msg='Success'
END
End try
Begin catch
SELECT 'Error'
Set #msg='Error'
End catch
End
You can use TRY ... CATCH
https://msdn.microsoft.com/en-us/library/ms175976.aspx - there is a sample code here.
The error says it all, you are trying to put a string value in an int datatype and hence the error. If you want to catch this error then try to use TRY...CATCH. Something like
BEGIN TRY
-- Your code.
END TRY
BEGIN CATCH
-- Catch the exception/error here.
END CATCH;

How to use same stored procedure both insert,update and delete in Entity Framework?

my problem same this.but i don't understand solution.in my SP parameter "#OperationType" determine that what is type of operation.(if 1 then Insert,if 2 then Update,if 3 then Delete)
my stored procedure is this:
ALTER PROCEDURE [dbo].[JobOperation] (
#ID INT = NULL OUTPUT,
#JobTitle NVARCHAR(50) = NULL,
#JobLevel NVARCHAR(50) = NULL,
#Des NVARCHAR(MAX) = NULL,
#IsDbCommandCommitted BIT = 0 OUTPUT,
#DbCommitError VARCHAR(200) = NULL OUTPUT,
#OperationType INT = NULL,
#LanguageID INT = NULL
)
AS
IF #operationType = 1
BEGIN
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO ....
SELECT #ID = MAX(ID)
FROM JOB
SET #IsDbCommandCommitted = 1
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SET #DbCommitError = ERROR_MESSAGE()
ROLLBACK TRANSACTION
END CATCH
END
ELSE
IF #OperationType = 2
BEGIN
BEGIN TRY
BEGIN TRANSACTION
UPDATE JOB
......
SET #IsDbCommandCommitted = 1
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SET #DbCommitError = ERROR_MESSAGE()
ROLLBACK TRANSACTION
END CATCH
END
ELSE
IF #OperationType = 3
BEGIN
BEGIN TRY
BEGIN TRANSACTION
DELETE
FROM JOB
WHERE ID = #ID
SET #IsDbCommandCommitted = 1
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SET #DbCommitError = ERROR_MESSAGE()
ROLLBACK TRANSACTION
END CATCH
END
any idea?
Pass parameter Using EF
Follow this tutorial to pass the parameter to your SP using EF, this should solve your query

stored procedure even after null value saves the data

ALTER PROCEDURE [dbo].[STL_ADDNEWROLE](#ROLENAME VARCHAR(100), #STATUS BIT)
AS
BEGIN
SET NOCOUNT ON;
IF(#ROLENAME IS NULL OR #STATUS IS NULL)
BEGIN
RETURN 0
END
ELSE
BEGIN
IF EXISTS (SELECT [RoleName], [Status] FROM ST_Roles
WHERE [RoleName] = #ROLENAME)
BEGIN
RETURN 0
END
ELSE IF(#ROLENAME IS NOT NULL)
BEGIN
INSERT INTO ST_Roles ([RoleName], [Status]) VALUES(#ROLENAME, #STATUS)
RETURN 1
END
END
END
The above is my stored proc. When NULL values are passed it should return 0. Even when 1 value is passed and another value is not passed it should return 0 instead of inserting the record.
Any help is really appreciated.
Before you describe your problem, I'll just guess. I suppose the problem is in default parameters. Maybe you just don't pass parameters or you pass empty string, so try this way
ALTER PROCEDURE [dbo].[STL_ADDNEWROLE](
#ROLENAME VARCHAR(100) = NULL,
#STATUS BIT = NULL)
AS
BEGIN
SET NOCOUNT ON;
IF(ISNULL(#ROLENAME, '') = '' OR #STATUS IS NULL)
BEGIN
RETURN 0
END
ELSE
BEGIN
IF EXISTS (SELECT [RoleName],[Status] from ST_Roles where [RoleName] = #ROLENAME)
BEGIN
RETURN 0
END
ELSE IF(#ROLENAME IS NOT NULL)
BEGIN
INSERT INTO ST_Roles ([RoleName],[Status]) VALUES(#ROLENAME,#STATUS)
RETURN 1
END
END
END

Resources