本地 SQL Server 实例和 Azure SQL Server 中的 LoadData 脚本
Posted
技术标签:
【中文标题】本地 SQL Server 实例和 Azure SQL Server 中的 LoadData 脚本【英文标题】:LoadData script in Local SQL Server instance and Azure SQL Server 【发布时间】:2020-06-21 16:31:08 【问题描述】:我可以在本地 SQL Server 机器上运行以下命令而不会出现任何问题:
exec sp_configure 'show advanced options', 1
reconfigure
go
exec sp_configure 'Ad Hoc Distributed Queries', 1
reconfigure
go
exec LoadData 'C:\MyDataFile.urg';
go
但是当我尝试在 Azure SQL 上运行 SP_CONFIGURE
命令时,我收到以下错误:
此版本的 SQL Server 不支持语句“CONFIG”。
当我执行加载数据命令时,出现以下错误
无法批量加载,因为文件 C:\MyDataFile.urg" 无法打开。操作系统错误代码 (null)。
上述错误是有道理的,因为我试图从 Azure 云访问我本地计算机上的文件。是否有一个等效的加载数据的过程,我可以在 Azure 中遵循以转储文件的内容?
我可以将文件放在 Azure blob 中,但是我执行的命令类似于加载数据?
-- 更新 1 回答时请注意两点 1) 我正在使用以 .urg 结尾且不是 csv 文件的第三方文件。
2) 当我使用 exec LoadData 'C:\MyDataFile.urg';请注意,我没有使用文件数据所在的表名。 LoadData 命令执行文件并将数据转储到各自的文件中。我假设 .urg 文件被打开并执行,并且其中包含命令以了解哪些数据在哪里。
--更新2 所以我的理解是不正确的。发现 LoadData 是第三方正在使用的存储过程,它采用这样的文件路径。磁盘上的文件很好用,我需要将其发送到 azure storage blob path。
CREATE PROCEDURE [dbo].[LoadData]
@DataFile NVARCHAR(MAX)
AS
DECLARE @LoadSql NVARCHAR(MAX)
SET @LoadSql = '
BULK INSERT UrgLoad FROM ''' + @DataFile + '''
WITH (
FIRSTROW = 2,
FIELDTERMINATOR = ''~'',
ROWTERMINATOR = ''0x0a'',
KEEPNULLS,
CODEPAGE = ''ACP''
)
'
EXEC sp_executesql @LoadSql
SELECT @Err = @@ERROR
现在我需要找到一种方法来将 Azure 存储 blob 路径发送到此存储过程,以便它可以打开它。如果我遇到问题,我会更新。
--更新3 由于我的 blob 存储帐户不是公开的,我确定我需要添加授权块。我将这段代码添加到 proc
CREATE DATABASE SCOPED CREDENTIAL MyAzureBlobStorageCredential
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = 'sp=r&st=2020-03-10T01:04:16Z&se=2020-03-10T09:04:16Z&spr=https&sv=2019-02-02&sr=b&sig=Udxa%2FvPrUBZt09GAH4YgWd9joTlyxYDC%2Bt7j7CmuhvQ%3D';
-- Create external data source with the URL of the Blob storage Account and associated credential since its not public
CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE,
LOCATION = 'https://dev.blob.core.windows.net/urg',
CREDENTIAL= MyAzureBlobStorageCredential
);
当我执行 proc 时说它已经存在。
Msg 15530, Level 16, State 1, Procedure LoadData, Line 14 [Batch Start Line 1]
The credential with name "MyAzureBlobStorageCredential" already exists.
Msg 46502, Level 16, State 1, Procedure LoadData, Line 27 [Batch Start Line 1]
Type with name 'MyAzureBlobStorage' already exists.
当我取出它并像这样更新批量插入代码时
DECLARE @LoadSql NVARCHAR(MAX)
SET @LoadSql = '
BULK INSERT UrjanetLoad FROM ''' + @DataFile + '''
WITH ( DATA_SOURCE = ''MyAzureBlobStorage'',
FIRSTROW = 2,
FIELDTERMINATOR = ''~'',
ROWTERMINATOR = ''0x0a'',
KEEPNULLS,
CODEPAGE = ''ACP''
)
'
但它告诉我
Cannot bulk load because the file "https://dev.blob.core.windows.net/urg/03_06_20_16_23.urg" could not be opened. Operating system error code 5(Access is denied.).
我想问题是我在授权过程中遗漏了什么,我怎样才能使它成为我猜想的存储过程的一部分,所以每当它运行时,它都会选择它。
更新 4:本文帮助使用凭据从 blob 存储访问文件,删除外部数据源和范围凭据,并在存储过程中获取新的 SAS 令牌,以防它可以帮助其他人`https://social.technet.microsoft.com/wiki/contents/articles/52061.t-sql-bulk-insert-azure-csv-blob-into-azure-sql-database.aspx
现在我遇到错误
Cannot bulk load because the file "03_06_20_16_23.urg" could not be opened. Operating system error code 32(The process cannot access the file because it is being used by another process.).
试过这篇文章,但没有解决文件正在被另一个进程使用的问题。
更新 5:这是 proc 的样子
alter PROCEDURE [dbo].[TestLoad]
@DataFile NVARCHAR(MAX), @SAS_Token VARCHAR(MAX),@Location VARCHAR(MAX)
AS
BEGIN TRAN
-- Turn on NOCOUNT to prevent message spamming
SET NOCOUNT ON;
DECLARE @CrtDSSQL NVARCHAR(MAX), @DrpDSSQL NVARCHAR(MAX), @ExtlDS SYSNAME, @DBCred SYSNAME, @BulkInsSQL NVARCHAR(MAX) ;
SELECT @ExtlDS = 'MyAzureBlobStorage'
SELECT @DBCred = 'MyAzureBlobStorageCredential'
SET @DrpDSSQL = N'
IF EXISTS ( SELECT 1 FROM sys.external_data_sources WHERE Name = ''' + @ExtlDS + ''' )
BEGIN
DROP EXTERNAL DATA SOURCE ' + @ExtlDS + ' ;
END;
IF EXISTS ( SELECT 1 FROM sys.database_scoped_credentials WHERE Name = ''' + @DBCred + ''' )
BEGIN
DROP DATABASE SCOPED CREDENTIAL ' + @DBCred + ';
END;
';
SET @CrtDSSQL = @DrpDSSQL + N'
CREATE DATABASE SCOPED CREDENTIAL ' + @DBCred + '
WITH IDENTITY = ''SHARED ACCESS SIGNATURE'',
SECRET = ''' + @SAS_Token + ''';
CREATE EXTERNAL DATA SOURCE ' + @ExtlDS + '
WITH (
TYPE = BLOB_STORAGE,
LOCATION = ''' + @Location + ''' ,
CREDENTIAL = ' + @DBCred + '
);
';
-- PRINT @CrtDSSQL
EXEC (@CrtDSSQL);
-- Set up the load timestamp
DECLARE @LoadTime DATETIME, @Err varchar(60)
SELECT @LoadTime = GETDATE()
-- Set the bulk load command to a string and execute with sp_executesql.
-- This is the only way to do parameterized bulk loads
DECLARE @LoadSql NVARCHAR(MAX)
SET @LoadSql = '
BULK INSERT TestLoadTable FROM ''' + @DataFile + '''
WITH ( DATA_SOURCE = ''MyAzureBlobStorage'',
FIRSTROW = 2,
FIELDTERMINATOR = ''~'',
ROWTERMINATOR = ''0x0a'',
KEEPNULLS,
CODEPAGE = ''ACP''
)
'
EXEC (@LoadSql);
--EXEC sp_executesql @LoadSql
SELECT @Err = @@ERROR
IF @Err <> 0 BEGIN
PRINT 'Errors with data file ... aborting'
ROLLBACK
RETURN -1
END
SET NOCOUNT OFF;
COMMIT
GO
这就是我试图称呼它的方式。
EXEC TestLoad 'TestFile.csv',
'sv=2019-02-02&ss=bfqt&srt=sco&sp=rwdlacup&se=2020-03-16T02:07:03Z&st=2020-03-10T18:07:03Z&spr=https&sig=TleUPwAyEVT6dzX17fH6rq1lQQRAhIRImDHdJRKIrKE%3D',
''https://dev.blob.core.windows.net/urg';
这是错误
Cannot bulk load because the file "TestFile.csv" could not be opened. Operating system error code 32(The process cannot access the file because it is being used by another process.).
Errors with data file ... aborting
【问题讨论】:
【参考方案1】:如果您的文件放置在公共 Azure Blob 存储帐户上,则需要定义指向该帐户的外部数据源:
CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE, LOCATION = 'https://myazureblobstorage.blob.core.windows.net');
一旦定义了外部数据源,就可以在 BULK INSERT 和 OPENROWSET 中使用该源的名称。
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'some strong password';
CREATE DATABASE SCOPED CREDENTIAL MyAzureBlobStorageCredential
WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
SECRET = 'sv=2015-12-11&ss=b&srt=sco&sp=rwac&se=2017-02-01T00:55:34Z&st=2016-12-29T16:55:34Z&spr=https&sig=copyFromAzurePortal';
CREATE EXTERNAL DATA SOURCE MyAzureBlobStorage
WITH ( TYPE = BLOB_STORAGE,
LOCATION = 'https://myazureblobstorage.blob.core.windows.net',
CREDENTIAL= MyAzureBlobStorageCredential);
【讨论】:
感谢大卫在这里的帮助,我确实查找了这里提到的示例.. docs.microsoft.com/en-us/sql/relational-databases/import-export/… 我有两个问题,文件格式不是 .csv 并且加载数据命令没有指定数据是哪个表进去,我只在数据库上调用它。如果我按照你的例子和微软的例子,我需要 .csv 文件格式和一个指定的表来转储数据。【参考方案2】:根据我的经验和所有 Azure SQL 数据库文档,我们只能回答您:
-
Azure SQL 数据库不支持直接从本地/本地计算机加载文件。
Ref:
-
Azure SQL 数据库不支持 .urg 数据文件。我们找不到任何方式支持 urg 文件。甚至数据工厂也没有。
参考:
-
Limitions: 只有 .mdf、.ldf 和 .ndf 文件可以存储在
Azure 存储,使用 Azure 功能中的 SQL Server 数据文件。
Data formats for import and export
更新:
不知道urg文件会不会加载成功,但是我找到了一些方法你可以试试:
-
您可以先将您的 urg 文件上传到 Blob 存储,然后参考
本教程:Importing data from a file in Azure blob
storage。
这是另一个博客
Bulk insert using stored procedure 和 Bulk insert file path as stored procedure parameter
可以帮助您将批量插入文件路径作为参数传递给
存储过程“LoadData”。
希望这会有所帮助。
【讨论】:
非常感谢您的意见。请查看我的最新更新。 @Sarah 我在回答中更新了一些内容,希望对您有所帮助。 非常感谢。我想我很接近解决它只是不知道在 Buik Insert 语句中我提到了 blob 存储的数据源,如果我添加外部数据源我会收到错误(不确定我是否需要在 proc 中添加它)请见更新 3 @Sarah 回到第一个问题,Azure SQL 不支持导入 org 文件。您可以使用 csv /txt 文件进行测试。如果它成功了,那么我们可以证明这一点。我也试过 SSMS 导入,都失败了。 谢谢!此时,从 blob 存储中访问文件似乎不是错误所暗示的文件类型的问题。我尝试使用 csv 文件、txt 文件。我正在上传我在更新 5 上的代码。所有人都给出了以下错误。 “无法批量加载,因为无法打开文件“Test.csv”。操作系统错误代码 32(该进程无法访问该文件,因为它正被另一个进程使用。)。”以上是关于本地 SQL Server 实例和 Azure SQL Server 中的 LoadData 脚本的主要内容,如果未能解决你的问题,请参考以下文章
疑难解答'建立与SQL Server的连接时发生的与网络相关或特定于实例的错误'连接到Azure SQL Server
将 MVC 项目从本地迁移到 Azure - SQL Server 问题
我可以在 Azure Sql 数据库和 Sql Server 2012(本地服务器)之间创建复制吗?
计划的 SQL Server 实例推送到 Azure SQL 数据库