MySQL - Using stored procedure results to define an IN statement - sql

I'd like to use a stored procedure to define the IN clause of a select statement.
This is (a simplified version of) what I'm trying to do:
SELECT *
FROM myTable
WHERE columnName IN (CALL myStoredProc)
myStoredProc performs some complicated logic in the database and returns a list of possible matching values for columnName. The statement above does not work obviously. The select statement may be performed in another stored procedure if that makes a difference.
Is this at all possible in mySQL?

What return type does your current stored procedure have? You are speaking of "a list", so TEXT?
Maybe there's an easier way, but one thing you can do (inside another stored procedure) is to build another query.
To do that, we need to work around two limitations of MySQL: a) To execute dynamic SQL inside a stored procedure, it needs to be a prepared statement. b) Prepared statements can only be created out of user variables. So the complete SQL is:
SET #the_list = myStoredProc();
SET #the_query = CONCAT('SELECT * FROM myTable WHERE columnName IN (' , #the_list , ')');
PREPARE the_statement FROM #the_query;
EXECUTE the_statement;
If you're talking about returning a result set from a stored routine and then using it as table, that is not possible. You need to make a temporary table to work around this limitation.

Related

Using results of one stored procedure in another stored procedure - SQL Server

Is there any way to use the results of one stored procedure in another stored procedure without using a table variable or temp table? The logic is as follows:
IF (#example = 1)
BEGIN
DECLARE #temp TABLE (Id INT);
INSERT INTO #temp
EXEC [Procedure1] #ItemId = #StockId
set #Cost = (select top 1 id from #temp)
Ideally i would like to know if there is a way to do this without having to use a temp table. Looked around online but can't find anything that works. Any advice would be great.
In general, if you want to use user-defined code in a SELECT, then it is better to phrase the code as a user-defined function rather than a user-defined procedure.
That is, procedures should be used for their side effects and functions should be used for their return values.
That said, you can use openquery (documented here) to run an exec on a linked server. The linked server can be the server you are running on.

Single variable consists of number of characters in stored procedure?

CREATE PROCEDURE Testing1
#Varaible nvarchar(50),
#value integer
AS
BEGIN
DECLARE #SUMM FLOAT
SET #SUMM=(#value*2.38/7.456)*2
PRINT #Varaible
PRINT 'EXPENSES IS'
PRINT #SUMM
END
Output is:
PETER
EXPENSES IS
24.2597
The above is my code where I am passing a single input parameter.
If I want to pass multiple values like peter,robber,licoln,mat
#varaible peter,robber,licoln,mat
#value 37 45 66 77
is it possible in SQL??
If you're only sending a few values in your delimited strings, I would suggest simply using the proper datatypes and calling the stored procedure a few times with individual values.
If, however, your delimited strings might contain hundreds or thousands of discrete values, then calling a proc that many times could be costly in terms of performance, especially if you can't send them all in one batch (I'm sure you want to use parameters rather than a giant concatenated command). If this is the case, you have a few options:
Use Table Valued Parameters. This is like passing arrays as arguments to your proc.
Pass XML to your proc, then shred and process it within the procedure.
Insert your data to staging/temp tables, then call the procedure to operate on those tables.
Take a step back and see if it makes sense to do more processing in your app. DB code usually doesn't scale nearly as well as app code.
Send these delimited strings to your proc, split/parse them, then loop over the results in SQL. This seems to be what you're asking about and is possibly the least elegant option, even though it's one of the more popular ways to abuse a relational database.
The table valued parameters approach seems very 'approachable', but is only available as of MSSQL 2008. If you are still stuck with MSSQL 2005 then, maybe, the temporary table approach works best for you?
Your code could look something like:
-- define your stored procedure
CREATE PROC sptest1 AS
BEGIN
-- do some stuff with #tmp, like join it to other tables
-- and UPDATE values in these tables with it!
-- or simply list a processed version of #tmp:
SELECT nam,val*(2.38/7.456)*2 FROM #tmp
END
-- prepare input values by creating a temporary table on the fly
SELECT 'Peter' nam,23 val INTO #tmp
UNION ALL SELECT 'Paul',27
UNION ALL SELECT 'Harry',16
UNION ALL SELECT 'Mary-Ann',45;
-- and call the procedure:
EXEC sptest1
So, your frontend will have to build the SELECT ... INTO #tmp ... string. After that the rest of the processing can be done inside your stored procedure.

use output of SQL statement as the table to run a query on

I believe what I am attempting to achieve may only be done through the use of Dynamic SQL. However, I have tried a couple of things without success.
I have a table in database DB1 (lets say DB1.dbo.table1, in a MS SQL server) that contains the names of other databases in the server (DB2,DB3, etc). Now, all the dbs listed in that table contain a particular table (lets call it desiredTable) which I want to query. So what I'm looking for is a way of creating a stored procedure/script/whatever that queries DB1.dbotable1 for the other DBs and then run a statement on each of the dbs retrieved, something like:
#DBNAME = select dbName from DB1.dbo.table1
select value1 from #DBNAME.dbo.desiredTable
Is that possible? I'm planning on running the sp/script in various systems DB1.dbo.table1 being a constant.
You need to build a query dinamically and then execute it. Something like this:
DECLARE #MyDynamicQuery VARCHAR(MAX)
DECLARE #MyDynamicDBName VARCHAR(20)
SELECT #MyDynamicDBName = dbName
FROM DB1.dbo.table1
SET #MyDynamicQuery = 'SELECT value1 FROM ' + #MyDynamicDBName + '.dbo.desiredTable'
EXEC(#MyDynamicQuery)
You can use the undocumented stored procedure, sp_MSForEachDB. The usual warnings about using an undocumented stored procedure apply though. Here's an example of how you might use it in your case:
EXEC sp_MSForEachDB 'SELECT value1 FROM ?.dbo.desiredTable'
Notice the use of ? in place of the DB name.
I'm not sure how you would limit it to only DBs in your own table. If I come up with something, then I'll post it here.

Debug SQL in pgAdmin when SQL contains variables

In SQL Server I could copy sql code out of an application and paste it into SSMS, declare & assign vars that exist in the sql and run. yay great debugging scenario.
E.g. (please note I am rusty and syntax may be incorrect):
declare #x as varchar(10)
set #x = 'abc'
select * from sometable where somefield = #x
I want to do something similar with Postgres in pgAdmin (or another postgres tool, any recommendations?) where I can just drop my SQL (params & all) into something that will run against Postgres DB.
I realise you can create pgscript, but it doesn't appear to be very good, for example, if I do the equivalent of above, it doesn't put the single quotes around the value in #x, nor does it let me by doubling them up and you don't get a table out after - only text...
Currently I have a piece of SQL someone has written that has 3 unique variables in it which are used around 6 times each...
So the question is how do other people debug SQL efficiently, preferably in a similar fashion to my SQL Server days.
You can achieve this using the PREPARE, EXECUTE, DEALLOCATE commands for handling statements, which is really what we are talking about here.
For example:
PREPARE test AS SELECT * FROM users WHERE first_name = $1;
EXECUTE test ('paul');
DEALLOCATE test;
Perhaps not as graphical as some may like, but certainly workable.
I would give a shot at writing a SQL function that wraps your query. It can be something as simple as
CREATE OR REPLACE FUNCTION my_function(integer, integer)
RETURNS integer
AS
$$
SELECT $1 + $2;
$$
LANGUAGE SQL;
SELECT my_function(1, 2);
I would do this instead of a PREPARE since it will be simpler to update it. Depending on how complex the function is, you might want to also look at some of the other PL's in Postgres.
SQL procs are notoriously hard to debug. My lame but practical solution has been to write log messages to a log table, like this (please excuse syntax issues):
create table log_message (
log_timestamp timestamp not null default current_timestamp,
message varchar(1000)
);
then add lines to your stored proc like:
insert into log_message (message) values ("The value of x is " || #x);
Then after a run:
select * from log_message order by 1;
It's not pretty, but works in every DB.

SQL Server 2005: Call a stored procedure from a WHERE clause

I need to make a SELECT with a call of a stored procedure in the WHERE clause.
It should be something like that....
SELECT distinct top 10 i.x, d.droit
FROM v_droit d, v_info i
WHERE d.nomdroit='yy'
AND i.id<>2
AND (select val from (exec up_droits(i.x, d.droit)) <>3
But it does not work...
Any idea?
Don't say to replace the stored procedure with a function because is not possible to use the existing code in a function. So the function is not a valid option. I really need to be able to use a stored procedure
This is achieved by first executing the stored procedure, capturing the output into a #temp table or a #tabel variable, then running your query against the table. Something like this:
declare #droits_table (val ,... );
insert into #droits_table
exec up_droits(param, param);
SELECT distinct top 10 i.x, d.droit FROM v_droit d, v_info i WHERE d.nomdroit='yy' AND i.id<>2 AND (select val from #droits) <>3
Of course this will not work for you because the up_droits needs the i.x and d.droit parameters from the query. This indicates that your stored procedure should probably be a a view or table valued function.
Sorry but, make it a table valued function rather than stored procedure.
Eg:
Scalar - SELECT id, name FROM test WHERE id < (SELECT dbo.mytestfunction())
Table - SELECT id, name FROM test WHERE id = (SELECT col1 from dbo.mytestfunction())
You can't. The content of the WHERE clause must be a search expression.
Is the reason that the code doesn't work as a function because it modifies some data? If so, then you're out of luck, functions used in where clauses must be immutable.
If the stored procedure doesn't modify any data, you may be able to wrap it inside of a function.
If you are on SQL Server I don't think you can do what you propose.
But one thing you can do is build dynamic queries, but be careful doing it because they open up many interesting problemareas.
The syntax is :
EXEC #<query>
But anotherthing you can do, which is probably much better for you, is to make the up_droits function deliver it's results in a temp table, if you select into a #table it is temporary for the duration of your function/procedure scope
declare procedure up_droits() as
select val .. into #temp
So what you do is create a procedure
create procedure Top10FromDroit
begin
exec up_droits
SELECT distinct top 10 i.x, d.droit FROM v_droit d, v_info i WHERE d.nomdroit='yy' AND i.id2 AND (select val from (#temp) 3
Hopefully that will give you the results you want to achieve.
If at first you don't succeed, code around it^^
Could anyone of you explain reasons for executing dynamic SQl inside stored procedure. I know very few situations when you need them - but really very few. 99.9% (or 999 of a 1000) of execute strings could be rewritten as normal sql statements with parameters.
The very same is with Selects that have functions inside select or where clauses.
Try to think about your sets of data, not about procedural ways how to solve it.