问题
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?
回答1:
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.
回答2:
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 .
来源:https://stackoverflow.com/questions/36735179/sql-server-express-equivalent-for-external-data-source