简体   繁体   中英

Codeigniter Postgresql: Transaction with foreign key deadlock

Im having a problem with a postgresql transaction (with codeigniter), here is the tables involved:

CREATE TABLE factura(
nro_factura serial NOT NULL,
fecha_emision date NOT NULL,    
(... more columns)
PRIMARY KEY (nro_factura));

CREATE TABLE detalle(
id_articulo integer NOT NULL REFERENCES articulos(id) ON UPDATE CASCADE ON DELETE RESTRICT,
nro_factura integer NOT NULL REFERENCES factura(nro_factura) ON UPDATE CASCADE ON DELETE RESTRICT,
(... more columns)
PRIMARY KEY(id_articulo,nro_factura));

And this is the transaction:

$this->db->trans_start();

        $queryFactura = $this->db->query("INSERT INTO factura (... all columns) VALUES (CURRENT_DATE,?,?,?,?,?,?,?,?,?,?,?,?)",$factura);

        $id_factura = $this->db->query("SELECT nro_factura FROM factura WHERE id_vehiculo=?",array($factura['id_vehiculo'])); 

        foreach ($articulos as $key){
            $queryFactura = $this->db->query("INSERT INTO detalle (id_articulo,nro_factura,precio_venta,descuento,cantidad) VALUES (?,$id_factura,?,?,?)",$key);
        } 

        $this->db->trans_complete();

Now, I cant do the SELECT query because the previous insert has not yet been made. How I can do the second insert without the foreign key from the first insert?

EDIT: 24/06/2014

Finally I used the currval() function of postgre. Only replace the select query for this:

 $id_factura = $this->db->query("SELECT currval(pg_get_serial_sequence('factura', 'nro_factura'))",array())->result()[0]->currval;

If you just need the value of "nro_factura" from the INSERT statement, you shouldn't use a SELECT statement to get it.

PostgreSQL exposes the last number returned by a particular sequence through its currval() function . It's documented behavior is

Return the value most recently obtained by nextval for this sequence in the current session. (An error is reported if nextval has never been called for this sequence in this session.) Because this is returning a session-local value, it gives a predictable answer whether or not other sessions have executed nextval since the current session did.

CodeIgniter seems to wrap its own function, $this->db->insert_id() , around that PostgreSQL function.

AFAIK, the current versions of every widely used dbms, every ORM, and every database abstraction layer include a function like this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM