【问题标题】:Can I specify an input sql file with bcp?我可以用 bcp 指定输入 sql 文件吗?
【发布时间】:2012-05-21 02:09:40
【问题描述】:

如何在使用 bcp 时指定带有长查询的输入 sql 文件?我尝试使用 -i 选项,但它一直在抱怨没有额外信息的命令行错误。这可能吗?

【问题讨论】:

  • 输入SQL文件?不可以。您可以指定数据文件和格式文件。如果你想使用 SQL,也许批量插入是更好的选择。
  • @GordonLinoff:实际上,我正在尝试从表中提取数据。在此之前,我基于字符串执行 SELECT 并将其提供给 bcp,但我现在有更长的查询。
  • 也许你可以用查询创建一个视图。
  • @GordonLinoff:很遗憾,我没有足够的权限来创建视图。
  • @Legend:即使您没有 DDL 权限,您也应该能够创建临时过程。 CREATE PROC #MYPROC AS SELECT* FROM MYTABLE,然后运行新创建的 proc。这个过程必须返回一个持久的结果。最好的办法是将它放到临时表中,然后使用 select * from temp table 完成 proc。

标签: sql sql-server sql-server-2008 bcp


【解决方案1】:

我今天遇到了这个问题,并找到了一个方便的解决方法,至少在临时情况下是这样。

任何具有连接权限的用户都可以创建临时表。这意味着您还可以创建 GLOBAL 临时表。

只需使用带有全局临时表的 SELECT ...INTO 在企业管理器(或 sql cmd 或其他)中运行您的查询,例如

SELECT * 
INTO ##mytemptable
FROM SomeTable 
WHERE [massive where clause, for example] 

然后,您可以在 BCP 查询中使用临时表,并使用一个简单的方法

SELECT * FROM ##mytemptable

然后通过企业管理器删除临时表

DROP TABLE ##mytemptable

【讨论】:

  • 这些椒盐卷饼口渴了
  • 如果你使用 SQLCMD 创建一个全局临时表,它会在命令完成后立即被删除。
【解决方案2】:

我做了其他方法来解决这个问题。

我创建了一个批处理文件,它读取文件并在 bcp 命令中发送您的内容。见:

@ECHO off

SETLOCAL EnableDelayedExpansion

SET queryFile=%1
SET outFileName=%2

FOR /F "delims=" %%i IN (%queryFile%) DO SET join=!join! %%i

ECHO %join%

bcp "%join%" queryout %outFileName% /S.\SQLE_CAESAR /d /c /t"|" /T

该脚本接收两个参数:

  1. 有查询的文件名;
  2. 导出数据的文件名;

像这样在 cmd 中执行脚本: export-query.bat query.sql export.txt

希望有所帮助。

【讨论】:

    【解决方案3】:

    就我而言,BCP 实用程序仅支持直接写入命令行的 Transact-SQL 查询。例如:

    bcp "SELECT Name FROM AdventureWorks.Sales.Currency" queryout Currency.Name.dat -T -c

    根据its reference“-i”选项:

    指定响应文件的名称,其中包含在使用交互模式(未指定-n、-c、-w 或-N)执行大容量复制时对每个数据字段的命令提示问题的响应。

    注意它与sqlcmd Utility“-i”选项不同:

    标识包含一批 SQL 语句或存储过程的文件。可以指定将按顺序读取和处理的多个文件 (...)

    【讨论】:

    • +1 谢谢。当SELECT 命令过长时,您是否知道该怎么做?
    • 我自己从未使用过长查询,但此链接中的快速 Google 搜索结果可能对您有所帮助:FIX: Bcp.exe with Long Query String Can Result in Assertion Failure
    • 当我遇到过长的 BCP 查询时,我们求助于在源上存储视图。然后我们的 BCP 查询可以简单地是“从 [VIEW] 中选择 x,y,z”
    【解决方案4】:

    试试:

    query=$( cat < /file.sql )
    export query
    bcp "${query}" queryout /home/file.csv
    

    【讨论】:

    • /opt/mssql-tools/bin/bcp: Argument list too long 例如 83315393 字节的文件。如果您的文件非常大,这可能是一个不好的选择。
    【解决方案5】:

    使用 powershell 可以轻松地向 bcp 提供多行查询:

    PS> $query = @'
        select * 
        from <table>
    '@
    PS> bcp $query queryout <outfile> -d <database> -T -S <server> -c
    

    【讨论】:

      【解决方案6】:

      我遇到了同样的问题,可能不是一个很好的方法。但是,我做了类似以下的事情

      bcp "declare @query nvarchar(max)  set @query = (SELECT * FROM OPENROWSET(BULK 'F:\tasks\report_v2.sql', SINGLE_CLOB) AS Contents) exec sp_executesql @query" queryout %outFileName%  /c /C RAW -S . -U sa -P 123 -d blog /T
      

      我必须说,如果你使用全局临时表,那么全局临时表会在查询执行后自行删除。在某些情况下你不能使用它

      【讨论】:

        【解决方案7】:

        真正对我有用的是:

        @ECHO off
        setlocal enableextensions enabledelayedexpansion
        SET "queryFile=%1"
        SET "outFileName=%2"
        
        SET RESULT=
        FOR /F "delims=" %%i IN ('type %queryFile%') DO SET RESULT=!RESULT! %%i
        
        echo %RESULT%
        
        rem bcp "%RESULT%" queryout %outFileName% -t^ -r \n -T -k -c -d DB_NAME -S SERVER_NAME
        

        type file 相当于 unix 中的cat file

        【讨论】:

          【解决方案8】:

          我对复杂查询所做的是使用所需语句创建一个存储过程并从 BCP 调用它:

          bcp "exec db.schema.stored_procedure" queryout "c:\file.txt" -T -S localhost -t "|" -c
          

          这对我很有用。问候!

          【讨论】:

            【解决方案9】:

            我制作了自己的脚本(称为bulk.sh)来执行此操作(不是最佳实践,也不是最佳实践......脚本太丑了,但非常实用)。

            #!/bin/bash
            input="SQL_FILE.sql"
            count=0
            const=1000
            lines=()
            mkdir -p bulk
            while IFS= read -r line
            do
              lines+=("$line")
              count=$((count+1))
              check=$((count % const))
              if [[ $check -eq 0 ]]; then
                 bulk="${lines[*]}"
                 unset lines
                 number=$(printf "%010d" $count)
                 echo $bulk > "bulk/bulk${number}.sql"
                 bulk=""
              fi
            done < "$input"
            
            FILES="bulk/*"
            for f in $FILES
            do
              echo "Processing $f file..."
              sqlcmd -S SERVER -d DATABASE -U USER -P "PASSWORD" -i "$f"
              sleep 2s
            done
            

            你可以试试,用:

            $ docker run -v /path/to/your/sql/file/folder:/backup -it mcr.microsoft.com/mssql-tools
            $ bash bulk.sh
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-01-10
              • 2023-01-11
              • 2010-12-02
              • 2020-04-06
              • 1970-01-01
              • 2015-09-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多