在Azure SQL中使用“SELECT INTO”从另一个数据库

时间:2016-08-29 15:09:08

标签: sql azure azure-sql-database

我正在尝试在Azure上自动初始化SQL DB。对于某些(查找)表,每次初始化时都需要将数据从源数据库复制到新数据库中。

为此,我执行一个包含

的查询
SELECT * INTO [target_db_name]..[my_table_name] FROM [source_db_name].dbo.[my_table_name]

此时抛出异常告诉我

  

在'source_db_name.dbo.my_table_name'中引用数据库和/或服务器名称   此版本的SQL Server不支持。

研究过这个,我发现现在可以引用另一个Azure SQL数据库,只要它已被配置为外部数据源。 [herehere]

所以,在我的目标数据库中,我执行了以下语句:

CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<password>';

CREATE DATABASE SCOPED CREDENTIAL cred  
WITH IDENTITY = '<username>',
SECRET = '<password>';

CREATE EXTERNAL DATA SOURCE [source_db_name]
WITH
(
    TYPE=RDBMS,
    LOCATION='my_location.database.windows.net',
    DATABASE_NAME='source_db_name',
    CREDENTIAL= cred
);

CREATE EXTERNAL TABLE [dbo].[my_table_name](
    [my_column_name] BIGINT NOT NULL
)
WITH
(
    DATA_SOURCE = [source_db_name],
    SCHEMA_NAME = 'dbo',
    OBJECT_NAME = 'my_table_name'
)

但是SELECT INTO语句仍会产生相同的异常。

此外,简单的SELECT * FROM [source_db_name].[my_table_name]会产生异常“无效的对象名称'source_db_name.my_table_name'”。

我错过了什么?

更新
我发现了问题:CREATE EXTERNAL TABLE在目标数据库中创建似乎的表。要查询此信息,不应使用源DB名称。所以我失败了:

SELECT * FROM [source_db_name].[my_table_name]

我看到我应该真的在查询

SELECT * FROM [my_table_name]

2 个答案:

答案 0 :(得分:2)

看起来您可能需要定义外部表according to what appears to be the correct syntax

CREATE EXTERNAL TABLE [dbo].[source_table](
...
)
WITH
(
DATA_SOURCE = source_db_name
);

The three part name approach is unsupported, except through elastic database query.

现在,既然您正在创建外部表,那么查询可以假装外部表是我们[target_db]的原生对象 - 这可以让您编写查询SELECT * FROM [my_table_name],如您所知来自您的编辑。从文档中,重要的是要注意&#34;这允许对远程数据库进行只读查询。&#34;所以,这个表对象不可写,但你的问题只是提到从中读取以填充新表。

答案 1 :(得分:2)

正如所承诺的,这里是我如何处理SQL Server的数据库部署。我在Azure中的VM上使用相同的方法用于本地,Windows Azure SQL数据库或SQL。这花了很多痛苦,试验和错误。

这一切都始于SQL Server数据工具,SSDT 如果您尚未使用SSDT将数据库作为与应用程序分开的项目进行管理,则需要执行此操作。抓取副本here。如果您已在计算机上运行Visual Studio版本,则可以获得特定于该版本Visual Studio的SSDT版本。如果你还没有运行VS,那么你可以抓住SSDT并安装最小的Visual Studio组件来帮助你。

设置您的第一个数据库项目很简单!启动一个新的数据库项目。 new project dialog

然后,右键单击您的数据库项目并选择Import - &gt;数据库。 Importing an existing database

现在,您可以指向数据库的当前开发副本,并将其导入到项目中。此过程将从源数据库中提取所有表,视图,存储过程,函数等。完成后,您将看到类似下图的内容。 your new database project

导入的每个模式都有一个文件夹,以及用于定义数据库中模式的安全性文件夹。浏览这些文件夹并查看创建的文件。

您会发现创建的所有脚本都是CREATE脚本。这对于管理项目很重要。您现在可以保存新的解决方案,然后将其检入当前的源控制系统。这是你最初的提交。

这是管理数据库项目的新思维过程。当您需要进行架构更改时,您将进入此项目以更改这些create语句以定义您希望该对象的状态。您总是在模式中创建CREATE语句,而不是ALTER语句。看看下面的例子。

更新表格 我们已经决定开始跟踪我们的dbo.ETLProcess表中的更改。我们需要列来跟踪CreatedDateTime,CreatedByID,LastUpdatedDateTime和LastUpdatedByID。打开dbo \ Tables文件夹中的dbo.ETLProcess文件,您将看到该表的当前版本如下所示:

CREATE TABLE [dbo].[ETLProcess] (
       [ETLProcessID] INT             IDENTITY (1, 1) NOT NULL
     , [TenantID]     INT             NOT NULL
     , [Name]         NVARCHAR (255)  NULL
     , [Description]  NVARCHAR (1000) NULL
     , [Enabled]      BIT             DEFAULT ((1)) NOT NULL
     , CONSTRAINT [PK_ETLProcess__ETLProcessID_TenantID] 
            PRIMARY KEY CLUSTERED ([ETLProcessID], [TenantID])
     , CONSTRAINT [FK_ETLProcess_Tenant__TenantID] 
            FOREIGN KEY ([TenantID]) 
            REFERENCES [dbo].[Tenant] ([TenantID])
 );

要记录我们想要进行的更改,我们只需将列添加到表中,如下所示:

CREATE TABLE [dbo].[ETLProcess] (
       [ETLProcessID]         INT             IDENTITY (1, 1) NOT NULL
     , [TenantID]             INT             NOT NULL
     , [Name]                 NVARCHAR (255)  NULL
     , [Description]          NVARCHAR (1000) NULL
     , [Enabled]              BIT             DEFAULT ((1)) NOT NULL
     , [CreatedDateTime]      DATETIME        DEFAULT(GETUTCDATE())
     , [CreatedByID]          INT
     , [LastUpdatedDateTime]  DATETIME        DEFAULT(GETUTCDATE())
     , [LastUpdatedByID]      INT
     , CONSTRAINT [PK_ETLProcess__ETLProcessID_TenantID] 
            PRIMARY KEY CLUSTERED ([ETLProcessID], [TenantID])
     , CONSTRAINT [FK_ETLProcess_Tenant__TenantID] 
            FOREIGN KEY ([TenantID]) 
            REFERENCES [dbo].[Tenant] ([TenantID])
 );

我没有在定义中添加任何外键,但是如果你想创建它们,你可以将它们添加到租户的外键下面。一旦您对文件进行了更改,请将其保存。

您希望养成的下一件事是检查数据库以确保其有效。在编程世界中,您运行测试版本以确保编译。在这里,我们做了非常相似的事情。从主菜单点击Build - &gt;构建Database1(我们的数据库项目的名称)。

输出窗口将打开并告诉您项目是否有任何问题。在这里,您可以看到外键引用尚未存在的表,创建对象语句中的语法错误等等。在检查更新之前,您需要清除这些内容。源控制。在您能够将更改部署到开发环境之前,您将 来修复它们。

成功构建数据库项目并将其签入源代码管理后,您就可以为下一个更改过程做好准备。

部署更改 之前我告诉过你,记住所有的模式语句都是CREATE语句是很重要的。原因如下:SSDT为您提供了两种将更改部署到目标实例的方法。他们都使用这些create语句来比较您的项目与目标。通过比较两个create语句,它可以生成使目标实例与项目保持同步所需的ALTER语句。

部署这些更改的两个选项是T-SQL更改脚本或dacpac。基于原始帖子,听起来更改脚本将是最熟悉的。

右键单击您的数据库项目,然后选择Schema Compare。 Schema Compare

默认情况下,您的数据库项目将是左侧的源。单击右侧的“选择目标”,然后选择要升级的数据库实例&#34;。然后单击左上角的Compare,SSDT将比较项目的状态与目标数据库。

然后,您将获得目标数据库中不在项目中的所有对象的列表(在DROP部分中),列出项目和目标数据库之间不同的所有对象(在ALTER部分中) ,以及项目中尚未存在于目标数据库中的对象列表(在ADD部分中)。

有时您会看到列出的更改,您不想做出更改(对象名称的更改,或默认语句周围的括号数。您可以取消选择此类更改。其他如果您没有准备好在目标部署中部署这些更改,您也可以取消选择这些更改。如果您选择更新(下面的红色框)或添加到您的更改脚本(如果您选择更新(下面的红色框)),则所有选中的项目将在目标数据库中更改(如果你点击&#34;生成脚本&#34;图标,请点击下面的绿框)。 Deploy change options

处理数据库项目中的查找数据 现在我们最后回答您的原始问题,如何将查找数据部署到目标数据库。在您的数据库项目中,您可以在解决方案资源管理器中右键单击该项目,然后选择添加 - &gt;新物品。您将收到一个对话框。在左侧,单击User Scripts,然后在右侧,选择Post-Deployment Script。 Post Deployment step

通过添加此类型的脚本,SSDT知道您希望在任何架构更改后运行此步骤。您可以在此处输入查找值,因此它们会包含在源代码管理中!

现在,这是关于这些部署后脚本的重要说明。如果在新数据库中调用脚本,在现有数据库中调用脚本,或者连续调用100次,则需要确保此处添加的任何T-SQL都能正常工作。由于这个要求,我已经考虑将所有查找值包含在合并语句中。这样我就可以处理插入,更新和删除。

在将此文件提交给源代码控制之前,请在上述所有三种情况下对其进行测试,以确保它不会失败。

全部包装 从直接在目标环境中进行更改转变为使用SSDT和控制更改的源代码,是软件开发生命周期成熟的重要一步。好消息是,它使您能够以与持续集成/持续部署方法兼容的方式将您的数据库视为部署过程的一部分。

一旦习惯了新流程,您就可以了解如何将从SSDT生成的dacpac添加到部署脚本中,并在部署中的恰当时间推送更改。

它还可以让您摆脱SELECT INTO问题,原始问题。