SQL Server Express equivalent for EXTERNAL DATA SOURCE - sql-server

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 .

Related

Copy Oracle table to SQL Server

I need to copy data from a linked server Oracle table and append to SQL Server table in a regular time interval.
Without using SSIS or any external etl, can this be done by using open query? I have read in forums that the table has to be exported to csv and then imported back again into SQL Server . Is there an alternative as this will be continuous process ?
Certainly. As long as you've configured the Linked Server properly within SQL Server, and your user account has the right permissions in Oracle, getting and sending data between the two is fairly trivial.
Selecting data from Oracle into SQL Server:
IF OBJECT_ID('tempdb..#myTemp') IS NOT NULL DROP TABLE #myTemp
SELECT *
INTO #myTemp
FROM OPENQUERY(MyLinkedServer, 'SELECT col1, col2
FROM OracleTableName
WHERE SomeColumn = ''Human Resources''')
Inserting data from SQL Server into Oracle:
-- note: please make sure you have your columns in the exact same order!
INSERT INTO OPENQUERY(MyLinkedServer, 'SELECT col1
FROM OracleTableName ')
SELECT myPK
FROM AdventureWorks2014.dbo.SomeTable
And you can even drop or recreate a table in Oracle from SQL Server, and run stored procedures.
To create a linked server, I use the below script and these settings:
-- make sure you have Oracle drivers on your SQL Server, and an up-to-date TNSNames.ora file
EXEC master.dbo.sp_addlinkedserver #server = N'MyLinkedServer', #srvproduct=N'Oracle', #provider=N'OraOLEDB.Oracle', #datasrc=N'TNS_NAME_HERE'
-- disable any logins not explicitly mapped
EXEC master.dbo.sp_droplinkedsrvlogin #rmtsrvname = N'MyLinkedServer', #locallogin = NULL
-- login mapping between SQL Server user and their appropriate Oracle account
EXEC master.dbo.sp_addlinkedsrvlogin #rmtsrvname=N'MyLinkedServer',#useself=N'False',#locallogin=N'domain\username',#rmtuser=N'ORACLE_USERNAME',#rmtpassword='ORACLE_PASSWORD'
-- add a mapping for your SQL Agent account if these will run under jobs,
-- and your SQL Engine account if you still get errors on things that are automated,
-- unless those automated jobs are explicitly running under user accounts
Honestly, the hardest part is making sure you get Oracle drivers installed right on the SQL Server. After that, it's very straightforward.

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

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]

Matching the schema of a SQL Server DB to an Oracle DB

Are there known products that can perform schema matching on any level between SQL Server and Oracle as described here? If not a product, would there be a documented methodology on how to perform maybe some semantic search and comparison of db tables, fields, and even data?
I have an existing SQL Server database which currently experiences a lot of trouble updating its data as it uses a lot of undocumented and unreadable legacy code to extract information from various external data sources. Fortunately, there exists an Oracle database that, based on the nature of the business, seems to contain all the information required by the SQL Server DB. The problem is, the schemas between the two environments are vastly different. They don't follow a common naming convention, and may not even follow the same normalization (some tables may be flat on one and normalized on the other).
The naive approach of trying to go through each table and column in SQL Server and then manually and visually searching for possible matches on the Oracle one seems quite impractical, given that there are hundreds of tables between the two databases.
There are commercial solutions(i.e. Database Compare Suite, Cross Database Studio) in the market which can be used to compare both homogeneous and heterogeneous database environments. But it's not good idea to spent money for those tools only for the schema comparison.
There might be several methods/tools/solutions which has certain limitations based on their scope. I am giving solution to compare schema matching between SQL Server and Oracle. Level of matching like table contents and data structure depends on your level of implementation.
In my Approach, suggesting following steps to full fill your requirements:
Establish SQL Server link server to Oracle Database. Steps are mentioned in the reply trail.
Now, access SQL Server and Oracle tables directly from SQL Server environment itself. It's feasible to compare table data using following approach:
SQL Server :
select field1, field2, field_N from openquery(DEV, 'select * from oracle_owner_schema.testtable')
minus
select field1, field2, field_N from sqlserver_database.schema_name.testtable
3 You can compare data structure(field length, data type, default value, etc.) by using dictionary table from SQL Server and Oracle in a same way.
Establish SQL Server link server to Oracle Database
Setup ODAC
Copy missing DLLs from instaclient to c:\oracle\product...\client_1\BIN [Location in which ODAC was installed.]
Add hostname, portnumber, and service name in c:\oracle\product...\client_1\network\admin\tnsnames.ora, sample:
LOCALSERVER =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = IP_Hostname_Oracle_Server)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = orcl)
)
)
Configuration in the SQL Server:
a. Connect to SQL server
b. Database>Server Objects>link servers>providers>OraOLEDB.Oracle>Right
c. Click>Properties>"Check Enable for 'Allow Inprocess'", then Save it.
d. Database>Server Objects>link servers>Right Click>New Link Server>
**************General TAB*************************
Linked server: Any Name for link server in MSSQL
Provide name: Oracle Provider
Product Name: Oracle
Datasource: Provide name which you have added in tnsnames.ora
****************Security TAB***************************
Choose "Be made using this security contest:"
Remote login: username for remote database <<e.g. guest >>
With password: password <<e.g. guest>>
How to use:
select * from openquery(Linked_server_Name, 'select * from schema_name.table_name');
i.e. select * from openquery(Any Name_for_link_server_in_MSSQL, 'select * from oracle_owner_schema.testtable');
Note: Version of ODAC and oracle client should be same.

Cannot get Linked Servers to work in Sql Azure

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.

Resources