Postgresql:带有外键死锁的事务


Codeigniter Postgresql: Transaction with foreign key deadlock

我有一个问题与postgresql事务(与codeigniter),这里是涉及的表:

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));

交易如下:

$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();

现在,我不能执行SELECT查询,因为之前的插入还没有完成。如何在没有第一次插入的外键的情况下进行第二次插入?

编辑:24/06/2014

最后我使用了postgre的currval()函数。只替换下面的select查询:

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

如果只需要从INSERT语句中获取"nro_factura"的值,则不应该使用SELECT语句来获取它。

PostgreSQL通过它的currval()函数公开一个特定序列返回的最后一个数字。它的记录行为是

返回nextval在该序列中最近获得的值在本届会议上。(如果nextval没有在这个会话中被调用这个序列。)因为这是返回一个会话本地值,它给出一个可预测的答案或者自当前会话以来没有其他会话执行nextval了。

CodeIgniter似乎在PostgreSQL函数周围包装了自己的函数,$this->db->insert_id()。

AFAIK,当前版本的每一个广泛使用的dbms,每一个ORM,每一个数据库抽象层都包含这样的函数