Entity Framework no columns from simple query - sql-server-2008

I have the following stored procedure:
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[GetData]
#taskName VARCHAR(205) = NULL
AS
BEGIN
SELECT *
FROM [dbo].[Table] WITH (NOLOCK)
WHERE #taskName IS NULL
OR #taskName = ''
OR Name LIKE '%' + #taskName + '%'
ORDER BY Name
END
Now I created an File.edmx generated model, selected the GetData stored procedure, when I do a function import and I get "Get Column Information", it says
The selected stored procedure returns no columns
I am dbo_owner on the database and it is my user that is in the app.config on generation, and I am even storing the password in app.config (temporarily), when I run the procedure from Management Studio, it shows the columns..
I'm puzzled!

You need to specify the field names in your select statement rather than just using the *

try
ALTER PROCEDURE [dbo].[GetData]
#taskName VARCHAR(205) = NULL
AS
BEGIN
exec ('SELECT * FROM [dbo].[Table] WITH (NOLOCK) WHERE ' + #taskName + 'IS NULL OR ' + #taskName + ' = \'\' OR Name LIKE \'%' + #taskName + '%\' ORDER BY Name')
END
GO

I would try the same process but using only
SELECT *
FROM [dbo].[Table] WITH (NOLOCK)
instead of the full query. Then you can alter your proc to add the where.
Sometimes EF has problems identifying the return columns due to the were clause

Related

SSRS issue with using dynamic fields in SP

I have a SP like this:
ALTER PROCEDURE [dbo].[ReportGateWay]
(
#ISO bigint= 0,
#Gateway bigint= 0
)
AS
BEGIN
DECLARE #SQL nvarchar(max)
SET #SQL= 'SELECT * FROM
(
SELECT DISTINCT I.DBAName [ISOName], BG.GatewayName
FROM Iso I
LEFT OUTER JOIN BusinessGateway BG
ON I.GatewayName = BG.MerchantBusinessGatewayId AND I.IsActive = 1 and BG.IsActive = 1
WHERE ('+CAST(#ISO AS varchar(10))+' = 0 OR I.IsoId = '+ CAST(#ISO AS varchar(10)) +')
AND ('+CAST(#Gateway AS varchar(10))+' = 0 OR BG.MerchantBusinessGatewayId = '+ CAST(#Gateway AS varchar(10)) +')
) AS tb1
PIVOT
(
Count(GatewayName) for GatewayName in ('+ SUBSTRING((SELECT ',[' + BG.GatewayName + ']' FROM BusinessGateway BG
WHERE #Gateway = 0 OR BG.MerchantBusinessGatewayId = #Gateway
FOR XML PATH('')), 2, 200000 ) + ')
) AS pvt
ORDER BY pvt.ISOName'
EXECUTE (#SQL)
END
I need to invoke this in SSRS. The problem is that when on creating dataset for this, I get an error which read:
You must have atleast one field for your dataset
What can be done in this case?
You have this error message because SSRS cannot infer your schema from the query.
You could declare manually your fields in DataSet Properties => Fields:
Field Name, Field Source
ISOName, ISOName
Gateway1, Gateway1
Gateway2, Gateway2
EDIT
If you really want to have dynamic columns and can't define static column names, you could try a trick like this.
The idea is to create a function returning an Arraylist containing Column headers and values.
Why are you not executing the Procedure by creating a dataset of query type "Stored Procedure"?
By doing this you will be able to see the fields getting returned from the SP in your dataset.
You can also pass the parameter values to the SP by creating the report parameters.
Edit:
How to pass parameter to SP in SSRS:
Say you have sp as below:
create procedure [dbo].[TestProcpk] #value varchar(20)
as
select * from testProc where value = #value
You have to create parameters with same name as above i.e. #value.
I have below data in testProc:
ID|Value
1|xxx
2|yyy
3|zzz
If I run the report with parameter value of xxx, I will get 1|xxx only.
Also, You don't have to specify anything after selecting the SP from drop down.
How you are not able to pass param value to SP?

Cannot get results of a stored procedure into a #TempTable to work [duplicate]

This question already has answers here:
Insert results of a stored procedure into a temporary table
(33 answers)
Closed 9 years ago.
I am using SQL Server 2008 R2 and am trying to get the results of a stored procedure into a temporary table that I can access later on in the calling stored proc. My TSQL is as follows:
CREATE PROCEDURE sp_ToBeCalled AS
(
#SomeParam INT
)
BEGIN
SELECT * FROM tblSomeTable WHERE SomeField = #SomeParam
END
CREATE PROCEDURE sp_CallingProcedure AS
(
#SomeOtherParam INT
)
BEGIN
-- A
SELECT * INTO #MyTempTable FROM sp_ToBeCalled(#SomeOtherParam)
-- B
SELECT * FROM #MyTempTable FOR XML RAW
END
This all compiles fine however when I call sp_CallingProcedure statement -- B returns an error that #MyTempTable.
How can I do "A" so that I can access its results from within a #MyTempTable table without having to declare the structure of #MyTempTable first?
I am looking for a solution that I can use generically. I have a number of existing stored procedures that I need to call from various callers where getting the results queryable is a necessity. I cannot change the existing stored procedures.
I don't want to use
OPENQUOERY() - requires a custom linked server definition
sp_ExecSql() - means I have to build up dynamic SQL which does not give me SP compile time checking.
You are trying to use a Procedure like a tabular function.
Try using
INSERT INTO #MyTempTable (column1, column2...)
exec sp_ToBeCalled(#SomeOtherParam)
A great reference: http://www.sommarskog.se/share_data.html
I managed to partially solve my issue by doing the following:
1) Custom Stored Procedure to select a ROWSET into a global temp table
2) Calling SP calls 1) and then transfers the ##GlobalTempTable into a local #TempTable for processing
This works but has the following "issues":
Potential security risk as "Adhoc Distributed Queries" functionality needs to be turned on
Still requires a Global Temp table that needs to be cleaned up by the caller. Temp table naming is also problematic as multiple 2) will cause an issue.
I include my code below in case it helps someone else. If anyone is able to improve on it please feel free to post.
/* This requires Adhoc Distributed Queries to be turned on:
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
*/
-- Adapted from: http://stackoverflow.com/questions/653714/how-to-select-into-temp-table-from-stored-procedure
CREATE PROCEDURE [dbo].[ExecIntoTable]
(
#tableName NVARCHAR(256),
#storedProcWithParameters NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #driver VARCHAR(10)
DECLARE #connectionString NVARCHAR(600)
DECLARE #sql NVARCHAR(MAX)
DECLARE #rowsetSql NVARCHAR(MAX)
SET #driver = '''SQLNCLI'''
SET #connectionString =
'''server=' +
CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)) +
COALESCE('\' + CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(256)), '') +
';trusted_connection=yes;Database=' + DB_NAME() + ''''
SET #rowsetSql = '''EXEC ' + REPLACE(#storedProcWithParameters, '''', '''''') + ''''
SET #sql = '
SELECT
*
INTO
' + #tableName + '
FROM
OPENROWSET(' + #driver + ',' + #connectionString + ',' + #rowsetSql + ')'
EXEC (#sql)
END
GO
and then to use in another SP as follows:
EXEC ExecIntoTable '##MyGlobalTable', 'sp_MyStoredProc 13, 1'
SELECT *
INTO #MyLocalTable
FROM ##MyGlobalTable
DROP TABLE ##MyGlobalTable
SELECT * FROM #MyLocalTable

"Looping" through databases with sp_MSforeachdb and returning 1 data set

So, I've been wrestling with the code I found on my buddy's website:
8 Steps to Moving Database Logins
I want to generate the Database Level Security, Roles, and Explicit Permissions statements in one output so I'm not copying and pasting over and over again and so that they run for all databases on the server (minus tempdb of course).
Declare #FullStatement varchar(MAX)
Set #FullStatement = ' use [?]; SELECT dp.state_desc + N'' '' + dp.permission_name + N'' TO '' + cast(QUOTENAME(dpl.name COLLATE DATABASE_DEFAULT) as nvarchar(500)) AS TSQLScript
FROM sys.database_permissions AS dp
INNER JOIN sys.database_principals AS dpl ON (dp.grantee_principal_id = dpl.principal_id)
WHERE dp.major_id = 0
and dpl.name not like ''##%'' -- excluds PBM accounts
and dpl.name not in (''dbo'', ''sa'', ''public'')
ORDER BY dp.permission_name ASC, dp.state_desc ASC'
Exec sp_MSforeachdb #FullStatement
How can I modify what I have, which works as is but is inconvenient, using a Table Variable, Temp Table, etc so all of the statements are in one data set?
David,
Is this what you want?
CREATE TABLE tempdb.dbo.Results (c1 VARCHAR(8000))
Declare #FullStatement varchar(MAX)
Set #FullStatement = 'SELECT ''use [?]''; SELECT dp.state_desc + N'' '' + dp.permission_name + N'' TO '' + cast(QUOTENAME(dpl.name COLLATE DATABASE_DEFAULT) as nvarchar(500)) AS TSQLScript
FROM [?].sys.database_permissions AS dp
INNER JOIN [?].sys.database_principals AS dpl ON (dp.grantee_principal_id = dpl.principal_id)
WHERE dp.major_id = 0
and dpl.name not like ''##%'' -- excluds PBM accounts
and dpl.name not in (''dbo'', ''sa'', ''public'')
ORDER BY dp.permission_name ASC, dp.state_desc ASC'
INSERT INTO tempdb.dbo.Results Exec sp_MSforeachdb #FullStatement
select * FROM tempdb.dbo.Results
There are multiple ways to get this done. You can use powershell to loop through all databases and put the results in excel. Mr Nelson has this on his powershell sql university series. Sorry, would pull the link for you but i am typing on my phone at the airport.
Why are you scripting database users and permissions? They are in the database and will still be there when you migrate the databases. You don't need to do that unless you're recreating the databases from scratch.

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

Creating a dynamic where clause in SQL Server stored procedure

I am trying to create a stored that will accept two values, a column name and a value. It will then check if there is a record that exists for the passed in column name with the passed in value. I've tried the following
CREATE PROCEDURE p_HasActiveReference
#pi_colName varchar(100)
,#pi_colValue varchar(100)
AS
BEGIN
SET NOCOUNT ON
declare #sql varchar(1000)
set #sql = 'IF EXISTS(SELECT TOP 1 p.PaymentId
FROM Payments p
WHERE ' + #pi_colName + ' = ' + #pi_colValue + 'AND Active = 1)
SELECT ''True'' AS RETVAL
ELSE
SELECT ''False'' AS RETVAL'
exec(#sql)
END
However, I always get this error
Conversion failed when converting the varchar value 'InternalOr' to data type int.
When I call the procedure with the following
p_HasActiveReference 'InternalOrgCode', '10110'
The internalOrgCode column is of value varchar(10)
I am not a SQL expert, so I am not even sure if what I need to achieve is even possible using that technique!
Thanks!
At least one issue: you should be surrounding your string value with single quotes, and to escape those inside a string you need to double them up:
WHERE ' + #pi_colName + ' = ''' + #pi_colValue + ''' AND ...
You also may want to declare your #sql variable as something bigger than 100 characters! Looks like your string is getting truncated.
If the possible values for #pi_colName are finite, the data type is always string, and the columns are collation compatible, you could do something like this and avoid dynamic SQL:
SELECT ...
WHERE CASE #pi_colName
WHEN 'col1' THEN col1
WHEN 'col2' THEN col2
END = #pi_ColValue;