Sybase query:save an output to a file - shell

I´ve created the following script:
#!/bin/bash
isql -U databasename_dba -P password -b <<EOF!
select quantity, date from name_table where numer_id="1234"
go
quit
EOF!
Running the script I got the desirable output, see:
user#system$ ./EXECUTE_DAILY_4:
But now, how can I save this result that I see in my terminal window in a file? (.csv for example)
I adapted the following to my Sybase query:
#!/bin/bash
cat > test.sql <<EOF!
isql -U databasename_dba -P password -b
select quantity, date from name_table where numer_id="1234"
go
quit
EOF!
isql test.sql >result.csv
Without success, the above is not working.
Thanks in advance

A couple options:
isql -U databasename_dba -P password -b <<-EOF > result.csv 2>&1
select quantity, date from name_table where numer_id="1234"
go
EOF
The '> result.csv 2>&1' says to write stdout to the file 'result.csv'; also redirect stderr (fd=2) to stdout (fd=1) (ie, also write stderr to the file 'result.csv'; from here you can do what you want with 'result.csv' (eg, check for errors, parse/process the file as needed, etc).
NOTE: The 'quit' is superfluous as the isql session will automatically exit/quit when it has nothing else to do.
If you want to place the query in a *.sql file:
echo "select quantity, date from name_table where numer_id='1234'" > test.sql
echo "go" >> test.sql
From here you have a couple options for submitting to isql:
isql -U databasename_dba -P password -b -i test.sql -o result.csv
or
isql -U databasename_dba -P password -b -i test.sql > result.csv 2>&1
The '-i test.sql' tells isql to take it's input from the file 'test.sql'; the first example uses '-o result.csv' to diredct stdout to 'result.csv' while the second example directs stdout/stderr to 'result.csv'.

You could effectively do the same thing but within the script itself. Something like:
#!/bin/bash
command=$(
isql -U databasename_dba -P password -b <<EOF!
select quantity, date from name_table where numer_id="1234"
go
EOF!
)
echo "$command" >> FILE.csv

I solved it using this (a basic solution):
./EXECUTE_DAILY_4> FILE.csv
I'm open to seeing more suggestions,
thanks.

Related

Using a bash variables in sqlcmd

I have been tasked with replacing ISQL in a lot of our bash scripts with sqlcmd. ISQL allows piping a variable in it's execution.
An example would be:
SQL_STATEMENT="SELECT TOP 1 SYS_USER_NAME FROM SYS_USER"
echo $SQL_STATEMENT | isql -b -d, $DSN $DBUID $DBPWD >> setupdb_test.txt
From what I can tell this is not viable in sqlcmd. How can I do this? What flags does sqlcmd have to allow this to happen?
Here is what I have tried and have had a good result BUT I really do not want to create the file sql_command.sql every time a particular script runs:
echo "SELECT TOP 1 SYS_USER_NAME FROM SYS_USER" > sql_command.sql
sqlcmd -S $DB -U $DBUID -P $DBPWD -d $DSN -i sql_command.sql >> setupdb_test.txt
Programs originating on Windows can be picky about how they handle non-regular files and I don't have the opportunity to test, but you can try the typical Unix tricks for providing a "file" with data from an echo.
Either /dev/stdin:
echo "SELECT TOP 1 SYS_USER_NAME FROM SYS_USER" | sqlcmd -S "$DB" -U "$DBUID" -P "$DBPWD" -d "$DSN" -i /dev/stdin
or process substitution:
sqlcmd -S "$DB" -U "$DBUID" -P "$DBPWD" -d "$DSN" -i <(echo "SELECT TOP 1 SYS_USER_NAME FROM SYS_USER")

Copy output of sql-query to a file

I want to export a random entry of my database into a file with the command
SELECT * FROM my_table ORDER BY RANDOM() LIMIT 1 \g /path/file;
This query works if I enter it in my db terminal, but I want to us this query with a bash script but then I get the error: syntax error at or near "\g"
My bash script looks like this:
PGPASSWORD=*** psql -U user -d db_name -h localhost -p port -t -c "SELECT * FROM my_table ORDER BY RANDOM() LIMIT 1 \g /path/file"
Bash is interpreting the string and trying to interpolate it. Probably, escaping the backslash will solve your problem.
PGPASSWORD=*** psql -U user -d db_name -h localhost -p port -t -c "SELECT * FROM my_table ORDER BY RANDOM() LIMIT 1 \\g /path/file"
A SQL statement terminated by \g is not supported by the -c command switch. Per documentation of -c:
-c command
...
command must be either a command string that is completely parsable by the server (i.e., it contains no psql-specific features), or a single backslash command. Thus you cannot mix SQL
and psql meta-commands with this option
To redirect the results to a file, there are several options:
shell redirection: psql [other options] -Atc 'SELECT...' >/path/to/data.txt
-A is to switch to unaligned mode (no space fillers to align columns).
put the SQL part in a heredoc text instead of the command line:
psql [options] <<EOF
SELECT ... \g /path/to/file
EOF
This form has the advantage that multiline statements or multiple statements are supported directly.
\copy of the query. Be aware that COPY to a FILE is different: it creates the file on the server with the permissions of postgres and requires being a database superuser. COPY TO STDOUT works too but is not better than SELECT concerning the redirection.
I found a solution for my script, and now it works.
#!/bin/bash
RANDOM_NUMBER=0
while true
do
for i in `seq 1`
do
RANDOM_NUMBER=$(($RANDOM % 100000))
echo $RANDOM_NUMBER
PGPASSWORD=*** psql -U user_name -d db_name -h localhost -p PORT -c
"INSERT INTO numbers (number) VALUES ('$RANDOM_NUMBER');"
done
sleep 10
for i in `seq 1`
do
PGPASSWORD=*** psql -U user_name -d db_name -h localhost -p PORT -c
"DELETE FROM numbers WHERE id = (SELECT id FROM numbers ORDER BY RANDOM() LIMIT 1);"
done
done

crontab multiple postgresql issue

I'm trying to run a script (automation.sh) automated in crontab.
(I'm on Ubuntu 14.04).
#!/usr/bin/env bash
day=$(date +%F -d'yesterday')
cat /home/tomi/logs/$day |grep registration > /home/tomi/registrations/$day
cat /home/tomi/logs/$day |grep free_tree > /home/tomi/free_tree/$day
cat /home/tomi/logs/$day |grep super_tree > /home/tomi/super_tree/$day
psql -U hello -d postgres -c "\COPY registrations FROM '/home/tomi/registrations/$day' DELIMITER ' '";
psql -U hello -d postgres -c "\COPY free_tree FROM '/home/tomi/free_tree/$day' DELIMITER ' '";
psql -U hello -d postgres -c "\COPY super_tree FROM '/home/tomi/super_tree/$day' DELIMITER ' '";
psql -U hello -d postgres -f daily_active_users.sql > /home/tomi/tmp1
psql -U hello -d postgres -f daily_revenue.sql > /home/tomi/tmp2
If I run this script normally from the command line, then the last two lines generate tmp1 and tmp2 with data in them. (That's the expected result.)
However, if I run this very same script in crontab, everything works, but the last two lines generate empty files (tmp1 and tmp2).
The tricky thing is that when I break this script into two scripts (eg. automated.sh and automated2.sh) and run the last two lines in crontab 5 minutes later (via this automated2.sh script), tmp1 and tmp2 are generated correctly, with data in them.
Any idea, what can cause this?
Answer is in the comments:
full path is missing on last two lines in automation.sh!
Thanks!

sqlcmd return only count - suppress text

I have a bash file which executes a SQLCMD query to check for the existence of a database:
sqlcmd -S localhost -U sa -P $SA_PASSWORD -d master -Q "SET NOCOUNT ON SELECT count(*) FROM master.sys.databases WHERE name = N'MyDatabaseHere'")
I tried adding the SET NOCOUNT ON but it still outputs like this:
------
1
I am assigning the result to a variable and I want to be able to check it like this
myvariable == 1
Is there a way to do this?
Took me a while but I found a solution only using sqlcmd.
You need to use -W -h-1 -k
-W removes trailing space
-h-1 removes headers
-k Removes all control characters, such as tabs and new line characters from the output.
TABLENAME=$(/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P $SA_PASSWORD -d master -W -h-1 -k -Q "SET NOCOUNT ON SELECT name FROM master.sys.databases WHERE name = N'MyDatabaseNameHere'")

Run Postgres File from Command Line (Without actually printing out code)

I can successfully run SQL (Postgres) files from command line following instructions here:
Run a PostgreSQL .sql file using command line arguments
In particular, I use something like
psql -d DBPASSWORD -a -f FILENAME
Problem is that this (and specifically, I believe the -a) prints the sql code out to the terminal. This is annoying because I am running a lot of files in sequence within a Python script using subprocess, and I would rather not have the SQL code print out in terminal. Is there a way to not print the SQL code out to terminal?
EDIT: I've tried adding the -q option like people said, but the code in the SQL file is still being printed out to terminal.
What I tried was
psql -q -d DBPASSWORD -a -f FILENAME
psql -d DBPASSWORD -q -a -f FILENAME
psql -d DBPASSWORD -a -q -f FILENAME
psql -d DBPASSWORD -a -f FILENAME -q
And in each of those cases, the code in FILENAME is being printed to terminal
You may want to redirect STDOUT, STDERR or both to a log file.
Something like one of these
psql ... > out.log
psql ... 2> err.log
psql ... &> out_and_err.log

Resources