53

I'm trying to drop a few tables with the "DROP TABLE" command but for a unknown reason, the program just "sits" and doesn't delete the table that I want it to in the database.

I have 3 tables in the database:

Product, Bill and Bill_Products which is used for referencing products in bills.

I managed to delete/drop Product, but I can't do the same for bill and Bill_Products. I'm issuing the same "DROP TABLE Bill CASCADE;" command but the command line just stalls. I've also used the simple version without the CASCADE option.

Do you have any idea why this is happening?

Update:

I've been thinking that it is possible for the databases to keep some references from products to bills and maybe that's why it won't delete the Bill table.

So, for that matter i issued a simple SELECT * from Bill_Products and after a few (10-15) seconds (strangely, because I don't think it's normal for it to last such a long time when there's an empty table) it printed out the table and it's contents, which are none. (so apparently there are no references left from Products to Bill).

14
  • what about not doing the CASCADE. perhaps the constraint was referring to the now missing PRODUCT Commented Apr 25, 2012 at 13:52
  • Tried without that too, but no effect. Commented Apr 25, 2012 at 13:53
  • 1
    "The command line just stalls" What does that mean? psql crashes, hangs, or freezes? Do you have to kill it? What does Ctrl-C do? I guess I'm just saying define 'stalls'. Or are you not using psql? Commented Apr 25, 2012 at 13:56
  • 3
    Maybe another transaction has a lock on the table so you cannot drop it? Commented Apr 25, 2012 at 14:01
  • 1
    Rebooting only works for tables named "Bill" ;-) Commented Apr 25, 2012 at 14:03

9 Answers 9

71

What is the output of

SELECT *
  FROM pg_locks l
  JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r'
 WHERE t.relname = 'Bill';

It might be that there're other sessions using your table in parallel and you cannot obtain Access Exclusive lock to drop it.

Sign up to request clarification or add additional context in comments.

4 Comments

psdemo=> SELECT * from pg_locks l join pg_class t on l.relation = t.oid AND t.relkind = 'r' WHERE t.relname="ps_bill"; ERROR: column "ps_bill" does not exist LINE 1: ...ation = t.oid AND t.relkind = 'r' WHERE t.relname="ps_bill";
For a literal value, use single quotes (the apostrophe). PostgreSQL conforms to the SQL standard in treating double-quotes as wrapping an identifier.
Thank you but I managed to fix it with a simple reboot. It's kind of a silly and not a demystifying thing, what I did, but it was the shortest way around the problem. I up voted your answer so you know I appreciate your help. I guess indeed there was a transaction that held a lock on the tables.
Yes , I did manage to get over this issue by simply restarting the postgresql and then dropping the table.
28

Just do

SELECT pid, relname
FROM pg_locks l
JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r'
WHERE t.relname = 'Bill';

And then kill every pid by

kill 1234

Where 1234 is your actual pid from query results.

You can pipe it all together like this (so you don't have to copy-paste every pid manually):

psql -c "SELECT pid FROM pg_locks l 
    JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r' 
    WHERE t.relname = 'Bill';" | tail -n +3 | head -n -2 | xargs kill

2 Comments

Even if it's been more than 3 years since I posted the question, I want to thank you for coming and sharing your solution. But, my question is what would relname be?
@RaduGheorghiu relname is actually a table name.
19

If this is for AWS postgres run the first statement to get the PID (Process ID) and then run the second query to terminate the process (it would be very similar to do kill -9 but since this is in the cloud that's what AWS recommends)

-- gets you the PID
SELECT pid, relname FROM pg_locks l JOIN pg_class t ON l.relation = t.oid AND t.relkind = 'r' WHERE t.relname = 'YOUR_TABLE_NAME'

-- what actually kills the PID ...it is select statement but it kills the job!
SELECT pg_terminate_backend(YOUR_PID_FROM_PREVIOUS_QUERY);

source

Comments

11

So I was hitting my head against the wall for some hours trying to solve the same issue, and here is the solution that worked for me:

Check if PostgreSQL has a pending prepared transaction that's never been committed or rolled back:

SELECT database, gid FROM pg_prepared_xacts;

If you get a result, then for each transaction gid you must execute a ROLLBACK from the database having the problem:

ROLLBACK PREPARED 'the_gid';

For further information, click here.

Comments

9

I ran into this today, I was issuing a:

DROP TABLE TableNameHere

and getting ERROR: table "tablenamehere" does not exist. I realized that for case-sensitive tables (as was mine), you need to quote the table name:

DROP TABLE "TableNameHere"

Comments

7

The same thing happened for me--except that it was because I forgot the semicolon. face palm

1 Comment

OMG, you saved me. I was wondering why I'm not getting a message even if I misspell the table name. makes so much sense now. Thank you!
5

Had the same problem.

There were not any locks on the table.

Reboot helped.

1 Comment

Same thing for me. I didn't have to reboot, only had to restart postgresql.
2

Old question but ran into a similar issue. Could not reboot the database so tested a few things until this sequence worked :

  • truncate table foo;
  • drop index concurrently foo_something; times 4-5x
  • alter table foo drop column whatever_foreign_key; times 3x
  • alter table foo drop column id;
  • drop table foo;

Comments

0

This happened to me.

What I noticed is that there were processes running that simply wouldn't let me execute DROP TABLE or ALTER TABLE on the PK or FK.

First I did:

SELECT * FROM pg_stat_activity

I didn't filter by just the active ones because the ones that were blocking were in "idle" status

And then I killed those processes:

SELECT pg_cancel_backend(<pid of the process>)

I killed all the processes that were running for that database. I made sure that this wouldn't affect my application.

If it still doesn't work, try:

  SELECT pg_terminate_backend(<pid of the process>)

Link : How to stop/kill a query in postgresql?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.