【问题标题】:SQL Server on Linux > Bulk Import errorLinux 上的 SQL Server > 批量导入错误
【发布时间】:2016-12-30 09:36:47
【问题描述】:

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

Referenced external data source "(null)" not found.

命令如下,表存在,文件存在于服务器上:

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

谢谢 托马斯

【问题讨论】:

  • 没有适用于 Linux 的 SQL Server docker 映像,除非您指的是 SQL Server for Linux 预览版。在这种情况下,您应该在标题和标签中指定。您指定的路径对 Windows 无效
  • 这不是预览版,hub.docker.com/r/microsoft/mssql-server-linux 或未指定。没关系......你有没有遇到过这个错误?
  • Microsoft SQL Server on Linux for Docker Engine 预览版 - 实际上是 CTP - 客户技术预览版。此时版本为SQL Server vNext CTP 1.1。这是预览之前的一个阶段。甚至还没有 SO 标签
  • 好的,标题已更改,标签已更改...您以前遇到过这个错误吗?
  • 我明白了,但我不明白的是使用相当简单的 SQL 命令时会出现这样的错误,即使是你提到的非常早期的版本......但算了,刚刚安装了 Win 10带有 SQL Server 2014 的 VirtualBox 映像

标签: sql-server linux docker bulkinsert


【解决方案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)

【讨论】:

    【解决方案2】:

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

    解决方案 1:挂载共享目录

    在运行容器时挂载一个共享目录。然后将 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
    

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

    【讨论】:

      【解决方案3】:

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

      Microsoft 内部参考的错误 #9380471。

      【讨论】:

      • 这对我不起作用(使用microsoft/mssql-server-linux docker 容器并将文件映射到卷中)。还有其他方法可以让它工作吗?
      • 这在 docker 中仍然存在问题。 C:\ 样式路径和 *nix 样式 / 路径都不起作用。令人难以置信的是,它已经被破坏了这么久。
      • 更多细节:我正在使用 docker for mac。我正在使用 microsoft/mssql-server-linux:2017-latest docker 映像。我通过将-v /host-path/AdventureWorks:/AdventureWorks 传递给docker run 来附加卷。我已经通过在容器上执行 bash 验证了我尝试加载的文件存在于容器中。
      • 还是坏了。我试过: /data.txt C:\data.txt \data.txt 没有成功。
      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-03
        • 2017-05-30
        • 1970-01-01
        • 2012-10-06
        • 1970-01-01
        • 2012-10-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多