Stored procedure update specific column by parameter - sql

I am developing a stored procedure to update specific columns using parameters.
For example:
CREATE PROCEDURE save_proc
(
#userid varchar(5),
#column varchar(10),
#data varchar(50)
)
AS
BEGIN
UPDATE MyProfile
SET #column = #data
WHERE userid = #userid
The following is my code that I've tried but didn't work. Is it possible to do such an update by updating specific columns through parameters? Thanks

You can build up a query in your stored procedure and execute.
CREATE PROCEDURE save_proc
(
#userid varchar(5),
#column varchar(10),
#data varchar(50)
)
AS
BEGIN
exec sp_executesql N'UPDATE MyProfile SET ' + #column + '=''' + #data + ''' WHERE userid = ''' + #userid + ''''
END
The method may lead to security concern however.

Its doable but i would avoid doing it.... you code should be like below:
DECLARE #column varchar(10)
DECLARE #data varchar(50)
UPDATE DummyTable
SET
col1 = CASE WHEN #column = 'Col1' THEN #data ELSE col1 END ,
col2 = CASE WHEN #column = 'Col2' THEN #data ELSE col2 END
where userid = #userid
.
.
.
Hope that this is what you are looking for

Using a CASE statement causes all columns identified to once again be updated; this would invoke a reindexing for some indexes upon columns wherein that change, even if the same value, occurs. Waste of execution updates on server.
An IF statement is best option for single value, especially if value is NOT the same type as the column datatype.
IF(#fieldName IS NULL) SELECT #fieldName = ''
IF(#updateValue IS NULL) SELECT #updateValue = ''
DECLARE #myCount int
SELECT #myCount = count(*) FROM [dbo].[myTable] WHERE #inventoryID = #updateInventoryID
--if no valid data to update, return -1 for noUpdate
IF(0 = #updateInventoryID
OR 0 = #myCount
OR '' = #fieldName
OR '' = #updateValue)
RETURN -1
BEGIN TRAN
IF('notes' = #fieldName)
UPDATE [dbo].[myTable]
SET [notes] = #updateValue, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
IF('reorderPoint' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [reorderPoint] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('safetyStock' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [safetyStock] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('quantityOnHand' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [quantityOnHand] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('totalLeadTimeDays' = #fieldName)
BEGIN
SET #newValueInt = CONVERT(int, #updateValue)
UPDATE [dbo].[myTable]
SET [totalLeadTimeDays] = #newValueInt, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
IF('stockTakeETADate' = #fieldName)
BEGIN
SET #newValueDatetime = CONVERT(datetime, #updateValue)
UPDATE [dbo].[myTable]
SET [stockTakeETADate] = #newValueDatetime, [modifyDate] = GETDATE()
WHERE [inventoryID] = #updateInventoryID
END
COMMIT
A Try/Catch is advisable

Related

How to split and replace with stored procedure?

I want to replace all e_Mail column where in #tablename with my users table (my main table).
For example:
#tablename
[name] [eMail] // columns
------------------------------------------------------
name surname blahblah#gmail.com
My users table
[name] [eMail]
----------------------------------------
name surname blahblah#hotmail.com
I want to update this row's eMail column as 'blahblah#hotmail.com' in #tablename.
What will procedure do?
1- Get first value of eMail column from #tablename
2- Split value (split char: #) and get first value (for example, if value blahblah#gmail.com, get gmail.com)
3- Search first value in users table
4- When the find value in users table, (Code must find blahblah#hotmail.com) Update eMail as blahblah#hotmail.com in #tablename
5- Get second value of eMail column from #tablename
.
.
.
So, I write a stored procedure. But this procedure is not working. Where is the problem?
Create Proc update_eMail
(#tablename nvarchar(50),
#columnname nvarchar(50))
AS
Begin
Declare #get_oldeMail nvarchar(100)
Declare #get_eMail nvarchar(100)
Declare #get_SplitValue nvarchar(100)
Declare #get_oldSplitValue nvarchar(100)
Declare #rowNumber int
Declare #users_rowNumber int
Declare #i int
Declare #j int
Declare #q_getRowNumber NVARCHAR(MAX)
Declare #q_getoldeMail NVARCHAR(MAX)
Declare #q_UpdateQuery NVARCHAR(MAX)
SET #q_getRowNumber = N'SELECT Count(ID)
FROM ' + QUOTENAME(#tablename)
EXECUTE #rowNumber = sp_executesql #q_getRowNumber
/*Set #rowNumber = (Select Count(ID) from #tablename)*/
Set #users_rowNumber = (Select Count(ID) from tblusers)
Set #i = 1
Set #j = 1
While(#i <= #rowNumber)
BEGIN
Set #q_getoldeMail = '(SELECT Lower(#columnname) FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY ID) AS rownumber
,ID
,[Name]
,[Description]
,[Status]
,[AssignedTo]
,[AssignedToMail]
,[CC]
FROM' + #tablename + '
) AS ar
WHERE rownumber = #i)'
EXECUTE #get_oldeMail = sp_executesql #q_getoldeMail
Set #get_oldeMail = REPLACE(#get_oldeMail,'ı','i')
WHILE LEN(#get_oldeMail) > 0
BEGIN
IF CHARINDEX('#',#get_oldeMail) > 0
SET #get_oldSplitValue = SUBSTRING(#get_oldeMail,0,CHARINDEX('#',#get_oldeMail))
ELSE
BEGIN
SET #get_oldSplitValue = #get_oldeMail
SET #get_oldeMail = ''
END
SET #get_oldeMail = REPLACE(#get_oldeMail,#get_oldSplitValue + '#' , '')
END
While(#j <= #users_rowNumber)
BEGIN
Set #get_eMail = (SELECT Replace(Lower(eMail),'ı','i') FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY ID) AS rownumber
,eMail
FROM tblusers) AS ar
WHERE rownumber = #j)
WHILE LEN(#get_eMail) > 0
BEGIN
IF CHARINDEX('#',#get_eMail) > 0
SET #get_SplitValue = SUBSTRING(#get_eMail,0,CHARINDEX('#',#get_eMail))
ELSE
BEGIN
SET #get_SplitValue = #get_eMail
SET #get_eMail = ''
END
SET #get_eMail = REPLACE(#get_eMail,#get_SplitValue + '#' , '')
END
if(#get_splitValue = #get_oldSplitValue)
begin
Set #q_UpdateQuery = 'Update ar Set ' + #columnname + ' = ' + #get_email + ' Where rownumber = ' +#i
EXECUTE sp_executesql #q_UpdateQuery
break
end
SET #j = #j+1
END
SET #i = #i+1
END
End
Thanks in advance.

Procedure to check annual date

I'm trying to create a procedure to verify annual dates. The date is stored one time in the BD, but in the calendar on my winform it shows annually(I use annually bolded dates in C#). So what I want to do with the query, is to check is the month and the day are like the date stored in the table, but does not work. This is my query:
SELECT IdCalendar,
Description,
DateCalendar,
Annualy
FROM Calendar
WHERE
(DATEPART(MONTH,DateCalendar) like DATEPART(MONTH,#DateCalendar)) AND
(DATEPART(DAY,DateCalendar) like DATEPART(DAY,#DateCalendar))
And for example, my stored DateCalendar is '2015-12-04', and I my paramenter #DateCalendar is '2016-12-04'. Any idea about how to do a better query?
EDIT
The query does not have any error or warning. Just returns 0 rows. And my DateCalendar is stored as DateTime.
The SP:
CREATE PROC [dbo].[usp_app_Calendar_Search]
#DateCalendar DATETIME,
#Result SMALLINT OUTPUT,
#Message VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #vResult SMALLINT, #vMessage VARCHAR(1000)
SELECT #vResult = 0, #vMessage = ''
BEGIN TRY
IF EXISTS (SELECT * FROM Calendar WHERE DateCalendar = #DateCalendar)
BEGIN
IF(#DateCalendar = 0) SET #DateCalendar = NULL
SELECT IdCalendar,
Description,
DateCalendar,
Annualy
FROM Calendar
WHERE
(DATEPART(MONTH,DateCalendar) like DATEPART(MONTH,#DateCalendar)) AND
(DATEPART(DAY,DateCalendar) like DATEPART(DAY,#DateCalendar))
SET #vResult = 1
SET #vMessage = 'Done'
END
ELSE BEGIN
SET #vResult = 0
SET #vMessage = 'Error.'
END
END TRY
BEGIN CATCH
SET #vResult = -1
SET #vMessage = 'Error: ' + ERROR_MESSAGE() + ' Line: ' + CAST(ERROR_LINE() AS VARCHAR)
END CATCH
SELECT #Result = #vResult, #Message = #vMessage
END
Thanks in advance.
The problem is with IF EXISTS (SELECT * FROM Calendar WHERE DateCalendar = #DateCalendar). I rewrite your SP:
CREATE PROC [dbo].[usp_app_Calendar_Search]
#DateCalendar DATETIME,
#Result SMALLINT OUTPUT,
#Message VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #vResult SMALLINT = 0
,#vMessage VARCHAR(1000) = '';
IF(#DateCalendar = 0) SET #DateCalendar = NULL;
BEGIN TRY
SELECT IdCalendar,
Description,
DateCalendar,
Annualy
FROM Calendar
WHERE DATEPART(MONTH,DateCalendar) = DATEPART(MONTH,#DateCalendar)
AND DATEPART(DAY,DateCalendar) = DATEPART(DAY,#DateCalendar);
IF ##ROWCOUNT > 0
SELECT #vResult = 1, #vMessage = 'Done'
ELSE
SELECT #vResult = 0, #vMessage = 'Error.';
END TRY
BEGIN CATCH
SET #vResult = -1
SET #vMessage = 'Error: ' + ERROR_MESSAGE() + ' Line: '
+ CAST(ERROR_LINE() AS VARCHAR)
END CATCH
SELECT #Result = #vResult, #Message = #vMessage;
END
EDIT:
Now the WHERE condition is not-SARGable so it means that query optimizer will skip index on DateCalendar column (if exists any).
You can use computed columns like #Tom Page suggested in comment:
ALTER TABLE Calendar ADD MonthCalendar AS DATEPART(MONTH,DateCalendar);
ALTER TABLE Calendar ADD DayCalendar AS DATEPART(day,DateCalendar);
/*Create Index on Calculated Columns for Month and day*/
CREATE INDEX IX_Calendar_Month_Day ON Calendar(MonthCalendar , DayCalendar);
/*Use Computed Column Index in W*/
DECLARE #DateCalendar datetime = '2015-12-25';
SELECT IdCalendar, Description, DateCalendar, Annualy
FROM Calendar
WHERE MonthCalendar = DATEPART(MONTH,#DateCalendar)
AND DayCalendar = DATEPART(DAY,#DateCalenda);

Passing parametrs to dynamic query

I have a stored procedure as following, I need to pass paramters to the dynamic pivot. My query runs, I just need to do some filtering based on the passed parameters
-- AND (#SelectedSystemIDs IS NULL OR System.ID IN(select * from dbo.SplitInts_RBAR_1(#SelectedSystemIDs, ',')))
--AND ((#PlatformID IS NULL) OR (System.PlatformID = #PlatformID) OR (#PlatformID = 12 AND System.PlatformID <= 2))
-- AND (ServiceEntry.ServiceDateTime between #StartDate and #EndDate)
so I want to add the above criteria, how could achieve that?
ALTER PROCEDURE [dbo].[spExportStuff]
(#StartDate datetime,
#EndDate datetime,
#SelectedSystemIDs nvarchar (2000) = NULL,
#SelectedTsbIDs nvarchar (2000) = NULL,
#UserRoleID int
)
AS
DECLARE #InstrumentType int = NULL
DECLARE #PlatformID int = null
IF (#SelectedSystemIDs = '')
begin
SET #SelectedSystemIDs = NULL
END
IF (#SelectedTsbIDs = '')
begin
SET #SelectedTsbIDs = NULL
END
IF(#UserRoleID = 1)
BEGIN
SET #PlatformID = 1
END
IF(#UserRoleID = 2)
BEGIN
SET #PlatformID = 2
END
IF (#UserRoleID = 3)
BEGIN
SET #PlatformID = 12
END
IF(#UserRoleID = 4)
BEGIN
SET #PlatformID = 3
END
IF(#UserRoleID = 5)
BEGIN
SET #PlatformID = 4
END
IF(#UserRoleID = 6)
BEGIN
SET #PlatformID = NULL
END
DECLARE #PivotColumnHeaders NVARCHAR(MAX)
SELECT #PivotColumnHeaders =
COALESCE(
#PivotColumnHeaders + ',[' + cast(SystemFullName as Nvarchar) + ']',
'[' + cast(SystemFullName as varchar)+ ']'
)
FROM System
DECLARE #PivotTableSQL NVARCHAR(MAX)
SET #PivotTableSQL = N'
SELECT *
FROM (
SELECT
TSBNumber [TSBNumber],
SystemFullName,
ClosedDate
FROM ServiceEntry
INNER JOIN System
ON ServiceEntry.SystemID = System.ID
Group By TSBNumber, SystemFullName, ClosedDate
) AS PivotData
PIVOT (
max(ClosedDate)
FOR SystemFullName IN (
' + #PivotColumnHeaders + '
)
) AS PivotTable
'
EXECUTE(#PivotTableSQL)
you can construct the required criteria as another input to the stored procedure and append it to the dynamic query
ALTER PROCEDURE [dbo].[spExportStuff]
(#StartDate datetime,
#EndDate datetime,
#SelectedSystemIDs nvarchar (2000) = NULL,
#SelectedTsbIDs nvarchar (2000) = NULL,
#UserRoleID int,
#WhereClause varchar(max) -> this is the new parameter.
)
DECLARE #PivotTableSQL NVARCHAR(MAX)
SET #PivotTableSQL = N'
SELECT *
FROM (
SELECT
TSBNumber [TSBNumber],
SystemFullName,
ClosedDate
FROM ServiceEntry
INNER JOIN System
ON ServiceEntry.SystemID = System.ID
Group By TSBNumber, SystemFullName, ClosedDate
) AS PivotData
PIVOT (
max(ClosedDate)
FOR SystemFullName IN (
' + #PivotColumnHeaders + '
)
) AS PivotTable
' + #WhereClause -> you can append the where clause here.
EXECUTE(#PivotTableSQL)

Update TableType variable in dynamic SQL query

I had created User defined table type in my database. After that I had declared a variable of that table type in my procedure. And I had return my rest of the logic. At the end I am trying to update that table type variable using dynamic SQL.
But I got an error:
Msg 10700, Level 16, State 1, Line 1
The table-valued parameter "#ttbl_TagList" is READONLY and cannot be modified.
How can I solve the error?
User defined table type:
CREATE TYPE [dbo].[tt_TagList] AS TABLE(
[tagListId] [tinyint] IDENTITY(1,1) NOT NULL,
[tagId] [tinyint] NOT NULL DEFAULT ((0)),
[tagName] [varchar](100) NOT NULL DEFAULT (''),
[tagValue] [nvarchar](max) NOT NULL DEFAULT ('')
)
GO
Procedure:
CREATE PROCEDURE [dbo].[P_ReplaceTemplateTag]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #ttbl_TagList dbo.tt_TagList, #V_TagId INT, #V_Counter TINYINT = 1,
#V_FinalQuery NVARCHAR(MAX) = '', #V_TagValue NVARCHAR(MAX);
INSERT INTO #ttbl_TagList (tagId, tagName, tagValue)
SELECT DISTINCT T.tagId, T.tagName, '' AS tagValue
FROM dbo.tbl_Tag T;
WHILE (1 = 1)
BEGIN
SET #V_TagValue = '';
SELECT #V_TagId = tagId FROM #ttbl_TagList WHERE tagListId = #V_Counter;
IF (##ROWCOUNT = 0)
BEGIN
BREAK;
END
IF (#V_TagId = 1)
BEGIN
/* Logic for getting tag value */
SET #V_TagValue = 'Tag Value 1';
END
ELSE IF (#V_TagId = 2)
BEGIN
/* Logic for getting tag value */
SET #V_TagValue = 'Tag Value 2';
END
ELSE IF (#V_TagId = 3)
BEGIN
/* Logic for getting tag value */
SET #V_TagValue = 'Tag Value 3';
END
ELSE IF (#V_TagId = 4)
BEGIN
/* Logic for getting tag value */
SET #V_TagValue = 'Tag Value 4';
END
IF (#V_TagValue != '')
BEGIN
SET #V_FinalQuery = #V_FinalQuery + ' WHEN ' + CONVERT(NVARCHAR(10), #V_Counter) + ' THEN ''' + #V_TagValue + '''';
END
SET #V_Counter = #V_Counter + 1;
END
IF (#V_FinalQuery != '')
BEGIN
SET #V_FinalQuery = N'UPDATE #ttbl_TagList SET tagValue = (CASE tagListId' + #V_FinalQuery + ' END)';
EXECUTE sp_executesql #V_FinalQuery, N'#ttbl_TagList dbo.tt_TagList readonly', #ttbl_TagList;
END
SELECT * FROM #ttbl_TagList;
END
TVP can not be updated directly. So try this one -
CREATE PROCEDURE [dbo].[P_ReplaceTemplateTag]
AS
BEGIN
SET NOCOUNT ON;
IF OBJECT_ID('tempdb.dbo.#t1') IS NOT NULL
DROP TABLE #t1
DECLARE
#ttbl_TagList dbo.tt_TagList
, #V_Counter TINYINT = 1
, #V_FinalQuery NVARCHAR(MAX) = ''
, #V_TagValue NVARCHAR(MAX);
INSERT INTO #ttbl_TagList (tagId, tagName, tagValue)
SELECT DISTINCT tagId, tagName, ''
FROM dbo.tbl_Tag;
WHILE (1 = 1) BEGIN
SELECT #V_TagValue =
CASE
WHEN tagId = 1 THEN 'Tag Value 1'
WHEN tagId = 2 THEN 'Tag Value 2'
WHEN tagId = 3 THEN 'Tag Value 3'
WHEN tagId = 4 THEN 'Tag Value 4'
ELSE ''
END
FROM #ttbl_TagList
WHERE tagListId = #V_Counter;
IF (##ROWCOUNT = 0) BREAK;
IF (#V_TagValue != '')
BEGIN
SET #V_FinalQuery = #V_FinalQuery + ' WHEN ' + CONVERT(NVARCHAR(10), #V_Counter) + ' THEN ''' + #V_TagValue + '''';
END
SET #V_Counter = #V_Counter + 1;
END
IF (#V_FinalQuery != '')
BEGIN
CREATE TABLE #t1
(
tagId TINYINT
, tagName VARCHAR(100)
, tagValue NVARCHAR(MAX)
)
SET #V_FinalQuery = N'
INSERT INTO #t1
SELECT tagId, tagName, (CASE tagListId' + #V_FinalQuery + ' END)
FROM #ttbl_TagList';
EXEC sys.sp_executesql
#V_FinalQuery
, N'#ttbl_TagList dbo.tt_TagList readonly'
, #ttbl_TagList;
END
SELECT * FROM #t1;
END

An object or column name is missing or empty

I am getting the following error
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Add a name or single space as the alias name.
for the query show below:
CREATE PROC [dbo].[Sp_Table1] #ctlg_ipt_event_id int
AS
SET NOCOUNT ON
DECLARE #current_status NCHAR(1), #ready_status_code NCHAR(1)
DECLARE #current_action NCHAR(1), #ready_action_code NCHAR(1), #done_action_code NCHAR(1)
DECLARE #pst_user_id int
SELECT #current_status = status_code
,#current_action = action_code
,#pst_user_id = last_mod_user_id
FROM merch_ctlg_ipt_event
WHERE ctlg_ipt_event_id = #ctlg_ipt_event_id
Select #ready_status_code = 'o'
, #ready_action_code = 'a'
, #done_action_code = 'b'
IF #current_status <> #ready_status_code OR #current_action <> #ready_action_code
BEGIN
RETURN
END
BEGIN TRAN
declare #rows int
,#err int
,#i int
,#name nvarchar(50) --COLLATE SQL_AltDiction_Pref_CP850_CI_AS
,#resolved_View_Name_category_id int
,#xref_value int
,#availability_start_date datetime
,#availability_end_date datetime
,#status_code int
,#last_mod_user_id int
,#CT datetime
,#supplier_id int
,#View_Name_id int
select #i = 1
,#CT = current_timestamp
Select Distinct mc.name,
mc.resolved_View_Name_category_id,
mc.xref_value,
mc.availability_start_date,
mc.availability_end_date,
mc.status_code,
CASE WHEN mc.last_mod_user_id = 42
THEN #pst_user_id
ELSE mc.last_mod_user_id
END as last_mod_user_id,
CURRENT_tsp
,IDENTITY(int,1,1) as rn
,si.supplier_id
,si.View_Name_id
into #temp
FROM View_Name AS si
JOIN merch_ctlg_ipt_View_Name AS mc
ON mc.supplier_id = si.supplier_id
AND mc.resolved_View_Name_id = si.View_Name_id
AND mc.cat_imp_event_id = #ctlg_ipt_event_id
AND mc.accept_flag = 'y'
WHERE si.shipper_flag = 'n'
select #rows=##ROWCOUNT,#err=##error
if #rows > 0 and #err=0
Begin
While #i <=#rows
begin
SElect #name = name,
#resolved_View_Name_category_id = resolved_View_Name_category_id,
#xref_value = xref_value,
#availability_start_date = availability_start_date,
#availability_end_date = availability_end_date,
#status_code = mc.status_code,
#last_mod_user_id =last_mod_user_id ,
,#i=#i+1
,#supplier_id=supplier_id
,#View_Name_id=View_Name_id
from #temp
Where rn=#i
UPDATE View_Name
SET name = #name,
View_Name_category_id = #resolved_View_Name_category_id,
xref_value = #xref_value,
availability_start_date = #availability_start_date,
availability_end_date = #availability_end_date,
status_code = #status_code,
last_mod_user_id = #last_mod_user_id ,
last_mod_timestamp = #CT
Where #sup_id = supplier_id
AND #View_Name_id = View_Name_id
AND shipper_flag = 'n'
IF ##ERROR > 0
BEGIN
ROLLBACK TRAN
RETURN
END
End
End
UPDATE
merch_ctlg_ipt_event
SET action_code = #done_action_code,
last_mod_timestamp = #CT
WHERE ctlg_ipt_event_id = #ctlg_ipt_event_id
IF ##ERROR > 0
BEGIN
ROLLBACK TRAN
RETURN
END
COMMIT TRAN
Return
go
Could you please help ?
You have 2 commas in a row here
#last_mod_user_id =last_mod_user_id ,
,#i=#i+1
Also probably not relevant to the error message but you have a line
Where #sup_id = supplier_id
but the declared variable is #supplier_id