简体   繁体   English

Codeigniter Postgresql:具有外键死锁的事务

[英]Codeigniter Postgresql: Transaction with foreign key deadlock

Im having a problem with a postgresql transaction (with codeigniter), here is the tables involved: 我在使用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));

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. 现在,我无法执行SELECT查询,因为尚未进行先前的插入。 How I can do the second insert without the foreign key from the first insert? 我如何才能在没有第一次插入中的外键的情况下进行第二次插入?

EDIT: 24/06/2014 编辑:2014年6月24日

Finally I used the currval() function of postgre. 最后,我使用了postgre的currval()函数。 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. 如果只需要INSERT语句中的“ nro_factura”值,则不应使用SELECT语句来获取它。

PostgreSQL exposes the last number returned by a particular sequence through its currval() function . PostgreSQL通过currval()函数公开特定序列返回的最后一个数字。 It's documented behavior is 它记录的行为是

Return the value most recently obtained by nextval for this sequence in the current session. 返回当前会话中nextval最近为该序列获取的值。 (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. (如果从未在此会话中为此序列调用nextval,则会报告一个错误。)由于此方法返回的是会话本地值,因此它提供了一个可预测的答案,即自当前会话执行以来,其他会话是否已执行nextval。

CodeIgniter seems to wrap its own function, $this->db->insert_id() , around that PostgreSQL function. CodeIgniter似乎在该PostgreSQL函数周围包装了自己的函数$ this-> db-> insert_id()

AFAIK, the current versions of every widely used dbms, every ORM, and every database abstraction layer include a function like this. AFAIK,每个广泛使用的dbms,每个ORM和每个数据库抽象层的当前版本都包含这样的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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