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