Convert a SQL Server stored procedure to LINQ with SQL Function - sql

A while ago I asked for help in creating a pivot table. You guys came through for me and I now have a stored procedure that creates my pivot and can store the results in a new table. The columns are dynamic so will always be different for each transaction in the application.
The issue I have is that my application is MVC and uses Entity Framework. Because the database is modelled I can't create on the fly tables with dynamic column names. In use, EF will never know they are there and neither will my views.
It looks like I need to convert the stored procedure to a LINQ statement that I can then process from the model end.
My stored procedure contains the SQL Server STUFF Function, I do not know how to call this function in a LINQ statement.
EXAMPLE OF SQL WITH SQL STUFF FUNCTION:
DECLARE #cols AS VARCHAR(MAX),
#query AS VARCHAR(MAX);
SELECT #cols = STUFF(( SELECT DISTINCT TOP 100 PERCENT
'],[' + convert(varchar(10), t2.date, 101)
FROM test AS t2
ORDER BY '],[' + convert(varchar(10), t2.date, 101)
FOR XML PATH('')
), 1, 2, '') + ']'
set #query = 'select name, ' + #cols + '
from
(
select name, date, cast(yesno as tinyint) as yesno
from test
) x
pivot
(
max(yesno)
for date in (' + #cols + ')
) p'
execute(#query)
MSDN has this method:
[EdmFunctionAttribute("SqlServer", "STUFF")]
public static string Stuff(
string stringInput,
Nullable<int> start,
Nullable<int> length,
string stringReplacement
)
...but I don't know where I place it and how I use it in LINQ.
Hope that made sense, any help much appreciated!

You can just call the stored procedure via ADO, or using ExecuteStoreQuery<DbDataRecord>

Related

Having a datatype problem with SQL Server dynamic pivot

Datatype problem with a SQL Server dynamic pivot query.
UPDATE: code works properly now by using datatype nvarchar(MAX) for both #cols and #query. Thanks for the input those who did.
I'm trying to create a SQL Server dynamic pivot query so I don't need to explicitly name all columns in the query statement (there will be 323 columns in the pivoted table and those might change from time to time).
I've build my pivot attempt off another example here in Stack Overflow, but I'm apparently having trouble with the datatypes. I'm not sure how to resolve the issue, so I'd appreciate some input if you can help with a solution.
For background, the source table MyTable to be pivoted contains the columns and datatypes seen in the screenshot below (left side). A sample of a 'select *' query result of that table is seen in image below (right side).
The SQL query code that I've used to try to create a dynamic pivot is shown here (corrected):
DECLARE #cols AS nvarchar(255),
#query AS nvarchar(255);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.attKey)
FROM MyTable c
FOR XML PATH(''), TYPE).value('.', 'varchar(255)'), 1, 1, '')
set #query = 'SELECT landingId, ' + #cols + ' from
(
select landingId
, attValue
, attKey
from MyTable
) x
pivot
(
max(attValue)
for attKey in (' + #cols + ')
) p '
execute(#query)
I get this error from SSMS when executing:
Msg 8114, Level 16, State 5, Line 5
Error converting data type varchar to real.
Any ideas? Thanks in advance. BT

Dynamic pivot inside procedure (SQL Server 2008) no fields on SSRS

I have a problem with find solution on how to put inside procedure 3 different dynamic pivot query (example below) and use it in SSRS where I can't add datasets, there are no fields. Another important thing is that at the beginning of my procedure I have one parameter "#Data_x" as the date when I am trying to ad datasets there is an info: "Define Query Parameters" and on the list is only "#Data_x" which I can't define "manually".
Here is example of dynamic pivot:
DECLARE #PmtCols AS NVARCHAR(MAX), #query_ppl AS NVARCHAR(MAX)
select #PmtCols = STUFF((SELECT ',' + QUOTENAME(number)
from #data
group by number
order by number
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
if OBJECT_ID ('tempdb..##ready') is not null drop table ##ready
set #query = 'SELECT ID,' + #PmtCols + ' into ##ready from
(select number, ID, przerwa_pl from #data) as x
PIVOT
(max(przerwa_pl) for number in (' + #PmtCols + ')) as p'
execute(#query) ;
I tried to function FMTONLY OFF/ON but still nothing. What can I do, please help?

How to return data from stored procedure in a view SQL Server 2008

So i have this code:
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get distinct values of the PIVOT Column
SELECT #ColumnName= ISNULL(#ColumnName + ',','')
+ QUOTENAME(period)
FROM (SELECT DISTINCT period FROM atbv_Accounting_OrdersDeliveries WHERE InvoiceNo IS NOT NULL) AS Periods
SET #DynamicPivotQuery =
N'SELECT ' + #ColumnName + '
FROM (SELECT
ArticleID, period, SUM(Amount) As Total
FROM atbv_Accounting_OrdersDeliveries
WHERE InvoiceNo IS NOT NULL
GROUP BY ArticleID, period
) AS T
PIVOT(SUM(TOTAL)
FOR period IN (' + #ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
I saved in i a stored procedure as i cannot declare variables in a view. Is there a way to call this procedure in a view? Note that column amount is dynamic as well :)
Thanks!
Try to use the Stored Procedure instead of a view.
If that isn't possible for any reason, you can create a SQL Server Agent Job that periodically fills a table using a stored procedure and the client than uses the "cached" data.
You can't have a dynamic view, what would be the point?
If you want to know how to share data from stored procedures then
How to Share Data between Stored Procedures
is a great text. If you want to understand dynamic SQL then I recommend
The Curse and Blessings of Dynamic SQL
by the same author, Erland Sommarskog. Both topics are too expansive for a simple answer on Stack Overflow.

Referencing a table variable in a query string

I have created a temprary table variable, which I then need to pivot:
Declare #TempTable TABLE(
Name varchar(150),
CloseDate Date,
Revenue Float)
.... <add data to it> .....
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(CloseDate)
FROM #TempTable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Name, ' + #cols + ' from
(select
t.Name,
t.CloseDate,
t.Revenue
from #TempTable as t
) x
pivot
(SUM(Revenue)
for CloseDate in (' + #cols + ')
) p '
execute(#query)
However, I am getting this error:
Must declare the scalar variable "#TempTable".
When I test the #TempTable variable using a normal SELECT it works fine:
SELECT * from #TempTable
How can I reference the variable successfully in the query string?
Unfortunately when you use execute and sp_executesql they are run within their own context, so they cannot reference table variable objects which are defined outside the scope of the dynamic SQL.
In cases like this, what I have tended to do is create a temp table instead and embed a GUID in the name of the temp table that gets created in tempdb. This ensures the table name is unique for simultaneous operations, and then I place that guid in the dynamic SQL that is created.
Performance wise it's slightly slower but still quick, but whether that is an issue for you or not depends on the number of times this will be executed and the frequency.
After some discussion with Damien in the comments to this answer we've determined that local temp tables (single hashtag) can be used when executing dynamic SQL.
Therefore if you change your declare table variable to CREATE TABLE #TempTable and change the reference in your dynamic SQL this should work properly for you.
The only concern I have about using temp tables is the persistence of objects if your calling code uses some form of connection pooling which doesn't sound like it's the case here.
However, as a general self-paranoid self practice I like to throw one of these before the create table and at the end of the statement to clean up the objects.
IF OBJECT_ID(N'tempdb..#TempTable') IS NOT NULL
DROP TABLE #TempTable
CREATE TABLE #TempTable (Value VARCHAR(50));

SQL Dynamic SELECT statement from values stored in a table

I have been researching this for a couple of days and feel like I am going around in circles. I have basic knowledge of SQL but there are many areas I do not understand.
I have a table that stores the names and fields of all the other tables in my database.
tblFields
===================================================
TableName FieldName BookmarkName
---------------------------------------------------
Customer FirstName CustomerFirstName
Customer LastName CustomerLastName
Customer DOB CustomerDOB
I want to write a SELECT statement like the following but i am unable to get it work:
SELECT (SELECT [FieldName] FROM [TableName]) FROM tblFields
Is this possible? The application I have developed requires this for user customization of reports.
If i understand what you are trying to do, i think this will help you. It is not pretty and it works for SQL Server 2005 and above, but maybe this is what you are looking for:
declare #tableName nvarchar(100)
declare #sqlQuery nvarchar(max)
declare #fields varchar(500)
set #tableName = 'YourTableName'
set #fields = ''
select #fields = #fields + QUOTENAME(t.fieldname) + ',' from (
select distinct fieldname from tblfields where tablename = #tableName)t
set #sqlQuery = 'select ' + left(#fields, LEN(#fields)-1) + ' from ' + QUOTENAME(#tableName)
execute sp_executesql #sqlQuery
Edit: As Martin suggested, i edited so that the columns and tablename are using QUOTENAME
If I understand correctly what you are trying to do, you are probably better off doing this as two separate queries from your program. One which gets the fields you want to select which you then use in your program to build up the second query which actually gets the data.
If it must be done entirely in SQL, then you will need to tell us what database you are using. If it is SQL Server, you might be able to user a cursor over the first query to build up the second query which you then execute with the sp_executesql stored procedure. But doing doing it outside of SQL would be recommended.