How to execute a stored procedure with parameters? - sql-server

I have a database with 40 tables. I want to select data from a certain table by using a single stored procedure. First table (TblSPAU1) has 6 columns, named: ID, COL_SPAU1_EA, COL_SPAU1_EQ, COL_SPAU1_ore, COL_SPAU1_nivel, DateTime. Fourth table (TblSPAU4), for example, has this 6 columns: ID, COL_SPAU4_EA, COL_SPAU4_EQ, COL_SPAU4_ore, COL_SPAU4_nivel, DateTime. So what I want is to select data from table X from DateStart to DateStop. What I've done so far is:
USE [DBRapBreaza]
GO
/****** Object: StoredProcedure [dbo].[PS_SpauOPompa] Script Date: 12/19/2018 15:48:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PS_SpauOPompa]
#DataStart datetime,
#DataStop datetime,
#val int
AS
BEGIN
SET NOCOUNT ON;
declare #sql NVARCHAR(max)
declare #col1 varchar
set #col1='ID'
declare #col2 varchar(25)
set #col2='COL_SPAU'+CONVERT(VARCHAR, #val)+'_EA'
declare #col3 varchar
set #col3='DateTime'
set #sql='select [ID]'+#col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, #val)+ '] WHERE DateTime between'+CONVERT(VARCHAR(25), #DataStart,121)+ 'and'+CONVERT(VARCHAR(25), #DataStop,121)+';'
END
EXEC sp_sqlexec #sql, N'#DataStart datetime,#DataStop datetime,#val int', #DataStart, #DataStop, #val
I want to select, let's say, the ID and fist column from a certain table. #val represents the number of the table I want to select data from.
On sp_sqlexec I have a tool-tip which says that I have too many arguments specified. When I execute the EXEC, it throws me this error: Msg 137, Level 15, State 2, Line 1. Must declare the scalar variable "#sql".
My question is how should I execute this stored procedure?
Many thanks in advance!

First, you need some spaces in your string build. Specifically, change it to:
set #sql= 'select [ID], '+#col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, #val)+ '] WHERE DateTime between '''+CONVERT(VARCHAR(25), #DataStart,121)+ ''' and '''+CONVERT(VARCHAR(25), #DataStop,121)+''';'
This will make your SQL look like this:
select [ID], COL_SPAU1_EA FROM [DBRapBreaza].[dbo].[TblSPAU1] WHERE DateTime between '2018-12-20 14:18:02.170' and '2018-12-20 14:18:02.170';
As opposed to the following:
select [ID]COL_SPAU1_EA FROM [DBRapBreaza].[dbo].[TblSPAU1] WHERE DateTime between2018-12-20 14:19:13.167and2018-12-20 14:19:13.167;
Which is missing:
A comma after the first column
Space between comma names (semantics)
Space after the word between
Quotes around the dates that will be evaluated from your parameters
Space before and after and in the where clause on your between statement
This is why it's always wise to use PRINT #sql while testing your dynamic SQL.
Then, once you move the END to the very bottom of the script, change your execution to:
EXEC sp_executesql
#sql,
N'#DataStart datetime, #DataStop datetime, #val int',
#DataStart, #DataStop, #val
This will leave you with the following code:
USE [DBRapBreaza]
GO
/****** Object: StoredProcedure [dbo].[PS_SpauOPompa] Script Date: 12/19/2018 15:48:38 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PS_SpauOPompa]
#DataStart datetime,
#DataStop datetime,
#val int
AS
BEGIN
SET NOCOUNT ON;
declare #sql NVARCHAR(max)
declare #col1 varchar --missing a length here
declare #col2 varchar(25)
declare #col3 varchar --missing a length here
set #col1='ID'
set #col2='COL_SPAU'+CONVERT(VARCHAR, #val)+'_EA'
set #col3='DateTime'
set #sql= 'select [ID], '+#col2+' FROM [DBRapBreaza].[dbo].[TblSPAU'+CONVERT(VARCHAR, #val)+ '] WHERE DateTime between '''+CONVERT(VARCHAR(25), #DataStart,121)+ ''' and '''+CONVERT(VARCHAR(25), #DataStop,121)+''';'
--print #sql;
EXEC sp_executesql
#sql,
N'#DataStart datetime, #DataStop datetime, #val int',
#DataStart, #DataStop, #val;
END
Of note, you didn't specify a length for #col1 or #col3 which would default to 8 so be careful there. You never used this variable, so I'm not sure what it's purpose is.

Related

Call SQL stored proc with OUTPUT param from another stored proc

It seems very simple solution, but I can't figure it out. Please help.
I have to call a stored proc with OUTPUT param from another stored proc. I think one of the issues is dynamic SQL, but I don't know how else to write it since #SQLWhere will change dynamically within C# code.
This is the proc being called from another proc:
ALTER PROCEDURE [dbo].[USP_RetrieveTotalRecord]
#SQLWhere AS NVARCHAR(1000),
#TotalRecordsFound as varchar(16) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL AS NVARCHAR(Max)
SET #SQL='Select #TotalRecordsFound = Count(Table_ID)
From TableName Where ' + #SQLWhere
EXEC(#SQL)
return
END
Here is how I am calling it from another proc:
Declare #TotalRec AS NVARCHAR(16);
Declare #SQLWhere AS NVARCHAR(1000);
SET #SQLWhere='Date Between ''12/13/2016'' AND ''12/14/2016'''
EXECUTE USP_RetrieveTotalRecord #SQLWhere, #TotalRec output;
Here is the error I am trying to resolve:
Msg 137, Level 15, State 1, Line 30
Must declare the scalar variable "#TotalRecordsFound".
Don't do what you are trying to do, Only pass values to stored procedure and then build the dynamic sql inside your procedure, something like ......
ALTER PROCEDURE [dbo].[USP_RetrieveTotalRecord]
#StartDate DATE = NULL
,#EndDate DATE = NULL
,#TotalRecordsFound INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(Max);
SET #SQL = N' Select #TotalRecordsFound = Count(Table_ID) '
+ N' From TableName Where 1 =1 '
+ CASE WHEN #StartDate IS NOT NULL THEN
N' AND [Date] >= #StartDate ' ELSE N' ' END
+ CASE WHEN #EndDate IS NOT NULL THEN
N' AND [Date] <= #EndDate ' ELSE N' ' END
EXEC sp_executesql #SQL
,N'#StartDate DATE, #EndDate DATE, #TotalRecordsFound INT OUTPUT'
,#StartDate
,#EndDate
,#TotalRecordsFound OUTPUT
END
Now #EndDate and #StartDate variables are optional , depending on what variable values you pass procedure will build the dynamic sql accordingly and return the results.
Also using parameterised query with sp_executesql will protect you against a possible SQL-Injection attach and also your proc will benefit from parameterised execution plans.
Not sure why you have a 2nd SP, just use one like so:
Declare #TotalRec AS NVARCHAR(16);
Declare #SQLWhere AS NVARCHAR(1000);
SET #SQLWhere='Date Between ''12/13/2016'' AND ''12/14/2016'''
SET #SQL='Select #TotalRecordsFound = Count(Table_ID)
From TableName Where ' + #SQLWhere
EXEC(#SQL)
Or use date variables if that's all you are using for selection (no dynamic sql necessary) - unless this is just a simplified example
--- comment section is broken, so, in response to get a value out, use something like this:
Ok - the simplest way is to use sp_ExecuteSQL
Declare #result int
Declare #sql nvarchar(max)
SET #SQL = ' SELECT COUNT(*) FROM MyTable'
exec sp_ExecuteSQL #sql, N' #Result int Output', #Result output
select #result as MyCount
M. ali, thanks for your help, but we have all SELECT, WHERE, and GROUP by criteria being passed from the application after dynamic selections. I needed a quick fix.
Finally I was able to resolve the issue using a temp table. I know they are not recommended, but I tried using Common table expression, table variable, but the #TotalRecordsFound was not visible outside the dynamic SQL. Therefore, created temp table, Inserted data into it using dynamic SQL, and then joined it with the next select statement.

Select data from another database in storedprocedure

I try to select data from a table of another database in my storedprocedure and the name of the other database is given by parameter. I get an error message:
'Invalid object name [#DbName].dbo.Setup'.
CREATE PROCEDURE [dbo].[spUndeliverableOrders]
#DbName sysname
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sortfield nvarchar(50)
SET #Sortfield = (SELECT COALESCE(Text, 'ToDoListeDatum') AS SortField FROM [#DbName].dbo.Setup WHERE label like 'ComboBoxSetupBatchReihenfolge')
END
GO
Can someone help me to solve this problem?
Like #ThomasSchremser said:
DECLARE #sqlquery varchar(1000)
SET #sqlquery = '(SELECT COALESCE(Text, ''ToDoListeDatum'') AS SortField FROM ['+#DbName+'].dbo.Setup WHERE label like ''ComboBoxSetupBatchReihenfolge'')'
It is upto you to decide weither you what to populate a table/variable with the results.
Either use:
insert into #table(column) exec #sqlquery...
or
sp_executesql #sqlquery...
You need to use dynamic query as below
CREATE PROCEDURE [dbo].[spUndeliverableOrders]
#DbName sysname
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #Str varchar(max)
CREATE TABLE #Result(Res VARCHAR(MAX))
SET #Str = 'insert into #Result SELECT TOP 1 COALESCE(Text, ''ToDoListeDatum'') AS SortField FROM ['+#DbName+'].dbo.Setup WHERE label like ''ComboBoxSetupBatchReihenfolge'''
exec(#str)
select Res from #Result
END
Modified per your script:
DECLARE #Str varchar(max)
CREATE TABLE #Result(Res VARCHAR(MAX))
SET #Str = ' SELECT TOP 1 COALESCE(Text, ''ToDoListeDatum'') AS SortField FROM ['+#DbName+'].dbo.Setup WHERE label like ''ComboBoxSetupBatchReihenfolge'''
insert into #Result
EXEC(#Str)

Appending string to SQL Server stored procedure

I'm trying to append table name dynamically to SQL Server stored procedure, but I get an error:
couldn't find the stored procedure 's'
Code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[atest_demo_sp]
#name varchar(10)
AS
BEGIN
Declare #tname nvarchar
Declare #sql nvarchar
set #tname = #name
Set #sql = 'select * from ' + convert(varchar(10), #tname)
-- select #sql
execute sp_executesql #sql
END
You need to explicitly define a length for your string variables!
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[atest_demo_sp]
#name varchar(10)
AS
BEGIN
Declare #tname nvarchar(200) -- DEFINE A LENGTH HERE !!!
Declare #sql nvarchar(200) -- DEFINE A LENGTH HERE !!!
set #tname = #name
Set #sql = N'select * from ' + convert(nvarchar(10), #tname)
-- select #sql
execute sp_executesql #sql
END
Otherwise, your variables #tname and #sql will be exactly 1 character long! Probably not what you want!
See this blog post for more details: Bad habits to kick : declaring VARCHAR without (length)
Also, as a side note: either pick varchar (non-Unicode), or use nvarchar (Unicode) - but don't mix the two. And if you use nvarchar, you should always use the N'...' notation for assigning string literals.
The issue with the set #tname = #name, no need to assign the varchar to nvarchar here. Avoid the #tname variable and directly use #name in the SET statement since it is already varchar.
Hope the #name's first character only assigning to #tname. Also need to define the #sql to some length.
Use the below statement, it will work:
Declare #sql varchar(100);
Set #sql = 'select * from ' + #name

sp_ExecuteSql: The parameterized query expects the parameter #XX, which was not supplied

I'm trying to build a dynamic stored procedure to allow me to pass my string where clause as part of the parameter. However, following this article from MSDN I still couldn't get it running and having the error as described by the title. Any help is much appreciated.
EXEC [dbo].[Get_Demand_By_Click_Test]
#Year = 2014
Error:
Msg 8178, Level 16, State 1, Line 9
The parameterized query '(#Year int)
SELECT
dbo.vw_Demand_By.*
FROM '
expects the parameter '#Year', which was not supplied.
Stored procedure:
ALTER PROCEDURE [dbo].[Get_demand_by_click_test]
#Year INT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET nocount ON;
-- Insert statements for procedure here
DECLARE #SQL NVARCHAR(max),
#ParamDefinition NVARCHAR(max)
SET #SQL = N'
SELECT
dbo.vw_Demand_By.*
FROM
dbo.vw_Demand_By
WHERE
Year(EventStartDate) = #Year'
SET #ParamDefinition = N'#Year int';
EXECUTE Sp_executesql
#SQL,
#ParamDefinition;
END
You have to pass the parameter as well:
EXECUTE Sp_executesql #SQL, #ParamDefinition, #Year = #Year;
You need to give a value to the #Year parameter. To execute the code use:
EXECUTE Sp_executesql
#SQL,
#ParamDefinition,
#Year = 2014
UPDATE
In response to your comments you can assign any variable in the place of the fixed 2014 value. In your code it will look like :
ALTER PROCEDURE [dbo].[Get_demand_by_click_test]
#Year INT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET nocount ON;
-- Insert statements for procedure here
DECLARE #SQL NVARCHAR(max),
#ParamDefinition NVARCHAR(max)
SET #SQL = N'
SELECT
dbo.vw_Demand_By.*
FROM
dbo.vw_Demand_By
WHERE
Year(EventStartDate) = #Year'
SET #ParamDefinition = N'#Year int';
EXECUTE Sp_executesql
#SQL,
#ParamDefinition,
#Year = #Year
END

SQL Server sp_execute - Error with DateTime Variable in the Dynamic SQL

I tried to create dynamic SQL using sp_executesql, but it gives me this error message:
Msg 137, Level 15, State 2, Line 20
Must declare the scalar variable "#start".
Here is my stored procedure script
CREATE PROCEDURE sp_test (#start datetime, #end datetime)
AS
BEGIN
DECLARE #sql nvarchar(MAX)
SET #sql = 'SELECT * FROM table1 WHERE '
SET #sql = #sql + N'startDate BETWEEN #start AND #end'
EXEC sp_executesql #sql
Any input will be appreciated.
The below T-SQL should take care of your problem. Although, I would not recommend prefixing your stored procedure name with "sp_" since the system stored procedures use this naming convention. You wouldn't want to have your stored procedures confused with system stored procedures, or worse, Microsoft decides to name one of their future system stored procedures with the name of yours.
Things to note:
You define/declare all the custom parameters that you want to pass into your dynamic SQL statement in the #ParameterDefinition variable.
You add each of your custom variables to the sp_executesql call as if they were already part of the procedure.
IF OBJECT_ID('sp_test', 'P') IS NOT NULL DROP PROCEDURE sp_test
GO
-- ============================================================================
-- CALLING EXAMPLE:
-- EXEC sp_test '01/01/1901', '01/02/1901'
-- ============================================================================
CREATE PROCEDURE sp_test (#start datetime, #end datetime)
AS
BEGIN
DECLARE #sql nvarchar(max)
SET #sql = 'SELECT * FROM table1 WHERE '
SET #sql = #sql + N'startDate BETWEEN #start AND #end'
-- Build the Parameter Definition list for the dynamic SQL statement below
DECLARE #ParameterDefinition nvarchar(1000);
SELECT #ParameterDefinition = ''
+ ' #start datetime'
+ ',#end datetime'
EXEC sp_executesql
#statement = #sql
,#params = #ParameterDefinition
-- Assign values to any of custom parameters defined in #ParameterDefinition:
,#start = #start
,#end = #end
END
GO

Resources