Cannot get Linked Servers to work in Sql Azure - sql-server

We are using a trial version of Azure. We are trying to perform cross server queries from our SQL Server 2012 in-house.
We seem to have our local 2012 linked with Azure. When I go into Server Object -> Linked Servers in management studio, I see our Azure database.
But if I try to open the catalog and tables, I get an error message saying
Reference to database and/or server name in 'Perseus.sys.sp_tables_rowset2' is not supported in this version of SQL Server
** Perseus is the name of our catalog in Azure Sql.
Running a query from local connection:
SELECT * FROM [azureDBServer].[Perseus].[dbo].[accounts]
Tesult is:
OLE DB provider "SQLNCLI11" for linked server "azureDBServer" returned message
"Unspecified error". Msg 40515, Level 16, State 2, Line 1 Reference to database and/or
server name in 'Perseus.sys.sp_tables_info_90_rowset' is not supported in this version of
SQL Server.
This same in house SQL 2012 Server is able to connect to our in-house 2008 by cross server queries and by viewing its structure through Linked Servers.
I know from this article Azure supports Linked Servers.
So I'm lost about what is wrong. Our Admin thinks it may be that we have a Web-Sql account vs a business SQL account. This Azure Web vs Business SQL outdated Stack link implies that SQL version is NOT the problem, but pre-dates when Azure offered Linked Servers.
So, I'm trying to understand if
a) we didn't set up something right to provide SQL Linking?
b) we are limited by trial?
c) are we limited by Web SQL version?
d) anything else?

Need to execute below mentioned three stored procedures to add SQL Azure. Using below these stored procedure I was able to query SQL azure.
EXEC sp_addlinkedserver
#server='PROD',
#srvproduct='',
#provider='sqlncli',
#datasrc='azureserver.database.windows.net',
#location='',
#provstr='',
#catalog='database name'
EXEC sp_addlinkedsrvlogin
#rmtsrvname = 'PROD',
#useself = 'false',
#rmtuser = 'Azure login',
#rmtpassword = 'password'
EXEC sp_serveroption 'PROD', 'rpc out', true

While adding linked server from SQL Management, you are not given option to set default database. So use something like below
EXEC sp_addlinkedserver
#server='name for referring locally', -- here you can specify the name of the linked server
#srvproduct='',
#provider='sqlncli', -- using SQL Server native client
#datasrc='AzureMachineName.database.windows.net', -- add here your server name
#location='',
#provstr='',
#catalog='yourdatabasename'
I figured this works.

Did you actually setup connection to perseus database? By looking at the error message your are sending a query with 3 part or 4 part name to Azure which doesn't work as is in Azure. Please check your query and set it to use 2 part name and only three part name if it is connecting to the same database

This works for me:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'mypassword';
CREATE DATABASE SCOPED CREDENTIAL MySecurity
WITH IDENTITY = 'mylogin',
SECRET = 'mypassword';
CREATE EXTERNAL DATA SOURCE MyDbAccess
WITH (
TYPE=RDBMS,
LOCATION='server name',
DATABASE_NAME='db_name',
CREDENTIAL= MySecurity);
CREATE EXTERNAL TABLE MyExtTable (
[Id] [int] NOT NULL,
[Name] [varchar(20)] NULL)
WITH
(DATA_SOURCE = MyDbAccess);
After that you can just use it:
SELECT * FROM MyExtTable

I got this error and my issue ended up being a type in the database name SERVER.Database.dbo.tableName.

Related

CREATE EXTERNAL DATA SOURCE from SS2019 CTP2.2 not working

So ... I have 2 SQL Server 2019 instances (CTP2.2) and I have one installed with Polybase in single node config (reference this as SS-A). I have created MASTER KEY in the master of SS-A, and created a DATABASE SCOPED CREDENTIAL in a database on SS-A. When I try to do the following:
CREATE EXTERNAL DATA SOURCE acmeAzureDB WITH
(TYPE = RDBMS,
LOCATION = 'ss2019azure.database.windows.net',
DATABASE_NAME = 'dbAcmeAzure',
CREDENTIAL = acmeAzureCred
);
I get an error
Msg 102, Level 15, State 1, Line 6
Incorrect syntax near 'RDBMS'
I have tried to work with MS SQL Server SMEs without any luck (been working on this for many weeks to no avail).
Any ideas here -- plus a message to Microsoft -- your docs on this are AWFUL!!
You have 2 SQL Server 2019 instances (CTP2.2).
But they are not Azure SQL Database instance.
RDBMS External Data Sources are currently only supported on Azure SQL Database.
-- Elastic Database query only: a remote database on Azure SQL Database as data source
-- (only on Azure SQL Database)
CREATE EXTERNAL DATA SOURCE data_source_name
WITH (
TYPE = RDBMS,
LOCATION = '<server_name>.database.windows.net',
DATABASE_NAME = '<Remote_Database_Name>',
CREDENTIAL = <SQL_Credential>
)
Another way, you can create a linked server for your SQL Server 2019 instance to Azure SQL Database. Then you can query data from the Azure SQL DB as EXTERNAL DATA SOURCE.
To see this official tutorial: How to Create a Linked Server.
Reference blob:Incorrect syntax near 'RDBMS'. When I try to create external data source, Anyone having the same issue?
Hope this helps.
SO - worked with MS today - and success -- you can do a CREATE EXTERNAL DATA SOURCE in SS2019 and point to AZURE SQL -- here is the TSQL I used:
(MASTER KEY ALREADY CREATED)
CREATE DATABASE SCOPED CREDENTIAL acmeCred WITH IDENTITY = 'remoteAdmin', SECRET ='XXXXXXXXX';
go
CREATE EXTERNAL DATA SOURCE AzureDB
WITH (
LOCATION = 'sqlserver://ss2019azure.database.windows.net',
CREDENTIAL = acmeCred
);
go
CREATE EXTERNAL TABLE [dbo].[tblAcmeDataAzure]
(
ID varchar(10)
)
WITH (
LOCATION='dbAcmeAzure.dbo.tblAcmeDataAzure',
DATA_SOURCE=AzureDB
);
go

How can I join two tables from two different connections or instances in SQL Server? [duplicate]

How can I select data in the same query from two different databases that are on two different servers in SQL Server?
What you are looking for are Linked Servers. You can get to them in SSMS from the following location in the tree of the Object Explorer:
Server Objects-->Linked Servers
or you can use sp_addlinkedserver.
You only have to set up one. Once you have that, you can call a table on the other server like so:
select
*
from
LocalTable,
[OtherServerName].[OtherDB].[dbo].[OtherTable]
Note that the owner isn't always dbo, so make sure to replace it with whatever schema you use.
You can do it using Linked Server.
Typically linked servers are configured to enable the Database Engine to execute a Transact-SQL statement that includes tables in another instance of SQL Server, or another database product such as Oracle. Many types OLE DB data sources can be configured as linked servers, including Microsoft Access and Excel.
Linked servers offer the following advantages:
The ability to access data from outside of SQL Server.
The ability to issue distributed queries, updates, commands, and transactions on heterogeneous data sources across the enterprise.
The ability to address diverse data sources similarly.
Read more about Linked Servers.
Follow these steps to create a Linked Server:
Server Objects -> Linked Servers -> New Linked Server
Provide Remote Server Name.
Select Remote Server Type (SQL Server or Other).
Select Security -> Be made using this security context and provide login and password of remote server.
Click OK and you are done !!
Here is a simple tutorial for creating a linked server.
OR
You can add linked server using query.
Syntax:
sp_addlinkedserver [ #server= ] 'server' [ , [ #srvproduct= ] 'product_name' ]
[ , [ #provider= ] 'provider_name' ]
[ , [ #datasrc= ] 'data_source' ]
[ , [ #location= ] 'location' ]
[ , [ #provstr= ] 'provider_string' ]
[ , [ #catalog= ] 'catalog' ]
Read more about sp_addlinkedserver.
You have to create linked server only once. After creating linked server, we can query it as follows:
select * from LinkedServerName.DatabaseName.OwnerName.TableName
SELECT
*
FROM
[SERVER2NAME].[THEDB].[THEOWNER].[THETABLE]
You can also look at using Linked Servers. Linked servers can be other types of data sources too such as DB2 platforms. This is one method for trying to access DB2 from a SQL Server TSQL or Sproc call...
Querying across 2 different databases is a distributed query. Here is a list of some techniques plus the pros and cons:
Linked servers: Provide access to a wider variety of data sources than SQL Server replication provides
Linked servers: Connect with data sources that replication does not support or which require ad hoc access
Linked servers: Perform better than OPENDATASOURCE or OPENROWSET
OPENDATASOURCE and OPENROWSET functions:
Convenient for retrieving data from data sources on an ad hoc basis.
OPENROWSET has BULK facilities as well that may/may not require a format file which might be fiddley
OPENQUERY: Doesn't support variables
All are T-SQL solutions. Relatively easy to implement and set up
All are dependent on connection between source and destionation which might affect performance and scalability
These are all fine answers, but this one is missing and it has it's own powerful uses. Possibly it doesn't fit what the OP wanted, but the question was vague and I feel others may find their way here. Basically you can use 1 window to simultaneously run a query against multiple servers, here's how:
In SSMS open Registered Servers and create a New Server Group under Local Server Groups.
Under this group create New Server Registration for each server you wish to query. If the DB names are different ensure to set a default for each in the properties.
Now go back to the Group you created in the first step, right click and select New Query. A new query window will open and any query you run will be executed on each server in the group. The results are presented in a single data set with an extra column name indicating which server the record came from. If you use the status bar you will note the server name is replaced with multiple.
try this:
SELECT * FROM OPENROWSET('SQLNCLI', 'Server=YOUR SERVER;Trusted_Connection=yes;','SELECT * FROM Table1') AS a
UNION
SELECT * FROM OPENROWSET('SQLNCLI', 'Server=ANOTHER SERVER;Trusted_Connection=yes;','SELECT * FROM Table1') AS a
I had the same issue to connect an SQL_server 2008 to an SQL_server 2016 hosted in a remote server. Other answers didn't worked for me straightforward. I write my tweaked solution here as I think it may be useful for someone else.
An extended answer for remote IP db connections:
Step 1: link servers
EXEC sp_addlinkedserver #server='SRV_NAME',
#srvproduct=N'',
#provider=N'SQLNCLI',
#datasrc=N'aaa.bbb.ccc.ddd';
EXEC sp_addlinkedsrvlogin 'SRV_NAME', 'false', NULL, 'your_remote_db_login_user', 'your_remote_db_login_password'
...where SRV_NAME is an invented name. We will use it to refer to the remote server from our queries. aaa.bbb.ccc.ddd is the ip address of the remote server hosting your SQLserver DB.
Step 2: Run your queries
For instance:
SELECT * FROM [SRV_NAME].your_remote_db_name.dbo.your_table
...and that's it!
Syntax details: sp_addlinkedserver and sp_addlinkedsrvlogin
Server 2008:
When in SSMS connected to server1.DB1 and try:
SELECT * FROM
[server2].[DB2].[dbo].[table1]
as others noted, if it doesn't work it's because the server isn't linked.
I get the error:
Could not find server DB2 in sys.servers. Verify that the correct
server name was specified. If necessary, execute stored procedure
sp_addlinkedserver to add the server to sys.servers.
To add the server:
reference: To add server using sp_addlinkedserver
Link: [1]: To add server using sp_addlinkedserver
To see what is in your sys.servers just query it:
SELECT * FROM [sys].[servers]
Simplified solution for adding linked servers
First server
EXEC sp_addlinkedserver #server='ip,port\instancename'
Second Login
EXEC sp_addlinkedsrvlogin 'ip,port\instancename', 'false', NULL, 'remote_db_loginname', 'remote_db_pass'
Execute queries from linked to local db
INSERT INTO Tbl (Col1, Col2, Col3)
SELECT Col1, Col2, Col3
FROM [ip,port\instancename].[linkedDBName].[linkedTblSchema].[linkedTblName]
Created a Linked Server definition in one server to the other (you need SA to do this), then just reference them with 4-part naming (see BOL).
select *
from [ServerName(IP)].[DatabaseName].[dbo].[TableName]
As #Super9 told about OPENDATASOURCE using SQL Server Authentication with data provider
SQLOLEDB
. I am just posting here a code snippet for one table is in the current sever database where the code is running and another in other server '192.166.41.123'
SELECT top 2 * from dbo.tblHamdoonSoft tbl1 inner JOIN
OpenDataSource('SQLOLEDB','Data Source=192.166.41.123;User ID=sa;Password=hamdoonsoft')
.[TestDatabase].[dbo].[tblHamdoonSoft1] tbl2 on tbl1.id = tbl2.id
I know this is an old question but I use synonyms. Supposedly the query is executed within database server A, and looks for a table in a database server B that does not exist on server A. Add then a synonym on A database that calls your table from server B. Your query doesn't have to include any schemas, or different database names, just call the table name per usual and it will work.
There's no need to link servers as synonyms per say are sort of linking.
sp_addlinkedserver('servername')
so its should go like this -
select * from table1
unionall
select * from [server1].[database].[dbo].[table1]
Server Objects---> linked server ---> new linked server
In linked server write server name or IP address for other server and choose SQL Server
In Security select (be made using this security context )
Write login and password for other server
Now connected then use
Select * from [server name or ip addresses ].databasename.dbo.tblname
I hope the clarifications all mentioned above, have answered the OP's original question. I just want to add a code snippet for adding SQL Server as a linked server.
At most basic, we can simply add SQL Server as a linked server by executing sp_addlinkedserver with only one parameter #server, i.e.
-- using IP address
exec sp_addlinkedserver #server='192.168.1.11'
-- PC domain name
exec sp_addlinkedserver #server='DESKTOP-P5V8JTN'
SQL Server will automatically fill SRV_PROVIDERNAME, SRV_PRODUCT, SRV_DATASOURCE etc. with default values.
By doing this, we've to write the IP or PC domain name in the 4 part table address in the query (example below). This can be more annoying or less readable when the linked server will not have a default port or instance, the address will look similar to this 192.168.1.11,1430 or 192.168.1.11,1430\MSSQLSERVER2019.
So, to keep 4 part address short and readable, we can add an alias name for the server instead of the full address by specifying other parameters as follows-
exec sp_addlinkedserver
#server='ReadSrv1',
#srvproduct='SQL Server',
#provider='SQLNCLI',
#datasrc='192.168.1.11,1430\MSSQLSERVER2019'
But when you'll execute the query, the following error will show- You cannot specify a provider or any properties for product 'SQL Server'.
If we keep the server product property value empty '' or any other value, the query will execute successfully.
Next step, make login to the remote linked server by executing the following query-
EXEC sp_addlinkedsrvlogin #rmtsrvname = 'ReadSrv1', #useself = 'false', #locallogin = NULL, #rmtuser = 'sa', #rmtpassword = 'LinkedServerPasswordForSA'
Finally, use the linked server with 4 part address, the syntax is-
[ServerName].[DatabaseName].[Schema].[ObjectName]
Example-
SELECT TOP 100 t.* FROM ReadSrv1.AppDB.dbo.ExceptionLog t
To list existing linked servers execute:
exec sp_linkedservers
To delete a linked server execute:
exec sp_dropserver #server = 'ReadSrv1', #droplogins='droplogins' (delete login as well) OR
exec sp_dropserver #server = 'ReadSrv1', #droplogins='NULL' (keep login)

How to add Sybase SQL Anywhere DB as linked server to MS SQL Server properly

I used the Microsoft OLE DB Provider for SQL Anywhere to create a linked server, it shows remote databases and tables, I can read data, but writing data seems to work only using OPENQUERY() and when doing the connection_authentication using EXEC ... AT ... directly in the script.
How can I have the SQL Server do the authentication automatically when opening a connection?
How can I make normal write operations work without OPENQUERY()?
Sorry for not adding detailed error messages, I will add them later maybe, when I have access to the server again... But they were not meaningful anyway, i.e. when the weird authentication was missing, it just said "could not insert" or "failed" instead of indicating any authentication issue.
How to get the real error messages that come from Sybase?
Details:
SAP Sybase SQL Anywhere 16 (OEM Authenticated Edition) <-> MS SQL Server 2014
EXEC 'SET TEMPORARY OPTION CONNECTION_AUTHENTICATION=''Company=...''' AT linkedserver
INSERT INTO OPENQUERY(linkedserver, 'SELECT column FROM table WHERE 0=1') VALUES ('')
...that's not nice.
Even more details:
This is how I created the linked server
This is the authentication I'm talking about

SQL Server Express equivalent for EXTERNAL DATA SOURCE

As per https://azure.microsoft.com/en-us/documentation/articles/sql-database-elastic-query-getting-started-vertical/, it is now possible for one database in Azure SQL to query other Azure SQL databases. For my use case, I plan to have one database serving reference data for other databases, which fits nicely to Topology 1 (vertical sharding).
This is great for a deployed environment, but for local development I typically develop using SQL Server Express. As of SQL Server 2012 Express, the CREATE EXTERNAL DATA SOURCE is not a valid syntax.
Is it possible to also reap the benefit of external data source for local development?
After weighing the feature sets, I decided to differentiate the setup of my local database and Azure SQL.
When local SQL Server database wants to reference an Azure SQL database, it can do so using Linked Server
When a fellow Azure SQL database wants to reference another Azure SQL database, only then it uses external data source
i.e. locally
-- Make a link to the cloud
EXEC sp_addlinkedserver
#server=N'MyExternalServer',
#srvproduct=N'Azure SQL Db',
#provider=N'SQLNCLI',
#datasrc=N'<server address>',
#catalog='<database name>';
GO
EXEC sp_addlinkedsrvlogin
#rmtsrvname = '<server address>',
#useself = 'FALSE',
#locallogin=NULL,
#rmtuser = '<username>',
#rmtpassword = '<password>'
GO
select * from [MyExternalServer].[<database name>].[<schema>].[<table name>]
Whereas for Azure SQL:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<password>';
CREATE DATABASE SCOPED CREDENTIAL ElasticDBQueryCred
WITH IDENTITY = '<username>',
SECRET = '<password>';
CREATE EXTERNAL DATA SOURCE MyElasticDBQueryDataSrc WITH
(TYPE = RDBMS,
LOCATION = '<server>',
DATABASE_NAME = '<database name>',
CREDENTIAL = ElasticDBQueryCred,
) ;
create schema <internalschema>
CREATE EXTERNAL TABLE <internalschema>.<internaltablename>
(
... // list of columns
WITH
( DATA_SOURCE = MyElasticDBQueryDataSrc,
SCHEMA_NAME = <schema>,
OBJECT_NAME = <table name>
)
select * from <internalschema>.<internaltablename>
The challenge now is to make the database scripts be common using both approaches. To reference a table using Linked Server, it has to be addressed using four-part identifier [server].[database].[schema].[tablename]. Contrast this with external data source where it can be addressed just by using [schema].[tablename].
Using inspiration from this question: https://dba.stackexchange.com/questions/74566/sql-server-using-4-part-identifiers-when-database-may-be-on-the-same-server, my approach is to create a synonym on my local database that redirects [schema].[tablename] to [externalserver].[externaldatabase].[externalschema].[tablename].
i.e. locally:
create schema <internalschema>
CREATE SYNONYM <internalschema>.<internaltablename> FOR [MyExternalServer].[<database name>].[<schema>].[<table name>]
After which, the same statement would work for both cases:
select * from <internalschema>.<internaltablename>
EDIT:
One big problem with this approach is that you cannot use wrap your script under distributed transaction, because Azure SQL does not allow DTC.
if we are talking about SQL Server, external data source/table/file format are supported starting from SQL Server 2016 - https://msdn.microsoft.com/en-us/library/dn935022.aspx .

Query database running on another physical SQL Server

Historically we have a product which installed two databases on the same server. There is an custom application which assumes that both databases are on the same server.
In a new version they have split the databases onto two separate servers and obviously now the custom application is giving the error:
Database 'DB_2' does not exist. Make sure that the
name is entered correctly.
Is there anything I can do in the SQL Server setup so that the application is still able to query the DB_2 database without modifying the custom application?
The query being used is structured as follows:
Use DB_2
SELECT * FROM MyUser.MyTable
You can create a linked Server, then Create a Database DB_2 add a Synonym for different objects. something like below.
use master
GO;
EXEC master.dbo.sp_addlinkedserver #server = N'RemoteServer', #srvproduct=N'SQL Server'
GO
CREATE DATABASE [DB_2];
GO
USE [DB_2]
GO
CREATE SYNONYM [MyUser].[MyTable] FOR [RemoteServer].[db].[MyUser].[MyTable]
GO
You can use Linked Servers feature. In SSMS go to Server Object/Linked Servers folder in Object Explorer. And link second server. So you can query another DB using this SELECT * FROM [Linked_Server_Name].[Database_Name].[Schema_Name].[Table_Name]

Resources