Linux上的SQL Server>批量导入错误

时间:2016-12-30 09:36:48

标签: sql-server linux docker bulkinsert

尝试将.tsv文件批量插入sql-server-linux docker映像时,是否遇到此错误:

BULK INSERT countries FROM '/import/file.tsv' WITH ( FIELDTERMINATOR = '\t' );

这里有命令,表存在,文件存在于服务器上:

loginBtn=login

谢谢 托马斯

4 个答案:

答案 0 :(得分:2)

这是Linux上SQL Server中的错误,我们处理路径的方式。我们仍在努力使SQL Server中的所有内容都能处理Linux路径语法。我已经提交了一个错误,我们会修复它。在此期间,您可以将路径指定为C:\ import \ file.tsv,其中C:\是Linux文件系统根目录的占位符(即'/'),斜杠只是反转。我在RHEL VM中测试了这个确切的场景,它运行正常。专业提示:这个C:\技巧可以在T-SQL中传递路径的任何地方工作,所以如果你遇到其他需要路径的问题,请尝试一下。

Bug#9380471 for Microsoft-internal reference。

答案 1 :(得分:1)

我在Ubuntu 18上运行了MSSQL,并通过将CSV文件移动到Ubuntu(/)的根目录中解决了相同的问题。终于看到了CSV文件,并且运行正常。

BULK INSERT Students FROM '/student.csv' WITH ( FORMAT='CSV');

答案 2 :(得分:1)

我在Linux上使用BULK INSERT遇到很多麻烦,在其中拒绝了有效的路径名:

# sqlcmd -S localhost -d leak -U sa -Q "BULK INSERT leak FROM '/tmp/data.txt'"
Msg 12703, Level 16, State 1, Server mssql, Line 1
Referenced external data source "(null)" not found.

# ll /tmp/data.txt
-rw-r--r-- 1 root root 30M Feb 20 02:40 /tmp/data.txt

并且建议的解决方法用反斜杠替换斜杠并在C:\前面加前缀不起作用:

# sqlcmd -S localhost -d leak -U sa -Q "BULK INSERT leak FROM 'C:\\tmp\\data.txt'"
Msg 12703, Level 16, State 1, Server mssql, Line 1
Referenced external data source "(null)" not found.

因此,我进行了一些调查,并通过在守护程序上运行strace来发现了这一点:

# strace -fp 3198 -e open
strace: Process 3198 attached with 175 threads
[pid  3202] open("/proc/self/status", O_RDONLY) = 170
[pid  3202] open("/proc/meminfo", O_RDONLY) = 170
[pid  3321] open("/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 175
[pid  3321] open("/tmp/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 175
[pid  3321] open("/tmp/data.txt", O_RDONLY) = 175
[pid  3321] open("/tmp/data.txt", O_RDONLY|O_DIRECT) = -1 EINVAL (Invalid argument)

open()失败,因为tmpfs文件系统不支持O_DIRECT。因此,我将文件移到了根目录中,并使其在世界范围内均可访问:

# ll /data.txt
-rw-rw-rw- 1 root root 30M Feb 20 02:28 /data.txt

# ll /data.txt
-rw-rw-rw- 1 root root 30M Feb 20 02:28 /data.txt
# sqlcmd -S localhost -d leak -U sa -Q "BULK INSERT leak FROM '/data.txt'"
Msg 4860, Level 16, State 1, Server mssql, Line 1
Cannot bulk load. The file "/data.txt" does not exist or you don't have file access rights.

但是这次服务器甚至没有尝试访问文件。将文件移到除根目录以外的世界可访问目录中,对其进行了修复:

# sqlcmd -S localhost -d leak -U sa -Q "BULK INSERT leak FROM '/media/data.txt'"

(1000000 rows affected)

答案 3 :(得分:1)

我在 Debian 10 PC 上运行官方 SQL Server 2019 docker 映像时遇到了这个问题。我找到了两个不需要反斜杠替换的解决方案。

方案一:挂载共享目录

在运行容器时挂载共享目录。然后将 CSV 文件复制或移动到那里,以便 SQL Server 可以通过 docker 映像所感知的路径访问它。

例如,我用这个脚本启动了 SQL Server 容器:

#!/bin/bash
sudo docker run \
    -d \
    -e 'ACCEPT_EULA=Y' \
    -e 'SA_PASSWORD=my_password' \
    -p 1433:1433 \
    --name mssql2019 \
    -v /some/local/dir:/mnt/dir \
    mcr.microsoft.com/mssql/server:2019-latest   

现在将 data.csv 复制或移动到 /some/local/dir(容器将其视为 /mnt/dir)。可以通过以下命令导入:

-- First create table with the correct schema (not shown here)

bulk insert TargetTable
from '/mnt/dir/data.csv'  /* path SEEN BY THE CONTAINER */
with (FORMAT = 'CSV', FIRSTROW = 2);  /* a common CSV with header row*/

限制

  • 安装只能在运行容器时完成。如果要保留对 SQL Server 容器所做的更改,则必须stop the container, commit the changes and rerun the new image。这将创建一个新映像,因此请注意 I/O 成本。
  • 共享目录不能是 tmpfs(例如 ramdisk)。 ntfs-3gext4 很好。
  • 将文件符号链接到共享目录将不起作用。

解决方案 2:将 CSV 复制到容器中

文件也可以通过docker cp复制到容器中。例如:

# mssql2019 = your container name 
$ sudo docker cp /path/to/file.csv mssql2019:/home/file.csv

然后应用解决方案 1 中相同的 bulk insert 命令(除了导入路径现在是 /home/file.csv)。

请注意,可以通过

启动一个shell到容器中
$ (sudo) docker exec -u 0 -it mssql2019 bash

通过这种方式,您可以在复制之前轻松创建自定义文件夹或验证文件是否确实已复制。