I have a stored procedure in other database which is maintained by other team. Assume that it is currently returning 3 columns, and my system only needs those 3 columns
but the other team can add few more columns for their own use which is causing my system to fail.
Other database SP
ALTER PROCEDURE FirstSP
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #A (Id INT, Name VARCHAR(200), Amount VARCHAR(100), TestColumn INT)
INSERT INTO #A VALUES
(1,'ABC','23',1), (2,'CDF','35454',2), (3,'hjhj','9809909',3)
SELECT * FROM #A
DROP TABLE #A
END
GO
And below is my query, which was only expecting 3 columns from the source
CREATE TABLE #MyTable (Id INT, Name VARCHAR(200), Amount INT)
INSERT INTO #MyTable
EXEC dbo.FirstSP;
SELECT * FROM #MyTable
DROP TABLE #MyTable
Is there any way I can provide the column list?
This is what I am trying but it seems that I can't use server name as the parameter
DECLARE #ServerName VARCHAR(100) = ##SERVERNAME
SELECT * FROM OPENQUERY(#ServerName,'EXEC dbo.FirstSP')
My whole problem is to just select required columns from the SP. SP can have many columns in future.
Try this:
/*
-----------------------------------------------------------------------
Replace <SERVERNAME>\<INSTANCENAME>], <DATABASENAME> with your names
*/ ------------------------------------------------------------------------
-- First, enable Data Access (One time only)
EXEC sp_serveroption '<SERVERNAME>\<INSTANCENAME>', 'DATA ACCESS', TRUE;
-- Then SELECT just the fields you need
SELECT ID, Name, Amount
FROM OPENQUERY([<SERVERNAME>\<INSTANCENAME>], 'EXEC <DATABASENAME>.dbo.FirstSP')
I would ask the team that develops the stored procedure to create a parameter "Team" or something and slightly change the sp so that it will return the expected columns based on this parameter.
A more cumbersome solution is to use this stored procedure the get the colum names of the (first) result returned by the sp.
sp_describe_first_result_set 'dbo.usp_mySp';
And then use the result to create some dynamic SQL.
Related
I have a stored procedure which inserts values into a table.
Let's say its name is usp_InsertTableA with parameters #ID int and Name varchar(100).
I have a requirement to call this stored procedure multiple times from another stored procedure. I am thinking to call this stored procedure something like below
exp usp_InsertTableA
select ID, Name from #tempTable
Is this possible in SQL Server to execute this with the value of the table and send it into a stored procedure?
You can use table type parameters to stored procedure.
CREATE TYPE [dbo].[udt_MyCustomTable] AS TABLE(
[id] [int] NOT NULL,
[name] [nvarchar](100) NOT NULL
)
GO
And then you stored procedure would be:
CREATE PROC [dbo].[usp_InsertTableA]
(
#myCustomTable udt_MyCustomTable READONLY
)
AS
BEGIN
-- Your code goes in here
END
Is this possible in SQL Server to execute this with the value of the table and send it into a stored procedure?
No, not with the stored procedure you have there. There are ugly hacks that could make it happen, but it's not how you're supposed to do things in T-SQL. Everything you do in SQL Server is supposed to be optimized to work on a set of rows, not a single row / row by row
In practice what this means is, if you have a query like this that produces 100 rows:
select ID, Name from #tempTable
You would pass those 100 rows to your insert procedure and insert them in one operation:
--expanding on sam's advice
--create a type
CREATE TYPE [dbo].[udt_MyCustomTable] AS TABLE(
[id] [int] NOT NULL,
[name] [nvarchar](100) NOT NULL
)
--your insert procedure
CREATE PROC [dbo].[usp_InsertTableA]
(
#myCustomTable udt_MyCustomTable READONLY
)
AS
BEGIN
INSERT INTO TableA(idcolumn, namecolumn)
SELECT is, name FROM #myCustomTable
END
Now in your main sp that wants to insert 100 rows:
#DECLARE tmpVar udt_MyCustomTable;
--put 100 rows into table variable
INSERT INTO tmpVar(id,name)
select ID, Name from #tempTable
--pass 100 rows in variable to SP to insert all at once
EXECUTE usp_InsertTableA tmpVar
DECLARE #ID INT, #Name VARCHAR(255)
SELECT #ID = ID, #Name=Name FROM #tempTable -- assumes one record in the table.
EXEC dbo.usp_insertdata #id, #Name
After execution of my stored procedure, the following columns are returned:
srno
name
days
amount
bkt1
bkt2
but I want to change these column names to:
srno
name
days
amount
col_name_i/p_from_user
col_name_i/p_from_user
Could you assist?
As you have didn't mentioned the version so I will assume that you have SQL Server 2012+ version. You can use WITH RESULT SETS property to alter your output column name
Example:
CREATE PROCEDURE SP_Test
AS
BEGIN
SELECT 1 AS 'ColA', 2 AS 'ColB'
END
Now, you can alter the column name by using WITH RESULT SETS property
EXEC SP_Test
EXEC SP_Test WITH RESULT SETS(
(New_Col1 INT,
NEW_Col2 INT))
In case you are using older version of SQL Server then you can dump your stored procedure result set into a temp table or table variable and then you can alias the name(From same above example)
DECLARE #Mytest TABLE (New_Col1 INT, New_Col2 INT)
INSERT INTO #Mytest EXEC Sp_Test
SELECT * FROM #Mytest
use column alias as below with dynamic sql:
declare #q nvarchar(max)
set #q ='select bkt1 as ' + #ipfromuser +' from table1'
exec(#q)
I had a procedure it will return data from a temporary table.The temporary table structure may varies depends on the input parameter of the procedure.This procedure is a general procedure so i cant modify this one.
My requirement is that i want to use the return temporary table data to do some calculation from another procedure.Is it possible to achieve this one????
requirement is some thing like this
Create Procedure Proc2 ( #Condition int)
As
BEGIN
execute #temp = Proc1 input1,input2
select * from #temp where column1 = #Condition
END
This Proc1 is using in some other procedures also so i cant include the condition inside Proc1.
Am using SQL SERVER 2008 R2
Thejus T V
You need to create a temporary table and use like this
Create Procedure Proc2 ( #Condition int) As
BEGIN
create table #temp(col1 int, col2,....) -- similar to reseultset of proc1
insert into #temp
execute Proc1 input1,input2
select * from #temp where column1 = #Condition
END
If the column names are unknown you can use OPENROWSET
Select
*
from
OPENROWSET('SQLOLEDB','Data Source=Server_name;Trusted_Connection=yes;
Integrated Security=SSPI','Execute yourdb..proc1')
If you know the structure being returned by the procedure then you can simply create a temp table and insert the data into that temp table from the stored procedure result set.
Create Table #Temp (Col INT , Col2 INT)
INSERT INTO #Temp
Exec Proc1 input1,input2
But since you have mentioned you don't know the exact structure of the table begin returned from the stored procedure you can use OPENQUERY to manipulate further the result set of a stored procedure something like this....
SELECT *
FROM OPENQUERY(YOURSERVERNAME, 'Proc1 input1,input2')
where column1 = #Condition
I have a stored procedure that is responsible to import data from database A to database B. I have customers, they all have their own database B (with the same tables etc.) They also have their own database A. The stored procedure will be executed (deployed) on database B.
The problem:
Each customer have another database name for A and B. I found also that database A can be on a different server/instance. I need a generic way to put automatically the server/instance name and the database name from A in my stored procedure to select data from there. Every customer has a connectstring to database A which is already exists in database B. So from the connecstring, I can get the server/instance name and the databasename of A. (I already created a linked server)
1. What is the best way to put the server/instance name and the database name before the table name??
Stored procedure
In my stored procedure I have used a lot of variable (declare) tables to insert the data from database A. There are many articles about using dynamic sql but, I cant find an example with a declare table.
My solution
I am thinking about inserting all the data from database A to variable tables. I am importing data from 7 tables, so I need to declare 7 tables and further in my SP I can select data from my declare tables. Note that the hole stored procedure is very huge.
Questions
2.What do you think about my solution?
3.Do you have another solution?
4.How can I insert into my declare table using dynamic sql?
**note that I am using sql server 2005.
I have a few statements like below:
declare #Temp table (Id int, etc
insert into #Temp (Id, etc)
Select Id, etc
From [databasename].dbo.TableName //hardcoded
Where .......
// doing staff like selecting from the #Temp table etc.
I also have subqueries, but I can change if it is necessary.
You can't use dynamic sql to enter into declare tables as the temporary table is only available in the session. Executing any new sql i.e. through dynamic sql will create a new session.
You can get around it by not using any declared or temp tables but instead using a normal table. The dynamic sql will have access to this and anything you do to it isnt lost.
You can prefix your normal tables with something like Temp_ just to note they are temp tables and then make sure you drop them at the beginning of each query i.e.
DROP TABLE TEMP_Table
You can call multiple local databases by doing
SELECT * FROM [DatabaseName].dbo.[TableName]
Instead of creating #temp, create it as [TempDB].[DBO].[Temp] and it will be accessible outside the dynamic SQL. However, remember to explicitly drop the table, once you are done
DECLARE #sql VARCHAR(200)
SET #sql = 'CREATE TABLE tempdb.dbo.temp(id INT IDENTITY(1,1), DESCRIPTION VARCHAR(100))
INSERT INTO tempdb.dbo.temp SELECT ''1'' SELECT * FROM tempdb.dbo.temp'
PRINT (#sql)
EXEC (#sql)
SELECT * FROM tempdb.dbo.temp
DROP TABLE tempdb.dbo.temp
Raj
Check this for creating temporary table in dynamic query
DECLARE #sql VARCHAR(200)
SET #sql = 'CREATE TABLE #temp(id INT IDENTITY(1,1), DESCRIPTION VARCHAR(100))
INSERT INTO #temp SELECT ''1'' SELECT * FROM #temp'
PRINT (#sql)
EXEC (#sql)
SQLFiddle
to be precise
DECLARE #sql VARCHAR(1000)
SET #sql =
'DECLARE #Temp TABLE (
Id INT,
etc
INSERT INTO #Temp (Id, etc)
SELECT Id,
etc
FROM [databasename].dbo.TableName / / hardcoded
WHERE ....... SELECT * FROM #temp'
PRINT (#sql)
EXEC (#sql)
I have a following stored procedure
CREATE PROCEDURE [dbo].[MyStored]
#state int
AS
SELECT blahblahblah WHERE StoredState=#state LotsOfJoinsFollow;
RETURN 0
and I'd like to call that stored procedure with #state being 0 and 1 and have the result sets returned by both calls combined with UNION semantics so that I have a new resultset that has rows from both the first call and the second call.
Something like (imaginary SQL):
(EXEC MyStored 0) UNION (EXEC MyStored 1);
How do I achieve that?
This may be oversimplifying the problem, but if you have control over the sp, just use in rather than =:
CREATE PROCEDURE [dbo].[MyStored]
AS
SELECT blahblahblah WHERE StoredState IN (0,1) LotsOfJoinsFollow;
RETURN 0
If this is not an option, just push the results of both sproc calls into a temp table:
/*Create a table with the same columns that the sproc returns*/
CREATE TABLE #tempblahblah(blahblahblah NVARCHAR(50))
INSERT #tempblahblah ( blahblahblah )
EXEC MyStored 0
INSERT #tempblahblah ( blahblahblah )
EXEC MyStored 1
SELECT * FROM #tempblahblah
create table #table (
.....
)
insert into #table exec MyStored 0
insert into #table exec MyStored 1
select * from #table
drop table #table
Alternatively to a series of statements like these:
INSERT INTO #YourTempTable
EXEC MyStored 0;
INSERT INTO #YourTempTable
EXEC MyStored 1;
you could use one INSERT ... EXEC statement like below:
INSERT INTO #YourTempTable
EXEC ('
EXEC MyStored 0;
EXEC MyStored 1;
');
The results of the two calls to MyStored would be UNIONed (or, rather, UNION ALLed), just like with the former method.
A long way would be to create a wrapper that does this - a function that takes a list of states and adds them to a final table that would be returned.
You could also have whatever technology is calling this procedure do the concatination of records (i.e. having .NET append the result set of each state you are looking into)
If you're fine with passing in a list of states to your 'state' param, you could create a dynamic sql query
CREATE PROCEDURE [dbo].[MyStored]
#state nvarchar(150)
AS
-- #state needs to be pre-formatted in a list for an in-clause
-- i.e. 1,2,10 (if it was a string list, you'd need to do use double single quotes around the items - ''1'',''2'',''10''
DECLARE #SQL nVarChar(5000) = '
SELECT blahblahblah
FROM LotsOfJoins
WHERE StoredState in (' + #state + ')'
exec sp_executeSql #sql
This works great for simple procedures; although, it can get take longer to maintain if changes are needed down the road.
.
Here is a CodeProject Article and a MS SQL Tips Article that does a better job going into details
.
EDIT: The param #state will need to be a nVarChar since your passing in a comma delimited list of int values
If the stored procedure you are calling has a temp table with the same name as one in the calling procedure you will get this error.
e.g. sp1 has temp table #results
sp2 create table #results(fields)
then trying to insert into #results in sp2 the result of calling sp1 would fail with this error. change temp table in sp2 to #result and try again and you should see this now works.