Need for two level reference in T-SQL - sql

By using the dynamic SQL, I created a variable name like this:
set #tempresultStore = 'Temp'+#colVar
Now, #tempresultstore has the value 'TempMiddleName', then I declared this variable named TempMiddleName and assigned the value in the same line in dynamic sql query and executed.
The code is as follows :(Scroll down to code line with comment to follow where the problem is)
CREATE Procedure OutputProcedure
#LastNameFromUser nvarchar(20) = null,
#LastNameFromTable nvarchar(20),
#MiddleNameFromUser nvarchar(20) = null,
#MiddleNameFromTable nvarchar(20) = null,
#CityFromUser nvarchar(20) = null,
#CityFromTable nvarchar(20) = null,
#Percentage int out
AS
BEGIN
SELECT #MiddleNameFromTable AS'middlename'
select #LastNameFromTable as 'LASTNAMEFROMTABLE'
select #LastNameFromUser as 'LASTNAMEFROMUser'
select 'OUTPUTPROCEDURECALLED'
declare #maxvalue int , #finalpercentage int = 0
DECLARE #variableTable TABLE
(
idx int identity(1,1),
matchvalue nvarchar(15)
)
INSERT INTO #variableTable(matchvalue) values ('MiddleName')
INSERT INTO #variableTable(matchvalue) values ('LastName')
INSERT INTO #variableTable(matchvalue) values ('City')
SELECT * FROM #variableTable
DECLARE #counter int
declare #sql nvarchar(100)
declare #sql2 nvarchar(25), #finalResult nvarchar(100)
set #finalResult = 0;
declare #sql3 nvarchar(300), #sql4 nvarchar(15), #tempresultStore nvarchar(20), #temp int, #temp2 int, #average int
DECLARE #ParmeterDefinition nvarchar(500);
set #ParmeterDefinition =
N'#LastNameFromUsnvarchar(20),
#LastNameFromTab nvarchar(20),
#MiddleNameFromUs nvarchar(20),
#MiddleNameFromTab nvarchar(20),
#CityFromUs nvarchar(20),
#CityFromTab nvarchar(20),
#Percent int out'
SET #counter = 1
SELECT #maxvalue = (SELECT MAX(idx) FROM #variableTable)
select #maxvalue as 'MAXVALUE'
WHILE(#counter < #maxvalue)
BEGIN
DECLARE #colVar nvarchar(15)
SELECT #colVar = matchvalue FROM #variableTable WHERE idx = #counter
set #tempresultStore = 'Temp'+#colVar --here
SELECT #tempresultStore AS 'FINALCUTPART'
select 'JUSTBEFORSQL'
set #sql3 = 'declare #Temp' + #colVar + ' int = dbo.[Match' + #colVar + '](' + #colVar + 'FromUser,' + #colVar + 'FromTable, 0)'
select #sql3 as 'check sql query formed'
EXEC sp_executesql #sql3,
#ParmeterDefinition,
#LastNameFromUs = #LastNameFromUser,
#LastNameFromTab = #LastNameFromTable,
#MiddleNameFromUs = #MiddleNameFromUser,
#MiddleNameFromTab = #MiddleNameFromTable,
#CityFromUs = #CityFromUser,
#CityFromTab = #CityFromTable,
#Percent = #Percentage out
select #Percentage AS 'PERCENTRETRIVED'
set #finalResult = #finalResult + #Percentage /*here #Percentage always remains 0. It is the value returned by the UDF called by the dynamic SQL above.The function does return the value but probably I fail to store it correctly.*/
select #finalResult as 'SUM'
SET #counter = #counter + 1
select #counter as 'COUNTERVALUE'
END
set #finalpercentage = #finalResult/#maxvalue
SELECT #finalpercentage AS 'FINALRESULT'
RETURN
END
Go
How do I access the int value stored in variable called #TempMIddleName

It should work with output keyword. No need for creating table. I don't know but your code is not correct. You have output parameter #Percent and assign value of function to #TempMiddleName, then you should have not a #Percent as Output but #TempMiddleName.
You get dynamic SQL
declare #TempMiddleName int = dbo.[MatchMiddleName](MiddleNameFromUser,MiddleNameFromTable, 0)
I had answered you once, that you miss # before your variables.
Also you have provided variable #Percent(and others as well) for dynamic query, but you don't assign any value to it. Try changing
SET #sql3 = 'declare #Temp' + #colVar + ' int = dbo.[Match' + #colVar + '](' + #colVar + 'FromUser,' + #colVar + 'FromTable, 0)'
to
SET #sql3 = 'select #Percent = 1'
and you will see that 1 is returned as supposed to.
Also you have error here. Split first parameter from its type
set #ParmeterDefinition =
N'#LastNameFromUsnvarchar(20),
set #ParmeterDefinition =
N'#LastNameFromUs nvarchar(20),

You would need to dynamically create a temporary table, and access it's value by selecting the top 1 value from it. Something like the following;
CREATE TABLE #ResultValue (Value Varchar(200))
DECLARE #DynamicSql NVarchar(MAX) = ''
SELECT #DynamicSql = '
DECLARE #tempresultStore Varchar(50)
DECLARE #colVar Varchar(50) = ''MiddleName''
SET #tempresultStore = ''Temp'' + #colVar
insert into #ResultValue
select #tempresultStore
'
EXEC sp_sqlexec #DynamicSql
SELECT * FROM #ResultValue
DROP TABLE #ResultValue
If you paste all your code we might try to amend it for you.

Related

SQL Server error: An expression of non-boolean type specified in a context where a condition is expected, near ')'

I am trying to create a unique id based on the given input and the count of the table.
However, I am getting the required output but when using it in program it returns a error stating
SQL Server - An expression of non-boolean type specified in a context
where a condition is expected, near ')'
Here is my code
ALTER PROCEDURE [dbo].[GetpaymentCode]
(
#O_SupplierCode varchar(50) output,
#O_ErrorDesc varchar(100)output
)
AS
BEGIN
declare #Error int
declare #Count char(10)
declare #Qry nvarchar(4000)
declare #QryCondition nvarchar(1000)
DECLARE #Financial_Year VARCHAR(20)
DECLARE #Year VARCHAR(4)
DECLARE #TotalMax VARCHAR(10)
DECLARE #YearMax VARCHAR(10)
DECLARE #TotalCnt INT
DECLARE #YearCnt INT
DECLARE #BillPrefix VARCHAR(5)
DECLARE #BillId VARCHAR(20)
SET #Financial_Year = #O_SupplierCode
SET #BillPrefix = 'P'+SUBSTRING(#Financial_Year,8,2)
PRINT #BillPrefix
TRUNCATE TABLE Tbl_Max
DECLARE #Query NVARCHAR(MAX)
SET #Query = N'WITH T0 AS
(
SELECT MAX(Payment_Id) TotalMax FROM payment_master WHERE Payment_Id
)
, T1 AS
(
SELECT MAX(Payment_Id) YearMax FROM payment_master WHERE Payment_id LIKE ''' + #BillPrefix + '%''
)
INSERT INTO Tbl_Max
SELECT * FROM T0 INNER JOIN T1 ON 1 = 1'
PRINT #Query
EXEC sp_executesql #Query
SELECT #TotalMax = ISNULL(TotalMax,'0'), #YearMax = ISNULL(YearMax,'0') FROM Tbl_Max
IF(#TotalMax != '0')
BEGIN
SET #TotalCnt = CONVERT(INT, SUBSTRING(#TotalMax,6,3)) + 1
END
ELSE
BEGIN
SET #TotalCnt = 1
END
IF(#YearMax != '0')
BEGIN
SET #YearCnt = CONVERT(INT, SUBSTRING(#YearMax,4,2)) + 1
END
ELSE
BEGIN
SET #YearCnt = 1
END
--PRINT #TotalCnt
--PRINT #YearCnt
SET #BillId = #BillPrefix + replace(str(#YearCnt,2),' ','0') + replace(str(#TotalCnt,3),' ','0')
SELECT #BIllId AS BILL_CODE
end
In CTE command in T0 section you have written incomplete where condition.
SELECT MAX(Payment_Id) TotalMax FROM payment_master WHERE Payment_Id =?

Getting OUTPUT from Nested Dynamic SQL with a Remote Server

I am trying to execute some logic on a remote server using dynamic SQL, but when I set the dynamic SQL and try to call it nothing happens.. If I call the execution without making the execution dynamic it works without issue.
Not sure if what I am trying to do is allowed when passing OUTPUT values but figured I would see if anyone has any thoughts
DECLARE #sqlserver NVARCHAR(MAX) = ''
DECLARE #DBName NVARCHAR(MAX) = ''
DECLARE #parms NVARCHAR(MAX) = N'#output INT OUT', #output INT, #sql NVARCHAR(MAX) = '
;WITH DuplicateStatusCodes AS (
SELECT CodeTypeID FROM EDDSDBO.Code WHERE Name = ''Master'' OR Name = ''Unique'' OR Name = ''Duplicate''
)
SELECT ROW_NUMBER() OVER (ORDER BY CodeTypeID) RN, CodeTypeID INTO #temp
FROM DuplicateStatusCodes
GROUP BY CodeTypeID
HAVING COUNT(CodeTypeID) = 3
DECLARE #count INT = (SELECT COUNT(1) FROM #temp)
DECLARE #ctr INT = 1;
IF #count > 0
BEGIN
WHILE #ctr <= #count BEGIN
DECLARE #parms NVARCHAR(MAX) = N''#inneroutput INT OUT'';
DECLARE #inneroutput INT
DECLARE #codeartifact INT = (SELECT CodeTypeID FROM #temp WHERE RN <= 1 * #ctr and RN > 1 * (#ctr - 1))
DECLARE #duplicatestatuscheck NVARCHAR(MAX) = ''SELECT #inneroutput = COUNT(1) FROM eddsdbo.codeartifact_''+CAST(#codeartifact AS VARCHAR)+''''
EXEC sys.sp_executesql #duplicatestatuscheck, #parms, #inneroutput OUT
SELECT #output = #inneroutput
IF #inneroutput > 0
BREAK;
SET #ctr = #ctr + 1;
END
END
ELSE
BEGIN
SELECT #output = ''0''
END
'
DECLARE #linksql NVARCHAR(MAX) = '
DECLARE #sql NVARCHAR(MAX)
DECLARE #parms NVARCHAR(MAX) = N''#output INT OUT''
EXEC '+QUOTENAME(#sqlserver)+'.'+QUOTENAME(#DBName)+'.sys.sp_executesql #sql, #parms, #output = #output OUT'
--This does not work
EXEC sp_executesql #linksql, #parms, #output = #output
PRINT #output
--This works fine
EXEC [RemoteServerName].[DatabaseName].sys.sp_executesql #sql, #parms, #output = #output OUT ```
Appreciate any help
you would need to use OPENROWSET. Something like this:
DECLARE #ServerName VARCHAR(255) = '...'
,#DatabaseName VARCHAR(255) = '...'
,#Pwd VARCHAR(255) = '...'
,#UID VARCHAR(255) = '...'
,#Name VARCHAR(255) = 'Master'
DECLARE #connect varchar(max) = '''Server=' + #ServerName + ';database=' + #DatabaseName + ';Uid=' + #UID + ';Pwd=' + #Pwd + ';'''
declare #sqlstring varchar(max) = 'SET ANSI_NULLS OFF; SET ANSI_WARNINGS OFF;
SELECT CodeTypeID FROM EDDSDBO.Code WHERE Name = ''''' + #Name + ''''' '
declare #TheExecutableStr varchar(max) = '
SELECT *
FROM OPENROWSET(''SQLNCLI'', ' + #connect + ',
''' + #sqlstring + ''')'
SELECT #TheExecutableStr
--EXEC(#TheExecutableStr)
Please note you have to count single quote very diligently, hence SELECT #TheExecutableStr. It is for debugging purposes. You can view the query to be executed and actually copy/paste and execute before uncommenting last statement.
Hope it helps.
just noticed, you have sys.sp_executesql within sys.sp_executesql which might be problematic. you might need to find a way to refactor the code.

Insert into a table multiple variables using dynamic query

I'm trying to use an interim dynamic query to insert data into a table variable and then use that table variable to execute a final query. I have an error "must declare scalar variable "
DECLARE #t TABLE ( TableName NVARCHAR(250) )
declare #i as int = 1, #A_1 NVARCHAR(250) ='ABC', #A_2 NVARCHAR(250) ='XYZ', #A_3 NVARCHAR(250) = 'AEI';
WHILE (#i <= 3)
BEGIN
DECLARE #q NVARCHAR(MAX) = ' DECLARE #t TABLE ( TableName NVARCHAR(250) )
insert into #t
select #A_' + CAST(#i AS VARCHAR) + ' as field
from #t
'
INSERT INTO #t
EXEC(#q)
SET #i = #i + 1
END
SELECT * FROM #t
the expected result should be:
TableName
ABC
XYZ
AEI
variable #A_X could have 1 or 15 variables (#A_1, #A_2....#A15)
Instead of table variable you can use temp table. Check this out:
DROP TABLE #TableList
GO
CREATE TABLE #TableList (
A_1 NVARCHAR(250)
,A_2 NVARCHAR(250)
,A_3 NVARCHAR(250)
)
DROP TABLE #Result
GO
CREATE TABLE #Result (
TableName NVARCHAR(250)
)
INSERT INTO #TableList
VALUES('ABC','XYZ','AEI')
DECLARE #q NVARCHAR(MAX)='';
DECLARE #i as int = 1
WHILE (#i <= 3)
BEGIN
SET #q = #q+CHAR(13)+'
INSERT INTO #Result(TableName)
SELECT A_' + CAST(#i AS VARCHAR) + ' from #TableList;'
SET #i = #i + 1
END
EXEC sp_executesql #q
PRINT (#q)
SELECT *
FROM #Result

Adding two dynamic variable and store it in INT type column

I've two dynamic variable ...
declare #count nvarchar(max)
declare #totalCount int
set #count = ' ( SELECT COUNT(*) FROM '+ #Table +' where [Name] = '''+ CAST(#Name as nvarchar(max)) +''' ) '
set #totalCount = CAST(CAST(#count as nvarchar(max)) + CAST(#Qty as nvarchar(max)) as INT);
I'm getting an error
conversion failed when converting the nvarchar value to datatype int....
then I need to store #totalCount in [TotalCount] column of type INT ...PLease help
he variable table name requires using dynamic SQL. The example below assigns the computed value to the #totalCount variable using a parameterized query output parameter.
DECLARE
#totalCount int
, #Qty int = 5
, #Sql nvarchar(MAX)
, #Table sysname = 'Table'
, #Name nvarchar(MAX) = N'Name';
SET #Sql = N'SELECT #totalCount = COUNT(*) + #Qty
FROM ' + QUOTENAME(#Table) + ' where [Name] = #Name;';
EXEC sp_executesql
#Sql
, N'#Name nvarchar(MAX), #Qty int, #totalCount int OUTPUT'
, #Name = #Name
, #Qty = #Qty
, #totalCount = #totalCount OUT;

how to use print statement when you have more than 8000 characters

I have a procedure and the code looks like this:
ALTER PROCEDURE [dbo].[usp_Gen_Proc]
(#ID INT )
AS
Begin
IF OBJECT_ID('tempdb..#procedure') IS NOT NULL
DROP TABLE #procedure
DECLARE #Name VARCHAR(100)
DECLARE #SQL VARCHAR(MAX)
DECLARE #Script VARCHAR(MAX),
#DB VARCHAR(100),
#Schema VARCHAR(100),
#Proc_Name VARCHAR(max),
#BR CHAR(2)
SET #BR = CHAR(10)+ CHAR(13)
SET NOCOUNT ON
SELECT #Name= [Procedure_Name] FROM dbo.datsource
WHERE [ID] = #ID
SELECT #Proc_Name = PARSENAME(#Name, 1) ,
#Schema = PARSENAME(#Name, 2) ,
#DB = PARSENAME(#Name, 3)
CREATE TABLE #procedure ( script VARCHAR(MAX) )
EXEC('INSERT INTO #procedure(script)
SELECT definition FROM '+#DB+'.sys.all_sql_modules sq
WHERE sq.object_id = (SELECT object_id FROM '+#DB+'.sys.objects
WHERE type = ''P'' AND name = '''+#Proc_Name+''' ) ')
SET #Script = ' Use ' +#BR +#DB + #BR+ ' Go' +#BR
SELECT #Script = #Script+script
FROM #procedure
DECLARE #pos INT =7500
SELECT #pos=CHARINDEX(CHAR(13)+CHAR(10),#script,#pos)
PRINT SUBSTRING(#Script,1,#Pos)
DECLARE #Counter INT
SET #Counter = 0
DECLARE #TotalPrints INT
SET #TotalPrints = ( LEN(#script) / 8000 )
WHILE #Counter < #TotalPrints
BEGIN
SET #Counter = #Counter + 1
PRINT SUBSTRING(#script,#pos+1,7500)
SET #pos = #pos+7500
SELECT #pos=CHARINDEX(CHAR(13)+CHAR(10),#script,#pos)
END
END
Basically what the procedure is doing it just prints the procedure code. But the problem I am facing is when I am printing it i am loosing some characters in between.
Can anyone let me know where I am going wrong?
Why do you want to print ?
Why you don't do a select with the script, put it in xml if you want to see everything.
Select Convert(xml, #script)
EDIT :
between you don't need to do +1
PRINT SUBSTRING(#script,#pos,7500)