繁体   English   中英

使用Azure SQL中的“SELECT INTO”从另一个DB复制数据

[英]Using “SELECT INTO” with Azure SQL to copy data from another DB

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

为此,我执行一个包含的查询

SELECT * INTO [target_db_name]..[my_table_name] FROM [source_db_name].dbo.[my_table_name]

此时抛出异常告诉我

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

仔细研究过这个,我发现现在可以引用另一个Azure SQL DB,前提是它已被配置为外部数据源。 [ 这里这里 ]

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

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'”。

我错过了什么?

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

SELECT * FROM [source_db_name].[my_table_name]

我知道我应该真的在查询

SELECT * FROM [my_table_name]

看起来您可能需要根据看似正确的语法来定义外部表:

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

除弹性数据库查询外,三部分名称方法不受支持。

现在,由于您正在创建外部表,因此查询可以假装外部表是我们[target_db]的本机对象 - 这允许您编写查询SELECT * FROM [my_table_name] ,正如您从编辑中发现的那样。 从文档中,重要的是要注意“这允许对远程数据库进行只读查询”。 所以,这个表对象不可写,但你的问题只是提到从中读取以填充新表。

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

这一切都始于SQL Server数据工具,SSDT如果你还没有使用SSDT来管理数据库作为一个独立于你的应用程序的项目,你需要。 在这里抓一份。 如果您已在计算机上运行Visual Studio版本,则可以获得特定于该版本Visual Studio的SSDT版本。 如果你还没有运行VS,那么你可以抓住SSDT,它将安装最小的Visual Studio组件来让你前进。

设置您的第一个数据库项目很简单! 启动一个新的数据库项目。 新项目对话框

然后,右键单击数据库项目并选择Import - > Database。 导入现有数据库

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

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

您会发现创建的所有脚本都是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 - > Build Database1(我们的数据库项目的名称)。

输出窗口将打开并告诉您项目是否有任何问题。 在这里您可以看到外键引用尚不存在的表,创建对象语句中的语法错误等等。在检查更新到源代码管理之前,您需要清理它们。 在将更改部署到开发环境之前,您必须先修复它们。

成功构建数据库项目并将其签入源代码控制后,您就可以进行下一个更改过程。

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

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

右键单击数据库项目,然后选择Schema Compare。 架构比较

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

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

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

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM