Get variables of a stored procedure from a SELECT statement - sql

I'd like to execute a stored procedure with variables that I'm getting from a select statement like its possible in insert, update and delete.
EXEC [dbo].[upsert_release_artist_role_sp]
#release_guid = #release_guid,
#artist_id = #artist_id OUTPUT,
#external_role_id = #external_role_id
(
SELECT #release_guid, artist_id, #external_role_id
FROM #artist_ids
)
In the code, artist_id is defined in a table variable and I need a way to retrieve it.
Any idea what's the best way to tackle this?

Was solved by using https://chat.openai.com/ :D
Solved this by
DECLARE #artist_id INT
SELECT #artist_id = artist_id FROM #artist_ids
EXEC [dbo].[upsert_release_artist_role_sp]
#release_guid, #artist_id, #external_role_id
-- This has been verified in my code and works well.

Related

SELECT against stored procedure SQL Server

SELECT Val from storedp_Value within the query editor of SQL Server Management Studio, is this possible?
UPDATE
I tried to create a temp table but it didn't seem to work hence why I asked here.
CREATE TABLE #Result
(
batchno_seq_no int
)
INSERT #Result EXEC storedp_UPDATEBATCH
SELECT * from #Result
DROP TABLE #Result
RETURN
Stored Procedure UpdateBatch
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
RETURN #batchno_seq
What am I doing wrong and how do I call it from the query window?
UPDATE #2
Ok, I'd appreciate help on this one, direction or anything - this is what I'm trying to achieve.
select batchno_seq from (delete from batchno_seq;insert into batchno_seq default values;
select * from batchno_seq) BATCHNO
INTO TEMP_DW_EKSTICKER_CLASSIC
This is part of a larger select statement. Any help would be much appreciated. Essentially this SQL is broken as we've migrated for Oracle.
Well, no. To select from a stored procedure you can do the following:
declare #t table (
-- columns that are returned here
);
insert into #t(<column list here>)
exec('storedp_Value');
If you are using the results from a stored procedure in this way and you wrote the stored procedure, seriously consider changing the code to be a view or user defined function. In many cases, you can replace such code with a simpler, better suited construct.
This is not possible in sql server, you can insert the results into a temp table and then further query that
CREATE TABLE #temp ( /* columns */ )
INSERT INTO #temp ( /* columns */ )
EXEC sp_MyStoredProc
SELECT * FROM #temp
WHERE 1=1
DROP TABLE #temp
Or you can use OPENQUERY but this requires setting up a linked server, the SQL is
SELECT * FROM (ThisServer, 'Database.Schema.ProcedureName <params>')
The best article (in my opinion) about all possible methods for sharing data between stored procedures in SQL Server you can find here: http://www.sommarskog.se/share_data.html
Try this
Change 'Return'
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
RETURN #batchno_seq
to 'Select'
delete from batchno_seq;
insert into batchno_seq default values;
select #batchno_seq= batchno_seq_no from batchno_seq
SELECT #batchno_seq
My approach
select * into new_table from (select t1.col1,t1.col2,..
from table1 t1
union
select t2.cola,t2.colb,..
from table2 t2) as union_table
I MUST be missing something.
Since your stored procedure does not return a result set, and instead returns an integer, using the RETURN functionality of stored procs, you simply CANNOT INSERT into ANY table (since there isn't any result set coming back, at all).
BUT, you can (assuming that this is done iteratively, and not over a set) simply store the return value into a local variable, and insert that variable's value into whatever table is necessary.
However, if you simply want to return the value in the results of a Query Window in SSMS, doing the INSERT and SELECTING is overkill.
It seems to me like THIS would suffice (in a query window):
DECLARE #RetVal INT = 0;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
EXEC #RetVal = storedp_UPDATEBATCH;
COMMIT TRANSACTION;
SELECT #RetVal;
--OR
--PRINT #RetVal;
If this is way far off base, please provide the DDL for "batchno_seq", maybe I can be of better assistance that way.
Cheers!

sql lookup ID and insert if no result found

I have a select statement that needs to look up a customer ID from a customer name. If an ID does not exist for that name, a new record needs to be created in the customer table. this has to be done as part of a select statement (related to the app its being run from).
I tried looking at a UDF that returned either the existing ID or a new ID, before realizing that you can't modify tables from a function.
any idea how to accomplish this?
EDIT:
I think i need to clarify things a bit more. The select statement can and will change on a per-implementation basis. What I'm looking for is a generic way of looking up or creating the customer id (that table and the need to do the lookup does not change) as part of a larger select statement.
the app that is using the sql loads the select statement from a config file, and has 'SELECT' hard coded, so there's no chance of adding an exec before the select etc.
It looks like what I need is something like 'select a.1 (exec dotheLookup(name)) as customerID, a.2 FROM table, but I'm not sure how to go about that.
I suggest you to Create a stored procedure for this. Something like
Create procedure customer
--parameters
AS
Begin
IF exists(Select lookup(customerName) as customerID from table)
BEGIN
--Your select goes here
END
ELSE
BEGIN
--Insert into customer table and return scopeidentity
--Select goes here
END
END
Updated Answer:
You cannot perform data manipulation using select statement.
You could execute a stored procedure before you execute the SELECT statement, the run a function that returns ID from name:
exec CheckForCustomerByNameAndAddIDIfItDoesntExist(customerName)
declare iCustomerID int
select iCustomerID = GetCustomerIDFromName(customerName)
select a.1, a.2, iCustomerID as customerID from table
Something like that
Can you modify the database server? If so, add a linked server pointing to the local server.
EXEC master.dbo.sp_addlinkedserver #server = N'LinkedLocal', #srvproduct=N'', #provider=N'SQLNCLI', #datasrc=N'LocalServerName'
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'LinkedLocal',#useself=N'True',#locallogin=NULL,#rmtuser=NULL,#rmtpassword=NULL
Then just run an OPENQUERY that invokes a stored procedure that does your work:
select * from OPENQUERY("LinkedLocal", 'exec Database.Schema.StoredProcedure ''Param1'', ''Param2'')

Get the number of affected rows in a MySQL update statement?

I have stored procedure in MySQL, something like the below:
create procedure SP_Test (input1 varchar(20))
begin
update Table1 set Val1='Val' where country=input1;
//I want to see if this update changed how many rows and
//do some specific action based on this number
....
end
How can I determine how many rows were changed by this update?
Use ROW_COUNT():
SELECT ROW_COUNT();
one way, not very optimal is to simply do a select before you do the update.
select count(*) from table1 where country = 'country1'
Try the following code:
int mysql_affected_rows ([ resource $link_identifier = NULL ] )

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.

Can I use a store procedure output in an update statement in SQL Server?

I'm converting some data in SQL Server 2005. I have a table update like this:
update Invoices set Invoices.InvoiceReference = 'NewRef'
where Invoices.InvoiceReference='Unknown'
But what I'd like to plug in instead of 'NewRef' is the output from a stored procedure that uses parameters from the columns of the Invoices table. The stored procedure itself does updates to another table. Is it possible? Something like this below (which is wrong of course :)
DECLARE #Ref nvarchar(20)
update Invoices set Invoices.InvoiceReference = (
EXEC InvoiceGenerateRef
#ClientCode = Invoices.ClientCode,
#EventCode = Invoices.EventCode,
#Ref = #Ref OUTPUT
SELECT #Ref)
where Invoices.InvoiceReference='Unknown'
Do I need to use a cursor or is the syntax just wrong?
Thanks,
Chris.
I think you would be better off changing your stored procedure into either a function or a view (depending on what you actually do in the proc).
I think what you are after is to join to the resultset of a stored proc which would not work.
You are almost there, the correct way to achieve what you are looking to do would be to define an output parameter as part of your stored procedure definition.
This paramter can then be used as part of your update statement.
DECLARE #Ref nvarchar(20)
EXEC InvoiceGenerateRef
#ClientCode = N'ABC2',
#EventCode = N'X1'
#Ref = #Ref OUTPUT
update Invoices
set Invoices.InvoiceReference = #Ref
where Invoices.InvoiceReference='Unknown'
by using OPENROWSET you can query your stored procedure results just like a view:
http://blogs.technet.com/wardpond/archive/2005/08/01/the-openrowset-trick-accessing-stored-procedure-output-in-a-select-statement.aspx
so for your case this might be useful.
1) You could change InvoiceGenerateRef so that it could optionally save the generated Ref into InvoiceReference field. Presumably you would also have to provide parameters to define the selection
2) You could us e cursor to step round each row in
SELECT ...
FROM Invoices
WHERE Invoices.InvoiceReference='Unknown'
and pass the details to InvoiceGenerateRef and then update the row. This is bad IMHO and will be slow (Your best bet is a set-based solution)
3) You could select the appropriate Invoices.ID's into a temporary table which would be in scope for the InvoiceGenerateRef so that it could iterate that (i.e. the choice of WHICH rows to update is external to the SProc, but the SProc does the actual updating)
CREATE TABLE #TEMP
(
T_ID int NOT NULL
)
INSERT INTO #TEMP (T_ID)
SELECT ID
FROM Invoices
WHERE Invoices.InvoiceReference='Unknown'
EXEC InvoiceGenerateRef #ACTION='UpdateFromTemporaryTable'
4) You could change InvoiceGenerateRef to a function that performed the same task:
UPDATE U
SET U.InvoiceReference =
dbo.MyInvoiceGenerateRefFunction(U.ClientCode, U.EventCode)
FROM Invoices AS U
WHERE U.InvoiceReference='Unknown'
MyInvoiceGenerateRefFunction would have to be deterministic (I think!)
This would be my preferred choice