【问题标题】:Building SQL update statements using a Bash script使用 Bash 脚本构建 SQL 更新语句
【发布时间】:2020-09-24 01:50:44
【问题描述】:

对于最近的一个项目,我需要遍历 3 列的 csv (ignore.csv) 行:

acctnum, errcode, date← 按此顺序...

(列命名在这里无关紧要,它只是为了上下文)并使用这些变量来构建 SQL 语句。

CSV 可能有 500 行,也可能有 20k。我的 SQL 语句应该如下所示:

UPDATE O.ACCT_ERR SET REC_ACTV_IND='T'
  WHERE BUS_DT='20200603' and ERR_CD='R4442' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM O.ACCT
      WHERE ACCT_SRCH_NBR='10100000011'
  );

目前我在 Bash 中的草率示例是这样的:

while IFS=, read -r field1 field2 field3;
do
   echo "UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T' WHERE BUS_DT='$field3' and ETL_ERR_CD='$field2' AND ACCT_KEY in (SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO WHERE ACCT_SRCH_NBR='$field1');" > sqlfile.txt
done < ignore.csv

sqlfile.txt 的输出中验证,这仅适用于一行。

但是我如何遍历它以打印 CSV 的所有行?

我在循环逻辑方面仍然很糟糕——很幸运能成为这方面的产品支持人员。

非常感谢任何帮助。

【问题讨论】:

标签: sql bash loops csv


【解决方案1】:

作为Barmar pointed-out:

每次在循环内回显时都会覆盖文件。

您可以通过在 CSV 的字段分隔符中包含空格来做到这一点。

有一些重要的警告:

  • Shell 无法可靠地解析可能包含引号、转义引号的 CSV 字段。您应该考虑使用能够正确解析 CSV 并将值作为参数或 null 分隔字段(如 csvtool)返回的命令。
  • 如果您的 SQL 数据库引擎知道 PREPARE 语句,那么使用PREPARE SQL UPDATE 请求并为其提供参数会更安全。您将在循环之前准备请求,然后提供参数并在循环中执行准备好的语句。
#!/usr/bin/env bash

while IFS=', ' read -r acctnum errcode date; do

  cat <<SQL
UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T'
  WHERE BUS_DT='$date' and ETL_ERR_CD='$errcode' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO
      WHERE ACCT_SRCH_NBR='$acctnum');
SQL
done < ignore.csv > sqlfile.txt

使用csvtool 解析exclude.csv 并将其转换为SQL 查询:

excludeCSV2sql:

#!/usr/bin/env bash

# This script uses csvtool to parse exclude.csv CSV data from stdin
# and output SQL queries to stdout

# Convert arguments from csvtool call, into an SQL query
to_sql ()
{
  # Double single-quote for SQL string values if any
  local -- \
    acct_num="${1//\'/\'\'}" \
    err_code="${2//\'/\'\'}" \
    date="${3//\'/\'\'}"

  cat <<SQL
UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T'
  WHERE BUS_DT='$date' AND ETL_ERR_CD='$err_code' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO
      WHERE ACCT_SRCH_NBR='$acct_num'
  );
SQL
}

# Export for use in csvtool call
export -f to_sql

# Process CSV from stdin
csvtool call to_sql -

测试:

使上述脚本可执行:

chmod +x excludeCSV2sql

创建示例test_exclude.csv

cat >test_exclude.csv <<CSV
foo,bar,baz
here,it's using a single quote, string
this, "has a double-quoted string
with a newline", in it
10100000012, "R4242, has comma", 20200524
10100000042, R1337, 20200525
CSV

运行测试:

./excludeCSV2sql <test_exclude.csv >test.sql

检查结果:

test.sql

UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T'
  WHERE BUS_DT='baz' AND ETL_ERR_CD='bar' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO
      WHERE ACCT_SRCH_NBR='foo'
  );
UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T'
  WHERE BUS_DT='string' AND ETL_ERR_CD='it''s using a single quote' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO
      WHERE ACCT_SRCH_NBR='here'
  );
UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T'
  WHERE BUS_DT='in it' AND ETL_ERR_CD='has a double-quoted string
with a newline' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO
      WHERE ACCT_SRCH_NBR='this'
  );
UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T'
  WHERE BUS_DT='20200524' AND ETL_ERR_CD='R4242, has comma' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO
      WHERE ACCT_SRCH_NBR='10100000012'
  );
UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T'
  WHERE BUS_DT='20200525' AND ETL_ERR_CD='R1337' AND ACCT_KEY
  IN (
    SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO
      WHERE ACCT_SRCH_NBR='10100000042'
  );

【讨论】:

    【解决方案2】:

    每次在循环内回显时,您都会覆盖文件。将输出重定向移动到循环的末尾。

    while IFS=, read -r field1 field2 field3;
    do
       echo "UPDATE ODS.PERF_ACCT_ERR_DTL SET REC_ACTV_IND='T' WHERE BUS_DT='$field3' and ETL_ERR_CD='$field2' AND ACCT_KEY in (SELECT ACCT_KEY FROM ODS.ACCT_PORTFOLIO WHERE ACCT_SRCH_NBR='$field1');"
    done < ignore.csv > sqlfile.txt
    

    【讨论】:

      猜你喜欢
      • 2020-06-23
      • 2017-02-22
      • 1970-01-01
      • 1970-01-01
      • 2013-06-20
      • 2017-06-24
      • 1970-01-01
      • 1970-01-01
      • 2014-05-26
      相关资源
      最近更新 更多