从文件批量插入抛出错误无法批量加载,因为无法打开文件
Bulk insert from file thrown an error Cannot bulk load because the file could not be opened
我正在使用远程 Microsoft SQL 服务器。
在 Ubuntu 上使用 DataGrip 执行以下代码后,我收到错误消息:
CREATE TABLE #TempNullClass (
id nvarchar(10),
classCode nvarchar(10)
);
BULK INSERT #TempNullClass
FROM '/home/user/Downloads/data1.csv'
WITH (
FIELDTERMINATOR = ',',
ROWTERMINATOR = '0x0a'
);
[S0001][4861] Cannot bulk load because the file "/home/user/Downloads/data1.csv" could not be opened. Operating system error code 3(The system cannot find the path specified.).
文件拥有所有权限:
-rwxrwxrwx 1 user user 73399 may 15 15:11 data1.csv
我无法将文件放在远程服务器上。
文件应放在远程服务器上或共享到远程服务器的文件夹中。
可以使用本地文件,文件路径需要相对于服务器,所以另一台计算机上的文件需要是UNC路径,服务器本地路径不必共享(安全问题以及您需要配置和监控的另一件事)。
有时我必须像所有其他 DBA 一样循环导入文件。我这样解决。
您可以将其转储到 SQL 作业中并安排它。可以 运行 每秒或每天,仅取决于您的业务需求。这是我的一个脚本的示例:
SET NOCOUNT ON
DECLARE @BackupDirectory SYSNAME = 'G:\'
IF OBJECT_ID('tempdb..#DirTree') IS NOT NULL
DROP TABLE #DirTree
CREATE TABLE #DirTree (
Id int identity(1,1),
SubDirectory nvarchar(255),
Depth smallint,
FileFlag bit,
ParentDirectoryID int
)
INSERT INTO #DirTree (SubDirectory, Depth, FileFlag)
EXEC master..xp_dirtree @BackupDirectory, 10, 1
UPDATE #DirTree
SET ParentDirectoryID = (
SELECT MAX(Id) FROM #DirTree d2
WHERE Depth = d.Depth - 1 AND d2.Id < d.Id
)
FROM #DirTree d
DECLARE
@ID INT,
@BackupFile VARCHAR(MAX),
@Depth TINYINT,
@FileFlag BIT,
@ParentDirectoryID INT,
@wkSubParentDirectoryID INT,
@wkSubDirectory VARCHAR(MAX)
if OBJECT_ID('dbo.ImportFiles')=0
create table dbo.ImportFiles
(
FileNamePath VARCHAR(MAX)
)
else
truncate table dbo.ImportFiles
DECLARE FileCursor CURSOR LOCAL FORWARD_ONLY FOR
SELECT * FROM #DirTree WHERE FileFlag = 1
OPEN FileCursor
FETCH NEXT FROM FileCursor INTO
@ID,
@BackupFile,
@Depth,
@FileFlag,
@ParentDirectoryID
SET @wkSubParentDirectoryID = @ParentDirectoryID
WHILE @@FETCH_STATUS = 0
BEGIN
--loop to generate path in reverse, starting with backup file then prefixing subfolders in a loop
WHILE @wkSubParentDirectoryID IS NOT NULL
BEGIN
SELECT @wkSubDirectory = SubDirectory, @wkSubParentDirectoryID = ParentDirectoryID
FROM #DirTree
WHERE ID = @wkSubParentDirectoryID
SELECT @BackupFile = @wkSubDirectory + '\' + @BackupFile
END
--no more subfolders in loop so now prefix the root backup folder
SELECT @BackupFile = @BackupDirectory + @BackupFile
INSERT INTO ImportFiles (FileNamePath) VALUES(@BackupFile)
FETCH NEXT FROM FileCursor INTO
@ID,
@BackupFile,
@Depth,
@FileFlag,
@ParentDirectoryID
SET @wkSubParentDirectoryID = @ParentDirectoryID
END
CLOSE FileCursor
DEALLOCATE FileCursor
SET NOCOUNT ON
print 'loading files from file table'
-- =============================================
-- Declare and using a READ_ONLY cursor
-- =============================================
DECLARE eoddata_cursor CURSOR
READ_ONLY
FOR SELECT FileNamePath FROM ImportFiles
where FileNamePath like '%.csv'
DECLARE @name nvarchar(4000), @sql nvarchar(2000), @rows int
OPEN eoddata_cursor
FETCH NEXT FROM eoddata_cursor INTO @name
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
print 'file '+@name
begin try
truncate table [Tickers].[DataClient]
set @sql = '
bulk insert [Tickers].[DataClient]
from N'''+@name+'''
with (
FIELDTERMINATOR ='','',
ROWTERMINATOR =''\n'' ,
FIRSTROW = 2,
CODEPAGE = ''RAW'',
MAXERRORS = 2000000,
ERRORFILE = '''+@name+'.err''
)'
insert into [Tickers].[DataClient]
exec(@sql)
exec [Tickers].[MoveDataClientData] @filename = @name, @rows = @rows output
delete from ImportFiles where FileNamePath = @name
print 'loaded :'+str(@rows)
end try
begin catch
print 'error:'+ error_message()
end catch
END
FETCH NEXT FROM eoddata_cursor INTO @name
END
CLOSE eoddata_cursor
DEALLOCATE eoddata_cursor
GO
我正在使用远程 Microsoft SQL 服务器。
在 Ubuntu 上使用 DataGrip 执行以下代码后,我收到错误消息:
CREATE TABLE #TempNullClass (
id nvarchar(10),
classCode nvarchar(10)
);
BULK INSERT #TempNullClass
FROM '/home/user/Downloads/data1.csv'
WITH (
FIELDTERMINATOR = ',',
ROWTERMINATOR = '0x0a'
);
[S0001][4861] Cannot bulk load because the file "/home/user/Downloads/data1.csv" could not be opened. Operating system error code 3(The system cannot find the path specified.).
文件拥有所有权限:
-rwxrwxrwx 1 user user 73399 may 15 15:11 data1.csv
我无法将文件放在远程服务器上。
文件应放在远程服务器上或共享到远程服务器的文件夹中。
可以使用本地文件,文件路径需要相对于服务器,所以另一台计算机上的文件需要是UNC路径,服务器本地路径不必共享(安全问题以及您需要配置和监控的另一件事)。
有时我必须像所有其他 DBA 一样循环导入文件。我这样解决。 您可以将其转储到 SQL 作业中并安排它。可以 运行 每秒或每天,仅取决于您的业务需求。这是我的一个脚本的示例:
SET NOCOUNT ON
DECLARE @BackupDirectory SYSNAME = 'G:\'
IF OBJECT_ID('tempdb..#DirTree') IS NOT NULL
DROP TABLE #DirTree
CREATE TABLE #DirTree (
Id int identity(1,1),
SubDirectory nvarchar(255),
Depth smallint,
FileFlag bit,
ParentDirectoryID int
)
INSERT INTO #DirTree (SubDirectory, Depth, FileFlag)
EXEC master..xp_dirtree @BackupDirectory, 10, 1
UPDATE #DirTree
SET ParentDirectoryID = (
SELECT MAX(Id) FROM #DirTree d2
WHERE Depth = d.Depth - 1 AND d2.Id < d.Id
)
FROM #DirTree d
DECLARE
@ID INT,
@BackupFile VARCHAR(MAX),
@Depth TINYINT,
@FileFlag BIT,
@ParentDirectoryID INT,
@wkSubParentDirectoryID INT,
@wkSubDirectory VARCHAR(MAX)
if OBJECT_ID('dbo.ImportFiles')=0
create table dbo.ImportFiles
(
FileNamePath VARCHAR(MAX)
)
else
truncate table dbo.ImportFiles
DECLARE FileCursor CURSOR LOCAL FORWARD_ONLY FOR
SELECT * FROM #DirTree WHERE FileFlag = 1
OPEN FileCursor
FETCH NEXT FROM FileCursor INTO
@ID,
@BackupFile,
@Depth,
@FileFlag,
@ParentDirectoryID
SET @wkSubParentDirectoryID = @ParentDirectoryID
WHILE @@FETCH_STATUS = 0
BEGIN
--loop to generate path in reverse, starting with backup file then prefixing subfolders in a loop
WHILE @wkSubParentDirectoryID IS NOT NULL
BEGIN
SELECT @wkSubDirectory = SubDirectory, @wkSubParentDirectoryID = ParentDirectoryID
FROM #DirTree
WHERE ID = @wkSubParentDirectoryID
SELECT @BackupFile = @wkSubDirectory + '\' + @BackupFile
END
--no more subfolders in loop so now prefix the root backup folder
SELECT @BackupFile = @BackupDirectory + @BackupFile
INSERT INTO ImportFiles (FileNamePath) VALUES(@BackupFile)
FETCH NEXT FROM FileCursor INTO
@ID,
@BackupFile,
@Depth,
@FileFlag,
@ParentDirectoryID
SET @wkSubParentDirectoryID = @ParentDirectoryID
END
CLOSE FileCursor
DEALLOCATE FileCursor
SET NOCOUNT ON
print 'loading files from file table'
-- =============================================
-- Declare and using a READ_ONLY cursor
-- =============================================
DECLARE eoddata_cursor CURSOR
READ_ONLY
FOR SELECT FileNamePath FROM ImportFiles
where FileNamePath like '%.csv'
DECLARE @name nvarchar(4000), @sql nvarchar(2000), @rows int
OPEN eoddata_cursor
FETCH NEXT FROM eoddata_cursor INTO @name
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
print 'file '+@name
begin try
truncate table [Tickers].[DataClient]
set @sql = '
bulk insert [Tickers].[DataClient]
from N'''+@name+'''
with (
FIELDTERMINATOR ='','',
ROWTERMINATOR =''\n'' ,
FIRSTROW = 2,
CODEPAGE = ''RAW'',
MAXERRORS = 2000000,
ERRORFILE = '''+@name+'.err''
)'
insert into [Tickers].[DataClient]
exec(@sql)
exec [Tickers].[MoveDataClientData] @filename = @name, @rows = @rows output
delete from ImportFiles where FileNamePath = @name
print 'loaded :'+str(@rows)
end try
begin catch
print 'error:'+ error_message()
end catch
END
FETCH NEXT FROM eoddata_cursor INTO @name
END
CLOSE eoddata_cursor
DEALLOCATE eoddata_cursor
GO