问题
I am writing a shell script to run bunch of queries in postgres.
This is the script that I have written.
#!/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
There are two issues with this script.
pgtest1.sh: 17: Syntax error: end of file unexpected (expecting "done")
how do I pass $x in the sql dynamically
I want to create new db connection per iteration.
I am new to both postgre and shell.
Thanks
Priyank
回答1:
1) pgtest1.sh: 17: Syntax error: end of file unexpected (expecting "done")
You need to have EOF in its own line alone (without space etc)
psql -h $host $dbname $username << EOF
select * from students where sid = $x;
EOF
2) how do I pass $x in the sql dynamically
$ sh scriptname.sh value_of_x
then in your script
x=$1
回答2:
EOF
the way you've specified cannot be indented. You need to do the following (note the dash prior to the here-doc token:
while [ $x -le 3 ] ; do
psql foo bar <<-EOQ
select * from students where sid = $x;
EOQ
done
As a side note, why not use a for
loop instead of while
?
for (( x=$1 ; x<=3 ; x++ )) ; do
foo
done
回答3:
I did the same except for my case it's for mysql. I'm using zsh. I set up an alias so that the shell will not do any globbing when I call the script so that I can do this:
$ sql select * from Table
instead of:
$ sql select '*' from Table
The alias is:
alias sql='noglob sql'
I also use sed
to automagically add quoting where necessary so that I can do this:
$ sql select * from Client where first_name like John% and last_name = Wiley
instead of:
$ sql select '*' from Client where first_name like "'John%'" and last_name = "'Wiley'"
In cases where I don't want the shell script to automagically add the quoting I omit the spaces before and after the = operator like this:
$ sql select t1.col1,t2.col2 from Table1 t1 join Table t2 on t1.client_id=t2.client_id.
I'm pasting the script here in case you might profit from it. It is zsh, and mysql-specific. You'll have to modify it to suit the way you pass the sql commands to be run in psql. The mpager
program used in the script is another shell script that calls vim and ask it to act like a pager suitable for browsing the tabular output:
#!/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
来源:https://stackoverflow.com/questions/10649794/how-to-execute-sql-queries-from-a-shell-script