Currently work with multiple servers and need to return the results in a table, how can I do?
I intend to get data from each bank and return all through a single procedure.
Example, caught available space of the server and return in table format.
You must be in .NET
First create the links to other server
Example:
USE [master]
GO
EXEC master.dbo.sp_addlinkedserver
#server = N'SecondServer',
#srvproduct=N'SQL Server' ;
GO
EXEC master.dbo.sp_addlinkedsrvlogin
#rmtsrvname = N'SecondServer',
#locallogin = NULL ,
#useself = N'True' ;
GO
Then you can create procedure that can query multiple server.
Example:
CREATE PROCEDURE procedureName
(
#dateFrom datetime,
#dateTo datetime
)
AS
BEGIN
SELECT * FROM CurrentServerName.DatabaseName.TableName
UNION
SELECT * FROM SecondServerName.DatabaseName.TableName;
END
Related
I have been looking online for a few days to find a solution and
I may be asking the wrong questions.
I have the following stored proc which on insertion of a row to a db I want to get back the output int (#outResult). This is the stored proc :
USE [DB1]
GO
/****** Object: StoredProcedure [dbo].[storedProc1] Script Date: 04/12/2016 10:16:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[storedProc1]
-- Add the parameters for the stored procedure here
#inParam nvarchar(max),
#outResult int = 0 OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF NOT EXISTS
(
SELECT ID
FROM dbo.table1
WHERE Field1 = #inParam
)
Insert into [DB1].[dbo].[table1]
(
Field1
)
Values (
#inParam
)
SET #outResult = SCOPE_IDENTITY()
END
When I run the following SQL and try to retrieve the resultSet :
SELECT * FROM (EXEC storedProc1 'field1')
I get the following error:
"Incorrect syntax near the keyword 'exec'"
Maybe I am approaching this problem wrong from the first place?
I will continue to look into this and provide a solution if I find one.Any ideas?
To get the value of the output parameter you need to supply the call to the SP with an output argument. You do that by specifying the OUTPUT option on the second parameter.
DECLARE #returned_ID INT;
EXEC storedProc1 #inParam = 'field1',
#outResult = #returned_ID OUTPUT
SELECT #returned_ID
If you want to retrieve just the out parameter, then You can read it as :
DECLARE #output int
EXEC storedProc1 'field1',#output OUTPUT
SELECT #output
I am having an issue trying to SELECT specific columns from an EXEC statement on a stored procedure. I am trying to find the COUNT(*) that the stored procedure returns which I am successfully doing with :
INSERT INTO #temp
EXEC dbo.my_sp
SET #count = (SELECT COUNT(*) FROM #temp)
DELETE FROM #temp
However, this only works if the columns returned match specifically with the table columns and since I am trying to find the count of many different stored procedures (each of which return different columns), I cannot use this method without creating a new table for each stored procedure.
Is there a way I can SELECT specific columns from the EXEC dbo.my_sp?
Create a loopback linked server to the local instance, making sure that data access is enabled. Let's say you have a local named instance called YourServer\SQL2008:
USE [master];
GO
EXEC sp_addlinkedserver
#server = N'LoopbackLocal',
#srvproduct = N'',
#provider = N'SQLNCLI',
#datasrc = N'.\SQL2008',
#catalog = N'tempdb';
GO
EXEC sp_serveroption
#server = N'LoopbackLocal',
#optname = N'collation compatible',
#optvalue = N'true';
GO
EXEC sp_serveroption
#server = N'LoopbackLocal',
#optname = N'data access',
#optvalue = N'true';
GO
EXEC sp_addlinkedsrvlogin
#rmtsrvname = N'LoopbackLocal',
#locallogin = NULL ,
#useself = N'True';
GO
-- you may need to configure other security here
Then you can use OPENQUERY to run a stored procedure as if it were an ad hoc query.
SELECT COUNT(*)
FROM OPENQUERY
(
LoopbackLocal,
'EXEC dbo.my_sp'
) AS y;
Now, if dbo.my_sp dumps information into a #temp table first, you're going to have issues, since it is no longer a block of code that OPENQUERY can process. For example, if you try to execute sp_who2 this way, at least in SQL Server 2012, you will get an error from sp_describe_first_result_set which OPENQUERY has been altered to use (so maybe this works for you now, I don't have 2008 to test, but it will be an issue someday):
Msg 11526, Level 16, State 1, Procedure sp_describe_first_result_set, Line 1
The metadata could not be determined because ... uses a temp table.
If you're going to be doing this a lot, however, why not make specialized stored procedures (or add options to these ones) such that only a count is returned?
Would ##ROWCOUNT work for you?
if OBJECT_ID('SomeProc') is null
exec ('create procedure dbo.SomeProc as select 1 as SomeValue union all select 2 as SomeValue;')
exec dbo.SomeProc
Select ##ROWCOUNT as RowsAffected
http://technet.microsoft.com/en-us/library/ms187316(v=sql.105).aspx
Not sure how to implement this, but I need a way to get the current list of parameters for a stored procedure as well as their passed in values (this code will be executed in the stored procedure itself).
I know I can use sys.parameters to get the parameter names, but how to get the actual values?
What I need to do with this is to make a char string of the form
#param_name1=#value1,#param_name2=#value2,...,#param_namen=#valuen
I have tried to use dynamic sql, but not having much joy with that.
Any ideas??
Edit:
Currently I am just going through all the parameters one-by-one to build the string. However I want a "better" way to do it, since there are quite a few parameters. And incase parameters are added later on (but the code to generate the string is not updated).
I tried using dynamic sql but gave up, since the sp_executesql sp requires parameters be passed into it...
You state '(this code will be executed in the stored procedure itself).' so assuming you are in the procedure you will already know the parameter names as you have to declare them when creating your procedure. Just do a select and put the names inside text fields
ALTER PROCEDURE procname
(
#param1 NVARCHAR(255)
,#param2 INT
...
)
SELECT [Parameters] = '#param1=' + #param1
+ ',#param2=' + CONVERT(NVARCHAR(MAX),#param2)...
The CONVERT is there as an example for non-char datatypes.
update
You will need to create a linked server that points to itself to use the OPENQUERY function.
USE [master]
GO
/****** Object: LinkedServer [.] Script Date: 04/03/2013 16:22:13 ******/
EXEC master.dbo.sp_addlinkedserver #server = N'.', #srvproduct=N'', #provider=N'SQLNCLI', #datasrc=N'.', #provstr=N'Integrated Security=SSPI'
/* For security reasons the linked server remote logins password is changed with ######## */
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'.',#useself=N'True',#locallogin=NULL,#rmtuser=NULL,#rmtpassword=NULL
GO
Now you can do something like this cursor to get each parameter name and then use dynamic sql in OPENQUERY to get the value:
DECLARE curParms CURSOR FOR
SELECT
name
FROM sys.parameters
WHERE OBJECT_ID = OBJECT_ID('schema.procedurename')
ORDER BY parameter_id
OPEN curParms
FETCH curParms INTO #parmName
WHILE ##FETCH_STATUS <> -1
BEGIN
SELECT #parmName + '=' + (SELECT * FROM OPENQUERY('linkedservername','SELECT ' + #parmName))
FETCH curParms INTO #parmName
END
CLOSE curParms
DEALLOCATE curParms
Since SQL Server 2014 we have sys.dm_exec_input_buffer, it is a table valued function with an output column event_info that gives the full execution statement (including parameters).
We can parse the param values from sys.dm_exec_input_buffer and get the param names from sys.parameters and join them together to get the string you want.
For example:
create procedure [dbo].[get_proc_params_demo]
(
#number1 int,
#string1 varchar(50),
#calendar datetime,
#number2 int,
#string2 nvarchar(max)
)
as
begin
-- get the full execution statement
declare #statement nvarchar(max)
select #statement = event_info
from sys.dm_exec_input_buffer(##spid, current_request_id())
-- parse param values from the statement
declare #proc_name varchar(128) = object_name(##procid)
declare #param_idx int = charindex(#proc_name, #statement) + len(#proc_name)
declare #param_len int = len(#statement) - #param_idx
declare #params nvarchar(max) = right(#statement, #param_len)
-- create param values table
select value, row_number() over (order by current_timestamp) seq
into #params
from string_split(#params, ',')
-- get final string
declare #final nvarchar(max)
select #final = isnull(#final + ',','') + p1.name + '=' + ltrim(p2.value)
from sys.parameters p1
left join #params p2 on p2.seq = parameter_id
where object_id = ##procid
select #final params
end
To test it:
exec get_proc_params_demo 42, 'is the answer', '2019-06-19', 123456789, 'another string'
Returns the string you want:
#number1=42,#string1='is the answer',#calendar='2019-06-19',#number2=123456789,#string2='another string'
I have something similar wrapped as a UDF. I use it for error logging in catch blocks.
I have SQL Server 2008 with a linked Sybase server and I am trying to execute a stored procedure on the Sybase server using OPENQUERY. If I have a stored proc that doesn't take parameters it succeeds fine. If I have a stored proc with parameters it fails. I even tried a very basic stored proc that only took an int an that still failed. Below is the syntax I am using:
select * from
OPENQUERY([LINKSERVER],'exec database.user.my_stored_proc ''AT'',''XXXX%'',''1111'',1')
Msg 7357, Level 16, State 2, Line 3
Cannot process the object "exec database.user.my_stored_proc 'AT','XXXX%','1111',1". The OLE DB provider "ASEOLEDB" for linked server "LINKSERVER" indicates that either the object has no columns or the current user does not have permissions on that object.
As the proc will execute just fine without parameters, I don't think it is a permission issue.
This worked for me,
SELECT * FROM OPENQUERY(LOCALSERVER, 'SET FMTONLY OFF EXEC snr.dbo.GetAllSignals #controlRunId = 25, #experimentRunId = 26')
I was creating temporary tables, and that's why i got access denied
Here is more info http://www.sommarskog.se/share_data.html#OPENQUERY
I create a sp that doesn't return any value and it doesn't work.
Your SP in mysql have to return a value!
for example I do this in "mysql":
CREATE DEFINER=`root`#`localhost` PROCEDURE `MyPro`(IN `Name` VARCHAR(50), IN `Id` INT, OUT `Result` INT)
MODIFIES SQL DATA
BEGIN
DECLARE Result INT;
SET Result = 0;
INSERT into MyTable (Id,Name) VALUES(Id,Name);
SELECT Result;
END
That "Id" and "Name" is input parameter and "Result" is output parameter
and create linked server in SQL SERVER and call it like this:
select * from openquery
(
Test,'call mydb.MyPro(''Name'',''16'', #P0);'
)
It works for me :D
Linked Servers and OPENQUERY, Gems to MS SQL Server...that are wolves in sheep clothing. I've found the following solutions to work when dealing with parameters
If the SP is basically just SELECT statements, the move the same to a VIEW and just pass SQL statements via OPENQUERY.
Build the OPENQUERY as a string and then use execute_sql.
You could also see if it works to precede exec with SET FMTONLY ON:
OPENQUERY([LINKSERVER],'SET FMTONLY ON; exec database.user.my_stored_proc ''AT'',''XXXX%'',''1111'',1')
If you try this and it works, you should probably Google FMTONLY+OPENQUERY to get an idea of what it means.
Try this,
SELECT * FROM OPENQUERY(linked_server_name, 'SELECT postgres_procedure_name (parameters)');
I experienced a very similar issue, but my SP wasn't taking any parameters.
I tried experimenting with altering the query sent through the openquery to include 'SET NOCOUNT ON' and 'SET FMTONLY OFF' but this had no difference.
The only solution that worked for my stored procedure was dropping the existing version, and altering the code to specifically 'SET NOCOUNT ON'
After doing this I was able to successfully run my stored proc through my linked server connection.
First of all you have to add hard code text fields then you have to
replace it by your parameters value like FromDate,TillDate,EmpID,CompCode,0,DeptID,DesgId,LocationID,AtnType
DECLARE #startdate varchar(255) = '2019-12-17'
DECLARE #enddate varchar(255) = '2019-12-17'
Set #SQL = 'SELECT * FROM OPENQUERY(' + quotename(#LinkedServer) + ',' + '''' +
'SET FMTONLY OFF; exec [TAP].[dbo].[GetAttendanceList] ' + 'FromDate,TillDate,EmpID,CompCode,0,DeptID,DesgId,LocationID,AtnType,1'')'
You have to replace your parameters values shown below
set #SQL=REPLACE(#SQL,'FromDate',+''''+''''+#startdate+''''+'''')
set #SQL=REPLACE(#SQL,'TillDate',+''''+''''+#enddate+''''+'''')
set #SQL=REPLACE(#SQL,'CompCode',+''''+''''+#CompCode+''''+'''')
set #SQL=REPLACE(#SQL,'AtnType',+''''+''''+''''+'''')
if #EmpID is Null
begin
set #SQL=REPLACE(#SQL,'EmpID','null')
end
if #DeptID is Null
begin
set #SQL=REPLACE(#SQL,'DeptID','null')
end
if #DesgId is Null
begin
set #SQL=REPLACE(#SQL,'DesgId','null')
end
if #LocationID is Null
begin
set #SQL=REPLACE(#SQL,'LocationID','null')
end
print #SQL
exec ( #SQL)
I am trying to get data from different sever, and the sever name might change. So I set the server name as a parameter. The idea of my sql store procedure is something like this
CREATE PROCEDURE [dbo].[GetData]
#ServerName
AS
BEGIN
SELECT * FROM #ServerName.ClientDataBase.dbo.Client
END
Does anyone know how to achieve this?
The database version is sql server 2005
Use dynamic SQL, however evil this may be:
exec('select * from ' + #ServerName + '.ClientDatabase.dbo.Client')
Look at using Synonym(s)
Create syntax (from MSDN):
CREATE SYNONYM [ schema_name_1. ] synonym_name FOR < object >
< object > :: =
{
[ server_name.[ database_name ] . [ schema_name_2 ].|
database_name . [ schema_name_2 ].| schema_name_2. ] object_name
}
You could set up a linked server, says "BOB".
Then you could call sp_setnetname to change the underlying target server but keep the name BOB.
So your code would be:
CREATE PROCEDURE [dbo].[GetData]
#ServerName
AS
BEGIN
EXEC sp_setnetname 'BOB', #ServerName
SELECT * FROM BOB.ClientDataBase.dbo.Client
END
-- Proc to get remove server name (domaine+instance name)
IF OBJECT_ID('dbo.getRemoteName') IS NOT NULL
DROP PROC dbo.getRemoteName;
GO
CREATE PROC dbo.getRemoteName
#id AS INT,
#RETURN AS VARCHAR(100) OUTPUT
AS
BEGIN
DECLARE #GetInstances TABLE
( id INT IDENTITY(0,1),
VALUE NVARCHAR(100),
instanceName NVARCHAR(100),
DATA NVARCHAR(100))
INSERT INTO #GetInstances
EXECUTE xp_regread
#rootkey = 'HKEY_LOCAL_MACHINE',
#KEY = 'SOFTWAREMicrosoftMicrosoft SQL Server',
#value_name = 'InstalledInstances'
-- order ascendant
-- Select * from #GetInstances -- uncomment to see all the instances that your have
SELECT #RETURN=instanceName FROM #GetInstances WHERE id=#id ORDER BY instanceName ASC;
SET #RETURN=HOST_NAME()+''+#RETURN;
END;
GO
DECLARE #RETURN AS VARCHAR(100);
-- get the instance number 0
EXEC getRemoteName 0, #RETURN OUTPUT;
PRINT #RETURN;
--
exec('SELECT * FROM ['+#RETURN+'].RemoteDatabase.dbo.SampleTable');