can't run scripts from cmd line windows for postgresql - windows

I'm in a windows environemnt and kicked off psql. I've tried running -a -f filename.sql and psql filename.sql. This what I keep getting:
scala_db-# psql C:/Users/user/Desktop/emps.sql;
ERROR: syntax error at or near "psql"
LINE 1: psql C:/Users/user/Desktop/...

From the command line:
scala_db-# psql C:/Users/user/Desktop/emps.sql;
Looks like you already enter into the psql command line.
If so, you can use meta command \i to execute the SQL file.
e.g.
mydb=# \! echo "select 1" > c:/pgccc/tmp.sql
mydb=# \i c:/pgccc/tmp.sql
?column?
----------
1
(1 row)
If you hasn't logged into psql command line, you can use one single psql command line to execute the sql file.
e.g.
psql mydb -f c:/pgccc/tmp.sql
?column?
----------
1
(1 row)
Here the "mydb" is the target database. If not specified, you will connect to the default database.

When you run windows cmd
psql -U username dbname -f filename.sql
username is your user name,
dbname is your database name,
filename.sql is your file

Related

Invoking a bash command with an argument '#' in it

Consider the following code:
sqls='/mnt/c/alias/Binn/SQLCMD.EXE -b -S HostName -U Username -P MyPW# -d dbName'
which is the prefix of the command to connect to the SQL Server DB dbName with username Username on the HostName
`$sqls -Q "select 1;"`
executes select 1 statement on it and it works as expected.
$($sqls -Q "select 1;")
fails. Why? Is it because of the '#' in the password? How should I change the sqls line above so it works with $(...) expression?
Storing a command in a string is prone to failure. We could work out why it's not working, but the better thing to do would be to use a function:
sql() {
/mnt/c/alias/Binn/SQLCMD.EXE -b -S HostName -U Username -P 'MyPW#' -d dbName -Q "$1"
}
This allows the password to be quoted, removing the possibility that it can break the command.
Use it like sql 'select 1'. Save the result using a standard command substitution:
foo=$(sql 'select 1')
Also bear in mind that you can use a config file (possibly $HOME/.my.cnf, but it looks like you're on Windows so not sure) to store default user, pass and database, enabling you to run queries without passing all those options every time.

How can a PostgreSQL database cease to exist in between two consecutive shell commands?

I am trying to create a PostgreSQL database accounts_db in CI (GitLab CI, if it's relevant), but only if that database does not exist yet. Since native Postgres doesn't support that, I currently solve it by running a SELECT on pg_database using psql, and only when that does not return results, I use psql again to run a CREATE DATABASE:
psql -tc "SELECT 1 FROM pg_database WHERE datname = 'accounts_db';" | grep -q 1 || psql -c "CREATE DATABASE accounts_db;"
This works most of the time: accounts_db already exists, so grep exits successfully and the CREATE DATABASE is not executed.
Most of the time is not all the time, though. For some reason, it sometimes ends up in the second part of the ||, only to error out because the database already exists:
$ psql -tc "SELECT 1 FROM pg_database WHERE datname = 'accounts_db';" | grep -q 1 || psql -c "CREATE DATABASE accounts_db;"
ERROR: database "accounts_db" already exists
How is this possible?
BTW: You don't need grep; you can use psql's exit code,just attempt connecting to the new database:
(there are more reasons for psql to exit with non zero exit value; but in that case the second psql will also fail)
#!/bin/sh
THE_NAME="omg_wtf"
psql -U postgres ${THE_NAME} -tc "select 'yes';" || psql -U postgres postgres -tc "CREATE DATABASE ${THE_NAME} ;"
#Eof
But even simpler: just attempt to create the database, and bail out of the script if that fails:
#!/bin/sh
THE_NAME="omg_wtf"
psql -U postgres postgres -tc "CREATE DATABASE ${THE_NAME} ;"|| exit 1
# you wont get here if the above exited
echo "Created ${THE_NAME}"
#Eof
Any chance you've obfuscated the real db name, and the real one sometimes contains mixed case?
Because
SELECT 1 FROM pg_database WHERE datname = 'MyDB'
will match a database named MyDB but not one named mydb. However, if you create the database, you'll get a case-folded name; e.g.
CREATE DATABASE MyDB;
creates a db named mydb. So in this case, your test for existence would report that there's no db named MyDB then you'd go to create it, try to create mydb and fail if it already existed.
The fix is to use identifier quoting:
CREATE DATABASE "MyDB";
to preserve case there. Or alternately, case-fold your query of pg_database to lower case:
SELECT 1 FROM pg_database WHERE datname = lower('MyDB')
... assuming you know you'll only ever attempt to then create it in lower-case.
(It gets even more exciting if the user decides to supply identifier-quoted input to your script...)

Run postgres query from another server, in bash

I have a Ubuntu server that processes documents and another that have the database (postgresql 9.3).
I ran psql -? to understand how to connect to another DB and the final command would be:
psql -U postgres -W -h 1.2.3.4 -d testdb -p 5432
It works, but I must type the password after the command is issued.
I was trying to adapt this command in a bash script:
#!/bin/bash
psql -U postgres -W mypassword -h 1.2.3.4 -d testdb -p 5432 << EOF
select * from mytable;
\q
EOF
Needless to say this is not the right command.
Also, the password does not get recognized as a password, reporting the error:
psql: warning: extra command-line argument "mypassword" ignored
Password for user postgres:
psql: FATAL: password authentication failed for user "postgres"
FATAL: password authentication failed for user "postgres"
In another server, where the script runs on the local DB, my working script is:
su - postgres -c "psql myDatabase" << EOF
select * from "myOtherTable";
\q
EOF
The question is simple, how can I write the right command for bash, to connect to another database with user/password and issue commands?
A link I tried, but password seems to not be set:
run psql query in bash
Thanks!
Try
PGPASSWORD=yourpass psql -U postgres -W -h 1.2.3.4 -d testdb -p 5432
See: https://www.postgresql.org/docs/9.3/static/libpq-envars.html
or ~/.pgpass file https://www.postgresql.org/docs/9.3/static/libpq-pgpass.html

run psql query in bash

I am new in bash and psql, I want to write a bash code that login a server the connect to psql database do a select query and then return the output. the set up I have as follow.
server named dbs, it has psql install and running. database name = dname, user= tester passwrod = 1234
in the database there is table called node_info it has 3 colons ip, mac, connection_time.
I want to run following query
select ip, connection_time from node_info where ip=10.10.10.2;
Any tips how to write a shell script to do this remotely?
If you have properly set your "pg_hba.conf" configuration file to achieve remote connections, you may try the following:
psql -U tester -h remoteip -p remoteport -d dname -W -c "select ip, connection_time from node_info where ip='10.10.10.2'"

Shell script to execute pgsql commands in files

I am trying to automate a set of procedures that create TEMPLATE databases.
I have a set of files (file1, file2, ... fileN), each of which contains a set of pgsql commands required for creating a TEMPLATE database.
The contents of the file (createdbtemplate1.sql) looks roughly like this:
CREATE DATABASE mytemplate1 WITH ENCODING 'UTF8';
\c mytemplate1
CREATE TABLE first_table (
--- fields here ..
);
-- Add C language extension + functions
\i db_funcs.sql
I want to be able to write a shell script that will execute the commands in the file, so that I can write a script like this:
# run commands to create TEMPLATE db mytemplate1
# ./groksqlcommands.sh createdbtemplate1.sql
for dbname in foo foofoo foobar barbar
do
# Need to simply create a database based on an existing template in this script
psql CREATE DATABASE $dbname TEMPLATE mytemplate1
done
Any suggestions on how to do this? (As you may have guessed, I'm a shell scripting newbie.)
Edit
To clarify the question further, I want to know:
How to write groksqlcommands.sh (a bash script that will run a set of pgsql cmds from file)
How to create a database based on an existing template at the command line
First off, do not mix psql meta-commands and SQL commands. These are separate sets of commands. There are tricks to combine those (using the psql meta-commands \o and \\ and piping strings to psql in the shell), but that gets confusing quickly.
Make your files contain only SQL commands.
Do not include the CREATE DATABASE statement in the SQL files. Create the db separately, you have multiple files you want to execute in the same template db.
Assuming you are operating as OS user postgres and use the DB role postgres as (default) Postgres superuser, all databases are in the same DB cluster on the default port 5432 and the role postgres has password-less access due to an IDENT setting in pg_hba.conf - a default setup.
psql postgres -c "CREATE DATABASE mytemplate1 WITH ENCODING 'UTF8'
TEMPLATE template0"
I based the new template database on the default system template database template0. Basics in the manual here.
Your questions
How to (...) run a set of pgsql cmds from file
Try:
psql mytemplate1 -f file
Example script file for batch of files in a directory:
#! /bin/sh
for file in /path/to/files/*; do
psql mytemplate1 -f "$file"
done
The command option -f makes psql execute SQL commands in a file.
How to create a database based on an existing template at the command line
psql -c 'CREATE DATABASE my_db TEMPLATE mytemplate1'
The command option -c makes psql execute a single SQL command string. Can be multiple commands, terminated by ; - will be executed in one transaction and only the result of the last command returned.
Read about psql command options in the manual.
If you don't provide a database to connect to, psql will connect to the default maintenance database named "postgres". In the second answer it is irrelevant which database we connect to.
you can echo your commands to the psql input:
for dbname in foo foofoo foobar barbar
do
echo """
CREATE DATABASE $dbname TEMPLATE mytemplate1
""" | psql
done
If you're willing to go the extra mile, you'll probably have more success with sqlalchemy. It'll allow you to build scripts with python instead of bash, which is easier and has better control.
As requested in the comments: https://github.com/srathbun/sqlCmd
Store your sql scripts under a root dir
Use dev,tst,prd parametrized dbs
Use find to run all your pgsql scripts as shown here
Exit on errors
Or just git clone the whole tool from here
For that use case where you have to do it....
Here is a script I've used for importing JSON into PostgreSQL (WSL Ubuntu), which basically requires that you mix psql meta commands and SQL in the same command line. Note use of the somewhat obscure script command, which allocates a pseudo-tty:
$ more update.sh
#!/bin/bash
wget <filename>.json
echo '\set content `cat $(ls -t <redacted>.json.* | head -1)` \\ delete from <rable>; insert into <table> values(:'"'content'); refresh materialized view <view>; " | PGPASSWORD=<passwd> psql -h <host> -U <user> -d <database>
$

Resources