Execute SQL task with different servers/database - sql-server

Can i have my Execute SQL task look at 2 different connection manager.
For Instance: I need data from ServerA/DatabaseA querying against ServerB/DatabaseB.
So now i need to write a query and retrieve data from both servers.
Now 2 servers are not linked server, not necessarily.
Is this even possible, let me know, please.

Add a Data Flow Task with separate Data Flow Source tasks for Server A and Server B. Then join results using the appropriate Data Flow Transformation task.
As an example, this data flow takes a Flat File Source and OLEDB Source task, sorts results, then uses a Merge Join task for results. It sounds like your implementation would require two OLEDB Sources or (ODBC, ADO NET, etc.).
I like this method over the linked server or OPENROWSET, because you don't have to configure a linked server or enable Adhoc Distributed Queries on your SQL Server data sources.

I've had to find a way to work around lack of linked servers before, and I have done something like this - Give it a try:
if object_id('tempdb..#mytemptable') is not null begin drop table #mytemptable end
select * into #mytemptable
from openrowset('SQLNCLI10','Server=TheOtherServersName;Trusted_Connection=yes;','SELECT * FROM FullyQualifiedName.dbo.MyTable')
/* Now use the temptable created on this server to do your join/subquery on whatever */
select * from MyOtherTable a
join #mytemptable b on a.id = b.id
Cheers!

Related

Golang SQL: More Efficient to Query Two Tables at Once or Separate Queries/Connection Pools?

I have a connection pool for database A and database B. I am moving some Node.JS code over to Go (I'm using SQL Server if that matters), and some of the queries are doing this:
db.A.Query(`
select ... from some_table;
select ... from B..other_table;
`)
Is it better to do it that way, or like:
db.A.Query(...)
db.B.Query(...)
I read this line:
create one sql.DB object for each distinct datastore you need to access
from here. And only now do I realize I read 'datastore' as 'database', so now I'm not even sure if it's efficient to have these two database connection pools!
Thank you for any help!
For most scenarios and SQL Server client programs sending multiple SELECT queries in a batch is not materially more efficient. Perhaps if the queries returned very small result sets, and you ran them at very high frequency, you could see a material difference. But in the paradigm case, whether you send the queries in one or two batches won't matter much.
It won't matter to SQL Server at all, so the only difference will be in the client/server network traffic.
SSMS will let you compare the client statistics between running queries in a one-batch script and a multi-batch script. EG running
select top 10 * from sys.objects
select top 5 * from sys.columns
and then
select top 10 * from sys.objects
GO
select top 5 * from sys.columns
in SSMS outputs the following client statistics

OPENDATASOURCE (Transact-SQL) - Connecting to multiple tables

I have a use case for OPENDATASROUCE. However, my SQL query has multiple tables with left joins.
Most of the examples have one table only. How I connect in case I have 2 tables (2nd table has left join)
Below is a typical example and working great:
SELECT *
FROM OPENDATASOURCE('SQLNCLI', 'Data Source=RemoteServerName;Integrated Security=SSPI').Billing.dbo.Invoices
But I need to join invoices table with 'customer' table like below. I am not sure how I do that?? Please help
SELECT *
FROM OPENDATASOURCE('SQLNCLI', 'Data Source=RemoteServerName;Integrated Security=SSPI').Billing.dbo.Invoices as inv
left join Billing.dbo.customers as cust
on inv.customer = cust.customer
OPENDATASOURCE is one way to talk to a remote server using the "linked server" or "distributed query" functionality in SQL Server. However, it is not likely the best path for you to use in this case as it does not allow for the SQL Server Query Optimizer to rewrite the query and push parts of the query down to the remote source (potentially reducing the number of rows returned to you over a slower network connection vs. your local database). If possible, creating an actual linked server would help you here. This would give you the option to say to the optimizer "these two tables are from the same remote source". Then the optimizer can consider plans that remotes a single query to the remote server that joins those two tables together, applies any filters and group by clauses, and then returns the result to the calling server.
Here's the mechanism to add a linked server:
https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-addlinkedserver-transact-sql?view=sql-server-2017
Once you have a remote server (which I'll call "remote" here), you can write the query using the 4-part name syntax for remote servers instead of using OPENDATASOURCE.
SELECT * FROM REMOTE.Billing.DBO.Invoices LEFT JOIN REMOTE.Billing.DBO.Invoices on <join condition> <WHERE clause>
Here is a paper on how linked servers work under the covers which should give you a conceptual overview as to why this approach is likely better for you:
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.59.8007
Best of luck!

Table hint on linked server query

We have a DB2 database in AS400. Added a linked server, all went well, however occasionally the table is locked, even when we doing some select queries. Thinking about table hint in SQL Server, does the linked server query (e.g. select * from ...) support table hint?
Doubtful, but I don't know for sure.
Are you using openquery() , or 4 part names?
A query using 4 part names like so:
select * from LNKSVRNAME.IBMINAME.MYSCHEMA.MYTABLE where somecolumn = '00335';
Pulls back all the rows from MYTABLE and does the WHERE filtering on MS SQL Server.
In contrast, using openquery() like so:
select * from openquery(LNKSVRNAME, 'select * from MYSCHEMA.MYTABLE where somecolumn = ''00335''');
Sends the query to the IBM i, and only the matching rows from MYTABLE are pulled back into MS SQL Server.
If the table is being locked exclusively, there's not much you can do. However, if you're running into row locks. You may want to look at the following DB2 for IBM i clauses
FOR READ ONLY
SKIP LOCKED DATA or USE CURRENTLY COMMITTED or WAIT FOR OUTCOME
So something like this:
select * from openquery(LNKSVRNAME, 'select * from MYSCHEMA.MYTABLE where somecolumn = ''00335'' FOR READ ONLY USE CURRENTLY COMMITTED');
Note If you are actually talking to an AS/400, FOR READ ONLY is all you'll have available. But if you're talking to a relatively recent IBM POWER System running a relatively recent version of IBM i, then the concurrent-access-resolution clauses I've shown should be available.

SQL Server Linked Server Example Query

While in Management Studio, I am trying to run a query/do a join between two linked servers.
Is this a correct syntax using linked db servers:
select foo.id
from databaseserver1.db1.table1 foo,
databaseserver2.db1.table1 bar
where foo.name=bar.name
Basically, do you just preface the db server name to the db.table ?
The format should probably be:
<server>.<database>.<schema>.<table>
For example:
DatabaseServer1.db1.dbo.table1
Update: I know this is an old question and the answer I have is correct; however, I think any one else stumbling upon this should know a few things.
Namely, when querying against a linked server in a join situation the ENTIRE table from the linked server will likely be downloaded to the server the query is executing from in order to do the join operation. In the OP's case, both table1 from DB1 and table1 from DB2 will be transferred in their entirety to the server executing the query, presumably named DB3.
If you have large tables, this may result in an operation that takes a long time to execute. After all it is now constrained by network traffic speeds which is orders of magnitude slower than memory or even disk transfer speeds.
If possible, perform a single query against the remote server, without joining to a local table, to pull the data you need into a temp table. Then query off of that.
If that's not possible then you need to look at the various things that would cause SQL server to have to load the entire table locally. For example using GETDATE() or even certain joins. Others performance killers include not giving appropriate rights.
See http://thomaslarock.com/2013/05/top-3-performance-killers-for-linked-server-queries/ for some more info.
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME..TABLENAME')
This may help you.
For those having trouble with these other answers , try OPENQUERY
Example:
SELECT * FROM OPENQUERY([LinkedServer], 'select * from [DBName].[schema].[tablename]')
If you still find issue with <server>.<database>.<schema>.<table>
Enclose server name in []
You need to specify the schema/owner (dbo by default) as part of the reference. Also, it would be preferable to use the newer (ANSI-92) join style.
select foo.id
from databaseserver1.db1.dbo.table1 foo
inner join databaseserver2.db1.dbo.table1 bar
on foo.name = bar.name
select * from [Server].[database].[schema].[tablename]
This is the correct way to call.
Be sure to verify that the servers are linked before executing the query!
To check for linked servers call:
EXEC sys.sp_linkedservers
right click on a table and click script table as select
select name from drsql01.test.dbo.employee
drslq01 is servernmae --linked serer
test is database name
dbo is schema -default schema
employee is table name
I hope it helps to understand, how to execute query for linked server
Usually direct queries should not be used in case of linked server because it heavily use temp database of SQL server. At first step data is retrieved into temp DB then filtering occur. There are many threads about this. It is better to use open OPENQUERY because it passes SQL to the source linked server and then it return filtered results e.g.
SELECT *
FROM OPENQUERY(Linked_Server_Name , 'select * from TableName where ID = 500')
For what it's worth, I found the following syntax to work the best:
SELECT * FROM [LINKED_SERVER]...[TABLE]
I couldn't get the recommendations of others to work, using the database name. Additionally, this data source has no schema.
In sql-server(local) there are two ways to query data from a linked server(remote).
Distributed query (four part notation):
Might not work with all remote servers. If your remote server is MySQL then distributed query will not work.
Filters and joins might not work efficiently. If you have a simple query with WHERE clause, sql-server(local) might first fetch entire table from the remote server and then apply the WHERE clause locally. In case of large tables this is very inefficient since a lot of data will be moved from remote to local. However this is not always the case. If the local server has access to remote server's table statistics then it might be as efficient as using openquery More details
On the positive side T-SQL syntax will work.
SELECT * FROM [SERVER_NAME].[DATABASE_NAME].[SCHEMA_NAME].[TABLE_NAME]
OPENQUERY
This is basically a pass-through. The query is fully processed on the remote server thus will make use of index or any optimization on the remote server. Effectively reducing the amount of data transferred from the remote to local sql-server.
Minor drawback of this approach is that T-SQL syntax will not work if the remote server is anything other than sql-server.
SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME.SCHEMA_NAME.TABLENAME')
Overall OPENQUERY seems like a much better option to use in majority of the cases.
I have done to find out the data type in the table at link_server using openquery and the results were successful.
SELECT * FROM OPENQUERY (LINKSERVERNAME, '
SELECT DATA_TYPE, COLUMN_NAME
FROM [DATABASENAME].INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME =''TABLENAME''
')
Its work for me
Following Query is work best.
Try this Query:
SELECT * FROM OPENQUERY([LINKED_SERVER_NAME], 'SELECT * FROM [DATABASE_NAME].[SCHEMA].[TABLE_NAME]')
It Very helps to link MySQL to MS SQL
PostgreSQL:
You must provide a database name in the Data Source DSN.
Run Management Studio as Administrator
You must omit the DBName from the query:
SELECT * FROM OPENQUERY([LinkedServer], 'select * from schema."tablename"')
For MariaDB (and so probably MySQL), attempting to specify the schema using the three-dot syntax did not work, resulting in the error "invalid use of schema or catalog". The following solution worked:
In SSMS, go to Server Objects > Linked Servers > Providers > MSDASQL
Ensure that "Dynamic parameter", "Level zero only", and "Allow inprocess" are all checked
You can then query any schema and table using the following syntax:
SELECT TOP 10 *
FROM LinkedServerName...[SchemaName.TableName]
Source: SELECT * FROM MySQL Linked Server using SQL Server without OpenQuery
Have you tried adding " around the first name?
like:
select foo.id
from "databaseserver1".db1.table1 foo,
"databaseserver2".db1.table1 bar
where foo.name=bar.name

How to do a union across multiple instances of Sql Server?

I have two Sql Servers (two distinct databases, (i.e. two machines)) with the same structure. Is there a way to do a SELECT * FROM (SELECT * FROM TableOnServerA Union SELECT * FROM TableOnServerB)?
Thanks
Yes, just set them up as linked servers and then fully qualify the names in the form of LinkName.DatabaseName.SchemaName(dbo).TableName
SELECT * FROM serverA.database.owner.TableName
Union
SELECT * FROM serverB.database.owner.Tablename
assuming that they are setup as linked server, use books online and go to "linked"
You could create a Linked Server or use OPENROWSET to connect to other SQL database.
You can run a query relating two different machines adding one machine via the sp_addlinkedserver stored procedure. You run it in the database server instance where you will want to execute the query (or on both if you want to execute the query in any server), like this
use master
go
exec sp_addlinkedserver
#server='AnotherServer',
#provider='SQL Server'
The you can run
select * from AnotherServer.database.dbo.table t1
join database.dbo.table t2 on (t1.id = t2.id)
Incidentally if they are on two different servers and you are sure the data is not duplicated use union all, it will be much faster. Also never use select *,specify the field names. Other wise it will break if someone adds a column to A but not to B (or rearranges teh columns in B but not A) I would also add a column indicating which of the two servers the data came from, especially if they might have the same id number but attached to different data (which can happen if you are using autogenerated ids). This can save no end of trouble.

Resources