Why is my stored procedure working fine when executed manually, but not when called from another SP? - sql

I have a stored procedure which performs following steps: it updates a default values table for the software, and just runs a powershell cmdlet which is reload tradeloader defaults
The stored procedure takes a parameter like DefaultValue=ABC, where DefaultValue is the field that needs to be changed, and ABC be the value updated.
Now, this runs perfectly fine, when executed manually, but when I pass it from another stored procedure which does a lot of functions including running some other powershell commands, it fails; in fact, just locks the database and keeps running.
I am new to SQL, so I haven't tried much other than try catch and begin tran, commit tran etc.. but none work
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER Procedure [dbo].[changeDefaultSettings]
(#DefaultChange NVARCHAR(MAX))
AS
BEGIN;
BEGIN TRAN;
SET NOCOUNT ON;
DECLARE #DefaultField NVARCHAR(300)
DECLARE #DefaultValue NVARCHAR(1000)
DECLARE #PSString NVARCHAR(4000)
DECLARE #IPAdd NVARCHAR(50)
DECLARE #Port NVARCHAR(20)
DECLARE #FilePath NVARCHAR(1000)
DECLARE #FileName NVARCHAR(1000)
DECLARE #Hostname NVARCHAR(50)
DECLARE #SQL_Powershell NVARCHAR(4000)
DECLARE #CurrentDerivationRelease NVARCHAR(100)
SET #DefaultField = (SELECT [Item]
FROM Automation.config.fnsplit(#DefaultChange, '=')
WHERE [ID] = 1)
SET #DefaultValue = (SELECT [Item]
FROM Automation.config.fnsplit(#DefaultChange,'=')
WHERE [ID] = 2)
SET #DefaultValue = CONVERT(INT, #DefaultValue)
IF (#DefaultChange = 'Reset')
BEGIN
UPDATE Derivation_Automation.dbo.TradeLoaderSetting
SET iValue = -1
WHERE vc40Name NOT IN ('DefaultTrader', 'DifferentAccountPerAssetClass')
UPDATE Derivation_Automation.dbo.TradeLoaderSetting
SET iValue = (SELECT idsystemuser
FROM Derivation_Automation.dbo.systemuser
WHERE vc30Name = 'Admin')
WHERE vc40Name = 'DefaultTrader'
UPDATE Derivation_Automation.dbo.TradeLoaderSetting
SET iValue = 0
WHERE vc40Name = 'DifferentAccountPerAssetClass'
END
ELSE
BEGIN
UPDATE Derivation_Automation.dbo.TradeLoaderSetting
SET iValue = #DefaultValue
WHERE vc40Name = #DefaultField
End
Set #Hostname = (Select HOST_NAME())
Set #IPAdd = (Select GlobalVariables.VariableValue from Automation.dbo.GlobalVariables where GlobalVariables.VariableName = 'PowerShellIP')
If (#Hostname = 'MU1QA01')
Begin
Set #Port = (Select GlobalVariables.VariableValue from Automation.dbo.GlobalVariables where GlobalVariables.VariableName = 'PowerShellPort1')
End
Else IF (#Hostname = 'MU1QA02')
Begin
Set #Port = (Select GlobalVariables.VariableValue from Automation.dbo.GlobalVariables where GlobalVariables.VariableName = 'PowerShellPort2')
End
Set #FilePath = (Select GlobalVariables.VariableValue from Automation.dbo.GlobalVariables where GlobalVariables.VariableName = 'PowerShellFilePath')
Set #FileName = (Select GlobalVariables.VariableValue from Automation.dbo.GlobalVariables where GlobalVariables.VariableName = 'DefaultChangepowerShellFile')
Set #CurrentDerivationRelease = (Select GlobalVariables.VariableValue from Automation.dbo.GlobalVariables where GlobalVariables.VariableName = 'DerivationRelease')
Set #FilePath = '\\'+#Hostname+'\'+#FilePath
Set #PSString = 'import-module "C:\PROGRA~1\' + #CurrentDerivationRelease + '\DerivationPowershellModuleTradeLoader\Core.PowershellModule.TradeLoader.dll" -Verbose'
+ char(13) + char(10) +'Invoke-ReloadTradeLoaderDefaults -IPAddress ' + #IPAdd + ' -Port ' + #Port
Exec [dbo].[spWriteStringToFile] #PSString,#FilePath,#FileName
Set #FilePath = ''''+#FilePath + '\' + #FileName+''''
Set #SQL_Powershell = 'c:\PROGRA~1\PowerShell\6\pwsh.exe -Command Invoke-Command -ComputerName '+#hostname+ ' -ScriptBlock { c:\PROGRA~1\PowerShell\6\pwsh.exe -File '+#FilePath+ ' }'
Print(#SQL_Powershell)
EXEC master..xp_cmdshell #SQL_Powershell,no_output
WAITFOR DELAY '00:00:2'
SET nocount off;
Commit Tran;
End;

Related

SQL Server output param truncated where it is too long

I have 4 stored procedures.
The following is used to be invoked by C#:
ALTER PROCEDURE [dbo].[sp_retrieveResourceShell]
AS
BEGIN
SET NOCOUNT ON
DECLARE #result NVARCHAR(MAX)
EXEC [dbo].[sp_retrieveResTree]
#pid = NULL,
#ret = #result OUTPUT
***select*** #result
END
These are internal stored procedures:
ALTER PROCEDURE [dbo].[sp_retrieveResTree]
(#pid UNIQUEIDENTIFIER,
#ret NVARCHAR(MAX) OUTPUT)
AS
BEGIN
DECLARE #mdlId UNIQUEIDENTIFIER,
#mdlGroup NVARCHAR(MAX)
DECLARE mdlCursor CURSOR FOR
......
DECLARE #subRet NVARCHAR(MAX),
#viewRet NVARCHAR(MAX)
EXEC [dbo].[sp_retrieveResTree]
#pid = #mdlId,
#ret = #subRet OUTPUT
EXEC dbo.sp_retrieveResView
#mdlId = #mdlId,
#ret = #viewRet OUTPUT
SET #mdlGroup = #mdlGroup + FORMATMESSAGE('{"Id":"%s","Name":"%s","Subs":%s,"Views":%s},'...)
.......
SET #ret = FORMATMESSAGE('[%s]',#mdlGroup)
END
ALTER PROCEDURE [dbo].[sp_retrieveResView]
(#mdlId UNIQUEIDENTIFIER,
#ret NVARCHAR(MAX) OUTPUT)
AS
BEGIN
SET #ret = FORMATMESSAGE('[%s]',#viewGroup)
END
When I invoke sp_retrieveResourceShell like this:
DECLARE #return_value int
EXEC #return_value = [dbo].[sp_retrieveResourceShell]
SELECT 'Return Value' = #return_value
I can get a truncated string with ellipsis at the string tail.
how to get the full string without ellipsis?
update
Changed formatmessage function to string concatenation likes
SET #mdlGroup = #mdlGroup + '{"Id":"' + CAST(#mdlId AS CHAR(36))+ '","Name":"' + #mdlName + '","Subs":' + #subRet + ',"Views":' + #viewRet +'},'
when using string concatenation , likes
SET #ret = N'[' + #mdlGroup + N']'
and refernce to [n]varchar(max) + [n]varchar(max)
i got the right full string . Thanks to #MartinSmith at the same time .

How to execute a string in SQL Server and stored its result into a variable

ALTER PROCEDURE [dbo].[GetEmployeeSal]
#Mode varchar(50) = '',
#IsMultiple bit = 0,
#EmployeeMstID bigint = 0,
#EmployeeMstIDs varchar(MAX) = '',
#Message varchar(100) = ''
AS
BEGIN
BEGIN TRANSACTION
BEGIN TRY
IF (#Mode = 'GetEmployeeSal')
BEGIN
IF(#IsMultiple = 0)
BEGIN
SELECT #CurrentSal = COUNT(1)
FROM EmployeeMst
WHERE EmployeeMstID = #EmployeeMstID AND IsFinancialYear = 1
SELECT #PreviousSal = COUNT(1)
FROM EmployeeMst
WHERE EmployeeMstID = #EmployeeMstID
IF (#CurrentSal = #PreviousSal)
BEGIN
SET #Message = 'No Salary Revision has been performed'
END
END
ELSE
BEGIN
EXEC ('SELECT #CurrentSal = COUNT(1)
FROM EmployeeMst
WHERE EmployeeMstID IN (' + #EmployeeMstIDs + ')
AND IsFinancialYear = 1')
EXEC ('SELECT #PreviousSal = COUNT(1)
FROM EmployeeMst
WHERE EmployeeMstID IN '( + #EmployeeMstIDs + )'')
IF(#CurrentSal = #PreviousSal)
BEGIN
SET #Message = 'No Salary Revision has been performed'
END
END
END
IF(##ERROR = 0)
BEGIN
COMMIT TRANSACTION
END
ELSE
ROLLBACK TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
END CATCH
END
Your problem is: #CurrentSal variable is not in the context of your EXEC statement.
How to execute a string in SQL Server and stored its result into a
variable
You can use sp_executequery and output like this
DECLARE #CurrentSal INT
DECLARE #sql nvarchar(max) = 'select #CurrentSal = 2'
--EXEC #sql
EXEC sp_executesql #sql, N'#CurrentSal nvarchar(20) OUTPUT', #CurrentSal OUTPUT
SELECT #CurrentSal
Demo link: http://rextester.com/IHBP16111

Error Pass from nested MSSQL procedure to parent procedure

I have one parent stored procedure and one nested stored procedure. Parent Stored procedure calls the nested stored procedure on loop. Now when there is certain condition matches I have raised the error. When this error is raised I want to stop all the process and return the error.
CREATE Proc [dbo].[Usp_GenSalarySheet](#SalData [HRM].UTDT_SalaryData ReadOnly)
AS
set nocount on
DECLARE #SMT NVARCHAR(MAX)
SET #SMT = 'Create Table ##SalarySheet (StaffID INT,FullName NVARCHAR(1024),PresentDays NVARCHAR(1024),Absent NVARCHAR(1024),Department NVARCHAR(1024),Designation NVARCHAR(1024),'
DECLARE #HopName nvarchar(max)
Declare HOPCursor cursor for select ID from HRM.tbl_HOP
OPEN HOPCursor
FETCH NEXT FROM HOPCursor INTO #HopName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SMT = #SMT + ' [' + #HopName + '] DECIMAL(19,7),'
FETCH NEXT FROM HOPCursor into #HopName
END
SET #SMT = #SMT + '[Total] DECIMAL(19,7))'
CLOSE HOPCursor
DEALLOCATE HOPCursor
print (#smt)
exec (#SMT)
select * into #temp from #SalData
Declare #TopID INT
While (Select Count(*) From #Temp) > 0
Begin
Select Top 1 #TopID = StaffID From #temp
Declare #StaffID INT =(select top 1 StaffID from #temp)
Declare #StaffName NVARCHAR(1024) = (SELECT TOP 1 FullName FROM #temp)
Declare #WorkingDays Int = (SELECT top 1 WorkingDays from #temp)
Declare #Leave INT = (SELECT top 1 [Absent] from #temp)
INSERT INTO ##SalarySheet(StaffID,FullName,[Absent]) values(#StaffID,#StaffName,#Leave)
DECLARE #HOPType INT
DECLARE #Value Decimal(19,7)
DECLARE #CalcVal DECIMAL(19,7) = 0
DECLARE #Formula NVARCHAR(MAX)
DECLARE #Total DECIMAL(19,7)
DECLARE #PayEvery INT
DECLARE #Round Int
Declare HOPList Cursor for SELECT ID,HOPType,Value,Formula,RoundOff,PayEvery FROM HRM.Tbl_HOP order by Schedule
open HOPList
FETCH NEXT FROM HOPList INTO #HopName,#HOPType,#Value,#Formula,#Round,#PayEvery
WHILE ##FETCH_STATUS = 0
BEGIN
if exists(select * from HRM.[Tbl_ContractHOPDetails] where PersonalDetailsID = #StaffID and HOPID = #HopName)
print('select * from HRM.[Tbl_ContractHOPDetails] where PersonalDetailsID = ' + convert(varchar(max), #StaffID) + ' and HOPID =' + convert(varchar(max),#HopName))
begin
if(#HOPType=51)
begin
exec HRM.Usp_GetSalaryValueFromFormula #StaffID,#Formula,#HOPType,#Leave,#WorkingDays,#Value output
set #HOPType= 50
end
if(#HOPType=50)
begin
set #CalcVal = #value
END
IF(#HOPType=38)
BEGIN
SET #CalcVal = #Value - ((#Value/#WorkingDays) * #Leave)
END
if(#PayEvery= 40)
begin
set #CalcVal = ((#CalcVal * #WorkingDays) - (#CalcVal * #Leave))
end
if(#Round = 45)
begin
set #CalcVal = round(#CalcVal,2)
end
else if(#Round = 46)
begin
set #CalcVal = CEILING(#CalcVal)
end
else if(#Round = 47)
begin
set #CalcVal = FLOOR(#CalcVal)
end
set #SMT ='UPDATE ##SalarySheet SET [' + #HopName + '] = ' + cast(#CalcVal as nvarchar(max)) + ' where StaffID = ' + cast(#StaffID as nvarchar(max))
exec (#smt)
end
SET #CalcVal = 0
FETCH NEXT FROM HOPList INTO #HopName,#HOPType,#Value,#Formula,#Round,#PayEvery
END
close HOPList
DEALLOCATE HOPList
set #SMT ='UPDATE ##SalarySheet SET [Total] = ' + cast(#Total as nvarchar(max)) + ' where StaffID = ' + cast(#StaffID as nvarchar(max))
exec (#smt)
Delete #temp Where StaffID = #TopID
end
select * from ##SalarySheet
drop table ##SalarySheet
This is my parent Stored Procudere and nested procedure is as follow:
CREATE proc [HRM].[Usp_GetSalaryValueFromFormula](#StaffID INT,#val nvarchar(max),#HOPType INT,#Leave INT,#WorkingDays INT, #GetResult Decimal(19,7) output)
as
set nocount on
Declare #Formula Varchar(max)
declare #initial INT =0
declare #final INT =0
Declare #DataVal NVARCHAR(MAX) -- set the value from HOP table
declare #FieldVal nvarchar(max)
declare #cnt int = 0
Declare #Complete Int =CHARINDEX ('[',#val,0)
while (#Complete <> 0)
begin
set #initial = CHARINDEX ('[',#val,0)
set #final = CHARINDEX(']',#val,0)
set #FieldVal = SUBSTRING(#val,#initial,(#final-#initial) + 1)
if len(#FieldVal)<>0
begin
select #HOPType = HOPType, #DataVal= ( case when HOPType = 51 then [Formula] else cast([Value] as nvarchar(max)) end) from HRM.Tbl_ContractHOPDetails where PersonalDetailsID = #StaffID and HOPID in(select ID from HRM.tbl_HOP where HOPName = replace(replace(#fieldVal,'[',''),']',''))
if (#DataVal is null or #DataVal ='')
begin
RAISERROR ('Nested HOP is not defined.',11,1)
RETURN
end
print(#DataVal)
if ISNUMERIC(#DataVal)=1
begin
if(#HOPType = 38)
begin
SET #DataVal = cast(#DataVal as decimal(19,7)) - ((cast(#DataVal as decimal(19,7))/#WorkingDays) * #Leave)
end
end
set #val = replace(#val,#fieldVal,#DataVal)
set #fieldVal= ''
set #DataVal = ''
end
set #Complete = CHARINDEX ('[',#val,0)
set #fieldVal =''
set #final =0
set #initial = 0
end
SET #Complete =CHARINDEX ('{',#val,0)
while (#Complete <> 0)
BEGIN
set #initial = CHARINDEX ('{',#val,0)
set #final = CHARINDEX('}',#val,0)
set #FieldVal = SUBSTRING(#val,#initial+1,(#final-#initial)-1)
if len(#FieldVal)<>0
begin
set #DataVal = isnumeric((SELECT 0 FROM [HRM].Tbl_StaffTag where CValue = #FieldVal and StaffID = #StaffID))
set #FieldVal = '{' + #FieldVal + '}'
set #val = replace(#val,#fieldVal,#DataVal)
set #fieldVal= ''
set #DataVal = ''
end
set #Complete = CHARINDEX ('{',#val,0)
set #final =0
set #initial = 0
END
DECLARE #RetrunVal DECIMAL(19,7)
declare #ParmDefinition Nvarchar(512) = '#GetVal decimal(19,7) OUTPUT'
Declare #SMT NVARCHAR(MAX) = ' SET #GetVal = ' + #val
EXECUTE sp_executeSQL #Smt, #ParmDefinition, #GetVal =#RetrunVal OUTPUT
set #GetResult = #RetrunVal
But in current situation it raises error and again from the main procedure it runs next step of loop. But I want to terminate the complete process after this raiserror
Kindly help me
My guess is that RaiseError throws the control back to the caller, which might make the Return statement unreachable. The caller (loop) continues with next iteration.

Add custom text + variable to a varchar in sql

i'm trying to make a txt file with a single command line output in it.
However for some reason it doesn't want to add the text and the test name into it..
Here's my code:
declare #command AS varchar(200)
declare #cmd AS varchar(200)
declare #input AS varchar(200)
declare #timeinput AS varchar(200)
declare #test AS varchar(1000)
declare #failureid as int
select #timeinput = (select time from inserted)
select #input = (select action from inserted)
select #failureid = (select failureId from inserted)
select #test = (select name from dbo.Alert where FailureId = #failureid)
if (#input = 'start')
BEGIN
set #command = ('EnableTest' + #test)
END
if (#input = 'stop')
BEGIN
set #command = ('DisableTest' + #test)
END
if (#input = 'pauze')
set #command = ('PauseTest' + #test + #timeinput)
END
SET #cmd = 'echo ' + #command + ' > F:\commandfolder\testing.HMS'
EXECUTE Master.dbo.xp_CmdShell #cmd
and the output in the HMS file is: DisableTest (with the testname missing)
The #test doesn't add into the file.
The data in my tables is correct as far as I know
Any ideas?
Thanks in advance & kind regards,
Dave
how about:
declare #command AS varchar(200)
declare #cmd AS varchar(200)
declare #input AS varchar(200)
declare #timeinput AS varchar(200)
declare #test AS varchar(1000)
declare #failureid as int
select #timeinput = (select time from inserted)
select #input = (select action from inserted)
select #failureid = (select failureId from inserted)
select #test = (select name from dbo.Alert where FailureId = #failureid)
if (#input = 'start')
BEGIN
set #failureid = (select failureId from inserted where action= #input)
set #test = (select name from dbo.Alert where FailureId = #failureid)
set #command = ('EnableTest' + #test)
END
if (#input = 'stop')
BEGIN
set #failureid = (select failureId from inserted where action= #input)
set #test = (select name from dbo.Alert where FailureId = #failureid)
set #command = ('DisableTest' + #test)
END
if (#input = 'pauze')
begin
set #failureid = (select failureId from inserted where action= #input)
set #test = (select name from dbo.Alert where FailureId = #failureid)
set #command = ('PauseTest' + #test + #timeinput)
END
SET #cmd = 'echo ' + #command + ' > F:\commandfolder\testing.HMS'
EXECUTE Master.dbo.xp_CmdShell #cmd
Basicaly, my guess is that you will have to set the Variable for every single case otherswise it remains the same.
It appears to be working now with no adjustments.
I don't know why it didn't, but the code is correct.

Invalid Column Name '#FileName-- value'

I am getting 'Invalid Column Name '#FileName-- value'' ERROR WHILE executing below stored procedure. I tried to find the root cause of the issue with no luck...Please suggest me where i am wrong.
ALTER PROCEDURE [dbo].[usp_ICLExtract_GetFile]
#FileName Varchar(50),
#Image_Path Varchar(50) Output,
#FIleNameList varchar(4096) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #strProcName varchar(255)
SET #strProcName = 'usp_ICLExtract_GetFile'
DECLARE #strSQL1 varchar(1024), #strSQL2 varchar(1024)
DECLARE #strFileName Varchar(50)
DECLARE #intErrorReturn int
SET #intErrorReturn = 0
SET #FileNameList = ''
SET #Image_Path = ''
SET #strSQL1 = N'SELECT tbl_ICLExtCashLetter.Image_Path from tbl_ICLExtCashLetter INNER JOIN tbl_ICLExtFile on [tbl_ICLExtCashLetter].ICLExtFileUID = [tbl_ICLExtFile].ICLExtFileUID where tbl_ICLExtFile.FileName = ' + #FileName --This line cause error
/*==============================================================================
* Run the query'
*==============================================================================*/
SET #strSQL2 = 'DECLARE curCategory INSENSITIVE SCROLL CURSOR FOR ' + #strSQL1
EXEC(#strSQL2)
SELECT #intErrorReturn = ##ERROR
IF (#intErrorReturn <> 0) GOTO usp_ICLExtract_GetFile_Error
OPEN curCategory
SELECT #intErrorReturn = ##ERROR
IF (#intErrorReturn <> 0) GOTO usp_ICLExtract_GetFile_Error
FETCH NEXT FROM curCategory INTO #strFileName
WHILE (##FETCH_STATUS <> -1)
BEGIN
SET #FileNameList = #FileNameList + #strFileName + ';'
SET #Image_Path = #Image_Path + 1
FETCH NEXT FROM curCategory INTO #strFileName
END
CLOSE curCategory
DEALLOCATE curCategory
RETURN(0)
usp_ICLExtract_GetFile_Error:
RETURN(#intErrorReturn)
END
replace line with this
SET #strSQL1 = N'SELECT tbl_ICLExtCashLetter.Image_Path from tbl_ICLExtCashLetter INNER JOIN tbl_ICLExtFile on [tbl_ICLExtCashLetter].ICLExtFileUID = [tbl_ICLExtFile].ICLExtFileUID where tbl_ICLExtFile.FileName = ''' + #FileName +'''
Change your query to this:
N'SELECT tbl_ICLExtCashLetter.Image_Path from tbl_ICLExtCashLetter
INNER JOIN tbl_ICLExtFile on [tbl_ICLExtCashLetter].ICLExtFileUID =
[tbl_ICLExtFile].ICLExtFileUID where tbl_ICLExtFile.FileName = ''' + #FileName + ''''
you have to pass value between apostrophes '.