How to use dynamic SQL string? - sql-server

Instead of this:
-- Method call
SELECT #FunctionResult = DWH_Staging.adm.SalesPlanExists(#Year, #Month, #CountryID, #Type)
I want to use something like this:
DECLARE
#TestedDatabase = 'DWH_Staging',
#TestedSchema = 'adm',
#TestedObject = 'SalesPlanExists'
DECLARE #sql NVARHCAR(4000) = '#TestedDatabase+'.'+#TestedSchema+'.'+#TestedObject (#Year, #Month, #CountryID, #Type)'
-- Method call
SELECT #FunctionResult = #sql
Hints would be appreciated.

Below is a parameterized SQL example, guessing at your data types:
DECLARE
#TestedDatabase sysname = 'DWH_Staging'
,#TestedSchema sysname = 'adm'
,#TestedObject sysname = 'SalesPlanExists'
,#FunctionResult int
,#Year int
,#Month int
,#CountryID int
,#Type int;
DECLARE #sql nvarchar(MAX) = N'SELECT #FunctionResult = '
+QUOTENAME(#TestedDatabase)
+N'.'
+QUOTENAME(#TestedSchema)
+N'.'
+QUOTENAME(#TestedObject)
+ N'(#Year, #Month, #CountryID, #Type)';
SELECT #sql
-- Method call
EXECUTE sp_executesql
#sql
,N'#FunctionResult int OUTPUT
,#Year int
,#Month int
,#CountryID int
,#Type int'
,#FunctionResult = #FunctionResult OUTPUT
,#Year = #Year
,#Month = #Month
,#CountryID = #CountryID
,#Type = #Type;

What you can do is to set a template for the query, and replace the string while execution:
DECLARE #sql NVARHCAR(4000) = '{DATABASENAME}.{SCHEMANAME}.{OBJECTNAME} (' + #Year + ', ' + #Month + ', ' + #CountryID + ', ' + #Type + ')'
SET #SQL_SCRIPT = REPLACE(#sql, '{DATABASENAME}', #DBNAME)
and then, execute it:
EXECUTE (#SQL_SCRIPT)

Related

Error while running a stored procedure having where condition dynamically generated

I have select statement that has where condition generated based on incoming parameter. `
DECLARE #ApplicationNumber int = 0;
DECLARE #AccountReferenceNumber int= 4820829;
DECLARE #SecurityNumber int = 1;
DECLARE #StreetAddress1 varchar(250)= '15 Prosper Court';
DECLARE #StreetAddress2 varchar(250) = NULL;
DECLARE #Suburb varchar(250)= 'wong';
DECLARE #State varchar(250) = NULL;
DECLARE #Postcode varchar(250) = '1245';
DECLARE #IsDeleted bit = 0;
DECLARE #IsClass bit = 1;
declare #BaseQuery nvarchar(max) = ' ';
IF #IsClass = 1
DECLARE #tableid INT = 0;
DECLARE #WhereClause VARCHAR(max) = '';
--SET #WhereClause = #AccountReferenceNumber ;
IF #StreetAddress1 IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND StreetAddress1 = '+ #StreetAddress1;
END
IF #StreetAddress2 IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause
+ ' AND StreetAddress2 = ' + #StreetAddress2;
END
IF #Suburb IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Suburb= ' + #Suburb;
END
IF #Postcode IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Postcode= '+ #Postcode;
END
SET #BaseQuery = 'SELECT LoanSecurityId FROM LoanSecurity WHERE AccountReferenceNumber = #AccountReferenceNumber'
+ #WhereClause
EXEC sp_executesql #BaseQuery, N'#AccountReferenceNumber int', #AccountReferenceNumber
i executed the statement and following errors is coming up
Incorrect syntax near 'Prosper'..
Can some one shed a light what am i missing in the following
After the suggetion and changes done , following is the select statment available at execute
SELECT LoanSecurityId FROM LoanSecurity WHERE AccountReferenceNumber = #AccountReferenceNumber AND StreetAddress1 = 15 Prosper Court AND Suburb= WODONGA AND Postcode= 1245
The string ins the whereclause is not coming proper
Your can't just append a string to your query where clause. You need to use Dynamic SQL
SET #sql = 'SELECT LoanSecurityId FROM LoanSecurity WHERE AccountReferenceNumber = #AccountReferenceNumber'
+ #WhereClause
EXEC sp_executesql #sql, N'#AccountReferenceNumber int', #AccountReferenceNumber
when you have int value you should use cast(#Param as nvarchar(n))
for example :
IF #Postcode IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Postcode =cast(#Postcode as nvarchar(50)) ';
END
After adjusting the input string and following code change, it is working
DECLARE #ApplicationNumber int = 0;
DECLARE #AccountReferenceNumber int;
set #AccountReferenceNumber= 820829;
DECLARE #SecurityNumber int = 1;
DECLARE #StreetAddress1 varchar(250)= '''15 prprpCourt''';
DECLARE #StreetAddress2 varchar(250) = NULL;
DECLARE #Suburb varchar(250)= '''tester''';
DECLARE #State varchar(250) = NULL;
DECLARE #Postcode varchar(250) = '''5589''';
DECLARE #IsDeleted bit = 0;
DECLARE #IsClass bit = 1;
declare #BaseQuery nvarchar(max) = N'SELECT LoanSecurityId
FROM LoanSecurity WHERE AccountReferenceNumber = ';
IF #IsClass = 1
DECLARE #tableid INT = 0;
DECLARE #WhereClause VARCHAR(max) = '';
SET #WhereClause = #AccountReferenceNumber ;
IF #StreetAddress1 IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND StreetAddress1 = ' + #StreetAddress1;
END
IF #StreetAddress2 IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause
+ ' AND StreetAddress2 = ' + #StreetAddress2;
END
IF #Suburb IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Suburb= ' + #Suburb;
END
IF #Postcode IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' AND Postcode= ' + #Postcode;
END
SET #BaseQuery = #BaseQuery + #WhereClause;
-- SELECT #BaseQuery
execute sp_executesql #BaseQuery;
You are using SQL wrong if you are building your SQL statements dynamically. There are only rare edge cases where that is ever required, usually when the table or view name is unknown at the time of execution.
You can perform your query without constructing the SQL Statement Dynamically using ISNULL to your advantage.
DECLARE #ApplicationNumber int = 0;
DECLARE #AccountReferenceNumber int = 820829;
DECLARE #SecurityNumber int = 1;
DECLARE #StreetAddress1 varchar(250) = '15 prprpCourt';
DECLARE #StreetAddress2 varchar(250) = NULL;
DECLARE #Suburb varchar(250)= 'tester';
DECLARE #State varchar(250) = NULL;
DECLARE #Postcode varchar(250) = '5589';
DECLARE #IsDeleted bit = 0;
DECLARE #IsClass bit = 1;
-- Not sure what this is for ...
IF #IsClass = 1
DECLARE #tableid INT = 0;
SELECT
LoanSecurityId
FROM
LoanSecurity
WHERE
AccountReferenceNumber = #AccountReferenceNumber AND
StreetAddress1 = ISNULL(#StreetAddress1, StreetAddress1) AND
StreetAddress2 = ISNULL(#StreetAddress2, StreetAddress2) AND
Suburb = ISNULL(#Suburb, Suburb) AND
Postcode = ISNULL(#Postcode, Postcode)
P.S. ... Your execution performance will generally be much better if you use native SQL instead of creating a SQL statement on the fly.

Using table type param in SQL server stored procedure

I use table type param (#listdraftIds) and split data in table to compare with data in DB but the error is as below. Help me, thank you.
CREATE OR ALTER PROCEDURE [dbo].[sp_sel_contract]
(
#listDraftId nvarchar(max),
#Page int,
#PageNumber int,
#TotalRecord int OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
BEGIN
DECLARE #listdraftIds TABLE (draftIds nvarchar(max))
INSERT INTO #listdraftIds VALUES(#listDraftId)
DECLARE #sql varchar(MAX)
SET #sql= ' ALTER DATABASE '+ quotename(db_name()) + ' SET COMPATIBILITY_LEVEL = 130 ';
EXEC(#sql)
END
DECLARE #query NVARCHAR(MAX)
DECLARE #newquery NVARCHAR(MAX)
DECLARE #RowIndex int
SET #RowIndex = (#Page-1) * #PageNumber
SET #query = ''
SET #query = #query + ' SELECT DISTINCT'
SET #query = #query + ' [d].[draft_id], '
...
SET #query = #query + 'WHERE '
SET #query = #query + ' [d].[del_flg] = ''FALSE'''
SET #query = #query + 'AND '
SET #query = #query + ' [d].[draft_id] '
SET #query = #query + 'IN ('
SET #query = #query + ' SELECT DISTINCT '
SET #query = #query + ' value AS draft_id '
SET #query = #query + 'FROM '
SET #query = #query + ' #listdraftIds '
SET #query = #query + 'CROSS APPLY STRING_SPLIT(draftIds, '','') '
SET #query = #query + 'WHERE '
SET #query = #query + ' RTRIM(value) <> '''' )'
PRINT #query
SET #newquery = ' SET #TotalRecord = (SELECT COUNT(*) FROM (' + #query +') AS t) '
SET #newquery = #newquery + ' ORDER BY '
SET #newquery = #newquery + ' [draft_date] DESC, [d].[draft_id] DESC, [g].[detail_no] ASC'
SET #newquery = #newquery + ' OFFSET #RowIndex ROWS FETCH NEXT #PageNumber ROWS ONLY'
EXECUTE sp_executesql #newquery,
#listDraftId = #listDraftId,
#RowIndex = #RowIndex,
#PageNumber = #PageNumber,
#TotalRecord = #TotalRecord OUTPUT
END
Then Exec proc:
DECLARE #return_value int,
#TotalRecord int
EXEC #return_value = [dbo].[sp_sel_draft_condition_api1]
#listDraftId = N'123,345',
#Page = 1,
#PageNumber = 20,
#TotalRecord = #TotalRecord OUTPUT
SELECT #TotalRecord as N'#TotalRecord'
SELECT 'Return Value' = #return_value
GO
Error:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '30302'.
Msg 1087, Level 15, State 2, Line 3
Must declare the table variable "#listdraftIds".
Msg 137, Level 15, State 2, Line 3
Must declare the scalar variable "#PageNumber".
few issue here with the stored procedure
First, sp_executesql execute in its own context. So variable declared outside of it is not recognized. Which means, if you need to use a variable, you need to pass it into sp_executesql.
Your sp_executesql statement does not defined any variable
it should be
EXECUTE sp_executesql #newquery,
N'#RowIndex int, #PageNumber int, #TotalRecord int OUTPUT',
#RowIndex = #RowIndex,
#PageNumber = #PageNumber,
#TotalRecord = #TotalRecord OUTPUT
Note that I didn't include the #listDraftId. That is because you can't pass a table variable into sp_executesql. One alternative is to use a temp table
So in your sp_sel_contract
create table #listdraftId ( draftIds nvarchar(max) )
And then you can reference the temp table #listdraftId in you dynamic query
Actually looking at your dynamic query, you don't required a table variable or temp table. You only have one value of #listDraftId that is pass into sp_sel_contract and then it is pass into the dynamic query. So you can pass that variable directly into the dynamic query. Example :
EXECUTE sp_executesql #newquery,
N'#listDraftId nvarchar(max), #RowIndex int, #PageNumber int, #TotalRecord int OUTPUT',
#listDraftId = #listDraftId,
#RowIndex = #RowIndex,
#PageNumber = #PageNumber,
#TotalRecord = #TotalRecord OUTPUT
EDIT :
Now i have a closer look at your dynamic query ? I don't see a need to use dynamic query at all. You can achieve what you want with normal query

Update a declared tabled dynamic column name

I am running a SQL loop to update a declared table. Please have a look at the following
DECLARE #tblResults TABLE ( [idx] INT IDENTITY(0,1)
,[cityCode] VARCHAR(3)
,[month_1_perc] INT
,[month_2_perc] INT
,[month_3_perc] INT
,[month_4_perc] INT
,[month_5_perc] INT
,[month_6_perc] INT
,[month_7_perc] INT
,[month_8_perc] INT
,[month_9_perc] INT
,[month_10_perc] INT
,[month_11_perc] INT
,[month_12_perc] INT)
loop will start here
DECLARE #colName VARCHAR(15)
DECLARE #sqlExec VARCHAR(500) = CONACT('UPDATE #tblResults SET [month_', #colName, '_perc] = 9;
EXECUTE(#sql)
loop
This obviously doesn't work - I am trying to find a work around if any -
Open to suggestions
DECLARE #colName VARCHAR(15)
DECLARE #sqlExec VARCHAR(500)
SET #colName = '1'
SET #sqlExec = 'UPDATE #tblResults SET [month_' + #colName + '_perc] = 9'
EXECUTE( #sqlExec)
I am a bit confused with your request, but if you really want to use a loop
declare #i int = 1;
declare #sqlUpdate nvarchar(max) = 'UPDATE tblResults SET ';
declare #sql;
while #i <= 12
BEGIN
set #sql = #sqlUpdate + '[month_' + cast(#i as nvarchar(5)) + '_perc] = 9;' -- value?
print (#sql)
-- execute (#sql)
set #i = #i + 1;
END
Or you want to set same value to all columns in one go
declare #cols nvarchar(max)
select #cols = STUFF((SELECT ',' + QUOTENAME(col.name) + ' = 9' -- value?
from tempdb.sys.columns col
join tempdb.sys.tables tab on col.object_id = tab.object_id
where tempdb.tab.name = 'tblResults'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #sql nvarchar(max) = 'UPDATE tblResults SET ' + #cols;
print (#sql)
-- execute (#sql)
Note, none of scripts are tested

Passing negative values into stored procedure

I am trying to insert ID values in stored procedure from .net and the int value for ID is inserting negative value in the stored procedure.
But when a negative value is passed its giving me an error incorrect syntax near '*'.
Please help me.
Here is my stored procedure
ALTER PROCEDURE [dbo].[HotlinePlusAdministration_ArticleMigrator]
#Id AS INT,
--#CategoryID AS INT,
--#Title AS Varchar(200),
--#ArticleDate AS datetime,
#DestLinkServer AS VARCHAR(50),
#UserID AS VARCHAR(8),
#ReturnMsg AS VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #Query AS NVARCHAR(4000)
DECLARE #Log AS VARCHAR(8000)
DECLARE #ArticleID as int
DECLARE #NewArticleID as int
DECLARE #ArticleKeyExists as int
DECLARE #Title as varchar(200)
DECLARE #CategoryID as INT
DECLARE #ArticleDate as varchar(30)
DECLARE #ParmDefinition nvarchar(500);
SET XACT_ABORT ON -- Required for nested transaction
BEGIN TRAN
-- Check if ArticleID exists in Destination Server
SET #Query = N' SELECT #ArticleKeyExists = COUNT(*)
FROM ' + #DestLinkServer + '.HL2_61.dbo.Article' + ' where ArticleKey = ' + str(#Id)
SET #ParmDefinition = N' #ID int, #ArticleKeyExists int OUTPUT';
EXECUTE sp_executesql #Query , #ParmDefinition, #ID, #ArticleKeyExists OUTPUT;
--EXECUTE sp_executesql 1234,'BRHLSQL8','BRWSQLDC',#return = retnmsg
IF ##ERROR <> 0
BEGIN
ROLLBACK TRANSACTION
SET #ReturnMsg = #Log + '<span style="color:red;">ERROR: <br></span>'
RETURN -1
END
--Delete existing Articles for select page
set #Query = 'DELETE FROM ' + #DestLinkServer +
'.HL2_61.dbo.Article ' +
'WHERE ArticleKey = ' + CONVERT(VARCHAR, #Id)
--'WHERE CategoryID = ' + CONVERT(VARCHAR, #CategoryID) + ' and Title = ''' + #Title + ''' and ArticleDate = ''' + #ArticleDate + ''''
Print #Query
EXEC(#Query)
When I am executing the code as below I am getting the error.
DECLARE #return_value int,
#ReturnMsg varchar(1000)
EXEC #return_value = [dbo].[Migrator]
#Id = -1591276581,
#DestLinkServer = N'SQLDC',
#UserID = N'10c1',
#ReturnMsg = #ReturnMsg OUTPUT
SELECT #ReturnMsg as N'#ReturnMsg'
SELECT 'Return Value' = #return_value
GO
Please someone help me..
Thanks
When you convert an int to a varchar, you have to specify the size:
Try this:
CONVERT(VARCHAR(50), #Id)
and avoid using str(#Id)

incorrect syntax near '*'

I was trying to execute one of my Stored procedure but i am getting an syntax error and i am unable to understand why.
here is the sproc:
ALTER PROCEDURE [dbo].[HotlinePlusAdministration_ArticleMigrator]
#ArticleKey AS INT,
--#CategoryID AS INT,
--#Title AS Varchar(200),
--#ArticleDate AS datetime,
#DestLinkServer AS VARCHAR(50),
#UserID AS VARCHAR(8),
#ReturnMsg AS VARCHAR(1000) OUTPUT
AS
BEGIN
DECLARE #Query AS NVARCHAR(4000)
DECLARE #Log AS VARCHAR(8000)
DECLARE #ArticleID as int
DECLARE #NewArticleID as int
DECLARE #ArticleKeyExists as int
DECLARE #Title as varchar(200)
DECLARE #CategoryID as INT
DECLARE #ArticleDate as varchar(30)
DECLARE #ParmDefinition nvarchar(500);
SET XACT_ABORT ON -- Required for nested transaction
BEGIN TRAN
-- Check if ArticleID exists in Destination Server
SET #Query = N' SELECT #ArticleKeyExists = COUNT(*)
FROM ' + #DestLinkServer + '.HL2_61.dbo.Article' + ' where ArticleKey = ' + str(#ArticleKey)
SET #ParmDefinition = N'#ArticleKey int, #ArticleKeyExists int OUTPUT';
EXECUTE sp_executesql #Query , #ParmDefinition, #ArticleKey , #ArticleKeyExists OUTPUT;
IF ##ERROR <> 0
BEGIN
ROLLBACK TRANSACTION
SET #ReturnMsg = #Log + '<span style="color:red;">ERROR: <br></span>'
RETURN -1
END
--Delete existing Articles for select page
set #Query = 'DELETE FROM ' + #DestLinkServer +
'.HL2_61.dbo.Article ' +
'WHERE ArticleKey = ' + CONVERT(VARCHAR, #ArticleKey)
--'WHERE CategoryID = ' + CONVERT(VARCHAR, #CategoryID) + ' and Title = ''' + #Title + ''' and ArticleDate = ''' + #ArticleDate + ''''
Print #Query
EXEC(#Query)
when i am trying to execute it i am getting an error here:
SELECT #ArticleKeyExists = COUNT(*)
FROM BRWSQLDC.HL2_61.dbo.Article where ArticleKey = 1591276581
Can some body please help me on this,
Thanks.
SET #ArticleKeyExists = (SELECT COUNT(*) FROM BRWSQLDC.HL2_61.dbo.Article where ArticleKey = 1591276581)

Resources