Dynamic update of string values in tables using Stored procedure - sql

The following is my stored procedure to update a column in SQL SERVER
ALTER PROCEDURE [dbo].[AspPageUpdate]
(#type varchar(50),#comp varchar(50),
#place varchar(50))
AS
BEGIN
SET NOCOUNT ON;
DECLARE #tid varchar;
DECLARE #ph int;
SET #ph = CAST(#place AS int);
select #tid = Type_Id
from TypeTable
where Type_Name = #type
UPDATE TypeSetupTable
SET PLACE_HOLDERS = #ph
WHERE complexity = #comp
AND Type_Id = #tid
END
But the table is not getting updated. I think the problem is with Quotes(Strings need to be in quotes, right?).
If i'm giving static values, it is execting, like:
UPDATE TypeSetupTable SET PLACE_HOLDERS = #ph WHERE complexity = 'Simple' AND Type_Id = 'SSRS'
Please tell me a solution.
Thanks in Advance.

you didn't set the size of the variable #tid.
Are you sure of the content of that variable while executing the stored procedure?
Try to put a raiserror(#tid,15,1) and check the content of that variable.
There are blogs about the habit not to size varchar variables.
It is also officially documented that the size of unsized varchars is 1.

Related

Stored procedure for return a value based on multiple input

This is my stored procedure to return a value based on multiple inputs.But it is not working.
USE [E_clinic]
GO
ALTER PROCEDURE [dbo].[Diseasesp1]
#id1 nchar(10),
#id2 nchar(10),
#id3 nchar(10)
AS
BEGIN
SET NOCOUNT ON;
set #id1=#id1+1
set #id2=#id2+1
set #id3=#id3+1
SELECT [Dname]
From [dbo].[Disease] AS D
Left Join [dbo].[Symptom] AS S ON D.[DiseaseID] = S.[DiseaseID]
Where [SymptomID] = #id1 AND [SymptomID] = #id2 AND [SymptomID] = #id3
END
Consider changing your procedure like
ALTER PROCEDURE [dbo].[Diseasesp1]
#id1 int,
#id2 int,
#id3 int
AS
BEGIN
SET NOCOUNT ON;
set #id1=#id1+1
set #id2=#id2+1
set #id3=#id3+1
SELECT [Dname]
From [dbo].[Disease] AS D
Left Join [dbo].[Symptom] AS S ON D.[DiseaseID] = S.[DiseaseID]
AND s.[SymptomID] = #id1
Left Join [dbo].[Symptom] AS S1 ON D.[DiseaseID] = S1.[DiseaseID]
AND s1.[SymptomID] = #id2
Left Join [dbo].[Symptom] AS S2 ON D.[DiseaseID] = S2.[DiseaseID]
AND s2.[SymptomID] = #id3;
END
You could simply use IN for this.
Where [SymptomID] in (#id1, #id2, #id3)
But I would be significantly concerned that you receive parameters as character data and then do math with them. This is just a bad approach concerning datatypes. What happens when you receive 'a'?
You need to change following things in your stored procedure.
1.#id1,#id2 and #id3 datatypes are nchar(10) but you are try to perform the addition operation with integer(#id1=#id1+1). This is not possible so please change the datatype of #id.
2.In that select statement, where clause you have used the same column with AND logical operator. This is not a correct way to write a SQL select with join query. please use correct where clause with alias name and use correct logical operator and then try..

declare variables in sql 2005

In my script i have few select statements and update statements, as an example
SELECT * from TABLE1
WHERE userID= 'US001'
UPDATE TABLE2
SET value= 'months'
WHERE userID='US001'
statements going so on, so in this i have to copy and paste userID to every statement.
i want to declare a variable and assign to userID to refer it, so i don't need to add userID number to every query and i need to execute
i have tried this
Delcare #theID userID
SET userID ='us001'
but didn't work it out
please let me know..
thanks
You'll need to declare the type, and assign it. In Sql Server, variables are prefixed with #, like so:
DECLARE #theID NVARCHAR(20);
SET #theID ='us001';
UPDATE TABLE2 SET value= 'months' WHERE userID=#theID;
DECLARE #theID varchar(10);
SET #theID = 'us001';
In your statement you are declaring your variable as userID, which is not a valid data type.
In addition to the previous answers, in SQL Server 2008 and higher you can also declare and set the variable in a single line.
DECLARE #UserID NVARCHAR(20) = 'us001';
This is what works for me under SQL2005 in a stored procedure:
DECLARE #name varchar(100)
SELECT #name = 'Robin'
// and this should be do the update
SET userID = #name
// or in you query it should be
WHERE userID = #name

Stored procedure to update multiple tables

I have a stored procedure that updates two tables. The first table is always the same table, but the second table changes depending on a parameter that is passed in. Is it more efficient to write it all into one big procudure, as such
CREATE PROCEDURE MyBigProc
#id int
#param int,
#value1 int,
#value2 int
AS
BEGIN
SET NOCOUNT ON;
-- First table to update
UPDATE MyTable SET field1 = #value1 WHERE id = #id
-- Then choose which table to update based on #param
IF #param = 1
UPDATE MySecondTable SET field2 = #value2 WHERE id = #id
IF #param = 2
UPDATE MyThirdTable SET field2 = #value2 WHERE id = #id
END
Or should I write a separate procedure for each table and then call EXEC the procedure from the main procedure.
I suppose the latter is more flexible, say if I wanted to update a subtable but no the main table?
I suppose the latter is more flexible, say if I wanted to update a
subtable but no the main table?
Exactly, you have a good reason to split the work on 2 separate procs. If it makes sense for you for everything else, I don't see why not follow that approach.
One possible reason not to do it, would be if you need both updates to succeed or fail at the same time. Under a scenario like this, I would leave everything in one proc and enclose everything in one transaction.
CREATE PROCEDURE MyBigProc
#id int,
#param int,
#value1 int,
#value2 int
AS
BEGIN
SET NOCOUNT ON;
-- First table to update
UPDATE MyTable SET field1 = #value1 WHERE id = #id;
-- Then choose which table to update based on #param
IF #param = 1
exec SP_MySecondTable #id,#value2;
IF #param = 2
exec SP_MyThirdTable #id,#value2;
END
CREATE PROCEDURE SP_MySecondTable
#id int,
#value2 int
AS
BEGIN
UPDATE MySecondTable SET field2 = #value2 WHERE id = #id;
END
CREATE PROCEDURE SP_MyThirdTable
#id int,
#value2 int
AS
BEGIN
UPDATE MyThirdTable SET field2 = #value2 WHERE id = #id;
END
Its better to have different stored procedures and then call them all at a single place. It'll help you a lot while performing maintenance activities.
Best option is to use a CASE statement to update your tables

Execute Stored Procedure for List of Parameters in SQL

I have an Stored Procedure that have an argument named Id:
CREATE PROCEDURE [TargetSp](
#Id [bigint]
)
AS
BEGIN
Update [ATable]
SET [AColumn] =
(
Select [ACalculatedValue] From [AnotherTable]
)
Where [ATable].[Member_Id] = #Id
END
So I need to use it for a list of Id's not for one Id like :
Exec [TargetSp]
#Id IN (Select [M].[Id] From [Member] AS [M] Where [M].[Title] = 'Example');
First: How can I Execute it for a list?
Second: Is there any Performance difference between I execute the sp many times or rewrite it in target script?
You could use a table-valued parameter (see http://msdn.microsoft.com/en-us/library/bb510489.aspx). Generally, if you send only one request to the server instead of a list of requests you will see a shorter execution time.
I normally pass in the information like that as XML, then you can use it just like it's a table... selecting, inserting, updating as necessary
DECLARE #IDS NVARCHAR(MAX), #IDOC INT
SET #IDS = N'<ROOT><ID>1</ID><ID>2<ID></ROOT>'
EXEC sp_xml_preparedocument #IDOC OUTPUT, #IDS
SELECT [ID] FROM OPENXML (#IDOC, '/ROOT/ID', 2) WITH ([ID] INT '.') AS XMLDOC
EXEC sp_xml_removedocument #IDOC
Similar to freefaller's example, but using xml type instead and inserting into a table variable #ParsedIds
DECLARE #IdXml XML = N'<root><id value="1"/><id value="2"/></root>'
DECLARE #ParsedIds TABLE (parsedId int not null)
INSERT INTO #ParsedIds (parsedId)
SELECT v.parsedId.value('#value', 'int')
FROM #IdXml.nodes('/root/id') as v(parsedId)
SELECT * FROM #ParsedIds
Interestingly I've worked on an large scale system with 1000's of users and we found that using this method out performed the table-valued parameter approach for small lists of id's (no more than say 5 id's). The table-valued parameter approach was faster for larger lists of Id's.
EDIT following edited question:
Looking at your example it looks like you want to update ATable based on the Title parameter. If you can you'd benefit from rewriting your stored procedure to instead except the title parameter.
create procedure [TargetSP](
#title varchar(50)
)
as
begin
update [ATable]
set [AColumn] =
(
select [ACalculatedValue] from [AnotherTable]
)
where [ATable].[Member_Id] in (select [M].[Id] from [Member] as [M] where [M].[Title] = #title);
end
Since you only care about all the rows with a title of 'Example', you shouldn't need to determine the list first and then tell SQL Server the list you want to update, since you can already identify those with a query. So why not do this instead (I'm guessing at some data types here):
ALTER PROCEDURE dbo.TargetSP
#title VARCHAR(255)
AS
BEGIN
SET NOCOUNT ON;
-- only do this once instead of as a subquery:
DECLARE #v VARCHAR(255) = (SELECT [ACalculatedValue] From [AnotherTable]);
UPDATE a
SET AColumn = #v
FROM dbo.ATable AS a
INNER JOIN dbo.Member AS m
ON a.Member_Id = m.Id
WHERE m.Title = #title;
END
GO
Now call it as:
EXEC dbo.TargetSP #title = 'Example';
DECLARE #VId BIGINT;
DECLARE [My_Cursor] CURSOR FAST_FORWARD READ_ONLY FOR
Select [M].[Id] From [Member] AS [M] Where [M].[Title] = 'Example'
OPEN [My_Cursor]
FETCH NEXT FROM [My_Cursor] INTO #VId
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC [TargetSp]
#Id = #VId
FETCH NEXT FROM [My_Cursor] INTO #VId
END
CLOSE [My_Cursor]
DEALLOCATE [My_Cursor];
GO
if the parameter is integer, you can only pass one value at a time.
Your options are:
call the proc several times, one for each parameter
Change the proc to accept a structure where you can pass more than
one id like a varchar where you pass a coma separated list of values
(not so good) or a table-value parameter
About the performance question, it would be faster to re-write the proc to iterate through a list of ids than call it several times, once per id, BUT unless you are dealing with a HUGE list of ids, I dont think you will see much of a difference

Store the result of a stored procedure without using an output parameter

I have 2 stored procedures: up_proc1 and up_proc2.
This is (a simplified version of) up_proc2:
CREATE PROCEDURE dbo.up_proc2
#id_campaign uniqueidentifier, #id_subcampaign uniqueidentifier,
#id_lead uniqueidentifier, #offer NVARCHAR(1000) = NULL
AS
SET NOCOUNT ON
DECLARE #id UNIQUEIDENTIFIER
SELECT #id = id FROM prospects WHERE id_lead = #id_lead
AND id_campaign = #id_campaign AND id_subcampaign = #id_subcampaign
IF #id IS NULL
BEGIN
SET #id = newid ()
INSERT INTO prospects (id, id_campaign, id_subcampaign, id_lead, offer)
values (#id, #id_campaign, #id_subcampaign, #id_lead, #offer)
END
ELSE
BEGIN
UPDATE prospects set offer = #offer WHERE id=#id
END
SELECT #id AS ID
GO
From up_proc1 I call up_proc2. What I would like to achieve is to store the #id of up_proc2 in a variable declared in up_proc1. Is this possible without using an output parameter?
This is how up_proc1 looks like:
CREATE PROCEDURE dbo.up_proc1
AS
SET NOCOUNT ON
DECLARE #fromProc2 UNIQUEIDENTIFIER
-- NOT WORKING
-- select #fromProc2 = exec up_insertProspects [snip]
-- ALSO NOT WORKING
-- exec #fromProc2 = up_insertProspects [snip]
What you could do is store the output into a table variable:
DECLARE #tmpTable TABLE (ID UNIQUEIDENTIFIER)
INSERT INTO #tmpTable
EXEC dbo.up_proc2 ..........
and then go from there and use that table variable later on.
You can certainly consume this as an output parameter in proc2 without affecting how your C# code retrieves the eventual resultset.
ALTER PROCEDURE dbo.up_proc2
#id_campaign uniqueidentifier,
#id_subcampaign uniqueidentifier,
#id_lead uniqueidentifier,
#offer NVARCHAR(1000) = NULL,
#fromProc2 UNIQUEIDENTIFER = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
...
C# can ignore the new parameter since it is nullable (but since a single output parameter is more efficient than a data reader, you may consider updating your C# code to take advantage of the output parameter later).
Now in proc1:
ALTER PROCEDURE dbo.up_proc1
AS
BEGIN
SET NOCOUNT ON;
DECLARE #fromProc2 UNIQUEIDENTIFIER;
EXEC dbo.up_proc2
--... other parameters ...,
#fromProc2 = #fromProc2 OUTPUT;
-- now you can use #fromProc2
END
GO