sqlalchemy在插入触发器后不执行oracle

时间:2015-08-07 14:48:14

标签: python oracle triggers sqlalchemy

我有两个名为 movimiento (id_operacion,id_pago,importe)和票证(id_movimiento,id_localidad,nro_ticket,precio,impreso,id_movimiento_anterior)的表格,票证表格后插入触发器,用于从保存序列值的名为 funcion 的表中指定 nro_ticket 值。

这里是插入前触发器:

create or replace TRIGGER "TICKETS4_TST"."TRG_B_I_TICKET" 
BEFORE INSERT ON TICKET REFERENCING NEW AS NEW
FOR EACH ROW
DECLARE
  ticket NUMBER;
BEGIN
  ticket := OBTENER_NUMERO_TICKET(SUBSTR(:new.id_localidad,0,9));
  :new.nro_ticket := ticket;
END;

获取nro_ticket值的函数:

create or replace FUNCTION obtener_numero_ticket (id_fun IN VARCHAR2)
RETURN NUMBER
IS
nro_ticket NUMBER;
BEGIN
  SELECT seq_ticket into nro_ticket FROM funcion where id_funcion = id_fun;
  RETURN (nro_ticket + 1);
END obtener_numero_ticket;

这里是插入后的触发器:

create or replace TRIGGER "TICKETS4_TST"."TRG_A_I_TICKET" 
AFTER INSERT ON TICKET REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
  UPDATE funcion SET seq_ticket = :new.nro_ticket WHERE id_funcion= SUBSTR(:new.id_localidad,0,9);
END;

这是SQLAlchemy代码:

sql_movimientos = """INSERT INTO movimiento (id_operacion, id_pago,
                                             importe)
                     VALUES ('%s', '%s', '%s')
                     RETURNING id_movimiento INTO :id_movimiento"""
sql_tickets = """INSERT INTO ticket (id_movimiento, id_localidad,
                                     precio, impreso,
                                     id_movimiento_anterior)
                 VALUES ('%s', '%s', '%s',
                         '%s', '%s')
                 RETURNING nro_ticket INTO :nro_ticket"""

with db.session as session:
    try:
        cursor = session.connection().connection.cursor()
        nuevo_id_movimiento = cursor.var(NUMBER)
        nuevo_nro_ticket = cursor.var(NUMBER)
        print sql_movimientos % (
            movimiento.operacion, movimiento.pago, movimiento.importe)
        session.execute(sql_movimientos % (
            movimiento.operacion, movimiento.pago, movimiento.importe),
             {'id_movimiento': nuevo_id_movimiento})
        nuevo_id_movimiento = int(nuevo_id_movimiento.getvalue())
    except Exception, e:
        session.rollback()
        raise e

    try:
        print sql_tickets % (nuevo_id_movimiento,
            ticket.localidad.id, ticket.precio, ticket.impreso,
            ticket.movimiento_anterior)
        session.execute(sql_tickets % (nuevo_id_movimiento,
            ticket.localidad.id, ticket.precio, ticket.impreso,
            ticket.movimiento_anterior),
            {'nro_ticket': nuevo_nro_ticket})
        nuevo_nro_ticket = int(nuevo_nro_ticket.getvalue())
        print nuevo_nro_ticket
    except Exception, e:
        session.rollback()
        raise e

这就是sqlalchemy翻译查询的方式:

INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO :id_movimiento
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES ('5725976', '------------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO :nro_ticket
17 << nro_ticket value
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO :id_movimiento
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES ('5725977', '-------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO :nro_ticket
17 << nro_ticket value
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO :id_movimiento
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES ('5725978', '----------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO :nro_ticket
17 << nro_ticket value
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO :id_movimiento
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES ('5725979', '--------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO :nro_ticket
17 << nro_ticket value
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO :id_movimiento
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES ('5725980', '--------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO :nro_ticket
17 << nro_ticket value

但是如果在SQLDeveloper中执行与匿名块相同的操作,我会得到正确的值:

declare
  id_movimiento number;
  nro_ticket number;
begin
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO id_movimiento;
DBMS_OUTPUT.put_line(id_movimiento);
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES (id_movimiento, '------------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO nro_ticket;
DBMS_OUTPUT.put_line(nro_ticket);
INSERT INTO movimiento (id_operacion, id_pago, importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO id_movimiento;
DBMS_OUTPUT.put_line(id_movimiento);
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES (id_movimiento, '--------------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO nro_ticket;
DBMS_OUTPUT.put_line(nro_ticket);
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO id_movimiento;
DBMS_OUTPUT.put_line(id_movimiento);
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES (id_movimiento, '---------------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO nro_ticket;
DBMS_OUTPUT.put_line(nro_ticket);
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO id_movimiento;
DBMS_OUTPUT.put_line(id_movimiento);
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES (id_movimiento, '--------------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO nro_ticket;
DBMS_OUTPUT.put_line(nro_ticket);
INSERT INTO movimiento (id_operacion, id_pago,
                                                     importe)
                             VALUES ('639086', '566365', '100')
                             RETURNING id_movimiento INTO id_movimiento;
DBMS_OUTPUT.put_line(id_movimiento);
INSERT INTO ticket (id_movimiento, id_localidad,
                                             precio, impreso,
                                             id_movimiento_anterior)
                         VALUES (id_movimiento, '---------------------', '100',
                                 '0', '')
                         RETURNING nro_ticket INTO nro_ticket;
DBMS_OUTPUT.put_line(nro_ticket);
end;

哪个输出:

5725981
17 << nro_ticket value
5725982
18 << nro_ticket value
5725983
19 << nro_ticket value
5725984
20 << nro_ticket value
5725985
21 << nro_ticket value

所以我认为问题是SQLALchemy,但我不明白为什么它不起作用。

1 个答案:

答案 0 :(得分:0)

根据您发布的代码,对我而言,您不清楚如何创建SQLAlchemy session。无论如何,既然我的代码看起来很好,我已经对Oracle数据库进行了试验并且它有效。我就是这样做的,

通过SQLAlchemy创建了2个表格(可能您已直接完成)。

In [2]:

class Movimiento(Base):
    __tablename__ = 'movimiento'

    id_movimiento = Column(Integer, primary_key=True)
    id_operacion = Column(Integer)
    id_pago = Column(Integer)
    importe = Column(Integer)

In [3]:

class Ticket(Base):
    __tablename__ = 'ticket'

    nro_ticket = Column(Integer, primary_key=True)
    id_movimiento = Column(Integer)
    id_localidad = Column(Integer)
    precio = Column(Integer)
    impreso = Column(Integer)
    id_movimiento_anterior = Column(Integer)

直接创建序列

create sequence movimiento_seq;
create sequence ticket_seq;

create or replace trigger movimiento_trigger
  before insert on movimiento
  for each row
  begin
    select movimiento_seq.nextval into :new.id_movimiento from dual;
  end;

create or replace trigger ticket_trigger
  before insert on ticket
  for each row
  begin
    select ticket_seq.nextval into :new.nro_ticket from dual;
  end;

然后会议:

engine = create_engine('oracle://test:test@localhost:1521/orcl')

Base.metadata.create_all(engine)

Base.metadata.bind = engine

DBSession = sessionmaker(bind=engine)

session = DBSession()

获取代码并使其成为一个函数,

from cx_Oracle import NUMBER

sql_movimientos = """INSERT INTO movimiento (id_operacion, id_pago,
                                             importe)
                     VALUES ('%s', '%s', '%s')
                     RETURNING id_movimiento INTO :id_movimiento"""
sql_tickets = """INSERT INTO ticket (id_movimiento, id_localidad,
                                     precio, impreso,
                                     id_movimiento_anterior)
                 VALUES ('%s', '%s', '%s',
                         '%s', '%s')
                 RETURNING nro_ticket INTO :nro_ticket"""

#with session as session:
def ins_mov_tick(movimiento, ticket):
    try:
        cursor = session.connection().connection.cursor()
        nuevo_id_movimiento = cursor.var(NUMBER)
        nuevo_nro_ticket = cursor.var(NUMBER)
        print sql_movimientos % (
            movimiento.id_operacion, movimiento.id_pago, movimiento.importe)
        session.execute(sql_movimientos % (
            movimiento.id_operacion, movimiento.id_pago, movimiento.importe),
             {'id_movimiento': nuevo_id_movimiento})
        nuevo_id_movimiento = int(nuevo_id_movimiento.getvalue())
    except Exception, e:
        session.rollback()
        raise e

    try:
        print sql_tickets % (nuevo_id_movimiento,
            ticket.id_localidad, ticket.precio, ticket.impreso,
            ticket.id_movimiento_anterior)
        session.execute(sql_tickets % (nuevo_id_movimiento,
            ticket.id_localidad, ticket.precio, ticket.impreso,
            ticket.id_movimiento_anterior),
            {'nro_ticket': nuevo_nro_ticket})
        nuevo_nro_ticket = int(nuevo_nro_ticket.getvalue())
        print nuevo_nro_ticket
    except Exception, e:
        session.rollback()

(因为我正在使用上面创建的类MovimientoTicket,而您正在使用一些更复杂的类结构,所以您也会看到一些小修改。)

然后每次我运行该功能时,我都会看到票号递增:

In [21]:

ins_mov_tick(movimiento, ticket)
INSERT INTO movimiento (id_operacion, id_pago,
                                             importe)
                     VALUES ('1', '2', '45')
                     RETURNING id_movimiento INTO :id_movimiento
INSERT INTO ticket (id_movimiento, id_localidad,
                                     precio, impreso,
                                     id_movimiento_anterior)
                 VALUES ('3', '17', '45',
                         '1', '4')
                 RETURNING nro_ticket INTO :nro_ticket
3

In [23]:

ins_mov_tick(movimiento, ticket)
INSERT INTO movimiento (id_operacion, id_pago,
                                             importe)
                     VALUES ('1', '2', '45')
                     RETURNING id_movimiento INTO :id_movimiento
INSERT INTO ticket (id_movimiento, id_localidad,
                                     precio, impreso,
                                     id_movimiento_anterior)
                 VALUES ('4', '17', '45',
                         '1', '4')
                 RETURNING nro_ticket INTO :nro_ticket
4

我没有创建表格funcion或触发器,因为我认为这对您的问题不重要。

无论如何,从这个漫长的解释来看,我只想说你的代码应该没问题,而我发现它不适合你的唯一原因就是你必须处理{{{ 1}}(基本上,因为我不太了解你是怎么做到的,所以我不知道它是从哪里来的)。另一种可能性是我误解了一切。

希望它有所帮助。