calling one stored proc from another by executing command - sql-server

In my stored procedure I have to pass a table and column name which may change everytime. So I build command and execute it. I want the output in another variable #curr_id. This store procedure will be called by second stored procedure by using #curr_id as input.
My problem is populating the #curr_id vriable. It is returned as zero. If I remove the
curr_id variable then it works(see commented line)
Can someone pl. tell me
- how to get #curr_id populated and returned as OUTPUT?
- how to call the first stored proc from a second stored proc?
ALTER PROCEDURE [dbo].[sp_astm_getcurrid]
#ColName as nvarchar(250),
#TblName as nvarchar(250),
#curr_id nvarchar(max) OUTPUT
AS
BEGIN
DECLARE #cmd nvarchar(max)
SET #cmd =N'SET '+#curr_id+'= SELECT MAX('+#ColName+') FROM '+#TblName;
--SET #cmd =N'SELECT MAX('+#ColName+') FROM '+#TblName;
EXEC (#cmd)
END

Because EXEC runs in a different context, it is not aware of your #curr_id variable. Instead, you can place the output of your dynamic SQL into a table variable, and then use that to set #curr_id.
Also, never start a stored procedure name with sp_.
ALTER PROCEDURE [dbo].[usp_astm_getcurrid]
#ColName as nvarchar(250),
#TblName as nvarchar(250),
#curr_id nvarchar(max) OUTPUT
AS
BEGIN
DECLARE #cmd nvarchar(max)
declare #dummy table (
ReturnColumn nvarchar(max)
)
SET #cmd = N'SELECT MAX(' + #ColName + N') FROM ' + #TblName;
insert into #dummy
(ReturnColumn)
exec (#cmd)
set #curr_id = (select ReturnColumn from #dummy)
END
Then, an example of calling this procedure from within another could be something like this. The important key is to use the OUTPUT keyword here in the call as well as in the declaration of the procedure above.
CREATE PROCEDURE CallMyProcedure
AS
BEGIN
declare #curr_id nvarchar(max)
exec dbo.usp_astm_getcurrid N'YourColumnName', N'YourTableName', #curr_id OUTPUT
select #curr_id
END

Friend Function execSP(ByVal spName As String, Optional ByVal params As Collection = Nothing) As Integer
Dim cmd As SqlCommand
Dim param As SqlParameter
Dim ret As Integer
Dim iParam As Integer
cmd = New SqlCommand
cmd.CommandText = spName
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = _sqlConn
cmd.CommandTimeout = 0
If Not params Is Nothing Then
For iParam = 1 To params.Count
param = params(iParam)
cmd.Parameters.Add(param)
Next
End If
If _sqlConn.State <> ConnectionState.Open Then
_sqlConn.Open()
End If
Try
ret = cmd.ExecuteNonQuery()
Catch ex As Exception
Throw New Exception(ex.Message)
Finally
_sqlConn.Close()
End Try
Return ret
End Function

You can use the OUTPUT parameter in sp_executesql:
ALTER PROCEDURE [dbo].[sp_astm_getcurrid]
#ColName as nvarchar(250),
#TblName as nvarchar(250),
#curr_id nvarchar(max) OUTPUT
AS
BEGIN
DECLARE
#cmd nvarchar(max)
SET #cmd =N'SELECT #curr_id_out = MAX('+#ColName+') FROM '+#TblName
EXEC sp_executesql
#cmd,
N'#curr_id_out nvarchar(max) OUTPUT',
#curr_id_out = #curr_id OUTPUT
END
I would be remiss not to mention that, in this case, using EXEC(#cmd) or sp_executesql(#cmd) leaves you vulnerable to SQL injection attacks.
I recommend adding something like the following to the beginning of the stored procedure:
SELECT
#ColName = REPLACE(
REPLACE(
REPLACE(#ColName, ';', ''), '-', ''), '''', ''),
#TblName = REPLACE(
REPLACE(
REPLACE(#TblName, ';', ''), '-', ''), '''', '')

Related

Looping through the cursor in T-SQL

I am creating a procedure in T-SQL:
CREATE PROCEDURE usp_QC1
AS
BEGIN
DECLARE #tablename varchar(100);
DECLARE #sfilename varchar(100);
DECLARE #rread varchar(100);
DECLARE #rwrite varchar(100);
DECLARE #sserver varchar(100);
DECLARE #dbname varchar(100);
DECLARE cur_tracking CURSOR FOR
SELECT
[TableName],
sfilename,
[RecordsRead],
[RecordsWritten],
[SQLServer],
[SQLDatabase]
FROM
[ADataTracker].[dbo].[TrackerLoadLog]
WHERE
LOWER(datagroup) LIKE '%Oracle RMS%'
AND SUBSTRING(sfilename, 1, 10) = '2022-03-16'
OPEN cur_tracking;
FETCH NEXT FROM cur_tracking INTO #tablename, #sfilename, #rread, #rwrite, #sserver, #dbname;
WHILE ##Fetch_status = 0
BEGIN
SELECT
sfilename, COUNT(*)
FROM
#sserver + '.dbo.' + #dbname
WHERE
sfilename = #sfilename
GROUP BY
sfilename
FETCH NEXT FROM cur_tracking INTO #tablename, #sfilename, #rread, #rwrite, #sserver, #dbname;
END;
CLOSE cur_tracking;
DEALLOCATE cur_tracking;
END
The cursor cur_tracking is holding the data (just showing 1 record)
---------------------------------------------------------------------------------------------------------------------------
TableName |sfilename | RecordsRead |RecordsWritten |SQLServer |SQLDatabase |
History |2022-03-16\20220316032322.dat| 5819560 |5819560 |a.stg.sql.ccaintranet.com |DataRms_Back |
So the cursor is having all the information of server, Databasename, tablename. I want to go to those each server.db.table and retrieve the information using these cursor elements:
SELECT sfilename, COUNT(*)
FROM #sserver + '.dbo.' + #dbname
WHERE sfilename = #sfilename
GROUP BY sfilename
But I get an error:
invalid column name sfilename
must declare the table variable #sserver
This is never going to work:
select sfilename,count(*) from #sserver+'.dbo.'+#dbname
You can't parameterize entity names like this (also database comes before schema, and you missed #tablename entirely).
Instead you can do:
DECLARE #sql nvarchar(max), #exec nvarchar(1000);
...
-- then inside the cursor:
SET #sql = N'select sfilename = #sfilename,count(*)
FROM dbo.' + QUOTENAME(#tablename)
+ N' WHERE sfilename = #sfilename;';
SET #exec = QUOTENAME(#dbname) + N'.sys.sp_executesql';
EXEC #exec #sql, N'#sfilename varchar(100)', #sfilename;
Note that all of these need to be nvarchar(128), and you can use the same DECLARE for multiple variables to lighten eye strain:
DECLARE #tablename nvarchar(128),
#sfilename nvarchar(128),
#dbname nvarchar(128);
Please review this collection of links.

Must declare the scalar variable error for stored procedure in nopcommerce 4.3

I want to search GTIN option in admin product list. So, for that I am providing GTIN value in ProductLoadAllPaged store procedure. Now, when I search GTIN value from product list at that time throw datatable error and from console application get message that System.Data.SqlClient.SqlException (0x80131904): Must declare the scalar variable "#GTIN"..
Here is store procedure added code,
ALTER PROCEDURE [dbo].[ProductLoadAllPaged]
(
#GTIN nvarchar(50) = null--AWAZ
)
AS
BEGIN
...........
--SKU (exact match)
IF #SearchSku = 1
BEGIN
SET #sql = #sql + 'OR p.[Sku] = #OriginalKeywords '
END
--NEW ADDED CODE FOR GTIN SEARCH
IF #GTIN is not null
BEGIN
SET #sql = #sql + 'AND p.Gtin = #GTIN'
END
--localized product name
SET #sql = #sql + '
UNION
SELECT lp.EntityId
FROM LocalizedProperty lp with (NOLOCK)
WHERE
lp.LocaleKeyGroup = N''Product''
AND lp.LanguageId = ' + ISNULL(CAST(#LanguageId AS nvarchar(max)), '0') + '
AND ( (lp.LocaleKey = N''Name'''
..........
END
In the stored procedure change this line of code:
EXEC sp_executesql #sql, N'#Keywords nvarchar(4000), #OriginalKeywords nvarchar(4000)', #Keywords, #OriginalKeywords
To this:
EXEC sp_executesql #sql, N'#Keywords nvarchar(4000), #OriginalKeywords nvarchar(4000), #GTIN nvarchar(50)', #Keywords, #OriginalKeywords, #GTIN
This will add your new parameter when executing the dynamic SQL query.

Getting Empty Output

Iam trying to Execute Dynamic Query, But Iam getting Empty Output.Where I'm Wrong?
SET #SQL=N'
SELECT GETDATE(),'+#AMUID+','+ #BNO +
',LOT,BARCODEID,'+#ACTWT+',TARE_QUANTITY,''NA'',STAGE,0,0,0,
'+ #UNAME+ ','+#PR + ',GETDATE()
FROM DISPENSE_HOLD_START WHERE BATCH_NO='''+#BNO+''' AND BARCODEID='''+
#BARID +''' and IS_OUT=0';
PRINT(#SQL)
Here #AMUID,#BNO,#ACTWT etc are Input Parameters Declared with NVARCHAR(MAX) data type.They are dynamic Iam getting nothing When I Print this.
as you are not executing the query but printing it
this is same as
3+3=6 and "3"+"3"="33"
the dynamic queries are typically executed like this(simplest method)
DECLARE #IntVariable int;
DECLARE #SQLString nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
/* Build the SQL string one time.*/
SET #SQLString =
N'SELECT BusinessEntityID, NationalIDNumber, JobTitle, LoginID
FROM AdventureWorks2012.HumanResources.Employee
WHERE BusinessEntityID = #BusinessEntityID';
SET #ParmDefinition = N'#BusinessEntityID tinyint';
/* Execute the string with the first parameter value. */
SET #IntVariable = 197;
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#BusinessEntityID = #IntVariable;
/* Execute the same string with the second parameter value. */
SET #IntVariable = 109;
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#BusinessEntityID = #IntVariable;
Case#1 :
In your Above Query, You are using PRINT instead of EXEC. So Make sure you are executing the Query in your actual Code
EXEC(#SQL)
Case#2 :
If you are executing this, there is a possibility that if any of the Parameter Value is NULL, then the entire String will become NULL
If you add any Value to NULL the Result will be NULL
SELECT
'ABC',
'ABC'+NULL
Gives Me this
So Use ISNULL
SET #SQL = N'
SELECT
GETDATE(),
'+ISNULL(#AMUID,'')+','+ISNULL(#BNO,'')+',LOT,
BARCODEID,'+ISNULL(#ACTWT,'')+',TARE_QUANTITY,''NA'',STAGE,0,0,0,
'+ISNULL(#UNAME,'')+','+ISNULL(#PR,'')+',GETDATE()
FROM DISPENSE_HOLD_START
WHERE BATCH_NO='''+ISNULL(#BNO,'')+'''
AND BARCODEID='''+ISNULL(#BARID,'')+'''
and IS_OUT=0';
EXEC(#SQL);
Case#3
Looking at your Code, I think you don't need a Dynamic SQL here. Instead, you can directly go Like this
SELECT
GETDATE(),
#AMUID,
#BNO,
LOT,
BARCODEID,
#ACTWT,
TARE_QUANTITY,
'NA',
STAGE,
0,
0,
0,
#UNAME,
#PR,
GETDATE()
FROM DISPENSE_HOLD_START
WHERE BATCH_NO = #BNO
AND BARCODEID = #BARID
AND IS_OUT = 0
Works just fine for me
declare #val nvarchar(100) = 'tommy can you see me'
declare #SQL nvarchar(100) = N'SELECT GETDATE(), ''' + #val + '''';
PRINT(#SQL);

Msg 102, Level 15, State 1, Line 34 Incorrect syntax near '.'

I am getting above error while executing query as following, which is a stored procedure command line execution
exec sp_Bind_Division_Store_Camera_On_Filter_In_Liveview
null, null, null, null
Stored procedure is as following
ALTER PROCEDURE [dbo].[sp_Bind_Division_Store_Camera_On_Filter_In_Liveview]
#division varchar(45),
#store varchar(45),
#camera varchar(68),
#group varchar(100)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#BaseQuery nvarchar(max) = 'select
distinct tblcameradetails.name as CameraName,
tblcameradetails.IsDeviceEnabled,
tblcameradetails.cameraID,
tblcameradetails.deviceIP,
tblmediasourcedetails.StreamName,
tblmediasourcedetails.streamID,
tblcameradetails.Model_ID,
tblcameradetails.IsHidden,
tblcameradetails.hasPTZcapability,
tblcameradetails.CameraModelNo,
tblcameradetails.username as CameraUserName,
tblcameradetails.hasPTZCycle,
tblcameradetails.hasPreset,
tblcameradetails.password as CameraPassword,
tblmediasourcedetails.isRecordingStarted as IsRecordingOn,
tblcameradetails.IsCovert,
tblcameradetails.constCameraName,
tblmediasourcedetails.constStreamName,
tblstoredetails.Store_ID,
tblsystemlocationdetails.division,
tblstoredetails.Store_Name,
tblstoredetails.Store_IP,
tblstoreconfiguration.Liveview_Session_Timeout
from
tblmediasourcedetails,
tblcameradetails,
tblcameragroupdetails,
tblgroupdetails,
tblvssaddsourcedetails,
tblsystemlocationdetails,
tblstoredetails,
tblstoreconfiguration'
, #ParamList nvarchar(max) = N'#p1 varchar(45), #p2 varchar(45), #p3 varchar(68), #p4 varchar(100)'
, #WhereClause nvarchar(max) = N'where
tblmediasourcedetails.cameraID=tblcameradetails.cameraID
and tblmediasourcedetails.streamID=tblvssaddsourcedetails.streamID
and tblcameradetails.cameraID = tblcameragroupdetails.cameraID
and tblcameragroupdetails.groupID=tblgroupdetails.groupID
and tblstoredetails.Store_ID= tblcameradetails.Store_ID
and tblsystemlocationdetails.Store_ID= tblstoredetails.Store_ID
and tblstoredetails.Store_ID=tblstoreconfiguration.Store_ID and 1=1'
, #OrderByClause nvarchar(100) = 'order by CameraName';
IF #division IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and division like (#p1)';
END
IF #store IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and (store like (#p2))';
END
IF #camera IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and tblcameradetails.name like (#p3)';
END
IF #group IS NOT NULL
BEGIN
SET #WhereClause = #WhereClause + ' and tblgroupdetails.name in (#p4)';
END
SET #BaseQuery = #BaseQuery + #WhereClause + #OrderByClause;
EXECUTE sp_executesql #BaseQuery, #ParamList, #p1 = #division, #p2 = #store, #p3 = #camera, #p4 = #group;
END
Now error shows me that on line 34 error at syntax near '.', but I found no problem at all, because I am run this query form command prompt very well same applied in stored procedure, it will raised error. Please help me to solved out this.
You can easily print your variable #BaseQuery to check the resulting query.
the query in the variable #BaseQuery looks like this
select
distinct tblcameradetails.name as CameraName,
tblcameradetails.IsDeviceEnabled,
tblcameradetails.cameraID,
tblcameradetails.deviceIP,
tblmediasourcedetails.StreamName,
tblmediasourcedetails.streamID,
tblcameradetails.Model_ID,
tblcameradetails.IsHidden,
tblcameradetails.hasPTZcapability,
tblcameradetails.CameraModelNo,
tblcameradetails.username as CameraUserName,
tblcameradetails.hasPTZCycle,
tblcameradetails.hasPreset,
tblcameradetails.password as CameraPassword,
tblmediasourcedetails.isRecordingStarted as IsRecordingOn,
tblcameradetails.IsCovert,
tblcameradetails.constCameraName,
tblmediasourcedetails.constStreamName,
tblstoredetails.Store_ID,
tblsystemlocationdetails.division,
tblstoredetails.Store_Name,
tblstoredetails.Store_IP,
tblstoreconfiguration.Liveview_Session_Timeout
from
tblmediasourcedetails,
tblcameradetails,
tblcameragroupdetails,
tblgroupdetails,
tblvssaddsourcedetails,
tblsystemlocationdetails,
tblstoredetails,
tblstoreconfigurationwhere
tblmediasourcedetails.cameraID=tblcameradetails.cameraID
and tblmediasourcedetails.streamID=tblvssaddsourcedetails.streamID
and tblcameradetails.cameraID = tblcameragroupdetails.cameraID
and tblcameragroupdetails.groupID=tblgroupdetails.groupID
and tblstoredetails.Store_ID= tblcameradetails.Store_ID
and tblsystemlocationdetails.Store_ID= tblstoredetails.Store_ID
and tblstoredetails.Store_ID=tblstoreconfiguration.Store_ID and 1=1order by CameraName
You can see that you are missing a space before the WHERE and ORDER BY clause
You need to add a space in the starting of your WHERE and ORDER BY variables like this
#WhereClause nvarchar(max) = N' where
#OrderByClause nvarchar(100) = ' order by CameraName';
Try to put some PRINT in the middle of the query.
For example PRINT #BaseQuery after SET #BaseQuery = #BaseQuery + #WhereClause + #OrderByClause;
Because maybe you need a space in some variable (for example N' where...1=1' instead of N'where...1=1' )

SQL Server - Variable declared but still says "Must declare the scalar variable"

I'm trying to run this set of SQL commands on Microsoft SQL Server but I am getting this error:
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "#dbstatus".
I thought I did declare the variable so I'm not sure why it's still throwing the error?
DECLARE #dbname nvarchar(100)
DECLARE #dbstatus varchar(500)
DECLARE #sqlCommand NVARCHAR(1000)
create table #temptable (dbname nvarchar(100), status varchar(500))
DECLARE c1 CURSOR READ_ONLY
FOR
SELECT '[' + name + ']' FROM sys.databases WHERE name = 'EDDS1084543'
OPEN c1
FETCH NEXT FROM c1 INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'SET #dbstatus = (SELECT Status FROM ' + #dbname + '.[EDDSDBO].[dtSearchIndex])'
EXECUTE sp_executesql #sqlCommand
INSERT INTO #tempTable(dbname, [status])VALUES (#dbname, #dbstatus)
FETCH NEXT FROM c1 INTO #dbname
END
CLOSE c1
DEALLOCATE c1
EXEC/sp_executesql creates a new connection (SPID) to the SQL Server, which is not your current session, so it cannot see the variable. Check the documentation.
Basically, you have to declare the parameter you want to pass into the call, and give it a value. In this case, both have to include the OUTPUT specifier.
EXECUTE sp_executesql #sqlCommand, '#dbstatus varchar(500) output', #dbstatus output
The problem is here:
SET #sqlCommand = 'SET #dbstatus = (SELECT Status FROM ' + #dbname + '.[EDDSDBO].[dtSearchIndex])'
EXECUTE sp_executesql #sqlCommand
This causes the server to execute the value of #sqlCommand as a standalone statement. Within this statement, #dbstatus has not been declared as a variable, hence the error. This is what's getting executed:
SET #dbstatus = (SELECT Status FROM [value in #dbname].[EDDSDBO].[dtSearchIndex])
Try this instead:
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sqlCommand = 'SET #dbstatus = (SELECT Status FROM ' + #dbname + '.[EDDSDBO].[dtSearchIndex])'
EXECUTE sp_executesql #sqlCommand, '#dbstatus varchar(500) output', #dbstatus output
INSERT INTO #tempTable(dbname, [status])VALUES (#dbname, #dbstatus)
FETCH NEXT FROM c1
INTO #dbname
END

Resources