Update a Table with Dynamic SQL results within Stored Procedure - sql

I have a table EPFReport where I need to fill the tables with a stored procedure.
ALTER procedure [dbo].[getEPFData] #EPFCol varchar(max) , #empID varchar(max)
AS
DECLARE #sql nvarchar(max) ;
DECLARE #sql2 nvarchar(max);
set #sql = 'SELECT c.employeeID,c.empName, c.month,#sql1 from Common c where c.employeeID='+#empID
set #sql2= 'SELECT ' + #EPFCol + ' FROM Common where employeeID='+#empID
truncate table EPFReport;
INSERT into EPFReport (empID, empName, monthVal)
execute(#sql);
Up to here the requirement is fulfilled where the results of the query #sql will be inserted to the table. Now I need to update it with #sql2 query, so the question is how to execute a query within a stored procedure for an update statement?
PS: for insert I've used
INSERT into EPFReport (empID, empName, monthVal)
execute(#sql);
Also here a set of results are returned (for each month). Not one row or cell of result. So assigning to a variable and updating doesn't work.
Update: the table contains these columns
[empID] [empName] [EPFItemValues] [monthVal]
First query updates only 3 columns , and the second query should update the column EPFItemValues.

Try;
Based on your comment, the following should work;
DECLARE #ID int = (Select MAX(ID) From EPFReport) // or SCOPE_IDENTITY
Update EPFReport
set EPFItemValues = #sql2
where ID = #ID

Related

How to add database name dynamically in a table while update statement

I have 50 databases and each of them has a tblEmp table. There is one row in tblEmp table in each database. I want to update some column data in tblEmp.
I have written below script for to update one column in tblEmp table. There is a challenge in update statement. I am getting all database name by using this script.
SELECT name
FROM master.dbo.sysdatabases
and I'm looping over each row (each database), then I want to update the tblEmp table in that database.
My question is how to add database name dynamically along with Update statement. Please see my SQL scripts below.
DECLARE #totalRecords int
DECLARE #name NVARCHAR(max)
DECLARE #userData AS TABLE (dbName NVARCHAR(max))
INSERT INTO #userData
SELECT name FROM master.dbo.sysdatabases
SET #totalRecords = ##rowcount
WHILE (#totalRecords > 0)
BEGIN
DECLARE #emptextout NVARCHAR(max)
SELECT TOP 1 #name = dbName FROM #userData
DECLARE #empdefaulttext nvarchar(max) = (N'SELECT #emptextout = CAST(empInfo AS NVARCHAR(max)) FROM '+#name +'.dbo.tblEmp')
EXECUTE sp_executesql #empdefaulttext,#Params=N'#emptextout NVARCHAR(max) OUTPUT', #emptextout = #emptextout OUTPUT
-- Here in update statement how to add database name dynamically. It should be as Update **DBName.dbo.tblEmp** set..
UPDATE tblEmp
SET empInfo = REPLACE(#emptextout, 'Rajesh', 'InfoRajesh')
SET #totalRecords = #totalRecords - 1
DELETE FROM #userData
WHERE dbname = #name
END
As Dale K mentioned:
set #empdefaulttext = N'Update '+#name +N'.dbo.tblEmp
SET empInfo = REPLACE(#emptextout, ''Rajesh'', ''Kuthrapali'')'
EXECUTE sp_executesql #empdefaulttext,#Params=N'#emptextout NVARCHAR(max) OUTPUT', #emptextout = #emptextout OUTPUT

HOw to Fix 'Sql Trigger for Insert not working with Declare Variable'

I'm trying to insert rows from one table into another using a trigger with declared variable. When I run the code separately, it works for insert, but I want to create a trigger and return 0 rows
This is what I tried
CREATE TRIGGER Final
ON schedule
FOR INSERT
AS
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = 'INSERT INTO Datatable (Name, SAP_ID, Enterprise_IDs, Queue,d)
SELECT Name, SAP_ID, Enterprise_IDs, Queue, [' +
CONVERT(NVARCHAR(MAX), DAY(GETDATE())) + '] AS d
FROM schedule'
EXEC (#sql)
END
I expect the rows must be inserted into another table, but 0 rows are getting inserted
My guess is that the schedule is empty. You don't want to insert the rows from schedule. You want to use inserted instead:
CREATE TRIGGER Final ON schedule
FOR INSERT
AS
begin
declare #sql nvarchar(max);
set #sql = N'
insert into Datatable(Name, SAP_ID, Enterprise_IDs,Queue,d)
select Name, SAP_ID, Enterprise_IDs, Queue, [#d]
from inserted
';
set #sql = replace(#sql, '#d', day(getdate());
exec sp_executesql #sql;
end;
go
Having written this, I'm not sure if inserted is allowed in dynamic SQL.
I don't see why you need to use dynamic query, when you can just do it as below?
CREATE TRIGGER Final
ON schedule
FOR INSERT
AS
BEGIN
INSERT INTO Datatable (Name, SAP_ID, Enterprise_IDs, Queue,d)
SELECT Name, SAP_ID, Enterprise_IDs, Queue, CONVERT(NVARCHAR(MAX),DAY(GETDATE()))
FROM inserted
END
UPDATE
just by executing this part
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'SELECT [' + convert(nvarchar(max),day(getdate())) + '] AS d '
print #sql
EXEC (#sql)
you will see that your script is throwing an error as [9] (if we consider todays date) is invalid column, sql engine thinks its a column from your table schedule, get rid of the brackets and it should work fine

How to get table from EXEC sp_executesql in #TempTable, within a stored procedure

I need some help
My goal:
I have a #query in a stored procedure which is working perfectly. Now I have to perform more operation on the returning table from #query execution within same stored procedure. e.g I have to add more columns in the returning table and add new data from more queries.
My problem:
I am not able to get returning table form (EXEC sp_executesql) into a variable (#TempTable). And one more problem is that the number of columns returning are not known (dynamic).
Steps should be like this:
Declare TempTable
TempTable = EXEC sq_executesql
Add new columns to TempTable
Fill more data
Kindly guide me
this can be achieved using global temp tables like below :
DECLARE #sql NVARCHAR(1000)
DECLARE #Column NVARCHAR(1000)
SET #Column = 'YouColumnList' -- id,name etc. created by you dynamically.
IF( Object_id('tempdb..##IntermediateTable') IS NOT NULL )
DROP TABLE ##IntermediateTable
SET #sql = '
SELECT ' + #Column + '
Into ##IntermediateTable
FROM YourTable
WHERE id = 123
'
EXEC sp_executesql
#sql
IF( Object_id('tempdb..#temptable') IS NOT NULL )
DROP TABLE #temptable
SELECT *
INTO #temptable
FROM ##IntermediateTable
IF( Object_id('tempdb..##IntermediateTable') IS NOT NULL )
DROP TABLE ##IntermediateTable
SELECT *
FROM #temptable --resulting temptable to use. alter it or do whatever desired.

How to use Table Variable in Dynamic Query

I want to use Table Variable instead of Temp Table but My main query construction is Dynamic .
Dynamic query is in single quote so how can I fetch data from #TableVariable.
I dont want to remove dynamic query because some of parameter will added later.
e.g. following is error code , where I have wrote table variable into Dynamic Query........
/*Declare Table Variable*/
DECLARE #TempVehicles TABLE
(
[VehicleID] INT
)
/*Insert data into Table Variable*/
INSERT INTO #TempVehicles
(
[VehicleID]
)
SELECT VehicleID
FROM tbl_Vehicles
/*Dynamic Query and Main SQL Construction*/
DECLARE #SQL NVARCHAR(MAX)
SET #SQL ='SELECT Cust_ID,A.VehicleID,GISInfo
FROM #TempVehicles A INNER JOIN tbl_GISData B ON A.VehicleID=B.VehicleID'
EXECUTE SP_EXECUTESQL #SQL
Help me , in this .
Thanks in Advance.
Try This :
CREATE TYPE IntegerTableType AS TABLE (ID INT);
go
DECLARE #TempVehicles IntegerTableType;
INSERT #TempVehicles
values (1);
DECLARE #SQL NVARCHAR(MAX);
SET #SQL ='SELECT *
FROM #TempVehicles;';
EXECUTE SP_EXECUTESQL #SQL,N'#TempVehicles IntegerTableType READONLY',
#TempVehicles;
As an alternate solution you can use #TempVehicles instead of storing it in variable.
SELECT VehicleID
into #TempVehicles
FROM tbl_Vehicles
/*Dynamic Query and Main SQL Construction*/
DECLARE #SQL NVARCHAR(MAX)
SET #SQL ='SELECT Cust_ID,A.VehicleID, GISInfo
FROM #TempVehicles A INNER JOIN tbl_GISData B ON A.VehicleID=B.VehicleID;
Drop Table #TempVehicles'
EXECUTE SP_EXECUTESQL #SQL
Try and check whether it meets your requirement.

Execute sp_executeSql for select...into #table but Can't Select out Temp Table Data

Was trying to select...into a temp Table #TempTable in sp_Executedsql.
Not its successfully inserted or not but there Messages there written
(359 row(s) affected) that mean successful inserted?
Script below
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = 'select distinct Coloum1,Coloum2 into #TempTable
from SPCTable with(nolock)
where Convert(varchar(10), Date_Tm, 120) Between #Date_From And #Date_To';
SET #Sql = 'DECLARE #Date_From VARCHAR(10);
DECLARE #Date_To VARCHAR(10);
SET #Date_From = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
SET #Date_To = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
'+ #Sql;
EXECUTE sp_executesql #Sql;
After executed,its return me on messages (359 row(s) affected).
Next when trying to select out the data from #TempTable.
Select * From #TempTable;
Its return me:
Msg 208, Level 16, State 0, Line 2
Invalid object name '#TempTable'.
Suspected its working only the 'select' section only. The insert is not working.
how fix it?
Using a global temporary table in this scenario could cause problems as the table would exist between sessions and may result in some problems using the calling code asynchronously.
A local temporary table can be used if it defined before calling sp_executesql e.g.
CREATE TABLE #tempTable(id int);
execute sp_executesql N'INSERT INTO #tempTable SELECT myId FROM myTable';
SELECT * FROM #tempTable;
Local temporary table #table_name is visible in current session only, global temporary ##table_name tables are visible in all sessions. Both lives until their session is closed.
sp_executesql - creates its own session (maybe word "scope" would be better) so that's why it happens.
In your #sql string, don't insert into #TempTable. Instead, call your SELECT statement without an INSERT statement.
Finally, insert the results into your temporary table like so:
INSERT INTO #tmpTbl EXEC sp_executesql #sql
Also, you'll need to declare the temporary table if you use this approach
DECLARE #tmpTbl TABLE (
//define columns here...
)
your temp table in dynamic SQL is out of scope in the non dynamic SQL part.
Look here how to deal with this: A bit about sql server's local temp tables
Temporary tables only live as long as the connection that creates them. I would expect that you're unintentionally issuing the select on a separate connection. You can test this by momentarily doing your insert into a non-temporary table and seeing if your data is there. If that is the case you can go back to your original solution and just be sure to pass the connection object to your select.
declare #sql varchar(1000)
set #sql="select * into #t from table;"
set #sql =#sql + "select * from #t;"
execute SP_EXECUTESQL #sql
This worked for me
declare #sql nvarchar(max)
create table #temp ( listId int, Name nvarchar(200))
set #sql = 'SELECT top 10 ListId, Name FROM [V12-ListSelector].[dbo].[List]'
insert into #temp
exec sp_executesql #sql
select * from #temp
drop table #temp
To work around this issue use a CREATE TABLE #TEMPTABLE command first to generate an empty temp table before running sp_executesql. Then run the INSERT INTO #TEMPTABLE with sp_executesql. This will work. This is how I overcome this problem as I have a setup in which all my queries are usually run via sp_executesql.
This one worked for me:
DECLARE #Query as NVARCHAR(MAX);
SET #Query=(SELECT * FROM MyTable) ;
SET #Query=(SELECT 'SELECT * INTO dbo.TempTable FROM ('+#Query +') MAIN;');
EXEC sp_executesql #Query;
SELECT * INTO #TempTable FROM dbo.TempTable;
DROP TABLE dbo.TempTable;
SELECT * FROM #TempTable;
Note, from T-SQL 2021 onwards, dm_exec_describe_first_result_set() can be used to build a temporary table in the right shape to INSERT INTO - as it gives you the column names and types that will be returned from your dynamic SELECT or EXEC ... so you can build dynamic SQL to ALTER a temporary table into the shape you need.
DECLARE #strSQL NVarChar(max) = 'EXEC [YourSP] #dtAsAt=''2022-11-09'', #intParameter2=42'
--*** Build temporary table: create it with dummy column, add columns dynamically
--*** using an exec of sys.dm_exec_describe_first_result_set() and dropping the dummy column
DROP TABLE IF EXISTS #tblResults;
CREATE TABLE #tblResults ([zz] INT);
DECLARE #strUpdateSQL NVarChar(max);
SELECT #strUpdateSQL = STRING_AGG( CONCAT( 'ALTER TABLE #tblResults ADD ',
QUOTENAME([name]), ' ',
[system_type_name], ';')
, ' ') WITHIN GROUP (ORDER BY [column_ordinal])
FROM sys.dm_exec_describe_first_result_set (#strSQL, NULL, 0)
SET #strUpdateSQL += 'ALTER TABLE #tblResults DROP COLUMN [zz];'
EXEC (#strUpdateSQL);
--*** Now we have #tblResults in the right shape to insert into, and use afterwards
INSERT INTO #tblResults EXEC (#strSQL);
SELECT * FROM #tblResults;
--*** And tidy up
DROP TABLE IF EXISTS #tblResults;