SQL Insert multiple records to Triggered table - sql-server

On SQL Agent job I'm downloading data from main table (X). If the status equal 'WW' or 'WXY' I just want to all records insert into another table (Y) where I have created a trigger. Could you give me advise what should I change in my trigger definition? I receive error message when I try insert multiple records to DB2.Y table (agent job failed)
First code (downloading new data)
DECLARE #STARTTIME datetime
DECLARE #TIME datetime
DECLARE #ENDTIME datetime
SET #TIME=(SELECT MAX(Time) FROM DB2.Y)
SET #STARTTIME=(select dateadd(hour,1,getdate()))
SET #ENDTIME=(SELECT MAX(TIME) FROM DB1.X where TIME is not null)
IF #TIME = #ENDTIME
BEGIN
TRUNCATE TABLE DB2.Y;
INSERT INTO DB2.Y (Time) Values (#TIME)
END
ELSE
BEGIN
TRUNCATE TABLE DB2.Y
INSERT INTO DB2.Y ([Serv],[Status])
SELECT [SERV],[STATUS] FROM DB1.X WHERE TIME > #TIME and [SERV]='Description' and ([STATUS]='WW' or [STATUS]='WXY') ;
UPDATE DB2.Y
SET [Time]= #ENDTIME
END
The trigger code:
USE DB2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT AS
DECLARE #SERV varchar(40)
DECLARE #STATUS varchar(3)
SET #SERV=(SELECT [SERV] FROM inserted)
SET #STATUS=(SELECT [STATUS] FROM inserted)
IF #STATUS in ('WW', 'WXY')
BEGIN
DECLARE #MSG varchar(500)
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
END

INSERTED can contain multiple rows for multi-row INSERTs - it runs once per operation, not once per row.
Try a trigger like this instead:
USE DB2
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT AS
DECLARE #SERV varchar(40)
DECLARE #STATUS varchar(3)
IF EXISTS(SELECT [Status] FROM Inserted WHERE [STATUS] in ('WW', 'WXY'))
BEGIN
DECLARE #MSG varchar(8000)
INSERT INTO JobLog(Serv, Status)
SELECT Serv, Status FROM Inserted WHERE [STATUS] in ('WW', 'WXY')
SET #MSG = CAST(##ROWCOUNT as nvarchar) + 'Job(s) failed - see log for details'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
END
SELECT

Try something like this...
CREATE TRIGGER [dbo].[TriggerName] ON Y
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SERV varchar(40),#STATUS varchar(3), #MSG varchar(500)
Select [SERV], [STATUS] INTO #Temp
FROM inserted
Where [STATUS] IN ('WW', 'WXY')
Declare Cur CURSOR FOR
SELECT [SERV], [STATUS] FROM #Temp
OPEN Cur
FETCH NEXT FROM Cur INTO #SERV, #STATUS
WHILE ##FETCH_STATUS = 0
BEGIN
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com'
, #body= #MSG
, #subject = #MSG
, #profile_name = 'profilename'
FETCH NEXT FROM Cur INTO #SERV, #STATUS
END
CLOSE Cur
DEALLOCATE Cur
END

You could use a cursor to resolve your error. The cursor below iterates over all inserted records with a STATUS of either WW or WXY and sends out an email for each of them.
DECLARE error_cursor CURSOR FOR
SELECT [SERV],[STATUS] FROM inserted
WHERE [STATUS] in ('WW', 'WXY')
OPEN error_cursor
FETCH NEXT FROM error_cursor
INTO #SERV, #STATUS
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE MSG varchar(500)
SET #MSG = 'Job "' + #SERV + '" failed!!!'
EXEC msdb.dbo.sp_send_dbmail #recipients=N'myemail#domain.com', #body= #MSG, #subject = #MSG, #profile_name = 'profilename'
FETCH NEXT FROM vendor_cursor
INTO #SERV, #STATUS
END
CLOSE error_cursor;
DEALLOCATE error_cursor;

Related

Have anyone a solution to send row parameter to a stored prodedure in MS-SQL Server with dynamic Column Arrangement?

I Could write a trigger for a table that is able to detect updated columns and logs the changes. I want to make a stored procedure from this trigger and call it when required. But I do not know how can I send "inserted" or "updated" rows that are valid in trigger body, to this SP.
Here is my trigger :
CREATE TRIGGER [dbo].[tgr_MyTable_TransactionLogUpdate]
ON [dbo].[MyTable]
AFTER UPDATE
AS
BEGIN
if (select F_SharhRadif from [Payeh.Decode] where F_ShJadval=18 and F_ShRadif=1)='2'
begin
return
end
declare #userid int=(select top 1 userid from inserted)
declare #computername nvarchar(50)=(select top 1 computername from inserted)
declare #ip nvarchar(50)=(select top 1 IP from inserted)
declare #zamantaqeer datetime=(select top 1 F_ZamanTaqeer from inserted)
declare #changetime =GETDATE()
DECLARE #tableID BIGINT=(SELECT id FROM sys.sysobjects WHERE [name]='MyTable')
DECLARE #ColCount INT=(SELECT COUNT(*) FROM sys.syscolumns WHERE id=#tableID)
DECLARE #ColIndex INT=1
DECLARE #UpdateDetails NVARCHAR(MAX)=''
DECLARE #ColName NVARCHAR(1000)
DECLARE #ByteIndex INT
SELECT * INTO #d FROM deleted
SELECT * INTO #i FROM inserted
WHILE (#ColIndex<=#ColCount)
BEGIN
--IF (COLUMNS_UPDATED()&POWER(2,#ColIndex-1) <> 0)
SET #ByteIndex=((#ColIndex-1)/8)+1
IF (CONVERT(INT,SUBSTRING(COLUMNS_UPDATED(),#ByteIndex,1))&POWER(2,((#ColIndex-1)%8)) <> 0)
BEGIN
SET #ColName=(SELECT [name] FROM sys.syscolumns WHERE id=#tableID AND colid=#ColIndex)
DECLARE #OldValue NVARCHAR(MAX)
DECLARE #NewValue NVARCHAR(MAX)
DECLARE #ParmDefinition NVARCHAR(100)=N'#DeletedValue NVARCHAR(MAX) OUTPUT'
DECLARE #SQL NVARCHAR(1000)='SELECT #DeletedValue=LTRIM(RTRIM(CONVERT(nvarchar(MAX),'+#ColName+'))) FROM #d'
EXEC sp_executesql #SQL,#ParmDefinition,#DeletedValue=#OldValue OUTPUT
SET #ParmDefinition = N'#InsertedValue NVARCHAR(MAX) OUTPUT'
SET #SQL= 'SELECT #InsertedValue=LTRIM(RTRIM(CONVERT(nvarchar(MAX),'+#ColName+'))) FROM #i'
EXEC sp_executesql #SQL,#ParmDefinition,#InsertedValue=#NewValue OUTPUT
IF (#OldValue<>#NewValue)
BEGIN
SET #UpdateDetails=#UpdateDetails+#ColName+': OLD="'+ #OldValue+'" -New="'+#NewValue+'", '
END
END
SET #ColIndex=#ColIndex+1
END
IF (LEN(#UpdateDetails)>0)
BEGIN
SET #UpdateDetails=SUBSTRING(#UpdateDetails,1,LEN(#UpdateDetails)-1)
END
ELSE
BEGIN
SET #UpdateDetails='No Changes'
END
--[User.TransactionLog] is the name of the table that stores the history of changes
INSERT INTO [User.TransactionLog]
([Tablename],[OperationType],[Desciption],[UserID],[ComputerName],[IP],[ChangeTime])
SELECT 'MyTable',2,#UpdateDetails,'',#userid,#computername,#ip, #changetime
DROP TABLE #d
DROP TABLE #i

Will all transaction in this stored procedure be rolled back

I have created a stored procedure (shown below) in SQL Server and tried to include a Rollback Transaction as I need to have a "stored procedure that has a transaction around it, so that if/when it fails all inserts will be rolled back."
I am unsure if this work or not, or will work, I cannot test yet as only developing locally, but wondered if someone wouldn't mind looking over the Rollback Transaction part of the stored procedure and advise if on the right path?
USE AutomatedTesting
GO
ALTER PROCEDURE [dbo].[spInsertTestCases]
(#AddedTFS INT,
#Scenario NVARCHAR(500),
#TargetTableName NVARCHAR(100),
#TargetFieldName NVARCHAR(100),
#ExpectedResult NVARCHAR(100),
#TargetTableDBName NVARCHAR(100),
#TargetTableSchema NVARCHAR(100),
#TargetFieldIsDateTime NVARCHAR(1),
#TestCaseIdentifiers dbo.TestCaseIdentifiers READONLY ) -- can only be READONLY. meaning you cannot amend the param
/* #TestCaseIdentifiers var will be prepopulated
TestDataIdentifiersNEW is a custom data type which has fields (TestSequence ColumnName ColumnValue IsAlphaNumeric)
so stored procedure is called like:
EXEC [dbo].[spTest_UserDefinedDatatype] 'param1','param2' #temp_testdata
#temp_testdata will already be defined and popualted(INSERT INTO ) before exec to add in 1 to many rows.
for example:
ColumnName ColumnValue
PATIENTID 123456
SOURCESYS PAS
in simple terms above EXEC is:
EXEC [dbo].[spTest_UserDefinedDatatype] 'param1','param2' 'PATIENTID 123456'
'SOURCESYS PAS'
*/
AS
BEGIN TRY
BEGIN TRANSACTION
BEGIN
--DECLARE #TableNameUpdate SYSNAME = #TargetTableName
--DECLARE #CDI SYSNAME = REPLACE(#TargetTableName,'CDO','CDI') -- so if targettablename param is CDO then swap it to CDI. why?
DECLARE #sql VARCHAR(MAX) = ' INSERT INTO [dbo].[TestCasesIdentifier] ([TestCaseId], [TestCaseSequence], [FieldName], [FieldValue], [AlphaNumeric]) VALUES '
DECLARE #i INT = 1
DECLARE #TableNameUpdate SYSNAME = #TargetTableName
DECLARE #CDI SYSNAME = REPLACE(#TargetTableName,'CDO','CDI')
DECLARE #ColName SYSNAME
DECLARE #Ret NVARCHAR(256)
DECLARE #sql2 NVARCHAR(MAX)
DECLARE #TestCaseID INT = -1 --does this need default variable?
DECLARE #ErrorCode INT = ##error
DECLARE #TestSequence INT
DECLARE #ColumnName VARCHAR(100)
DECLARE #ColumnValue VARCHAR(100)
DECLARE #IsAlphaNumeric BIT
DECLARE #TableTestSequence INT = ISNULL((SELECT MAX([TableTestSequence]) + 1 FROM TestCases WHERE #TargetTableName = [TargetTableName]), 1)
-- INSERT into TestCases. 1 record
-- An assumption that a number of fields will have defaults on them - if not, extra fields will need adding
INSERT INTO [dbo].[TestCases] ([AddedTFS], [TableTestSequence], [Scenario],
[TargetTableName], [TargetFieldName], [ExpectedResult],
[TargetTableDBName], [TargetTableSchema], [TargetFieldIsDateTime])
VALUES (#AddedTFS, -- AddedTFS (The TFS Number of the Development carried out)
ISNULL((SELECT MAX([TableTestSequence]) + 1 -- TableTestSequence (Generates the next Sequence Number for a Table)
FROM TestCases -- if table doesnt exist in TestCases then sets to 1
WHERE #TargetTableName = [TargetTableName]), 1),
#Scenario, -- Scenario (A description of the scenario use GIVEN and WHERE)
#TargetTableName, -- TargetTableName (References the Target Table entered at the top of this SQL - SET #TableName = 'CDO_APC_ELECTIVE_ADMISSION_LIST')
#TargetFieldName, -- TargetFieldName (The Field in which we want to test)
#ExpectedResult, -- ExpectedResult (The expected output/result of the field in which we want to test)
#TargetTableDBName, -- The DB to be used
#TargetTableSchema, -- the schema to be used
#TargetFieldIsDateTime) ---- 1 = Yes, 0 = No (Is Target field a datetime field)
-- Grab the identity value just generated by the last statement and the last error code generated
-- in order to reference TestCases PK when adding to TestCaseIdentifiers
SELECT #TestCaseID = SCOPE_IDENTITY(), #ErrorCode = ##error
IF #ErrorCode = 0 --OR #TestCaseID <> -1 -- #ErrorCode <> 0 if error then back out testcases INSERT? surely should use BEGIN/ROLLBACK tran
--IF #ErrorCode = 0 OR #TestCaseID <> -1
-- If there was no error creating the TestCase record, create the records for the WHERE clause
BEGIN
/*
rollback insert if no matching records
rollback insert if SQL returns more than 1 record
return error message to user
*/
SELECT
ic.index_column_id, c.name
INTO #tmp
FROM sys.indexes i
JOIN sys.index_columns ic ON i.object_id = ic.object_id
AND i.index_id = ic.index_id
JOIN sys.columns c ON c.column_id = ic.column_id
AND c.object_id = ic.object_id
JOIN sys.tables t ON c.object_id = t.object_id
WHERE t.name = #CDI
AND i.is_primary_key = 1
IF (SELECT COUNT(*) FROM #TestCaseIdentifiers) = 0
--IF #PKValues IS NULL
BEGIN
WHILE #i <= (SELECT COUNT(*) FROM #tmp)
BEGIN
SELECT #ColName = [name]
FROM #tmp
WHERE index_column_id = #i
-- if #expectedvalue IS NULL
SET #sql2 = 'SELECT TOP 1 #RetvalOut = ' + QUOTENAME(#ColName) + ' FROM ' + QUOTENAME(#CDI) + ' ORDER BY NEWID()'
-- else
-- SET #sql2 = ''
EXECUTE sp_executesql #command = #sql2, #ParmDefinition = N'#RetvalOut NVARCHAR(MAX) OUTPUT', #retvalOut = #Ret OUTPUT
SET #sql += '(' + CONVERT(VARCHAR(100),#TestCaseID) + ',' + CONVERT(VARCHAR(10),#i) + ',''' + #ColName + ''',''' + #Ret + ''',1),'
SET #i+=1
SELECT #sql = REVERSE(SUBSTRING(REVERSE(#sql),2,8000))
PRINT #sql
EXEC #sql
END
END
ELSE
BEGIN
--PRINT 'got here'
DECLARE csr_TestCaseIdentifierInsert CURSOR FOR
SELECT [TestSequence],[ColumnName],[ColumnValue],[IsAlphaNumeric]
FROM #TestCaseIdentifiers
ORDER BY [TestSequence]
OPEN csr_TestCaseIdentifierInsert
FETCH NEXT FROM csr_TestCaseIdentifierInsert INTO #TestSequence, #ColumnName, #ColumnValue, #IsAlphaNumeric
WHILE ##fetch_status = 0
BEGIN
INSERT INTO [dbo].[TestCasesIdentifier]
([TestCaseId],
[TestCaseSequence],
[FieldName],
[FieldValue],
[AlphaNumeric])
VALUES
(#TestCaseID, #TestSequence, #ColumnName, #ColumnValue,#IsAlphaNumeric)
FETCH NEXT FROM csr_TestCaseIdentifierInsert INTO #TestSequence, #ColumnName, #ColumnValue, #IsAlphaNumeric
END
CLOSE csr_TestCaseIdentifierInsert
DEALLOCATE csr_TestCaseIdentifierInsert
END -- loop to add records to testcasesidentifier
END
END
COMMIT
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN
DECLARE #ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE()
DECLARE #ErrorSeverity INT = ERROR_SEVERITY()
DECLARE #ErrorState INT = ERROR_STATE()
-- Use RAISERROR inside the CATCH block to return error
-- information about the original error that caused
-- execution to jump to the CATCH block.
RAISERROR (#ErrorMessage, #ErrorSeverity, #ErrorState);
END CATCH
You are almost there. I usually wrap the stored proc code within a BEGIN..END block as well, then next comes the most important part: you must add SET XACT_ABORT ON; before your TRY..CATCH and BEGIN TRAN, as SQL Server defaults the XACT_ABORT to OFF. Otherwise not everything will be rolled back.
Example setup:
CREATE PROCEDURE dbo.uspMyTestProc
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
-- Do your magic stuff here before committing...
COMMIT;
END TRY
BEGIN CATCH
IF ##trancount > 0
ROLLBACK TRANSACTION;
-- Add extra error logging here if you want...
END CATCH;
END;
GO
Also, if you want to add a possible stacktrace if you are using nested procedures et cetera you might want to consider using a generic error handler à la Erland Sommerskog. We adapted this approach completely. See for more details How to handle Transaction in Nested procedure in SQL server?

T-SQL Merge statement in stored procedure throws error

Recently I have had to change a query from the following (fully working):
/****** WORKING ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [operations].[ROIWarehouseDatas]
(#Operation VARCHAR(50) = NULL,
#TableName NVARCHAR(255) = NULL,
#Results [dbo].[ForeSightData] READONLY)
AS
BEGIN
DECLARE #err INT
SET #err = 0
IF (#Operation = 'Insert')
BEGIN
DECLARE #SQLString NVARCHAR(4000)
DECLARE #ParamDefinition NVARCHAR(4000)
SET #SQLString = N'TRUNCATE TABLE ['+ #TableName + N'];
INSERT INTO ['+ #TableName + N']
SELECT [ID], [BrandName], [AdvertName], [VersionName], [WCPM]
FROM #Results;';
SET #ParamDefinition = N'#Operation VARCHAR(50), #Results [dbo].[ForeSightData] READONLY';
EXECUTE sp_executesql #SQLString, #ParamDefinition, #TableName, #Results
END
--ENDIF Insert
SET #err = ##ERROR
RETURN #err
END
To the following (not working):
/****** NOT WORKING ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [operations].[ROIWarehouseDatas]
(#Operation VARCHAR(50) = NULL,
#TableName NVARCHAR(255) = NULL,
#Results [dbo].[ForeSightData] READONLY)
AS
BEGIN
DECLARE #err INT
DECLARE #SQLString NVARCHAR(4000)
DECLARE #ParamDefinition NVARCHAR(4000)
SET #err = 0
IF (#Operation = 'Insert')
BEGIN
SET #SQLString = N'MERGE INTO ['+ #TableName +'] AS T
USING #Results AS S ON T.ID = S.ID
WHEN MATCHED
THEN UPDATE
SET T.[BrandName] = S.[BrandName],
T.[AdvertName] = S.[AdvertName],
T.[VersionName] = S.[VersionName],
T.[VersionDuration] = S.[VersionDuration],
T.[WCPM] = S.[WCPM]
WHEN NOT MATCHED BY TARGET
THEN INSERT ([ID], [BrandName], [AdvertName], [VersionName], [WCPM])
VALUES (S.[ID], S.[BrandName], S.[AdvertName], S.[VersionName], S.[WCPM]);';
SET #ParamDefinition = N'#Operation VARCHAR(50), #Results [dbo].[ForeSightData] READONLY';
EXECUTE sp_executesql #SQLString, #ParamDefinition, #TableName, #Results
END
--ENDIF Insert
SET #err = ##ERROR
RETURN #err
END
However, when I run the program I get the following error:
An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. Unclosed quotation mark after the character string ''.
Incorrect syntax near ''.
I tried checking the syntax - and that came up as fine.
Seems not correct syntax for SQL MERGE.
WHEN NOT MATCHED BY T THEN should be Target not T:
WHEN NOT MATCHED BY Target
THEN .....

Looping through each table in a database dropping and creating a trigger

I have following two statements executing triggers:
IF EXISTS (SELECT * FROM sys.triggers
WHERE Object_ID = Object_ID("Insert_Serverdate_Into_CreatedAt"))
DROP TRIGGER Insert_Serverdate_Into_CreatedAt
GO
CREATE TRIGGER Insert_Serverdate_Into_CreatedAt ON *myTable*
AFTER INSERT
AS
BEGIN
INSERT INTO *myTable* (CreatedAt) VALUES(GETDATE())
END
GO
IF EXISTS (SELECT * FROM sys.triggers
WHERE Object_ID = Object_ID("Insert_Serverdate_Into_UpdatedAt"))
DROP TRIGGER Insert_Serverdate_Into_UpdatedAt
GO
CREATE TRIGGER Insert_Serverdate_Into_UpdatedAt ON *myTable*
AFTER UPDATE
AS
BEGIN
INSERT INTO *myTable* (UpdatedAt) VALUES(GETDATE())
END
GO
Now I have found two possibilities to loop through each table in my database
The first one is:
EXECUTE sp_MSforeachtable #command1 = myCommand
The second one is:
DECLARE #NAME VARCHAR(100)
DECLARE #SQL NVARCHAR(300)
DECLARE CUR CURSOR FOR
SELECT NAME
FROM SYS.TABLES
WHERE TYPE = 'U'
AND SCHEMA_ID = 1
OPEN CUR
FETCH NEXT FROM CUR INTO #NAME
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = myCommand
PRINT #SQL
EXEC Sp_executesql
#SQL
FETCH NEXT FROM CUR INTO #NAME
END
CLOSE CUR
DEALLOCATE CUR
The problem here is that these possibilities do not know the keyword GO which I need for executing my commands.
Is there a possibility to loop through all tables and execute my statement?
Thank you!
Give each of the four parts its own query like this:
DECLARE #NAME VARCHAR(100)
DECLARE #SQL1 NVARCHAR(300)
DECLARE #SQL2 NVARCHAR(300)
DECLARE #SQL3 NVARCHAR(300)
DECLARE #SQL4 NVARCHAR(300)
DECLARE CUR CURSOR FOR
SELECT NAME
FROM SYS.TABLES
WHERE TYPE = 'U'
AND SCHEMA_ID = 1
OPEN CUR
FETCH NEXT FROM CUR INTO #NAME
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL1 = 'IF EXISTS (SELECT *
FROM sys.triggers
WHERE Object_ID = Object_ID(''['+#Name+'_Insert_Serverdate_Into_CreatedAt]''))
DROP TRIGGER ['+#name+'_Insert_Serverdate_Into_CreatedAt]'
SET #SQL2 = 'CREATE TRIGGER ['+ #Name + '_Insert_Serverdate_Into_CreatedAt] ON ['+#Name+']
AFTER INSERT
AS
BEGIN
INSERT INTO ['+#Name+'] (CreatedAt) VALUES(GETDATE())
END'
SET #SQL3 = 'IF EXISTS (SELECT *
FROM sys.triggers
WHERE Object_ID = Object_ID(''['+#Name+'_Insert_Serverdate_Into_UpdatedAt]''))
DROP TRIGGER ['+#name+'_Insert_Serverdate_Into_UpdatedAt]'
SET #SQL4 = 'CREATE TRIGGER ['+#Name+'_Insert_Serverdate_Into_UpdatedAt] ON ['+#Name+']
AFTER UPDATE
AS
BEGIN
INSERT INTO ['+ #Name+'] (UpdatedAt) VALUES(GETDATE())
END'
PRINT #SQL1
EXEC Sp_executesql #SQL1
PRINT #SQL2
EXEC Sp_executesql #SQL2
PRINT #SQL3
EXEC Sp_executesql #SQL3
PRINT #SQL4
EXEC Sp_executesql #SQL4
FETCH NEXT FROM CUR INTO #NAME
END
CLOSE CUR
DEALLOCATE CUR

pass table name as parameter in sql server

I want to pass table name as parameter and I want to that parameter in where clause
CREATE PROC [dbo].[bb_GetPrepositionInfo]
#userid INT,#propId INT,#tabName varchar(50)
AS
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
SELECT *
FROM #tblname
WHERE ([acq_id] = #propId AND [user_id] = #userid)
COMMIT
GO
Not tested but You need to use Dynamic SQL.
CREATE PROC [dbo].[bb_GetPrepositionInfo]
#userid INT,#propId INT,#tabName varchar(50)
AS
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
DECLARE #SQL varchar(250)
SELECT #SQL = 'SELECT * FROM ' + QuoteName(#tabName) + ' where acq_id=' + Quotename(#propId) + ' AND user_id=' + Quotename(#userid)
EXEC (#SQL)
COMMIT
GO
CREATE PROC [dbo].[bb_GetPrepositionInfo]
DECLARE #userid INT
DECLARE #propId INT
DECLARE #tabName varchar(50)
DECLARE #sqlCommand varchar(200)
AS
SET NOCOUNT ON
SET XACT_ABORT ON
BEGIN TRAN
SET #sqlCommand = 'SELECT * from ' + #tabName +'WHERE [acq_id]='+ #propId +'AND [user_id] = '+ #userid
EXEC (#sqlCommand)
COMMIT
GO

Resources