使用 sqlcmd 时循环变量保持常量

loop variables stuck as constant when using sqlcmd

在创建一个 bash 脚本来为循环中的不同变量调用 sqlcmd 时,注意到它似乎是 将应该在循环中更新的循环变量设置为constant 一旦它被第一次调用(可以通过 continueing 和后来的循环段直到到达 sqlcmd 段来判断这很可能是罪魁祸首)。 IE。如果我们循环遍历 MSSQL Server table 名称的列表(长度为 L),其中 sqlcmd,循环将执行,而不是 L,而是 infinite 次迭代循环指令仅使用列表中的第一个条目

下面是一个最小的例子:

#!/bin/bash

tables_list=

while read -r line
do
    tablecols="$line"
    IFS=',' read -a arr_tablecols <<< "$tablecols"

    mssql_tablename=${arr_tablecols[0]}

    echo -e "\n\n\n##### Processing: $mssql_tablename #####\n"

    TO_SERVER_ODBCDSN="-D -S <ODBC DSN name for mssql host>"
    TO_SERVER_IP="-S <my mssql host IP>"
    DB="ClarityETL_test"
    TABLE="$mssql_tablename"
    USER=<my mssql username>
    PASSWORD=<my mssql login password>

    #uncomment to see that sqlcmd does in fact appear to be the problem
    #continue

    {
    echo -e "Counting destination table: $DB/$TABLE"
    sqlcmd -Q "PRINT '$mssql_tablename';" \
        $TO_SERVER_ODBCDSN \
        -U $USER -P $PASSWORD \
        -d $DB
    } || { echo -e "\nFailed to truncate MSSQL DB"; exit 255; } 

done < "$tables_list"

用作 $table_list 的文件看起来像

mymssqltable1
mymssqltable2
...

(因为该示例仅使用 PRINT 命令,所以该列表几乎可以是您想要使用的任何内容,真的)。

这种行为对我来说真的很奇怪,在文档中找不到任何提及这一点的内容 (https://docs.microsoft.com/en-us/sql/linux/quickstart-install-connect-red-hat?view=sql-server-2017#create-and-query-data)(我在 CentOS 7 上)。如果有人知道这里发生了什么或任何进一步的调试建议,请告诉我。

我怀疑 sqlcmd 正在从标准输入中读取,因此它正在使用输入文件的其余部分。我不确定为什么这会导致循环无限重复,而不是在第一次迭代后结束。但如果这是怎么回事,解决方案是重定向 sqlcmd.

的输入
sqlcmd -Q "PRINT '$mssql_tablename';" \
    $TO_SERVER_ODBCDSN \
    -U $USER -P $PASSWORD \
    -d $DB < /dev/null

当您重定向 while 循环的输入时,循环内的所有命令都会继承该重定向的输入。所以请注意,如果您从嵌套在循环中的另一个脚本中调用 sqlcmd(而不是直接在循环本身中),您将执行类似

的操作
while read -r line
do
    tablecols="$line"
    IFS=',' read -a arr_tablecols <<< "$tablecols"

    mssql_tablename=${arr_tablecols[0]}

    bash scriptThatUsesSqlcmd.sh mssql_tablename < /dev/null

done < "$tables_list" 

在将使用 sqlcmd 的脚本中取消继承循环的标准输入重定向。