0

我会尽力用英语解释我的问题。我创建了一个名为 Laboratory 的数据库,我想在其中控制用户何时插入、删除或更新表。我将此表称为“tablaLog”。

基本上 tablaLog 由触发器更新。它保存有关谁更改了已确定的表、旧数据、新数据、日期、用户和 pid 的信息。这就是我遇到问题的地方。pid是问题所在。我们的老师说,当我们说插入(使用 php 表单)时,我们应该在“detalle_sesion”表上查找它的 pid,以便我们现在可以知道哪个用户正在进行更改。这是我为此编写的函数:

CREATE OR REPLACE FUNCTION escuchar_cliente()
RETURNS trigger AS
$BODY$

DECLARE
res integer;
p int;

BEGIN
p = pg_backend_pid();
SELECT pid
INTO res
FROM detalle_sesion
WHERE pid = p;
IF res IS NOT NULL THEN
    DECLARE
        cod int;
        nombre character varying(20);

    BEGIN
        SELECT cod_usuario
        INTO cod
        FROM detalle_sesion
        WHERE pid = p;

        SELECT login
        INTO nombre
        FROM usuarios
        WHERE cod = cod_usuario;


        IF (TG_OP = 'DELETE') THEN
            INSERT INTO tablaLog (fecha, datoviejo, datonuevo, operacion, usuario, tabla, cod_tabla, cod_usuario)
            VALUES(now(), OLD.*, null, 'eliminar', nombre, 'Cliente', default, cod);
            RETURN OLD;
        ELSIF (TG_OP = 'UPDATE') THEN
            INSERT INTO tablaLog (fecha, datoviejo, datonuevo, operacion, usuario, tabla, cod_tabla, cod_usuario)
            VALUES(now(), OLD.*, NEW.*, 'actualizar', nombre, 'Cliente', default, cod);
            RETURN NEW;
        ELSIF (TG_OP = 'INSERT') THEN
            INSERT INTO tablaLog (fecha, datoviejo, datonuevo, operacion, usuario, tabla, cod_tabla, cod_usuario)
            VALUES(now(), null, NEW.*, 'insertar', nombre, 'Cliente', default, cod);
            RETURN NEW;
        END IF;
        RETURN NULL;            
    END;
END IF; 
RETURN NULL;    
END;
$BODY$
LANGUAGE plpgsql

我可以说这个功能不工作,因为很好......我没有在 tablaLog 上插入任何内容。一些同学也有同样的问题,他们说是由于 pid,每次进行查询时都会生成一个新的 pid,它与保存在“detalle_sesion”上的 pid 不同。

每次用户登录时,名为“detalle_sesion”的表都会更新 [cod_usuario, cod_sesion, ingreso, salida, pid] 以下是该表的更新方式。

CREATE OR REPLACE FUNCTION detallesesion(logi character varying, pass character varying)
 RETURNS boolean AS
 $BODY$

DECLARE
res character varying (20);
pid int;    
cod int;

 BEGIN
SELECT cod_usuario 
INTO res 
FROM usuarios 
WHERE login = logi AND password = pass;
IF res IS NOT NULL THEN

    DECLARE 
        cod int;
        pid int;
        bs timestamp with time zone;
        qs timestamp with time zone;        

    BEGIN
        cod := CAST(res AS integer);
        pid = pg_backend_pid();

        SELECT backend_start, query_start
        INTO bs, qs
        FROM pg_stat_activity
        WHERE procpid = pid;

        INSERT INTO detalle_sesion(cod_usuario, cod_sesion, ingreso, salida, pid)
        VALUES (cod, default, bs, qs, pid);

        RETURN(TRUE);
    END;
ELSE
RETURN(FALSE);
END IF;
    END;
    $BODY$
    LANGUAGE plpgsql

关于php,我有下一个:conexion.php

<?php
$conexion = pg_connect("host=localhost
                        port=5432
                        user=postgres
                        password=postgres
                        dbname=labo") or
die ("no se pudo conectar".pg_last_error());
?>

manejadorDB.php 所有带有查询的函数都在这里。

<?php
ini_set('display_errors', 1); 
error_reporting(E_ALL);
require_once "../funciones/conexion.php";
class manejadorDB
{

所以我问是否有办法在用户登录后保持相同的 pid。或者也许是一种不同的方式来更新“tablaLog”

4

1 回答 1

0

对于通过 建立的任何新连接,返回的值pg_backend_pid()都将不同pg_connect(),假设两者之间没有连接池。

同样在某些时候,这个值会回绕,就像 Unix 下的进程 ID(实际上它是一个进程 ID)一样,这意味着新会话将与pid不相关的断开连接的旧会话相同。

因此,pid仅此一项作为来自 Web 客户端的持久会话标识符并不好。如果有要登录的页面和后面的其他页面,则pid每个页面都会有所不同。

您仍然可以使用pid触发器中的 来查找会话,但您需要首先在 php中建立一个在页面之间保留的会话。用户登录时应插入唯一的会话 ID detalle_sesion。然后,每次调用后,应将pg_connect唯一的对应行更新为新的,以便触发器可以找到它。detalle_sesionpid

又既然pid都被重用了,pid光靠是不够的。pid和的组合backend_start会更好,因为这种组合在任何时期都是独一无二的。

于 2013-10-21T10:14:01.820 回答