Qué tal estoy programando una función en PLPGSQL y ya he avanzado bastante 
diría yo pero ahora me he topado con un problema el cual por ningún lado he 
podido resolver.

La función tiene como propósito el checar una tabla para encontrar similitudes 
entre sus datos (duplicados), para después quitarlos, por endé se le envían las 
columnas a comparar y el nombre de la tabla también.

Ahora he hecho que la función pueda construir las consulta necesarias, tanto 
para la creación de una tabla de respaldo donde trabajara y hasta ahora la 
consulta que detectará de forma única la "N" cantidad de elementos repetidos a 
los cuales debo pasar a otra tabla, la cuál solo tenga la estructura base de 
unicamente las columnas que se envían a través de la función, además de una 
columnas extra llamada "group_duplicate" la cual solo debe marcar con un 
identificador único a cada elmento de grupos repetidos.

Esta última consulta ya también esta, tanto para la creación de la tabla a base 
de las columnas enviadas.
Por ejemplo para una llamada como: 

SELECT emu_winpure('articulo, autor, clasif, u_fech_mov, fech_ped, codigo', 
'productos');

Obtengo estás consultas:

NOTICE:  CREATE TABLE productos_winpure AS (SELECT * FROM productos)
NOTICE:  ALTER TABLE productos_winpure ADD COLUMN orden_winpure SERIAL NOT NULL
NOTICE:  CREATE TABLE duplicados AS (SELECT (NULL)::integer AS group_duplicate, 
orden_winpure, articulo, autor, clasif, u_fech_mov, fech_ped, codigo FROM 
productos_winpure LIMIT 0)

NOTICE:
SELECT DISTINCT ON(a.articulo, a.autor, a.clasif, a.u_fech_mov, a.fech_ped, 
a.codigo)
       a.articulo, a.autor, a.clasif, a.u_fech_mov, a.fech_ped, a.codigo
FROM productos_winpure a, productos_winpure b
WHERE
     (CASE WHEN (quita_caracter(a.articulo, ' ') IS NULL) OR 
(quita_caracter(b.articulo, ' ') IS NULL) THEN (1=1)::boolean ELSE 
(UPPER(quita_caracter(a.articulo, ' '))=UPPER(quita_caracter(b.articulo, ' 
')))::boolean END)::boolean 
 AND (CASE WHEN (quita_caracter(a.autor, ' ') IS NULL) OR 
(quita_caracter(b.autor, ' ') IS NULL) THEN (1=1)::boolean ELSE 
(UPPER(quita_caracter(a.autor, ' '))=UPPER(quita_caracter(b.autor, ' 
')))::boolean END)::boolean 
 AND (CASE WHEN (quita_caracter(a.clasif, ' ') IS NULL) OR 
(quita_caracter(b.clasif, ' ') IS NULL) THEN (1=1)::boolean ELSE 
(UPPER(quita_caracter(a.clasif, ' '))=UPPER(quita_caracter(b.clasif, ' 
')))::boolean END)::boolean 
 AND (CASE WHEN (quita_caracter(a.u_fech_mov, ' ') IS NULL) OR 
(quita_caracter(b.u_fech_mov, ' ') IS NULL) THEN (1=1)::boolean ELSE 
(UPPER(quita_caracter(a.u_fech_mov, ' '))=UPPER(quita_caracter(b.u_fech_mov, ' 
')))::boolean END)::boolean 
 AND (CASE WHEN (quita_caracter(a.fech_ped, ' ') IS NULL) OR 
(quita_caracter(b.fech_ped, ' ') IS NULL) THEN (1=1)::boolean ELSE 
(UPPER(quita_caracter(a.fech_ped, ' '))=UPPER(quita_caracter(b.fech_ped, ' 
')))::boolean END)::boolean 
 AND (CASE WHEN (quita_caracter(a.codigo, ' ') IS NULL) OR 
(quita_caracter(b.codigo, ' ') IS NULL) THEN (1=1)::boolean ELSE 
(UPPER(quita_caracter(a.codigo, ' '))=UPPER(quita_caracter(b.codigo, ' 
')))::boolean END)::boolean
ORDER BY a.articulo, a.autor, a.clasif, a.u_fech_mov, a.fech_ped, a.codigo


Las cuales se ejecutan de forma correcta pero esta consulta:

NOTICE:
SELECT DISTINCT ON(a.orden_winpure, a.articulo, a.autor, a.clasif, 
a.u_fech_mov, a.fech_ped, a.codigo) 
       a.orden_winpure, a.articulo, a.autor, a.clasif, a.u_fech_mov, 
a.fech_ped, a.codigo
FROM productos_winpure a
WHERE
a.articulo::varchar=$$lista.articulo$$::varchar 
AND a.autor::varchar=$$lista.autor$$::varchar 
AND a.clasif::varchar=$$lista.clasif$$::varchar 
AND a.u_fech_mov::varchar=$$lista.u_fech_mov$$::varchar 
AND a.fech_ped::varchar=$$lista.fech_ped$$::varchar 
AND a.codigo::varchar=$$lista.codigo$$::varchar
ORDER BY a.orden_winpure, a.articulo, a.autor, a.clasif, a.u_fech_mov, 
a.fech_ped, a.codigo



Cómo verán depende de un elemento "lista" obtenido de este "for":


 FOR lista IN EXECUTE consulta LOOP
  cont:=cont+1;
  consulta_1:=('\nSELECT DISTINCT ON(a.orden_winpure, ' || columnas || ') \n    
   a.orden_winpure, ' || columnas || '\nFROM ' || new_table || ' a\nWHERE\n' || 
condiciones || '\nORDER BY a.orden_winpure, ' || columnas || '\n');
  RAISE NOTICE '%', consulta_1;

  FOR lista_aux1 IN EXECUTE consulta_1 LOOP
   RAISE NOTICE 'En segunda consulta';
--   EXECUTE 'INSERT INTO duplicados (SELECT ' || cont || ', lista_aux1.* || ' 
FROM ' || new_table || ')';
  END LOOP;
 END LOOP;


Más sin embargo al ejecutar la consulta en el segundo "for", los valores son 
pasados como cadena y no como una referencia en los elementos tales como 
"lista.articulo" que es lo que desearía.
Poniendo la consulta de forma directa como:


consulta_1:=
'
SELECT DISTINCT ON(a.orden_winpure, a.articulo, a.autor, a.clasif, 
a.u_fech_mov, a.fech_ped, a.codigo)
       a.orden_winpure, a.articulo, a.autor, a.clasif, a.u_fech_mov, 
a.fech_ped, a.codigo
FROM productos_winpure a
WHERE
     a.articulo::varchar=\$\$' || lista.articulo || '\$\$::varchar
 AND a.autor::varchar=\'' || lista.autor || '\'::varchar
 AND a.clasif::varchar=\'' || lista.clasif || '\'::varchar
 AND a.u_fech_mov::varchar=\'' || lista.u_fech_mov || '\'::varchar
 AND a.fech_ped::varchar=\'' || lista.fech_ped || '\'::varchar
 AND a.codigo::varchar=\'' || lista.codigo || '\'::varchar
ORDER BY a.orden_winpure, a.articulo, a.autor, a.clasif, a.u_fech_mov, 
a.fech_ped, a.codigo
';


Funciona bien, más sin embargo aun haciendo el código necesario para que me 
construya esta instrucción tal cual, me arroja un error o me toma la variable 
"linea.xx" de forma textual y no como referencia.
Cómo podría hacer para construir una consulta dentro de un varchar que pueda 
ejecutar con el comando EXECUTE y la cual haga referencia a los elementos de 
una variable perteneciente a un "for" superior, tal cual se presenta en los 
"for" aninados que les muestro arriba?

Alguna sugerencia?
_________________________________________________________________
Herramientas para combatir la crisis. MSN Dinero
http://dinero.es.msn.com/--
TIP 5: ¿Has leído nuestro extenso FAQ?
         http://www.postgresql.org/docs/faqs.FAQ.html

Responder a