PostgreSQL / psql meta-command silently fails and doesn't insert rows - postgresql

I've created a SQL file I run through the psql command that roughly looks like as follows:
truncate table my_table;
\set content `cat /workdir/test.json` insert into my_table values ('test_row', :'content');
The first line is somewhat irrelevant to the problem, except for the fact it does print out "TRUNCATE TABLE", so it is reading and running the SQL file correctly, at least initially. However, the insert row is never created, the table is always empty. Yet no error message pops up.
The JSON file has a valid value (even if I pare it down to super basic {}). I've also tried passing the sql command directly (just to cover my bases, tried it with just one '' and same, with three it gives invalid command error):
psql [...] -c "\\set content `cat /workdir/test.json` insert into my_table values ('test_row', :'content')"
Again, no output message, no new rows created. However not using the meta-command \set does work. E.g.:
psql [...] -c "insert into my_table values ('test_row', '{}')"
Seems like there's something it doesn't like about the meta-command \set, but without any error info, not sure what I'm doing wrong.
Both the script and database are running on the same VM. That is, script can call host via 'localhost' and the filesystem/filepaths should be the same, I think, should that matter.

A psql meta-command (something that starts with a backslash) are terminated by the end of line; you cannot have an SQL statement on the same line.
Write the \set in one line and the INSERT in another.
If you want to use the -c option of psql, use several -c options:
psql -c "\\set ..." -c "INSERT ..."

Related

Update a PostgreSQL field from the content of a file

I have a file containing a value which should go into a field of a PostgreSQL table.
By searching a little, I found many answers, e.g. How can I update column values with the content of a file without interpreting it? or https://stackoverflow.com/a/14123513/6630397, with this kind of snippet, but it has to be run in a psql terminal:
\set content `cat /home/username/file.txt`
UPDATE table SET field = :'content' WHERE id=1;
It works, but is it possible to programmatically execute it in one shot, directly from a bash prompt, without manually entering the psql command line, e.g. something like:
$ psql -d postgres://postgres#localhost/mydatabase -c \
"UPDATE table SET field = :'the_file_content' WHERE id=1;"
?
There is also the -v argument that seems promising but I'm not successful when using it:
$ psql -d postgres://postgres#localhost/mydatabase \
-v content=`cat ${HOME}/file.txt` \
-c "UPDATE table SET field = :'content' WHERE id=1;"
I've got thousands of psql: warning: extra command-line argument where psql actually seems to "execute" each comma separated strings of the file as pg commands, where it shouldn't of course; the file content, which consists of a single line, must be treated as a whole.
Doc PostgreSQL 14:
https://www.postgresql.org/docs/current/app-psql.html
How about reading the file content into a variable first and then use it?
content=$(<integer_infile); psql -p 5434 -c "update table set field = $content where id = 1;"
content=$(<text_infile); psql -p 5434 -c "update table set field = '$content' where id = 1;"
This at least works for me if the file contains an integer or text including spaces on a single line.

PostgreSQL copy command gives error for temporary table

I am trying to run the below command on the unix console :
env 'PGOPTIONS=-c search_path=admin -c client_min_messages=error' psql -h hostname -U user -p 1111 -d platform -c "CREATE TEMP TABLE admin.tmp_213 AS SELECT * FROM admin.file_status limit 0;\copy admin.tmp_213(feed_id,run_id,extracted_date,file_name,start_time,file_size,status,crypt_flag) FROM '/opt/temp/213/list.up' delimiter ',' csv;UPDATE admin.file_status SET file_size = admin.tmp_213.file_size FROM admin.tmp_213 A WHERE admin.file_status.feed_id = A.feed_id and admin.file_status.file_name = A.file_name;"
I am getting the below error:
ERROR: syntax error at or near "\"
LINE 1: ...* FROM admin.file_status limit 0;\copy admi...
If I use the above command without a backslash before COPY, it gives me the below error:
ERROR: cannot create temporary relation in non-temporary schema
I am doing the above to implement the solution as mentioned here:
How to update selected rows with values from a CSV file in Postgres?
Your first error is because metacommands like \copy cannot be combined in the same line as regular commands when given with -c. You can give two -c options, with one command in each instead.
The second error is self-explanatory. You don't get to decide what schema your temp table goes to. Just omit the schema.

Restore one table from a database in PostgreSQL and save it with plain/text data format

I have a table (tst2) in a database (tweets) in PostgreSQL and I need to have a plain/text format file out of it, I was wondering if there is any possible solution with pg_dump ? something like :
pg_dump -t tst2 tweets -f plain >...
also if I am in a wrong way please let me know?!
There are a couple of ways to dump a table into a text file.
First, you can use pg_dump, as you intended. In that case you'll get a SQL script to restore the tables. Just fix your command a bit:
pg_dump -t tst2 -t tweets -F plain >...
Second, you can dump contents of a table with copy command. There are either SQL version of the command (files will be created on the server):
copy tst2 to 'tst2.txt';
copy tweets to 'tweets.txt';
Or client-side psql version (files will be created on your client computer):
\copy tst2 to 'tst2.txt';
\copy tweets to 'tweets.txt';
pg_dump works for me, though there is some clutter before and after the table (after all, dumps are supposed to be used to fill up the table at recovery time).
I'm not sure what you use the > operator for; the dump goes to the file `plane'.
Your error message would help, of course.
On the other hand, what's wrong with using psql with a .pgpass password file and setting the PGDATABASE, PGHOST, PGPORT, and PGUSER anvironment variables, e.g.:
export PGDATABASE=tweet
# PGHOST, PGPORT, and PGUSER as per your setup
psql -c 'select * from tst2'

Difference between set, \set and \pset in psql

I get a little confused some times when working with psql between when to use a set vs. \set vs. \pset. I think that:
set is for session variables on my connection to the db. For example SET ROLE dba;
\set is for local variables for this psql session. For example \set time 'select current_timestamp'
\pset is for psql settings for this psql session. For example '\pset border 2'
But, I've never found what I thought was a good explanation of each. Are my assumptions above correct?
I'm using PostgreSQL 9.4
Basically correct. The important difference is that SET is an SQL command while the other two are psql meta-commands - indicated by the leading \.
SET is an SQL command to change run-time parameters. It is executed on the server and has nothing to do with psql per se.
\set is a psql meta-command:
Sets the psql variable name to value [...]
Note: This command is unrelated to the SQL command SET.
\pset is another psql meta-command:
This command sets options affecting the output of query result tables

How to use slash commands outside the database?

I tried to use the query outside of the database. That is, without login to data base
I want to get the result. I found the option (-c). Using that option we can execute the query from outside the data base:
test:~$ psql -U sat -c "select * from test.details";
It gives the output. I want to use that query for a crontab entry. So I have tried to store the output in a file:
test:~$ psql -U sat -c "select * from test.details \g sat";
Produced an error:
ERROR: syntax error at or near "\"
LINE 1: select * from test.details \g sat
How to do that?
This is not a slash, but a backslash .
Backslash is an escape character in PostgreSQL string literals, therefore you have to double it to get a single backslash into the actual data.
If you want to store the result of a query into a file from the command line you have to use the -o command line option,so your query will become :
psql -o filename -U sathishkumar -c "select * from hospital_management.patient_details";
There is no such thing as a "query outside of the data base" or "without login to data base".
You are trying to mix meta-commands of the psql client with SQL commands, which is strictly impossible. The backslash meta commands are interpreted by the psql client, SQL queries are interpreted by the database server.
Most meta-commands in psql are actually translated into (a series of) SQL queries to the database server. You can make psql print the commands it sends to the database engine if you start it up with the command option -E in interactive mode. Try:
psql -E mydb
And then execute any backslash command and observe the output. For the rest of your question #aleroot has already given good advice.