我正在尝试在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数据库,只要它已被配置为外部数据源。 [here和here]
所以,在我的目标数据库中,我执行了以下语句:
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]
答案 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组件来帮助你。
然后,右键单击您的数据库项目并选择Import - &gt;数据库。
现在,您可以指向数据库的当前开发副本,并将其导入到项目中。此过程将从源数据库中提取所有表,视图,存储过程,函数等。完成后,您将看到类似下图的内容。
导入的每个模式都有一个文件夹,以及用于定义数据库中模式的安全性文件夹。浏览这些文件夹并查看创建的文件。
您会发现创建的所有脚本都是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。
默认情况下,您的数据库项目将是左侧的源。单击右侧的“选择目标”,然后选择要升级的数据库实例&#34;。然后单击左上角的Compare,SSDT将比较项目的状态与目标数据库。
然后,您将获得目标数据库中不在项目中的所有对象的列表(在DROP部分中),列出项目和目标数据库之间不同的所有对象(在ALTER部分中) ,以及项目中尚未存在于目标数据库中的对象列表(在ADD部分中)。
有时您会看到列出的更改,您不想做出更改(对象名称的更改,或默认语句周围的括号数。您可以取消选择此类更改。其他如果您没有准备好在目标部署中部署这些更改,您也可以取消选择这些更改。如果您选择更新(下面的红色框)或添加到您的更改脚本(如果您选择更新(下面的红色框)),则所有选中的项目将在目标数据库中更改(如果你点击&#34;生成脚本&#34;图标,请点击下面的绿框)。
处理数据库项目中的查找数据 现在我们最后回答您的原始问题,如何将查找数据部署到目标数据库。在您的数据库项目中,您可以在解决方案资源管理器中右键单击该项目,然后选择添加 - &gt;新物品。您将收到一个对话框。在左侧,单击User Scripts,然后在右侧,选择Post-Deployment Script。
通过添加此类型的脚本,SSDT知道您希望在任何架构更改后运行此步骤。您可以在此处输入查找值,因此它们会包含在源代码管理中!
现在,这是关于这些部署后脚本的重要说明。如果在新数据库中调用脚本,在现有数据库中调用脚本,或者连续调用100次,则需要确保此处添加的任何T-SQL都能正常工作。由于这个要求,我已经考虑将所有查找值包含在合并语句中。这样我就可以处理插入,更新和删除。
在将此文件提交给源代码控制之前,请在上述所有三种情况下对其进行测试,以确保它不会失败。
全部包装 从直接在目标环境中进行更改转变为使用SSDT和控制更改的源代码,是软件开发生命周期成熟的重要一步。好消息是,它使您能够以与持续集成/持续部署方法兼容的方式将您的数据库视为部署过程的一部分。
一旦习惯了新流程,您就可以了解如何将从SSDT生成的dacpac添加到部署脚本中,并在部署中的恰当时间推送更改。
它还可以让您摆脱SELECT INTO问题,原始问题。