如何从外壳脚本执行 SQL 查询



我正在编写一个 shell 脚本来运行 postgres 中的一堆查询。

这是我写的剧本。

#!/bin/sh
host="172.16.7.102"
username="priyank"
dbname="truaxis"
x=1
echo "Connection done"
while [ $x -le 3 ]
do
        x=$(($x + 1 ))
        echo "Connection $x"
        psql -h $host $dbname $username << EOF
        select * from students where sid = $x;
        EOF
done

此脚本存在两个问题。

  1. pgtest1.sh:17:语法错误:文件结尾意外(预期"完成"(

  2. 如何在 SQL 中动态传递$x

我想在每次迭代中创建新的数据库连接。

我是邮政和壳牌的新手。

谢谢

普里扬克

1( pgtest1.sh:17:语法错误:文件结尾意外(预期"完成"(

您需要仅在自己的行中拥有EOF(没有空间等(

     psql -h $host $dbname $username << EOF
        select * from students where sid = $x;
EOF

2(如何在SQL中动态传递$x

$ sh scriptname.sh value_of_x

然后在您的脚本中

x=$1
EOF

指定的方式无法缩进。您需要执行以下操作(请注意 here-doc 标记之前的破折号(:

while [ $x -le 3 ] ; do
    psql foo bar <<-EOQ
        select * from students where sid = $x;
    EOQ
done

作为旁注,为什么不使用for循环而不是while

for (( x=$1 ; x<=3 ; x++ )) ; do
    foo
done

我做了同样的事情,除了我的情况是针对 mysql。我正在使用 zsh。我设置了一个别名,以便在调用脚本时 shell 不会执行任何通配,以便我可以执行以下操作:

$ sql select * from Table

而不是:

$ sql select '*' from Table

别名为:

alias sql='noglob sql' 

我还使用sed在必要时自动添加引用,以便我可以这样做:

$ sql select * from Client where first_name like John% and last_name = Wiley

而不是:

$ sql select '*' from Client where first_name like "'John%'" and last_name = "'Wiley'"

如果我不希望 shell 脚本自动添加引号,我会省略 = 运算符前后的空格,如下所示:

$ sql select t1.col1,t2.col2 from Table1 t1 join Table t2 on t1.client_id=t2.client_id.

我在这里粘贴脚本,以防您可能从中受益。它是zsh,并且特定于mysql。您必须修改它以适应您传递要在 psql 中运行的 sql 命令的方式。脚本中使用的mpager程序是另一个调用 vim 并要求它充当适合浏览表格输出的寻呼机的 shell 脚本:

#!/usr/bin/zsh
function usage() {
  echo -n "Usage: $0 [-h] [-t] [-d db] [-q] [-v] [-n] [p] [-q] [sql commands]
   -d db   Use specified database instead of the default one
   -t      Do not 'tabularize' (borders) the output
   -v      Be verbose
   -n      Dry-run - show what command to be executed
   -p      Pipe output to mpager
   -q      Surpress own output, only show output from mysql
   -h      Show this help message
"
}
password=${DB_PASS:-secret}
db=${DB:-default_db}
user=${DB_USER:-username}
USE_TABLE='--table'
while getopts d:tvnhpq o
do
  case "$o" in
    d)  db=$OPTARG ;;
    t)  USE_TABLE='' ;;
    v)  verbose=1 ;;
    n)  dry_run='echo' ;;
    p)  use_mpager=t ;;
    h)  usage; exit 0 ;;
    q)  quiet=1;;
    *)  usage;
        exit 1 ;;
  esac
done
shift `expr $OPTIND - 1`
case $2 in
    database|databases)
    db=
    ;;
esac
if [ -z "$quiet" -a -n "$db" ]; then
    echo 1>&2 "Database: $db"
fi
if [ $# -lt 1 ]; then
  mysql --table -u $user -p$password $db "$@"
  exit
fi
to_run=`echo $*|sed -e "s/ (=|like) *([^'][^ ]*+)/ 1 '2'/g"`
# This helps for debugging. Show what is going to run when output is going to a
# terminal:
if [ -t 1 ]; then
    echo "to_run: $to_run" 1>&2
fi
if [ -n "$verbose" ]; then
    echo "mysql $USE_TABLE -u $user -p$password $db -e ${(q)to_run}"
fi
if [ -n "$use_mpager" ]; then
    $dry_run mysql $USE_TABLE -u $user -p$password $db -e "$to_run" | mpager
else
    $dry_run mysql $USE_TABLE -u $user -p$password $db -e "$to_run"
fi

最新更新