Dynamic Pivot As Function, Table Function Or Stored Procedure - function

I have a table that was created to show a client's areas in rows not columns. I created a pivot as a solution for this. I understand that there are other options like CASE statement and JOINS that might also work. The next step was to see if I can add it to a function or Stored Procedure. I was not able to find something to help me with functions or table functions that was easy to understand, or I am too stupid. I did create a SP, but I can't seem to use it within a SELECT statement as per some blogs I read. So, to all the experts out there what is the best practice to make sure I do this effectively.
DATA EXTRACTION BEFORE
DATA EXTRACTION WITH PIVOT
The above is the data I extracted from one client - I will have anything from 10K to 50K records if not more. Not sure if that is relevant?? But the issue is that I need to link it to the client table and address table and and....
Below is my pivot attempt and my SP attempt as well as my Table Function.
Then when I try to do a table function, I get this error as per >>> [![PIVOT TABLE FUNCTION](https://i.stack.imgur.com/WWDhq.png)](https://i.stack.imgur.com/WWDhq.png)
Also this error: Invalid use of a side-effecting operator 'EXECUTE STRING' within a function
If anyone can point me in the right direction or advise me what I need to look for to continue my google search, I would and will really, really appreciate it.
Thanks
> SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ======================================================
-- Author: Stefan Kleinhans
-- Create date: 02-11-2022
-- Description: Supplying client areas in single columns
-- ======================================================
CREATE FUNCTION [crm].[UDF_GetClientAreas_Gain] (#AreaGroup Varchar(10), #TenantId INT)
RETURNS #T TABLE
(
TenantID INT,
CustID INT,
Division Char(2),
Technical Char(3),
SubDivision Char(3),
MainArea Char(3),
SubArea Char(3)
)
AS
BEGIN
DECLARE #FieldList varchar(1000)
/****** Script for SelectTopNRows command from SSMS ******/
SELECT #FieldList = CONCAT('[',STRING_AGG([AreaType],'],['),']')
FROM (
SELECT DISTINCT [AreaType], GroupLevel
FROM [Xyro_ADF].[crm].[dimClientAreas]
WHERE AreaGroup = #AreaGroup
AND AreaType <> 'Division'
) a
DECLARE #Str varchar(max)
SET #Str = 'SELECT TenantID, CustID, Division, ' + #FieldList + ' FROM
(
SELECT TenantID, CustID, Division, AreaType, AreaName
FROM [Xyro_ADF].[crm].[dimClientAreas]
WHERE AreaGroup = ''' + #AreaGroup + '''
AND TenantID = ' + CONVERT(varchar,#TenantId) + '
) AS DataTbl
PIVOT
( MAX(AreaName) FOR AreaType IN (' + #FieldList + ')
) AS PVTbl'
--PRINT(#Str)
EXEC(#Str)
RETURN
END
USE [Xyro_ADF]
GO
/****** Object: StoredProcedure [dbo].[usp_ClientArea_Pivot] Script Date: 28/10/2022 07:19:53 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ====================================================================================
-- Author: Stefan Kleinhans
-- Create date: 28-Oct-2022
-- Description: A procedure that uses dynamic SQL for a PIVOT operation
-- ====================================================================================
CREATE PROCEDURE [dbo].[USP_ClientArea_Pivot]
(#TenantID INT,
#CustID INT)
AS
BEGIN
DECLARE
#Col VARCHAR(MAX),
#Str VARCHAR(MAX)
SET NOCOUNT ON
SET #Col = (SELECT STRING_AGG(AreaType, ', ') FROM (SELECT DISTINCT AreaType FROM [Xyro_ADF].[crm].[dimClientAreas] WHERE AreaType <> 'Division') AS x)
SET #Str =
'SELECT AreaGroup, Division, '+ #Col +'
FROM
(SELECT TenantId, CustId, AreaGroup, Division, AreaType, AreaName
FROM [Xyro_ADF].[crm].[dimClientAreas]) AS Source_Table
PIVOT
(MAX(AreaName) for AreaType IN ('+ #Col +')
)as Pivot_Table
WHERE TenantId = '+ CONVERT(VARCHAR,#TenantID) +'
AND CustId = '+ CONVERT(VARCHAR,#CustID) +' '
EXEC (#Str)
SET NOCOUNT OFF
END
GO
/* EXECUTE SP WITH #TenantId & #ClientId */
--EXEC [dbo].[usp_ClientArea_Pivot] 1,33395

Related

is there any way we can name our table as our local variable value (T-SQL)

im tring this piece of code..
declareing a variable and than adding GETDATE() with casting so that table name is unique.. and than inserting all the data from the existing table to the new backuptbl i jux made..
begin
declare #st varchar(200);
SET #st = 'tblNameBackup_'+CAST(getdate() as varchar(100));
PRINT #st
create table mytbl -- <<-- i wish to set my table name as #st
(
tID int,
tName nchar(20)
)
select * into mytbl from thet-able-whose-backup-to-be-taken;
end
actually i wish to backup my table at every transaction therefore i was trying this.. i know this is not the real situation (as i am also doing this for practice if we can do this or not) hope u understand my question thanx for any help
You'll need to make dynamic SQL, if I understand you correct, and execute that:
Something similar to this:
declare #st varchar(200);
SET #st = 'tblNameBackup_'+CAST(getdate() as varchar(100));
EXEC('create table ' + #st + '
(
tID int,
tName nchar(20)
)
select * into mytbl from thet-able-whose-backup-to-be-taken;');
Be careful about injection possibilities, also instead of just EXEC you can wrap it in sp_executesql or similar. It's just to illustrate the method.

Cast in SQL Server query

I am having a problem with executing one SQL query, Below is my stored procedure
Query
ALTER PROCEDURE ProcName
(
#iID VARCHAR(50),
#AccountID INT
)
AS
SET NOCOUNT ON
DECLARE #Sql VARCHAR(MAX)
SET #Sql = 'DELETE FROM ReferringPhysician WHERE iID IN(' + #iID + ') AND AccountID = '+ #AccountID + ''
EXEC (#Sql)
I am trying to execute this query but it gives me error because i am using exec(), Here in my where condition i am dealing with the string, and in another condition i am dealing with the int, so in second condition i am getting casting error! how can i get through this?
Any help is greatly Appreciated!
Thanks
Your query is susceptible to SQL injection.
One way to avoid the data type problem you are having is to pass proper data types where you can and not use EXEC() (more details here):
DECLARE #sql NVARCHAR(MAX) = N'DELETE dbo.referringPhysician
WHERE iID IN (' + #iID + ') AND AccountID = #AccountID;';
EXEC sp_executesql #sql, N'#AccountID INT', #AccountID;
You can completely protect this from SQL injection by using table-valued parameters and passing in a DataTable or other collection with proper types instead of a comma-delimited string. e.g.:
CREATE TYPE dbo.iIDs TABLE(iID INT PRIMARY KEY);
Now your stored procedure can avoid dynamic SQL altogether:
ALTER PROCEDURE dbo.ProcName -- always use schema prefix!
#iIDs dbo.iIDs READONLY,
#AccountID INT
AS
BEGIN
SET NOCOUNT ON;
DELETE r
FROM dbo.ReferringPhysician AS r
INNER JOIN #iIDs AS i
ON r.iID = i.iID
WHERE r.AccountID = #AccountID;
END
GO
Try this:
ALTER PROCEDURE ProcName
(
#iID VARCHAR(50),
#AccountID INT
)
AS
SET NOCOUNT ON
DECLARE #Sql VARCHAR(MAX)
SET #Sql = 'DELETE FROM ReferringPhysician WHERE iID IN(' + CAST(#iID AS VARCHAR) + ') AND AccountID = '+ CAST(#AccountID AS VARCHAR) + ''
EXEC (#Sql)

How to pass list of items as parameter to a stored procedure

I have a stored procedure
create PROCEDURE [dbo].[SP]
(
#OrderList varchar(500)
)
AS
Begin
select *
from table
where id in ('+ #OrderList +')
Here I am passing orderlist....
When I execute like this
exec sp 'iss005,iss006'
I am not getting data
but when I hardcode in sp like this ...
select * from table where id in ('iss005','iss006')
then am getting data...
Thank you
Unfortunately it won't work that way. If you change your procedure to something like the following, this will work:
Create Procedure dbo.SP
#OrderList varchar(500)
AS
Declare #SQL VarChar(1000)
Select #SQL = 'SELECT * FROM table '
Select #SQL = #SQL + 'WHERE id in (' + #OrderList +')'
Exec ( #SQL)
GO
Looking more into your query, your ID's value varchar, so the procedure will fail as you'll still be getting :
WHERE id in (iss005,iss006)
when you want :
WHERE id in ('iss005','iss006')
You would need to either pass in the quote values, e.g. :
#OrderList = 'iss005','iss006'
Or work out some SQL to split the #OrderList by comma and use the QUOTENAME() function to add the quotes to the new variable.
I strongly recommend in this case the use of XML parameters, will give you a lot of flexibility.
Your XML might be something like
<ids>
<id>iss006</id>
<id>iss005</id>
</ids>
Your procedure should be something like this:
create PROCEDURE [dbo].[SP]
(
#OrderList XML
)
AS
Begin
select * from table
where id in (
select ParamValues.ID.value('.','VARCHAR(50)')
FROM #OrderList.nodes('/ids/id') as ParamValues(id)
)
Besides the use of store procedures outputs I also would recommend the use of functions but that is up to you.
Regards.
I had the same kind of requirement. i was getting list of user in a int list variable and i need to get all the order of those user. I have use a very simple trick which had solve my issue. please find the code.
public DataTable GetAllOrderData(List<int> UserID)
{
try
{
string listofuser = String.Join(",", UserID.ToArray());
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter("#USERID", listofuser)
};
return SqlDBHelper.ExecuteParamerizedSelectCommand("GetOrderByUserID", System.Data.CommandType.StoredProcedure, parameters);
}
finally { UserID = null; }
}
And this is the stored procedure
CREATE PROCEDURE [dbo].[GetOrderByUserID] (#USERID varchar(700))
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #SQL VarChar(1000)
Select #SQL = 'SELECT *,ORM.OrganisationName FROM OrderTransaction ORT LEFT JOIN OrganisationMaster ORM ON (ORT.OrganisationID=ORM.OrganisationID) '
Select #SQL = #SQL + 'WHERE ORT.CreatedBy IN (' + #USERID +')'
Exec ( #SQL)
END

The return types for the following stored procedures could not be detected

While drag-drop a stored procedure in dbml file I get this error:
Unknown Return Type
The return types for the following stored procedures could not be detected. Set the return type for each stored procedure in the Properties window.
How can I resolve this error?
This problem occurs whenever the designer cannot figure out the return type of the SP.
Same problem and solutions described here
How to get multiple result set of procedure using LINQ to SQL
Basically this is the solution from the link:
Avoid using #temp Table in your stored procedure, instead of you can use Table type variable like below (#TempTable)
Ex:
DECLARE #TempTable TABLE
(
AttributeID INT,
Value NVARCHAR(200)
)
INSERT INTO #TempTable Select * from Attribute
OR
--Execute SP and insert results into #TempTable
INSERT INTO #TempTable Exec GetAttribute #Id
You can do all operation which you was doing with #Temp table like
Join, Insert, Select etc.
Add these lines right after parameters declaration
AS
IF 1=0 BEGIN
SET FMTONLY OFF
END
After this, write BEGIN and start your procedure work .
I was using a temp table in my SQL and was getting this error. I converted the temp table to table variables and that resolved my issue.
This can be also the problem of access rights. If the stored procedure doesn't have an access to the table you get the same error. I had a query selecting data from another database I didn't have rights for (in fact the account running the Visual Studio connection didn't have the rights) and I received the same error. After adding proper rights everything went fine.
Trying to execute the stored procedure inside VS2010 (by right clicking in Server Explorer and selecting "Execute") helped me to solve the problem.
I've just added about 300 stored procs to my DBML and experienced many of the problems noted here and elsewhere.
Here is a summary of the causes & solutions for the error "The return types for the following stored procedures could not be detected", based on what I have personally experienced. Note that the problems described below can occur in the SP that you are having the error with, or any other SP that is being called from that SP directly or indirectly.
Concatenating integers with string using a '+' symbol. Use CAST() on the integers, or in SQL2012 or higher use the CONCAT() statement.
Referencing tables in other databases. Apparently a permissions issue. I wasn't able to resolve this one.
Any direct or indirect call to XP_CMDSHELL. I wasn't able to resolve this one.
Any syntax error in direct or indirect calls to other stored procs. Fix the call to the SP.
Temp Tables. Replace the Temp Table with a Table Variable.
SET QUOTED_IDENTIFIER OFF is in use, but the table being edited has a Indexed View on it. *Change the set statement to SET QUOTED_IDENTIFIER ON.*
Reason: Your Stored Procedure will be returning a complex type. that is, multiple results or uses a temp table.
Resolution
It entirely depends on what your Stored Procedure is doing. Useful links
http://odetocode.com/code/365.aspx
http://riteshkk2000.blogspot.com/2010/08/error-unknown-return-type-return-types.html
Just in case anyone else comes across this, I have just experienced it myself.
In my case, I was referencing a table in an insert statement that no longer existed in my schema. A closer inspection of my code revealed I was inserting into a table called "Account" which was now called "tblAccount". Visual Studio threw no errors on saving the sp, but I experienced the same error when trying to add the sp to the dbml file.
Hopefully this will help someone else out.
I also had this problem - had to comment out code that was constructing a polygon:
declare
#MapBounds geography
;
select
#MapBounds = geography::STGeomFromText('POLYGON((' +
cast(#NorthEastLng as varchar) + ' ' + cast(#NorthEastLat as varchar) + ', ' +
cast(#SouthWestLng as varchar) + ' ' + cast(#NorthEastLat as varchar) + ', ' +
cast(#SouthWestLng as varchar) + ' ' + cast(#SouthWestLat as varchar) + ', ' +
cast(#NorthEastLng as varchar) + ' ' + cast(#SouthWestLat as varchar) + ', ' +
cast(#NorthEastLng as varchar) + ' ' + cast(#NorthEastLat as varchar) +
'))', 4326)
;
Once it was added to the dmbl, I un-commented out the code and it worked like a champ!
I also had the problem (VS 2012, SQL Server 2008R2). In my case it was a combination of the + operator and various CAST statements in the code. I haven't found a way to replace them with something VisualStudio likes, but I have come up with a workaround:
Workaround "Dummy SELECT":
Create a dummy SELECT statement with all the fields you need to return. For example:
select 'bla bla' as field1, 123123 as field2, 'asñfs' as field3
Comment out your SP code and just leave the dummy SELECT in your SP.
Add your SP in the O/R designer and save (it should do know without an error message)
Restore your original SP (leave the dummy SELECT as a comment for future use)
You might as well consider using CONCAT() method instead of '+' to concat a string. Since I wasn't using temp table and yet still encounter this problem. I found out that concating strings using '+' triggering this.
In my case, I was using this:
SET #errorMessage = CONCAT('Update (ID=', #pnID, ') failed. Name already exists.');
Instead of:
SET #errorMessage = 'Update (ID=' + #pnID + ') failed. Name already exists.';
Just ran into this issue while trying to add a stored procedure into a DBML (LINQ) file.
Doing some research I found that this usually happens when the stored procedure returns multiple results or uses a #temp table for it's final select.
The solution that worked for me was to create a new stored procedure that wrapped the results of the original stored procedure result, into a table variable with the same columns as the temp table.
My wrapper stored proc looked something like this:
DECLARE #NewPrograms TABLE (
Campaign_Number int,
Campaign_Display nvarchar(255)
)
INSERT INTO #NewPrograms
EXEC [dbo].[Original_Stored_Proc_With_Temp_Table_Result] #Program_ID
Select *
From #NewPrograms
Open up your DBML file, drag-and-drop in your new wrapper stored proc.
Make sure the stored procedure runs without erroring. Just had this problem and I assumed the person who made the stored procedure had tested it and did not try it myself.
The solution I found ... I put a SELECT on top (IF) with conditions that are not correct and create a variable table with the result he wanted to exit and then "ELSE" put things right. The first part is only if you understand the process output I want. Look at my example
ALTER PROCEDURE [dbo].[SS_getSearchedProductsDetailsNew]
(
#mk int,
#md int,
#yr int = 0,
#caroption int = 0,
#condition int = 0,
#producttype int = 0 ,
#option int = 0,
#coloroption int = 0
)
AS
declare #sql nvarchar(max)
Begin
if #mk = 0 and #md = 0 and #yr = 0
begin
Declare #TempTable2 TABLE(
ProductID numeric(10),
TypeName nvarchar(50),
MakeID numeric(10),
ModelID numeric(10),
ConditionID numeric(10),
CarOptionsID numeric(10),
OptionsID numeric(10),
ColorOptionsID numeric(10),
Make nvarchar(50),
Model nvarchar(50),
YearID numeric(5),
Color nvarchar(50),
ProductType nvarchar(50),
CarOptionName nvarchar(50),
OptionName nvarchar(50),
ColorOptionName nvarchar(50),
ConditionName nvarchar(50),
Notes nvarchar(500),
Price money,
cog money)
select * from #TempTable2
end
else
begin
select #sql = '
declare #theNotes nvarchar(500)
declare #theMake numeric(10), #theModel numeric(10), #theYear numeric(10)
declare #makeName nvarchar(50), #modelName nvarchar(50), #ID numeric(5)
declare #theProductType nvarchar(50), #theTypeName nvarchar(50)
declare #theColor nvarchar(50),#theProductID numeric(10)
declare #theCondition numeric(10),#theCarOption numeric(10) , #theOption numeric(10), #theColorOption numeric(10)
declare #theConditionName nvarchar(50),#theCarOptionName nvarchar(50), #theOptionName nvarchar(50),#theColorOptionName nvarchar(50)
declare #thePrice money, #theCog money
declare #HoldingTable table(
ID numeric identity,
ProductID numeric(10),
MakeID numeric(10),
ModelID numeric(10),
ConditionID numeric(10),
CarOptionsID numeric(10),
OptionsID numeric(10),
ColorOptionsID numeric(10),
Make nvarchar(50),
Model nvarchar(50),
YearID numeric(5),
Color nvarchar(50),
ProductType nvarchar(50),
Notes nvarchar(500),
Price money,
cog money);
INSERT INTO #HoldingTable (ProductID,MakeID, ModelID , ConditionID, CarOptionsID,OptionsID,ColorOptionsID, Make ,Model,YearID,Color, ProductType, Notes, Price, cog)
SELECT
ProductNumber as ProductID,
tblProductsForSale.MakeID as MakeID,
tblProductsForSale.ModelID as ModelID ,
ConditionID,
CarOptionsID,
OptionsID,
ColorOptionsID,
tblVehicleMake.Make as Make ,
tblVehicleModel.Model as Model,
YearID,
Color,
ProductType, Notes,
tblProductsForSale.ResalePrice as Price,
tblProductsForSale.SellPrice as cog
from tblProductsForSale, tblVehicleMake, tblVehicleModel where
tblProductsForSale.MakeID = tblVehicleMake.MakeID and
tblProductsForSale.ModelID = tblVehicleModel.ModelID
and tblProductsForSale.ProductStatus=''available'' and tblProductsForSale.Custom=0'
if(#mk > 0)
begin
select #sql = #sql + ' and tblProductsForSale.MakeID = ' + convert(varchar, #mk)
end
if #md > 0
Begin
select #sql = #sql + ' and tblProductsForSale.ModelID = ' + convert(varchar, #md)
End
if #yr > 0
begin
select #sql = #sql + ' and tblProductsForSale.YearID = ' + convert(varchar, #yr)
end
if #caroption > 0
begin
select #sql = #sql + ' and tblProductsForSale.CarOptionsID = ' + convert(varchar, #caroption)
end
if #producttype > 0
begin
select #sql = #sql + ' and tblProductsForSale.ProductType = ''' + convert(varchar,#producttype) + ''''
end
if #option > 0
begin
select #sql = #sql + ' and tblProductsForSale.OptionsID = ' + convert(varchar, #option)
end
if #coloroption > 0
begin
select #sql = #sql + ' and tblProductsForSale.ColorOptionsID = ' + convert(varchar, #coloroption)
end
--select #sqlInsert = 'INSERT INTO #HoldingTable (ProductID,MakeID, ModelID , ConditionID, CarOptionsID,OptionsID,ColorOptionsID, Make ,Model,YearID,Color, ProductType, Price, cog) '
--select #sqlExec = #sqlInsert + #sql
--select * from #HoldingTable
select #sql = #sql + 'Declare #TempTable2 TABLE(
ProductID numeric(10),
TypeName nvarchar(50),
MakeID numeric(10),
ModelID numeric(10),
ConditionID numeric(10),
CarOptionsID numeric(10),
OptionsID numeric(10),
ColorOptionsID numeric(10),
Make nvarchar(50),
Model nvarchar(50),
YearID numeric(5),
Color nvarchar(50),
ProductType nvarchar(50),
CarOptionName nvarchar(50),
OptionName nvarchar(50),
ColorOptionName nvarchar(50),
ConditionName nvarchar(50),
Notes nvarchar(500),
Price money,
cog money)
WHILE Exists(Select * from #HoldingTable )
begin
Select #ID = ID FROM #HoldingTable
Select #theProductId = ProductID from #HoldingTable
Select #theMake = MakeID from #HoldingTable
Select #theModel = ModelID from #HoldingTable
Select #theCondition = ConditionID from #HoldingTable
Select #theCarOption = CarOptionsID from #HoldingTable
Select #theOption = OptionsID from #HoldingTable
Select #theColorOption = ColorOptionsID from #HoldingTable
Select #theYear = YearID from #HoldingTable
Select #theColor = Color from #HoldingTable
Select #theProductType = ProductType from #HoldingTable
Select #theTypeName = TypeName from tblProductType WHere ProductTypeID = cast (#theProductType as numeric(10))
Select #thePrice = Price from #HoldingTable
Select #theCog = cog from #HoldingTable
Select #theConditionName = ConditionName from tblConditions Where ConditionID = #theCondition
Select #makeName = Make from tblVehicleMake Where MakeID = #theMake
Select #modelName = Model from tblVehicleModel Where ModelID = #theModel
Select #theCarOptionName = CarOptionsName from tblCarOptions Where CarOptionsID = #theCarOption
Select #theOptionName = OptionsName from tblOptions Where OptionsID = #theOption
Select #theColorOptionName = ColorOptionsName from tblColorOptions Where ColorOptionsID = #theColorOption
Select #theNotes = Notes from #HoldingTable
Select #theProductType = ProductType from #HoldingTable
INSERT INTO #TempTable2 (ProductID,TypeName,MakeID,ModelID,ConditionID ,CarOptionsID,OptionsID ,ColorOptionsID ,Make , Model , YearID ,Color, ProductType, CarOptionName ,OptionName,ColorOptionName ,ConditionName, Notes, Price, cog)
VALUES (#theProductId,#theTypeName, #theMake, #theModel, #theCondition, #theCarOption,#theOption,#theColorOption, #makeName,#modelName, #theYear, #theColor,#theProductType, #theCarOptionName, #theOptionName, #theColorOptionName, #theConditionName, #theNotes, #thePrice , #theCog )
DELETE FROM #HoldingTable Where ID = #ID
end
Select * from #TempTable2 order by ProductID '
end
exec ( #sql )
End
I've struggled a lot on this and came to conclusion, that if your stored procedure is dynamic and is combined with strings you sometimes miss something.. so while importing Visual Studio DBML import/update can not execute/test the procedure, so return type stays undefined, once you correct the procedure (query strings that you are building up to execute) you can add the procedure without any problems.
I had this error too and finally I found out that I have changed a table field name and in procedure it did not change it yet, and so it showed an error when adding to dbml.
Now you can check this on your procedure and your table that fields are the same.
I hope this experience is useful.
A simple way to solve this issue is (December 2019)
1 Just making double # precede #tmp => ##tmp
2 Comment out DROP TABLE #tmp => --DROP TABLE #tmp
Execute stored procedure and make sure that data showed up
Drag stored procedure again and that's it, It will generate return type
Last, Turn your store back to first situation and then save.
Hope I can help.
I got the same error when I dragged and dropped the stored procedure, so I just followed what the error said:
Unknown Return Type
The return types for the following stored procedures could not be detected. Set the return type for each stored procedure in the Properties window.
I selected the stored procedure and then selected properties tab, there there is a option called ReturnType which was empty and then hit the dropdown button on it and selected the table the SP was created and the issue is resolved.
If this doesn't help you can try any of the above answers.
The issue for me was that I had OPTION (RECOMPILE) set to get round a parameter sniffing issue. I temporary removed this while adding the SP and all worked fine.
You must place the
SET NOCOUNT ON;
SET FMTONLY OFF
at the top of the procedure . Like for example:
ALTER PROCEDURE [dbo].[usp_Name]
#your_params
AS
BEGIN
SET NOCOUNT ON;
SET FMTONLY OFF
-- your other codes
End

Dynamic insert into variable table statement SQL Server

I have a variable table:
DECLARE #A_Table TABLE(ID INT, att1 VARCHAR(100), att2 nvarchar(200))
I want to make dynamic sql, so I insert into this table some data (all inside a loop):
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT ' + #A_Table+ '(ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM '+ #EVEN_OTHER_Table;
EXEC (#sql);
END
sql every time would look like:
INSERT INTO #A_Table SELECT 1 , 'subject', SUM(subject)
INSERT INTO #A_Table SELECT 2 , 'age', SUM(age)
INSERT INTO #A_Table SELECT 3 , 'sex', SUM(sex)....
AND after executing this :
SO I will get:
#A_Table:
id att1 att2
1 subject 4.3
2 age 4.5
3 sex 4.1
but I get an error:
Msg 137, Level 16, State 1, Line 48
Must declare the scalar variable "#A_Table".
SO what is it the syntax to insert dynamically into a variable table?
Ok I have understood it.
You could use the INSERT ... EXEC syntax to insert the data returned by the dynamic SELECT. Of course, you would then need to remove the INSERT part from the dynamic statement.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'SELECT '+CAST(#i AS VARCHAR)+' , ''' + #other_att+''', SUM('+ #other_att + ') FROM '+ #EVEN_OTHER_Table;
INSERT INTO #A_Table (ID,att1,att2)
EXEC (#sql);
END
You have a table variable, not a variable that contains the table name.
So you would need the following.
WHILE (#i <= 100) BEGIN
SELECT #other_att = NAME FROM #other_Table where ID = #i;
SET #sql = 'INSERT INTO #A_Table (ID,att1,att2) SELECT '+CAST(#i AS VARCHAR)+' , '''+ #other_att+''', SUM('+ #other_att') FROM #EVEN_OTHER_Table';
EXEC (#sql);
END
You would also need to declare the table variable as a statement inside the #sql variable, and execute your declare table and inserts together, or use a local/global temporary table.
With a local temporary table (stored in the tempdb) you could do something like this.
CREATE TABLE #testtbl (ID INT);
EXEC ('INSERT INTO #testtbl VALUES (1)');
SELECT * FROM #testtbl
DROP TABLE #testtbl
Some good info about temporary tables in BOL
http://msdn.microsoft.com/en-us/library/ms174979.aspx - quite far down the page
And the table type.
http://msdn.microsoft.com/en-us/library/ms175010.aspx
Your EXEC statement occurs in a different context and is therefore unaware of any variables created in your original context.
To create dynamic insert query it is really a task, I also struggle to find it ,finally I have tried in the following way and it's successfully working. Please find the code below.
CREATE PROCEDURE [dbo].[InsertTodaysData] (#tbl varchar(50),#Days int,
#MDate varchar(50), #EValue varchar(50), #Speed varchar(50),
#Totalreturn varchar(50),#Closingv varchar(50), #TotalReturnV varchar(50))
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #SQLQuery varchar(2000)
-- Insert statements for procedure here
set #SQLQuery = 'INSERT INTO '+#tbl+' (ID,MDate,EValue,Speed,TotalReturnRatio,ClosingValue,
TotalReturnValue) VALUES ('+#Days+','''+#MDate+''', '+#EValue+', '+#Speed+',
'+#Totalreturn+', '+#Closingv+', '+#TotalReturnV+')'
EXECUTE(#SQLQuery)
END
Hope this will help you..