使多个to_sql事务全部或全部不做的好方法是什么?

时间:2019-05-03 17:11:34

标签: pandas sqlite triggers

在下面,conn.rollback()不会删除数据帧“ a”的插入。您能告诉我是否有一种很好的方法可以使“ a”仅插入“ d”吗?

import sqlite3 as sql
import pandas as pd

conn = sql.connect(':memory:')

a = pd.DataFrame(['a','b','c'],columns=['col1'])
d = pd.DataFrame(['d'],columns=['col1'])

a.to_sql('test',con=conn,if_exists='append')

try:
    raise()
    d.to_sql('test',con=conn,if_exists='append')
except:
    print('failed')
    conn.rollback() 

print(pd.read_sql('select * from test',con=conn))

编辑:

实施以下内容的动态生成是否有效?对于每个最终表,都有一个缓冲表。一旦事务表中的状态更新为1,就会触发触发器,尝试将所有缓冲区表数据放入最终表中。

CREATE TABLE `sql_transactions` (
    `id_insert` INTEGER NOT NULL,
    'as_of' datetime not null,
    `status`    INTEGER NOT NULL, -- -1: fail 
                                  -- 0: inserting into buffer 
                                  -- 1: sending 
                                  -- 2: success 
    primary key (id_insert, as_of)
);


CREATE TABLE "tbl_1" ( 'k' TEXT NOT NULL, 'v' REAL not null,  PRIMARY KEY('k') ) WITHOUT ROWID;
CREATE TABLE "tbl_2" ( 'k' TEXT NOT NULL, 'v' REAL not null,  PRIMARY KEY('k') ) WITHOUT ROWID;
CREATE TABLE "buffer_tbl_1" ('id_insert' integer, 'k' TEXT NOT NULL, 'v' REAL,  PRIMARY KEY('id_insert','k')) WITHOUT ROWID;
CREATE TABLE "buffer_tbl_2" ('id_insert' integer, 'k' TEXT NOT NULL, 'v' REAL,  PRIMARY KEY('id_insert','k')) WITHOUT ROWID;

create trigger "into_tbls" after insert on sql_transactions
begin
    insert into tbl_1 (k,v)  select k, v from buffer_tbl_1 where buffer_tbl_1.id_insert = new.id_insert and new.status = 1;
    delete from buffer_tbl_1 where buffer_tbl_1.id_insert = new.id_insert;

    insert into tbl_2 (k,v)  select k, v from buffer_tbl_2 where buffer_tbl_2.id_insert = new.id_insert and new.status = 1;
    delete from buffer_tbl_2 where buffer_tbl_2.id_insert = new.id_insert;

    update sql_transactions set status = 2 where new.id_insert = new.id_insert and new.status = 1;
end

create trigger "delete_failure" after insert on sql_transactions
begin
    delete from buffer_tbl_1 where buffer_tbl_1.id_insert = new.id_insert and new.status = -1;
    delete from buffer_tbl_2 where buffer_tbl_2.id_insert = new.id_insert and new.status = -1;
end

insert into sql_transactions (id_insert,as_of,status) values (0,datetime('now'),0)  
insert into  buffer_tbl_1 (id_insert,k,v) values (0,"a",1), (0,"b",2)
insert into  buffer_tbl_2 (id_insert,k,v) values (0,"c",3), (0,"d",4)

select * from sql_transactions;
select * from buffer_tbl_1;
select * from buffer_tbl_2;

-- successfully move data from the buffer tables to the final tables
insert into sql_transactions (id_insert,as_of,status) values (0,datetime('now'),1)  

select * from tbl_1;
select * from tbl_2;
select * from buffer_tbl_1;
select * from buffer_tbl_2;


insert into sql_transactions (id_insert,as_of,status) values (1,datetime('now'),0)

-- allow null gets into the tbl_2 buffer, but prevents insert into tbl_1
insert into  buffer_tbl_1 (id_insert,k,v) values (1,"z",1), (1,"y",2)
insert into  buffer_tbl_2 (id_insert,k,v) values (1,"x",3), (1,"w",NULL) 

insert into sql_transactions (id_insert,as_of,status) values (1,datetime('now'),1)  

select * from tbl_1;
select * from tbl_2;
select * from buffer_tbl_1;
select * from buffer_tbl_2; -- bad insert stays in buffer for review

-- this would go in the except statement
insert into sql_transactions (id_insert,as_of,status) values (1,datetime('now'),-1) 

select * from tbl_1;
select * from tbl_2;
select * from buffer_tbl_1;
select * from buffer_tbl_2; -- bad insert stays in buffer for review

select * from sql_transactions

0 个答案:

没有答案