BCP 实用程序无法使用 JAVA 在 Linux 中导出数据:

Posted

技术标签:

【中文标题】BCP 实用程序无法使用 JAVA 在 Linux 中导出数据:【英文标题】:BCP Utility Unable to Export Data in Linux Using JAVA: 【发布时间】:2016-09-19 21:30:40 【问题描述】:

我尝试执行以下代码来导出数据(myFileName.csv):

bcp "select * from DataBase.schema.TABLE_NAME" queryout tableData.csv -c -t, , -S [server] -U [user] -P '[password(with special characters)]' > LogFile.txt 

以上代码在终端中运行良好

相比之下,我使用 java 尝试了相同的代码。

File dir = new File("Mydirectory");
    Path dataPath = Paths.get("tableData.csv");
    List<String> val = new ArrayList();
    val.add("bcp");
    val.add("\"select * from " + [Database] + ".[Schema]." + table_name + "\"");
    val.add("queryout");
    val.add(dataPath.toString());
    val.add("-c");
    val.add("-t");
    val.add(",");
    val.add("-S");
    val.add([server]);// ex: if Server is 10.0.0.1  then val.add("10.0.0.1");
    val.add("-U");
    val.add([user]); // ex: if User_name is TestA then val.add("TestA");
    val.add("-P");
    val.add([password(with special characters)]); // ex: if Password is !@#MyPassword*& then val.add("!@#MyPassword*&");
    ProcessBuilder builder = new ProcessBuilder(val);
    File logFile = new File("LogFile.txt");
    System.out.println("BCP command :" + builder.command());
    builder.redirectlogFile(logFile);
    builder.directory(dir);
    Process exec = builder.start();
    System.out.println("BCP process completed : with errors :" + exec.waitFor());
    System.out.println("BCP logFile :" + org.​apache.​commons.​io.FileUtils.readFileToString(logFile));

我收到以下错误:

BCP 命令 :[bcp, "select * from DataBase.schema.TABLE_NAME", 查询输出,tableData.csv,-c,-t,,,-S,10.0.0.1,-U,TestA,-P, !@#MyPassword*&]

BCP 流程已完成:出现错误:1

BCP 日志文件:开始复制... SQLState = S1000,NativeError = 0 错误 = [Microsoft][SQL Server Native Client 11.0]无法解析列级排序规则

SQLState = 37000,NativeError = 102 错误 = [Microsoft][SQL Server Native Client 11.0][SQL Server]'select * from 附近的语法不正确 数据库.schema.TABLE_NAME'。

通过查看错误,我检查了ServerDatabaseTable 的排序规则似乎都相似SQL_Latin1_General_CP1_CI_AS

系统规格:

Linux :
    uname -mrs
        Linux 3.10.0-327.10.1.el7.x86_64 x86_64
    uname -a
        Linux [domain] 3.10.0-327.10.1.el7.x86_64 #1 SMP Tue Feb 16 17:03:50 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
    cat /etc/redhat-release
        CentOS Linux release 7.2.1511 (Core)

ODBC Driver for linux:
    isql --version
        unixODBC 2.3.0

    odbcinst -q -d -n "SQL Server Native Client 11.0"
        [SQL Server Native Client 11.0]
        Description=Microsoft SQL Server ODBC Driver V1.0 for Linux
        Driver=/opt/microsoft/sqlncli/lib64/libsqlncli-11.0.so.1790.0

任何人都可以帮助我我在这里做错了什么。

【问题讨论】:

你检查过这个吗:***.com/questions/15383511/… 你用windows机器试过了吗? @ali786 - 是的,我在 Windows 中尝试过,它运行良好。同样在这里,我没有在BCPMSSQL 之间使用任何ORM ProcessBuilder 在每个数组条目之间插入一个逗号,导致逗号过多和您看到的语法错误。更改您的代码以删除多余的逗号。尝试使用StringBuilder 构建命令字符串。 @quest4truth array 或 arraylist 的元素之间的逗号是因为 'toString()' 方法。这些逗号不会作为“Process Builder”中的命令执行。 【参考方案1】:

我尝试过创建 shell 脚本 它工作正常。

File dir = new File("Mydirectory"); 
Path dataPath = Paths.get("tableData.csv"); 
SStringBuilder strb = new StringBuilder();
strb.append("bcp ");
strb.append("\"select " + column + "  from " + credentials.getSchema() + ".dbo." + table_name + "\" ");
strb.append("queryout ");
strb.append(dataPath.toString());
strb.append(" -c ");
strb.append("-t ");
strb.append(", ");
strb.append("-S ");
strb.append(credentials.getServer());
strb.append(" -U ");
strb.append(credentials.getUser());
strb.append(" -P ");
strb.append(credentials.getPassword());

File shellFile = new File(folderName + File.separator + "exec.sh");

try (FileOutputStream outShell = new FileOutputStream(shellFile)) 
    outShell.write(strb.toString().getBytes());
    outShell.flush();

shellFile.setExecutable(true, false);
shellFile.setWritable(true, false);
shellFile.setReadable(true, false);
builder = new ProcessBuilder(shellFile.getAbsolutePath());

File logFile = new File("LogFile.txt");
System.out.println("BCP command :" + builder.command());
builder.redirectlogFile(logFile); builder.directory(dir); 
Process exec = builder.start();
System.out.println("BCP process completed : with errors :" + exec.waitFor());
System.out.println("BCP logFile :" + org.​apache.​commons.​io.FileUtils.readFileToString(logFile));

感谢大家...

【讨论】:

【参考方案2】:

我想和你分享一些建议。你可以试试。希望它能解决您的问题。

建议一:

如果我们更改列的排序规则或对表/视图自己的属性进行任何更改,有时会出现此问题。 您可以做的一件事是检查列 b\w 源和目标表的排序规则设置,然后在源脚本中使用 COLLATE 子句更改排序规则以匹配目标。这个问题可能是通过重新创建表/视图来解决。所以我建议你从你的"DataBase.schema" 再次创建"TABLE_NAME"

建议二:

推荐解决方案:

有时 queryout 不起作用并给出错误。在这种情况下,如果我们使用 print 那么这个问题就解决了。 您可以浏览此部分:SQL query using bcp not working with queryout as a variable

建议 3:

艰巨的任务但很有用:

您可以尝试远程连接到服务器并在代码中不使用-S 选项运行bcp删除以下部分并尝试一下

val.add("-S");
val.add([server]);// ex: if Server is 10.0.0.1  then val.add("10.0.0.1");

如果服务器排序规则与数据库或列排序规则不同,请尝试创建格式文件并在 bcp 中明确指定它。

建议 4:

有时nullbulk insert 也可能导致此问题。你可以通过: Bulk Insert Collation Error

建议 5:

这个问题发生在SQL Server 2005 Native Client。但是微软不会在以前的版本中修复这个问题。他们已将其修复为 SQL Server 2008 Native Client。有关更多详细信息,您可以通过: BCP Error - Unable to resolve column level collations - by krishnc

【讨论】:

【参考方案3】:

ProcessBuilder 的行为与 CMD 不同,因此您不需要引号:

val.add("select * from " + database_name + ".[Schema]." + table_name);

【讨论】:

【参考方案4】:

使用 Linux 语法中的freebcp 命令与BCP 最相同。

bcp mydatabase.dbo.mytable out mytable.csv /U myusername /P mypassword /S myhost /c  

等价于

freebcp mydatabase.dbo.mytable out mytable.csv -U myusername -P mypassword -S myhost -c

【讨论】:

'freebcp' 你的意思是'FreeTDS'或'bcp'实习生在Linux服务器中支持'freebcp'。 linux.die.net/man/1/freebcpmanpages.ubuntu.com/manpages/wily/man1/freebcp.1.html 在我在mac上使用的最后一个项目中。

以上是关于BCP 实用程序无法使用 JAVA 在 Linux 中导出数据:的主要内容,如果未能解决你的问题,请参考以下文章

带有 xlsx ( Excel ) 文件的 sql bcp 实用程序

使用重新分发的组件导出 SQL Server 数据

使用BCP导出导入数据

让 bcp.exe 转义终止符

安装 BCP 而不在客户端计算机上安装 SQL Server?

bcp文件怎么打开