|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||
En el programa testlibpq.c, estas cinco sentencias SQL se ejecutan para ilustrar los mecanismos básicos del funcionamiento de los cursores. res = PQexec(conn, "BEGIN"); res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database"); res = PQexec(conn, "FETCH ALL in myportal"); res = PQexec(conn, "CLOSE myportal"); res = PQexec(conn, "END");Esto es el equivalente de res = PQexec(conn, "select * from pg_database");¿Por qué querría ejecutar cinco sentencias en lugar de una? Si los datos retornardos por la consulta son pocos, o si desea obtener todos los datos de una sola vez, entonces la consulta única es la mejor opción. Se seleccionarán todos los resultados y se enviarán al cliente de una sola vez. Si desea poder desplazarse a través del conjunto de datos sin transmitirlo completo, o si desea transmitirlo de a trozos, lo que desea es usar el cursor. Los cursores pueden ahorrar ancho de banda tanto de la red como procesamiento en el cliente. Si desea mostrar una página de datos cada vez, y permitir a la aplicación desplazarse hacia adelante y hacia atrás en los datos, entonces el cursor es la solución apropiada. Si desea obtener todos los datos lo más rápido posible, use el SELECT simple. Así como este ejemplo usa libpq, lo mismo se aplica a todas las interfaces cliente.
Jan Weick: ¿De veras crees que alguien va a querer usar más de 640 filas?
En ediciones anteriores se han mostrado varios de los cambios en 7.4 En la Edición #48, por ejemplo, se mostraron los cambios en postgresql.conf. Esta lista viene de la Documentación de 7.4, Apéndice E.1.2. Se muestra la migración a la versión 7.4 y aquellos cambios que puedan ser sorpresivos o problemáticos. Las Release Notes son lectura obligatoria.
Para desactivar autocommit, use
Si alguna aplicación procesa las cadenas de texto de los mensajes de error, es imperativo que consulte la nueva documentación acerca de los códigos de error en el Apéndice de la documentación de 7.4. Los códigos de error ahora son conformes a los estándares SQL. Esto significa que debe verificarse el código de error y no el mensaje. Es poco probable que los códigos cambien, mientras que los textos pueden variar y además serán diferentes en algunos idiomas. Puede que vea resultados de EXPLAIN diferentes con JOINs ANSI. Si la limpieza (vacuum) y estadísticas están al día, estas consultas deberían estar mejor optimizadas. Si ve un cambio de comportamiento que resulte en una consulta mucho más lenta, debe verificar "los sospechosos de siempre". Verifique los tipos de dato en las calificaciones e índices para asegurarse que coincidan, etc. Recuerde que las diferencias entre MOVE y FETCH sólo son que FETCH retorna datos, y MOVE no. Ambos mueven el CURSOR a una fila enumerada dentro de un resultado. Anteriormente, FETCH 0 era el dialecto PostgreSQL para indicar FETCH ALL. No se podía usar FETCH 0 o FETCH RELATIVE 0 para extraer la fila actual. El nuevo comportamiento de esos comandos es extraer la fila a la que el cursor está actualmente apuntando. Si espera poder usar archivos antiguos creados por COPY con datos que contengan retornos de carro y saltos de línea literales, es hora de utilizar un guión Perl para convertir esos caracteres a \r o \n. Si usa CHAR(n) y espera obtener los espacios al final de las cadenas, asegúrese de no usar conversiones explícitas o implícitas a TEXT o VARCHAR(n), puesto que estos tipos de dato no conservarán dichos espacios. Este cambio trae a PostgreSQL de vuelta con el estándar SQL. Verifique sus campos de números en punto flotante si se definen explícitamente con precisión para asegurarse que los está declarando correctamente. Verifique cualquier campo de marca de hora y fecha que tengan now o today como valor por omisión. Cámbielos por la llamada a función now() o las variables especiales current_timestamp, current_date, etc.
Dada una tabla como la que se muestra abajo, se ejecutan dos inserciones paralelas en conexiones separadas usando bloques de transacciones. El segundo INSERT se bloqueará hasta que la primera transacción se complete. CREATE TABLE take2 ( id serial not null, timestamp timestamp NOT NULL DEFAULT now(), description text, FOREIGN KEY (asset_id) REFERENCES public.asset (id), ON UPDATE CASCADE ON DELETE CASCADE, PRIMARY KEY(id) );
Cuando PostgreSQL hace una referencia a public.asset, crea un lock exclusivo en la tabla — el equivalente de un SELECT FOR UPDATE. Este lock exclusivo puede verse examinando pg_locks. relation | database | transaction | pid | mode | granted ----------+----------+-------------+-------+------------------+--------- 39356 | 34862 | NULL | 18671 | AccessShareLock | t 39356 | 34862 | NULL | 18671 | RowExclusiveLock | t NULL | NULL | 9914 | 18671 | ExclusiveLock | t 39354 | 34862 | NULL | 18671 | AccessShareLock | t 34886 | 34862 | NULL | 18671 | AccessShareLock | t 34886 | 34862 | NULL | 18671 | RowShareLock | t 16759 | 34862 | NULL | 18671 | AccessShareLock | t (7 rows)PostgreSQL no implementa locks compartidos de lectura a nivel de fila (Ed.: ¿aún?) Para evitar esta clase de conflicto, asegúrese que sus transacciones son lo más pequeñas posible. Nunca permita interacción del usuario cuando una transacción ha comenzado (los humanos son tan poco confiables :-) Este consejo se mantiene para todos los tipos de transacciones. En este caso particular, donde la transacción ya es lo más pequeña que se puede, puede postergar la verificación de llave foránea hasta el momento de comprometer (commit) la transacción. Hay dos maneras de hacer esto, dependiendo de las acciones dentro de la transacción. Puede definir FOREIGN KEY como DEFERRABLE y usar SET CONSTRAINTS ALL DEFERRED durante la transacción. El otro mecanismo es crear las restricciones INITIALLY DEFERRED. CREATE TABLE take2 ( id serial not null, timestamp timestamp NOT NULL DEFAULT now(), description text, FOREIGN KEY (asset_id) REFERENCES public.asset (id) DEFERRABLE, ON UPDATE CASCADE ON DELETE CASCADE, PRIMARY KEY(id) );Se puede cambiar el estado de las restricciones con: BEGIN SET CONSTRAINTS ALL DEFERRED insert into table take2
A continuación se presentan dos buenas implementaciones de una función que invierte el orden de un campo de texto. La primera, de Joe Conway, gana en simplicidad, pero requiere plperl. La segunda, de Greg Sabino Mullane, es un buen ejemplo del uso de bucles en plpgsql.
CREATE OR REPLACE FUNCTION reverse(TEXT) RETURNS TEXT AS ' RETURN reverse($_[0]); ' LANGUAGE 'plperl'; CREATE OR REPLACE FUNCTION reverse(TEXT) RETURNS TEXT AS ' DECLARE original ALIAS FOR $1; reversed TEXT := \'\'; onechar VARCHAR; mypos INTEGER; BEGIN SELECT LENGTH(original) INTO mypos; LOOP EXIT WHEN mypos < 1; SELECT substring(original FROM mypos FOR 1) INTO onechar; reversed := reversed || onechar; mypos := mypos -1; END LOOP; RETURN reversed; END ' LANGUAGE plpgsql IMMUTABLE RETURNS NULL ON NULL INPUT;
Para determinar la cantidad de filas afectadas por una sentencia en una función plpgsql, puede usar GET DIAGNOSTICS. Esto es muy útil si quiere verificar el número de filas que fueron afectadas por una sentencia que afecta muchas filas, ya sea directa o indirectamente a través de un disparador (trigger) o una regla. DECLARE RowsAffected INTEGER; BEGIN -- EJECUTAR la sentencia GET DIAGNOSTICS RowsAffected = ROW_COUNT; END
|
||||||||||||||||||||||||||||||||||||||
Comments and Corrections are welcome. Suggestions and contributions of items are also welcome. Send them in!. Copyright A. Elein Mustain 2003, 2004,2005 |