I have a stored procedure. I wanted to append the parameters to get all data from a specific table (e.g. tblJanuary2014). But the formatting is (probably) incorrect?
ALTER PROCEDURE GetReportAsOf
(
#Month varchar(15),
#Year varchar(15)
)
AS
BEGIN
SELECT * FROM tbl#Month#Year
RETURN
END
During execution it says:
Invalid object name 'tbl#Month#Year'
You should create dynamic sql on this.
ALTER PROCEDURE GetReportAsOf
(
#Month varchar(15),
#Year varchar(15)
)
AS
BEGIN
DECLARE #SQLQuery AS NVARCHAR(500)
SET #SQLQuery = 'SELECT * FROM tbl' + #Month + #Year
EXECUTE(#SQLQuery)
RETURN
END
Related
Create Function fnRMatrixColorGet1(
#RMID varchar(20)
)
returns varchar(100)
as
begin
EXEC (N'SELECT ' + 'C'+#RMID + ' FROM vwemployeeget where empid='+#RMID)
return
end
As Gordon wrote in the comments, user defined functions in SQL Server can't execute dynamic SQL.
From Create User-defined Functions:
User-defined functions cannot make use of dynamic SQL or temp tables. Table variables are allowed.
However, you can create a stored procedure to do that:
CREATE PROCEDURE stpRMatrixColorGet1
(
#RMID varchar(20)
#MatrixColor varchar(100) OUTPUT
)
AS
DECLARE #Sql nvarchar(4000),
#Column sysname = N'C' + #RMID;
-- White list column name since it can't be parameterized
IF EXISTS
(
SELECT 1
FROM Information_Schema.Columns
WHERE Table_Name = 'vwemployeeget'
AND Column_Name = #Column
)
BEGIN
SET #SQL = N'SELECT #MatrixColor = QUOTENAME('+ #Column +') FROM vwemployeeget where empid = #RMID'
-- Safely execute dynamic SQL using sp_ExecuteSql
EXEC sp_ExecuteSql
#Sql,
N'#RMID varchar(20), #MatrixColor varchar(100) OUTPUT',
#RMID,
#MatrixColor OUTPUT
END
alter PROCEDURE [dbo].[DisplayFinancialColumn]
(
#sectorid smallint
)
AS
BEGIN
SET NOCOUNT ON;
declare #sectorid_vc varchar(5)
set #sectorid_vc = REPLACE(#sectorid,',',''',''')
DECLARE #listStr varchar(MAX) = (select [SectorFinancialType_Desc] + ',' from SectorFinancialTypes where CONVERT(varchar(300), SectorFinancialType_ID) in (#sectorid_vc) for xml path(''))
DECLARE #query varchar(MAX) = 'SELECT ' + LEFT(#listStr, LEN(#listStr)-1) + ' FROM [dbo].[Financials] where project_id = ''1096'' '
execute(#query)
END
GO
But I encounter
Error converting data type varchar to smallint.
But I have converted the smallint to varchar format, so why there is still such an error?
The Problem is the first line of code in your procedure:
SET #sectorid = REPLACE(#sectorid,',',''',''')
will not convert #sectorid to varchar! You define #sectorid as SMALLINT parameter so #sectorid will never become a varchar variable. Change the type of your parameter or do something like that in your procedure instead:
declare #sectorid_vc nvarchar(5)
set #sectorid_vc = REPLACE(#sectorid,',',''',''')
this will do the trick i think.
set your query like below: Here you have change #sectorid to VARCHAR(MAX)
ALTER PROCEDURE [dbo].[DisplayFinancialColumn]
(
#sectorid VARCHAR(MAX)
)
AS
BEGIN
//write your procedure code here
END
GO
let me know, is this works for you ?
Try this to convert:
REPLACE(CONVERT(VARCHAR(MAX),#sectorID),',',''',''')
Below is my procedure
create proc abc -- 'all','18','18','12/12/2015','','','inactive'
#JoinedDate varchar(100),
#LastLogin varchar(100),
#Location varchar(100),
#Status varchar(50)
as
declare #WhereCondition varchar(1000)
set #WhereCondition=' '
if #LastLogin !=''
set #WhereCondition= ' and u.UpdatedDate>=' + CAST(#LastLogin as datetime)
exec('select * from tableName where' + #WhereCondition)
When I am passing the parameter LastLogin it is giving me error as below:
Conversion failed when converting date and/or time from character string.
First of all capture the data in correct data type, If you are expecting a datetime value use the datetime data type for your variable.
Dont get values in varchar and then try to convert them to datetime(poor practice) , Also use parameterised dynamic sql do not concatenate variables into your dynamic sql (open doors for sql injection).
see below:
create proc abc -- 'all','18','18','12/12/2015','','','inactive'
#JoinedDate datetime,
#LastLogin datetime,
#Location varchar(100),
#Status varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'select * from tableName where 1 = 1 '
+ CASE WHEN #LastLogin <> ''
THEN N' AND UpdatedDate >= #LastLogin' ELSE N'' END
Exec sp_executesql #Sql
,N'#LastLogin datetime'
,#LastLogin
END
You can't concatenate a Datetime datatype with a string.
EDITED:
Try this:
set #WhereCondition= ' and u.UpdatedDate>=CAST(''' + #LastLogin + ''' AS datetime)'
I got the solution, it is possible to pass datetime as varchar paramter to dynamic sql and convert it to datetime dynamically-
Below is the way -
set #WhereCondition= ' and u.UpdatedDate>=convert(datetime,''' + #LastLogin + ''', 110)'
Is there any way to pass a tsql function a database name so it can perform selects on that database
ALTER function [dbo].[getemailjcp]
(
#DB_Name varchar(100)
)
Returns varchar(4000)
AS
BEGIN
DECLARE #out varchar (4000);
DECLARE #in varchar (1000);
Set #out =
(select substring
((select ';' + e.email from
(SELECT DISTINCT ISNULL(U.nvarchar4, 'NA') as email
FROM [#DB_Name].dbo.Lists ...
In order to create dynamic SQL statement you should store procedure. For example:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+#DatabaseName+'].[dbo].[SourceTable]'
EXECUTE sp_executesql #DynamicSQLStatement,#ParmDefinition,#FirstID=#FirstID OUTPUT
SELECT #FirstID
In this example:
#DatabaseName is the passed as parameter to your procedure.
#FirstID is output parameter - this value might be return from your procedure.
Here you can find more information about "sp_executesql":
http://msdn.microsoft.com/en-us/library/ms188001.aspx
a better solution might be to replace "#DatabaseName" (a char variable)with:
"DB_NAME(<#DBId>)".
You can then continue to pass in the db names, but 1st converting them to IDs in the fcn. Also kinda resolves the contradiction of building a SQL stmt w/ a char variable in it, if using "sp_executesql" to help guard against SQL injection ("DB_NAME()" isn't a variable/can't be substituted).
So you'd have this:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(500)
DECLARE #FirstID BIGINT
DECLARE #DBId INT
SET #DBId = DB_ID(#Db_Name) --raise the proper security/robustness** concern if this doesn't resolve.
SET #ParmDefinition = N'#FirstID BIGINT OUTPUT'
SET #DynamicSQLStatement=N' SELECT #FirstID=MAX(ID) FROM ['+DB_NAME(#DBId)+'].[dbo].[SourceTable]'
if i want to write a procedure like below, is there some other way that,
to avoid using concatenate SQL statement, i am just afraid, if the input is too long, exceed the limit of max varchar, the code will have big problem.
Thanks
CREATE PROCEDURE UPDATE_ALL_STATUS
#IDs varchar(MAX) = null,
#status int = null
AS
BEGIN
IF #IDs is null
BEGIN
RETURN
END
DECLARE #SQL VARCHAR(MAX)
SET #SQL = 'UPDATE mytable SET status = ' + #status + ' WHERE id in (' + #IDs + ')'
EXECUTE #SQL
END
Instead of dynamic SQL (which is also vulnerable to SQL Injection Attacks) and passing in a VARCHAR(MAX), consider using Table Valued Parameters:
-- Creates the TVP type - only needed once!
CREATE TYPE IntegerTableType AS TABLE
( Identities INT );
GO
CREATE PROCEDURE UPDATE_ALL_STATUS
#IDs IntegerTableType READONLY,
#status int = null
AS
BEGIN
UPDATE mytable
SET status = #status
WHERE id IN
(SELECT Identities FROM #IDs)
END
This MSDN article shows how to call these from your .NET code.