I ran into a problem or maybe even a MySQL limitation.
The situation is as follows:
I have an SP X, selecting related records based on 1 or 2 arguments. The SP returns a list of 0, 1 or more id's. I wanna use that list in an IN clause like so:
SELECT
*
FROM
table
WHERE
id IN (spX(y));
This gives me an error:
Syntax error or access violation: 1305 FUNCTION z.spX does not exist
The error is a bit vague: I'm confident it's a syntax error rather than access violation or non-existence of the SP itself. If I CALL the SP directly I get my expected results.
This kinda feels like a dead end. My expectation was that MySQL would throw an error if the SP returned more than 1 column, not if it returned more than 1 row (in which case I could've used a FUNCTION instead and this would've worked straight away).
So, the question is: is there any way of using the SP's result in an IN clause?
On a side note: I'm aware I could achieve the same result by simply joining the table and then add a new where clause to the existing query, instead of using the SP. However, the real problem here is that new functionality has to be added to the application, and not having to join in tons of queries, but using a SP instead is the way of least resistance.
SELECT * FROM table WHERE id IN(SELECT spX FROM table WHERE y = ???);
you need a select statement in the parenthesis otherwise it is very unclear what you are doing.
If sPx is the name of your table and y is the variable you want to pull out of it, then you you need to say that with the select statement in parenthesis. Def just a syntax error
I implemented the solution as proposed in the chat:
https://chat.stackoverflow.com/rooms/12910/discussion-between-robin-v-g-and-hituptony
What I do step by step:
I put a placeholder in every query involved.
On a higher level in my application I call the stored procedure. To clarify: there're 2 things I know for sure when it comes to the SP:
It will always take 1 id as parameter.
It will always give 0 or more id's back.
I generate the IN() clause depending on the SP's outcome.
I replace the placeholder with the generated IN() clause and run my query.
This way I can always add or alter the conditions in the SP itself, without changing the application logic/queries.
Related
I got a Stored Procedure names getStocks that have a parameter. The code below is a example how I want to do with the query. Is it possible with the SELECT QUERY we can call a procedure?
PS I didn't use Function cuz I'm getting loading problem when I apply it in populating DataGridview in my VB.Net
BEGIN
SELECT ItemId, CatalogNumber, call getStocks(ItemId) AS quantity,
Cost, Minimum, Maximum, TypeId, SupplierId FROM items;
END
You cant do this. CALL is its own statement that you cant mix with SELECT in any way. If you cant use a UDF, you have to preform the integration manually.
It makes sense that a CALL cant be used like this when you consider that a CALL can optionally output a resultset. It might return a resultset, it might now. It might have one cell, one row, one column, or many rows/columns. The columns are not known at call time so the optimizer couldn't validate any JOINs to it if you put a call in the FROM and the because it can produce more than one cell (or nothing), you cant reliably put it in the SELECT. Additionally, stored procedures can have output variables, which also doesnt make sence in the context of a SELECT statement.
In other words, because the output of procedures is probably incompatible with any part of a SELECT query, the makers of mysql globally prevent their mixing.
You want to use a User-Defined Function (UDF) : http://dev.mysql.com/doc/refman/5.7/en/create-function-udf.html . Unlike stored procedures, UDF's may be called inline in a query.
I have a query in a base-data table that (given that my search criteria are correct) gives back approx. 950 records.
Except of the 3 criteria fields, i want to have about 10 more fields (the Project is still at the beginning) , every single one based on sub-queries, some of them normal select queries, some are aggregated queries.
As far as i know every sub-query must give 1 and only one value back.
This value school be individual for every Record of the top query.
My Problem now is, that i don't know how to pass the search criteria from the top query (simple select query) to the sub-query in the in 10 fields i mentioned before.
Is this possible at all, or is my Approach to complicated. Is there possibly an easier way?
I have a Windows 7 System with Office 2010 installed.
Your help is much appreciated.
Thanks a lot.
PS
The sub-queries are based on the same table as the top query. Sorry, I forgot to mention.
You can pass arguments between things with a function call to set a public variable. This vba must be in a Module, not behind a Form Module. I don't use this approach very often, because the global value is in volatile memory, I prefer to save the variable in a special data Table.
Public strGlobal As String
Function Func_ReadGlobal() As String
Func_ReadGlobal = strGlobal
End Function
Function Func_WriteGlobal() As String
strGlobal = Func_WriteGlobal
End Function
In all subqueries create parameter(s) and use it as search criteria. Parameter name should be the same for same column. Now, if you use those subqueries in your main query, Access will ask only once per each parameter name, you don't need to pass them explicitly to subqueries.
Thank you guys.
I did'nt think of the most obvious solution with the Globals. I will try it out as soon as my Boss gives me the time to continue with the Project.
#Sergey
I can't use the Parameter(s) way, because the whole query, incl. Subqueries shall run completely alone in VBA, without human input at all.
Is there a way to get the number of rows 'returned' from a stored procedure?
I know the result set is not really returned so I can't select from it or count on it.
I tried to use an out parameter but with no success..
Basically I have some logic in the stored procedure that finds some table lines. I use it in my C# app. in another place I need the exact same logic but only the count so I will be able to use in an SQL statement.
I could bring it to the C# and count there but I prefer not.
I could also create a stored function that duplicate the logic but returns COUNT but I prefer not to duplicate so I don't maintain it twice..
Try This
found_rows function
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
SELECT COUNT(id) AS example name FROM tablename
I have a table structure in place. But, the data I push into this data varies depending upon a input
Input A - Query X
Input B - Query Y
In order to achieve this, I was thinking, I will put in a IF Condition in the dataset and have it direct to "Query X" or "Query Y" based on the "Input".
I tried this,
IF(Input=='Hello')
(
...
)
But, this threw an error. Can you help me on how to proceed here? Is there a better way I can achieve my req.?
I'd advise against the IF statement for performance reasons, but if you must, the syntax in SQL is:
if ( 'blah' = 'blah' )
begin
--do stuff
end
Some other options you might consider, instead of an IF:
Use Stored Procedures, have a "master" sproc called by the report, which then executes the appropriate sproc based off the parameters it receives.
UNION ALL your potential queries together, and include a line in the WHERE clause to make only the query you want the results from return any rows.
If the differences in your queries are simple enough, perhaps you can just use CASE statements to apply the correct logic?
I need to do a count on the items in a joined result set where a condition is true. I thus have a "from join where where" type of expression. This expression must end with a select or groupby. I do not need the column data actually and figure it is thus faster not to select it:
count = (from e in dc.entries select new {}).Count();
I have 2 questions:
Is there a faster way to do this in terms of the db load?
I have to duplicate my entire copy of the query. Is there a way to structure my query where I can have it one place for both counts and for getting say a list with all fields?
Thanks.
Please pay especial attention:
The query is a join and not a simple table thus I must use a select statement.
I will need 2 different query bodies because I do not need to load all the actual fields for the count but will for the list.
I assume when I use the select query it is filling up with data when I use query.Count vs Table.Count. Look forward to those who understand what I'm asking for possible better ways to do this and some detailed knowledge of what actually happens. I need to pull out the logging to look into this deeper.
Queryable.Count
The query behavior that occurs as a
result of executing an expression tree
that represents calling
Count(IQueryable)
depends on the implementation of the
type of the source parameter. The
expected behavior is that it counts
the number of items in source.
In fact, if you use LinqToSql or LinqToEntities, Queryable.Count() is sent into the database. No columns are loaded to memory. Check the generated sql to confirm.
I assume when I use the select query it is filling up with data when I use query.Count vs Table.Count
This is not true. Check the generated sql to confirm.
I have to duplicate my entire copy of the query. Is there a way to structure my query where I can have it one place for both counts and for getting say a list with all fields
If you need both the count and the list, get the list and count it.
If you need the count sometimes and other times you need the list... write a method that returns the complex IQueryable, and sometimes call .Count() and other times call .ToList();
I do not need the column data actually and figure it is thus faster not to select it.
This is basically false in your scenario. It can be true in a scenario where an index covers the result columns, but you don't have any result columns.
In your scenario, whatever index is chosen by the query optimizer, that index can be used to make the count.
Sum up: Query optimizer will perform the optimization you desire.
//you can put a where condition here
var queryEntries = from e in dc.entries select e;
//Get count
queryEntries.Count();
//Loop through Entries, so you basically returned all entries
foreach(entry en in queryEntries)
{}