How to make PREPARE TRANSACTION work - sql

As per Postgres Documentation - Once prepared, a transaction can later be committed or rolled back with COMMIT PREPARED or ROLLBACK PREPARED, respectively. Those commands can be issued from any session, not only the one that executed the original transaction.
I am trying to import data from csv into database tables and for this, I am using the
COPY tablename [ ( column [, ...] ) ]
FROM { 'filename' }
all this is done in a shell script.
Now the issue is that I am executing psql command and passing this command as parameter via the -c option ( I start transaction via the command
prepare transaction 'some-id' in that command).
I want to create a Savepoint and rollback to it incase of any errors.
After a few other tasks in the shell script, I check for errors that the previous psql statement have produced and when I then try to rollback using the command
Prepared Rollback 'transaction-id' ( in separate psql command with sql statements )
It reports "No "transaction-id" found"
Am I getting the concept wrong or missing something in the process?
Is this happening because I am issuing psql command multiple time and each is resulting in new transaction ?

For your prepare to work, the COPY and PREPARE must be in the same session. Since your question lacks concrete commands, I'm assuming that when you write:
Prepared Rollback 'transaction-id' ( in separate psql command with sql statements )
You're using different psql commands to COPY and PREPARE. This is wrong. Combine the COPY and PREPARE to the same session.
E.g.
$ psql -c "BEGIN; COPY tablename FROM '/tmp/sql'; PREPARE TRANSACTION 'foobar';" db
$ while /bin/not-ready-to-commit ; do sleep 1 ; done
$ psql -c "COMMIT PREPARED 'foobar';" db
The PREPARE TRANSACTION works by writing the current transaction to the disc and exiting the transaction process in the current session. This is why you need a BEGIN: it starts the transaction you want to prepare. All commands you want to be affected by the prepeare must come after the transaction has been started (in your case the COPY command). When the PREPARE TRANSACTION is issued, the transaction you are currently in is written to disk with the identifier you give. Any statements issued after the transaction is prepared are no longer part of the transaction. So doing BEGIN; PREPARE... ; COPY runs the COPY operation without a transaction.
Here's an example in psql shell:
demo=# DELETE FROM foo;
DELETE 4
demo=# BEGIN; -- start a transaction
BEGIN
DEMO=# COPY foo FROM '/tmp/sql'; -- do what you want to commit later
COPY 4
demo=# PREPARE TRANSACTION 'demo'; -- prepare the transaction
PREPARE TRANSACTION
demo=# ROLLBACK; -- this is just to show that there is no longer a transaction
NOTICE: there is no transaction in progress
ROLLBACK
demo=# SELECT * FROM foo; -- the table is empty, copy waiting for commit
a | b
---+---
(0 rows)
demo=# COMMIT PREPARED 'demo'; -- do the commit
COMMIT PREPARED
demo=# SELECT * FROM foo; -- data is visible
a | b
---+---
1 | 2
3 | 4
5 | 6
7 | 8
(4 rows)
Edit: You must enable prepared transactions in postgresql.conf:
max_prepared_transactions = 1 # or more, zero (default) disables this feature.
If max_prepared_transactions is zero, psql reports that the transaction id is not found, but does not warn you about this feature being disabled. Psql gives a warning for PREPARE TRANSACTION but it's easy to miss if your shell scripts print stuff after the prepare statement.

PREPARE TRANSACTION is for distributed transactions across multiple servers, usually used by transaction monitors or similar application servers (e.g. EJB).
Simply wrap your copy in a regular transaction block:
START TRANSACTION;
COPY ....;
COMMIT;
If you want a savepoint in the middle, use SAVEPOINT some_name and then you can rollback to that savepoint.

Related

SQL Server - Can DDL commands be rolled back? [duplicate]

This question already has answers here:
Is it possible to roll back CREATE TABLE and ALTER TABLE statements in major SQL databases?
(5 answers)
Closed 2 years ago.
I found similar queries on stack overflow but was not able to find exact answer.
When I use DDL commands like drop and truncate on SQL Server 2012, I am able to
rollback the changes? In theory, I have always read that you can rollback DML commands but not DDL as they are not logged.
My question is, if DDL commands can also be rolled back? Or this some special feature or settings change in my SSMS which is causing it.
What about the other SQL platforms like Oracle and Postgres? Can we also rollback DDL commands on them?
DDL rolls back.
Example:
BEGIN TRANSACTION
CREATE TABLE a ( Id INT NOT NULL )
SELECT * FROM a -- returns an empty row
ROLLBACK TRANSACTION
SELECT * FROM a -- throws an error, object does not exist
I always include my CREATEs, ALTERs, DROPs and TRUNCATEs inside transactions for that exact reason. That way, if there is an error, I don't get some objects, but not others. Test the DDL you have questions about.
You can use Begin Transaction Block and Rollback - Commit as shown below:
BEGIN TRANSACTION
INSERT INTO YourTable VALUES(1), (2);
ROLLBACK TRANSACTION;
INSERT INTO YourTable VALUES(3),(4);
SELECT [value] FROM YourTable;
DROP TABLE YourTable;
COMMIT TRANSACTION;
and also if you want to do some actions (DDL commands or DML commands) you can turn off Auto commit
First, create a new query page and then, from the menu items: Query\ Query options
Set IMPLICIT_TRANSACTIONS to True
And whenever you did your job, either you can commit your transactions or rollback by commit \ rollback command or by closing page and confirm\reject the transactions
But after that, if your transactions applied to your DB and tables,
You can rollback drop table or truncate table with the Microsoft SQL recovery tool - EaseUS MS SQL Recovery
you will be able to recover the truncated table or recover the table after DROP. EaseUS MS SQL Recovery is a powerful tool to recover deleted or corrupted SQL database data. It can restore deleted SQL data in most situations and repair the corrupted database (the MDF and NDF files).

How to rollback my delete data in Postgres after delete operation?

I have not done anything. I just run this command DELETE FROM feed_republic. But I want to get my data again. What should I do?
When I run rollback I am getting the following message. Please help!
WARNING: there is no transaction in progress
I have not used any commit or any other command unlike this question Can I rollback a transaction I've already committed? (data loss).
PostgreSQL is running in autocommit mode, so every statement is running in its own transaction unless you explicitly start a transaction with BEGIN or START TRANSACTION.
The only way you can get your data back is by restoring from a backup.

Sql Transaction doesn't release lock after commit

I have run a script similar to the one below in a SSMS query window. After the script run successfully, some locks remained on affected tables. When I try to close the window, a messagebox is showed asking me if I want to commit or cancel the transaction.
After I choose one of the options, the locks are released.
What can cause this behaviour?
begin tran
delete from tableA
delete from tableB
insert into tableB
insert into tableA
commit tran
I'm connected to a remote Sql Server 2014 and running localy SSMS 2014
Thanks!
The following example illustrates how locks are not released as a result of an unfinished open transaction:
Open the SQL Server Query Analyzer and run the following batch but cancel the transaction before it completes:
Begin Tran
Update authors set state = 'CA'
waitfor delay "00:02:00" --Cancel the command
Commit Tran
View the locks that are held by executing the following command:
sp_lock
You see that locks are held for the authors table.
From the same server process id (SPID), execute the next batch:
Begin Tran
Update titleauthor set au_ord = 0
Commit Tran - Completed transaction.
View the locks that are held by executing the following command:
sp_lock
You see that although the last transaction is completed, locks are held on both the authors and titleauthors tables. The reason is that the first transaction did not complete and when the second transaction was executed from the same connection, it was treated as a nested transaction.
You can view the transaction count by checking the ##trancount global variable by issuing the following statement:
select ##trancount
This query returns 1, which indicates that one transaction is outstanding.
Any further transactions that are executed from this connection are treated as nested. Locks continue to accumulate and are not released until a ROLLBACK is executed, which rollbacks to the outer most transaction or to a savepoint.
In continuing with the example, you can see how a rollback may cause a completed transaction to be negated by executing the following transaction from the same connection:
Begin Tran
Update titles set royalty = 0
Rollback
The rollback rolls the batch back to the outermost transaction, even though there is a completed transaction (2) on titleauthors. The rollback on the completed transaction occurs because the completed transaction is treated as a nested transaction.
To avoid this kind of problem, check after each transaction to see if the transaction is complete by using the following statement:
If ##trancount > 0 rollback
Reference: Incomplete transaction may hold large number of locks and cause blocking

How to return back in SQL statement

I have run SQL server command (update command).
the command has been performed successfully and the table has been updated
is there any way to take back in that command ?
note: no backup taken
If you had originally asked the question how do I do an UPDATE with the possibility of ROLLBACK I would tell you you should do your ad-hoc updates like this.
BEGIN TRANSACTION
UPDATE blah
SET value = newvalue
WHERE condition = someothervalue
--COMMIT TRANSACTION
Then if the results are as expected run the COMMIT TRANSACTION. If they are not than you could do a ROLLBACK TRANSACTION. However since you already did the updates and have no backups or recovery plan you are pretty much out of luck.
After you have already executed an update command the only way back would be via restoring a backup.
Something I do when writing any modification scripts is to wrap the command in a transaction and then either run a rollback or a commit depending on if the query performed as suspected.
Example:
--start the transaction only execute the first three lines, this leaves the transaction open
BEGIN TRANSACTION
UPDATE TABLEA
SET COL1 = "newValue"
--examine data and based on the results run one of these two lines
ROLLBACK TRANSACTION
COMMIT TRANSACTION

SQL Server query dry run

I run a lot of queries that perform INSERT's, insert SELECT's, UPDATE's and ALTER's on tables, and when developing these queries, the intermediate steps that are run to test that various parts of the query work, potentially change the table or the data within the table.
Is it possible to do a dry run of a query and have SQL Management Studio give you what the results would be, without actually modifying the data or the table structure?
At the moment I have to back up the database, and run the query. If it works, good, if it doesn't, I have to restore the database (which can take around a hour) and I'm trying to avoid wasting all this time having to restore databases.
Use an SQL transaction to make your changes then back them out.
Before you execute your script:
BEGIN TRANSACTION;
After you execute your script and have done your checking:
ROLLBACK TRANSACTION;
Every change in your script will then be undone.
Note: Make sure you don't have a COMMIT in your script!
Begin the transaction, perform the table operations, and rollback as shown below:
BEGIN TRAN
UPDATE C
SET column1 = 'XXX'
FROM table1 C
SELECT *
FROM table1
WHERE column1 = 'XXX'
ROLLBACK TRAN
This will rollback all the operations performed since the last commit since the beginning of this transaction.