How do I combine executing of a stored procedure and using its result or parameters in a regular SQL query?
For example I would like to do something like the following:
-- passing result of SELECT to SP
SELECT a, b FROM t
EXEC my_sp a, b
-- passing result of SP to INSERT
INSERT INTO t
EXEC my_sp a, b
etc.
no, you need to use a temp table
create table #results (col1 int, col2 varchar(5) ...)
INSERT INTO #results
EXEC YourProcedure #parma...
then you can join to it
SELECT
*
FROM YourTable y
JOIN #results r ON ...
....
if you don't know the columns and data types from the procedure you can use this excellent answer: Insert results of a stored procedure into a temporary table
In brief it uses OPENROWSET to execute the stored procedure into a #temp table that is created on the fly, without the need to name and know the type all the columns.
If your SP can be rewritten as an inline table valued UDF, these typically perform very well and are equivalent to a parametrized view. ITVF can be used any place you would use a table or view.
If your SP won't work as an inline TVF (local variable manipulation required), it may work as a multi-statement TVF (contains a BEGIN/END) which may or may not perform poorly depending on what you have to do.
After your SP has been turned into a UDF, you can then still call the UDF from your SP (SELECT* FROM udf(params)) or elsewhere it can be used for joins, etc, so all your code is inside the UDF - no duplication.
Related
Being a recent convert from SQL Server, I am getting to know Postgresql a bit.
I really hate having to write nested selevt statements in SQL since I find that the readability and maintainability of the code suffers when I do.
Usually I would create a stored procedure in SQL Server where I would select something into a temporary table, that I can then use in another select statement.
CREATE OR ALTER PROCEDURE Procname
AS
BEGIN
SELECT
Somewhere.Col_1,
Somewhere.Col_2
INTO
#Temptable
FROM
Somewhere Somewhere
SELECT
Temptable.Col_1,
Somewhere_Else.Col3
FROM
#Temptable Temptable
INNER JOIN
Somewhere_Else.Col_2 = Temptable.Col_2
END
When I execute this procedure I would get returned the final select query
How would I replicate this procedure in Postgresql?
I know that you can select into a temporary table, but I cannot seem to figure out how to use this table in the next select statement within the same procedure
Create a set returning function, there is no need for a temp table at all.
CREATE function Procname()
returns table(col_1 ???, col2 ???) --<< change data types here
AS
$$
SELECT
Temptable.Col_1,
Somewhere_Else.Col3
FROM Somewhere Temptable
INNER JOIN Somewhere_Else ON Somewhere_Else.Col_2 = Temptable.Col_2;
$$
language sql
stable;
But for such a simple statement, I would rather create a view.
I have two fairly large and complex stored procedures. I want to call a second stored procedure from the first stored procedure. For example:
-- stored_procedure_one
select tb1.col1, tb1.col2, sp1.col3, sp1.col4
from table1 tb1
inner join stored_procedure_two sp1 on sp1.col1 = tbl1.col1
Is something similar possible with SQL as the above script gives me an invalid object error message.
Using a temp table is not good in this example, because if I did that, it would take an hour just to fill the temp table with all the data from the second stored procedure. I only want the stored procedure to return the needed data.
This is not going to work. You cannot join on a stored procedure. However, you could consider changing stored_procedure_two into a table-valued user defined function. You could then 'join' via a Cross Apply. I have done this on numerous occasions and it works quite well.
If the second stored procedure is too large and complex, it may not be possible to convert to a UDF. In this case, I think your only alternative is to save the results of the second stored proc to a table and join on that. But that could be somewhat inefficient and messy.
You may add the results of the second procedure in a local variable table
DECLARE #Table TABLE
(
Col1 int,
Col2 ...
)
INSERT INTO #Table
EXEC stored_procedure_two
select tb1.col1, tb1.col2, sp1.col3, sp1.col4
from table1 tb1
inner join #Table tbl2 on sp1.col1 = tbl1.col1
I need to access the result of a stored procedure within a select statement, i.e.:
SELECT * FROM [dbo].[sp_sample]
in SQL_Server 2005.
This isn't possible. You would have to create a temporary table to store the results.
Create Table #tmp
(
...
)
Insert into #tmp
Exec dbo.StoredProcedure
The table structure must match the output of the Stored Procedure.
#Barry is right you need to create a temp table and insert into it first, then join that table in your select.
However, there are numerous ways for sharing data between stored procedures, see this excellent article: How to Share Data Between Stored Procedures by Erland Sommarskog
One method that may work for you is to "share" a temp table. The #temp table is created in the Parent procedure and can be used by the Child: http://www.sommarskog.se/share_data.html#temptables
I would like to create a SP or UDF where I supply a table and column name as a parameter and it does something to that target. I'm using Sql Server 2005
Trivial Example of what I'm trying to accomplish:
CREATE FUNCTION Example (#TableName AS VARCHAR(100))
RETURNS TABLE
AS
BEGIN
SELECT *
INTO #temp
FROM #TableName
RETURN #temp
END
The example is just something trivial to illustrate what I'm trying to accomplish in terms of passing the Table name as a parameter.
Is this possible to do w/o concatinating strings and calling the EXEC function?
Ultimately, I'm trying to convert the answer from this question into something reusable.
This reeks of SQL injection. You would still need to use EXEC to do this.
No. Can't do it. Sadly, there is no macro pre-complier in T-SQL. The closest you'll get is SQLCMD mode, but that's only for scripts, can't use it in object definitions.
Are you doing the same thing to the table each time?
You could dynamically redefine a synonym, but that still requires an EXEC and you lose concurrency. You could serialize execution with a queue, but at that point you may be better off w/ plain old dynamic SQL.
You might try temporary tables, not passed in as a variable, but created in the parent connection or calling procedure. eg.
create proc #proc as
select * from #table
go
create table #table (col1 int)
insert #table values (1)
insert #table values (2)
insert #table values (3)
go
exec #proc
go
For more ways to share data between stored procedures, see here: http://www.sommarskog.se/share_data.html
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.