Sometimes my commands in psql seem to be having no effect. Any idea why?
The below is the list of all tables in the database library_development:
library_development=> \d
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+----------
public | Pavan | table | postgres
public | schema_migrations | table | sai
(2 rows)
After this I dropped the table Pavan using:
library_development-> drop table Pavan
But the Table isn't dropped and its shows as shown:
library_development=> \d
List of relations
Schema | Name | Type | Owner
--------+-------------------+-------+----------
public | Pavan | table | postgres
public | schema_migrations | table | sai
(2 rows)
Also:
I am using PostgreSQL in Windows. Is there any command to clear the console (Like cl scr present in Oracle)?
Is there any concept of a "commit" I need to perform in Postgresql when working with DML scripts?
Statements end with semicolons.
In psql, pressing enter without a semicolon continues the statement onto the next line, adding what you wrote to the query buffer rather than executing it. You will notice that the prompt changes from dbname=> to dbname-> to indicate that you're on a continuation line.
regress=> DROP TABLE sometable
regress-> \r
Query buffer reset (cleared).
regress=> DROP TABLE sometable;
ERROR: table "sometable" does not exist
regress=>
Notice how after I press enter without a semicolon, the prompt changes to regress-# and no action is taken. There is no table sometable, so if the statement had run an error would be reported.
Next, see the use of \r on the next line? That clears the query buffer. Notice that the prompt changes back to regress=# when the buffer is cleared, as there's no partial statement buffered anymore.
This shows how statements can be split across lines:
regress=> DROP TABLE
regress-> sometable
regress-> ;
ERROR: table "sometable" does not exist
The confusing thing is that psql backslash commands like \d are newline-terminated, not semicolon terminated, so they do run when you press enter. That's handy when you want to (say) view a table definition while writing a statement, but it's a bit confusing for newcomers.
As for your additional questions:
If there's a "clear screen" command in psql for Windows I haven't found it yet. On Linux I just use control-L, same as any other readline-using program. In Windows \! cls will work.
DDL in PostgreSQL is transactional. You can BEGIN a transaction, issue some DDL, and COMMIT the transaction to have it take effect. If you don't do your DDL in an explicit transaction then it takes effect immediately.
I just encountered something similar, but the cause was different.
I was trying to use the dropdb command and what I was seeing was like my command having no effect (change of prompt means my command is in the buffer, but that's not the issue here):
postgres=# dropdb databasename
postgres-#
Commands like dropdb should be entered OUTSIDE psql. What i had been doing was:
$ psql postgres
postgres=# dropdb databasename
Notice the first command is in Bash and fires psql, and the second is sent within psql.
The correct way is to send the command directly in bash (the console):
$ dropdb databasename
Related
I'm trying to execute two sql commands (create a new schema and table), in a way that would enable a rollback of both commands if the execution fails. The database I'm connecting to is AWS Redshift.
create schema if not exists test_schema;
create table test_schema.test_table as select 1;
Initially I tried to execute these commands programatically with python, using both psycopg2 and pyodbc, and got the following error:
ERROR: schema "test_schema" does not exist
I realised that it fails because the first command isn't being comitted, so to fix that , I tried setting the autocommit mode on, and wrapping the statements with "begin/end" block, which didn't help.
When I used psql CLI and ran the following, everything worked as intended (there was no "schema does not exist" error, and after the rollback, both schema and table were gone):
dev=# begin;
BEGIN
dev=# create schema test_schema;
CREATE SCHEMA
dev=# create table test_schema.test_table as select 1;
SELECT
dev=# rollback;
ROLLBACK
I tried to get the same results by running the following in the command line:
psql -c "begin; create schema test_schema; create table test_schema.test_table as select 1;"
This results in the same error:
ERROR: schema "test_schema" does not exist
However, when I put the above code in a file and ran the same command, this time using -f, it worked:
psql -f create_schema_and_table.sql
My questions are:
What is the difference between executing queries with "psql -c" and "psql -f"?
How can the same result be achieved programatically, with python?
Thanks a lot!
I don't know what you are doing wrong, your "psql -c" command works perfectly fine:
ads#diamond:~$ psql -c "begin; create schema test_schema; create table test_schema.test_table as select 1;" postgres
SELECT 1
psql will send the entire string to the server, and execute it in one single transaction. Your problem is that you start a transaction using "begin", but never commit it. Therefore at the end of the psql run, all your changes are rolled back. The next psql command will not find the schema, nor the table. But as long as everything stays in a single psql call, subsequent queries in the same command can see newly created objects.
Your query string should instead look like:
begin; create schema test_schema; create table test_schema.test_table as select 1; commit;
Or, more easy:
create schema test_schema; create table test_schema.test_table as select 1;
Both will work.
Running following statement in DB2 CLP (Command Window)
db2 "truncate table MYSCHEMA.TABLEA immediate"
DB21034E The command was processed as an SQL statement because it was not a
valid Command Line Processor command. During SQL processing it returned:
SQL0969N There is no message text corresponding to SQL error "-20356" in the
message file on this workstation. The error was returned from module
"SQLNQBE2" with original tokens "MYSCHEMA.TABLEA".
Can some please tell me what I'm doing wrong or what I'm missing? I'm trying to simply truncate from a single table and I'm getting the following error message. Not sure what I'm doing wrong. I've tried it with/without quotes, with/without schema, with/without immediate. I've also tried in Command Editor (remove db2 and quotes) and still not working. I'm using:
DB2/AIX64 9.7.9
Also, I have delete privilege as I am able to delete records but I want to truncate.
Thanks in advance!
The version of the DB2 client you're using doesn't seem to match that of the server, this is why you cannot see the actual error message for SQLCODE -20356. If you could, you'd see this:
The table MYSCHEMA.TABLEA cannot be truncated because DELETE triggers
exist for the table, or the table is the parent in a referential
constraint.
Further explanation and suggested actions can be found, as usual, in the fine manual.
ALTER TABLE MYSCHEMA.TABLEA ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE
or
import from /dev/null of del replace into MYSCHEMA.TABLEA
I had this problem recently too. In my case I had to do a COMMIT WORK right before TRUNCATE. This solved my problem. Please try and tell us if this helped.
I have the following script that I run using "isql -i scriptfile.sql":
CONNECT C:\Databasefile.fdb USER user PASSWORD password;
SET TERM !! ;
EXECUTE BLOCK AS BEGIN
IF (EXISTS(SELECT 1 FROM rdb$relations WHERE rdb$relation_name = 'MYTABLE')) THEN
EXECUTE STATEMENT 'DROP TABLE MYTABLE;';
END!!
SET TERM ; !!
CREATE TABLE MYTABLE
(
MYCOLUMN VARCHAR(14) NOT NULL
);
The very first time I run this (when the table does not already exist) the table is created as expected.
If I run the script again I get the following error:
Statement failed, SQLCODE = -607
unsuccessful metadata update
-STORE RDB$RELATIONS failed
-deadlock
After line 8 in file d:\myscript.sql
When the script exits, MYTABLE has been deleted and can no longer be found in the database.
If I run the script a third time the table is once again created and no errors are thrown.
Why can't the script both delete and then recreate a table?
DDL from PSQL is not allowed, using EXECUTE STATEMENT it is not directly forbidden, and usually possible, but still not wise exactly because of these kinds of problems. I am not exactly sure about the reasons, but part of it have to do with how DDL changes are applied in Firebird; the use of execute statement adds additional locks iirc which conflict with a subsequent DDL for the same table name.
Instead of dropping and creating this way, you should use the DDL statement RECREATE TABLE instead.
Note that the word deadlock in this error is actually a bit of a misnomer (there is no real deadlock).
So, given an SQL file to be executed in Oracle, we are asked to determine how many blocks are to be executed within the SQL file. For example, there is one block in an SQL file containing the following command,
CREATE TABLE customer (id varchar2(42));
two blocks in the following SQL file,
ALTER TABLE customer ADD name varchar2(42);
ALTER TABLE customer DROP COLUMN id;
and three blocks in the following SQL file
CREATE OR REPLACE PROCEDURE printHelloWorld IS
BEGIN
dbms_output.put_line('Hello World!');
END;
/
INSERT INTO customer VALUES ('ivan');
DROP TABLE customer;
We can't assume anything else about the input, other than the fact it will be executed without any error in Oracle SQLDeveloper.
UPDATE
The purpose of asking the question is to ensure that there would only be one statement, which is to be executed, in the SQL file. I am also open to the answer of this question. It would be even better to be able to create a script to split a multiple-statement SQL file to multiple files.
Not a perfect solution but will work in most cases I think.
First create a duff user with no rights except to create a session.
CREATE USER duff IDENTIFIED BY "password";
GRANT CREATE SESSION TO duff;
Then use this with sqlplus and grep to count the ORA- errors - should be one per statement.
sqlplus duff/password#db < script.sql | grep -c ORA-
If you have ALTER SESSION statements then you need a bit more
sqlplus duff/password#db < script.sql | grep -Ec 'ORA-|Session altered.'
There maybe other exceptions, but I think it gives you a workable solution for little overhead. Be careful that scripts don't switch user - but if you have hard-coded usernames and passwords in your scripts you have other issues.
I am currently trying to maintain a postgres database of player information when I've encountered an issue with one of our players. The player came to us saying that he could not load his character into the game world. I did a small SELECT statement to pull up the player information with no problems. However, when they try to use a character then we update a field in the row that says that the player character is active. However we noticed that we couldn't run an update or a delete statement on that row. Every other row in the table gets modified without any issues.
On of our DB admins thought that it was a lock that was applied on that row, but after further investigation with see nothing that could be locking that row.
Any advice or suggestions is greatly appreciated.
It certainly sounds like a lock.
The "big hammer" approach is bouncing (stoping/starting) your database to kill any running queries.
The "scalpel" approach is to run show full processlist; and try to find a query that's running that might have created a lock. Note that the query itself might not lock the row, but an earlier query in the same transaction might have locked it. Any long-running query is a suspect.
EDIT
I have found an issue in postgres that keeps the lock even after a restart. Here's how you find and fix it:
Run this query:
select * from pg_prepared_xacts
Here's the doc for this system view
If there are any rows, it means there are orphaned/dangling transactions, which can hold locks even after restarting postgres.
To kill them, for every row get the gid (a long UUID), and execute this:
ROLLBACK PREPARED '<paste gid here>'
That should clean things up.
If you are on a *nix platform, you can run this single command that will do the lot:
psql -U postgres mydatabase -c "select * from pg_prepared_xacts" | grep -v transaction | grep \| | awk '{print $3}' | xargs -I % psql -U postgres mydatabase -c "ROLLBACK PREPARED '%'"